]> git.kaiwu.me - quickjs.git/commitdiff
2020-11-08 release
authorbellard <6490144+bellard@users.noreply.github.com>
Sun, 8 Nov 2020 13:30:56 +0000 (14:30 +0100)
committerbellard <6490144+bellard@users.noreply.github.com>
Sun, 8 Nov 2020 13:30:56 +0000 (14:30 +0100)
23 files changed:
Changelog
Makefile
TODO
VERSION
doc/jsbignum.html [deleted file]
doc/jsbignum.pdf [deleted file]
doc/quickjs.html [deleted file]
doc/quickjs.pdf [deleted file]
doc/quickjs.texi
jscompress.c [deleted file]
libbf.h
libregexp.c
qjscalc.js
quickjs-atom.h
quickjs-libc.c
quickjs-opcode.h
quickjs.c
quickjs.h
release.sh
test262.conf
test262_errors.txt
tests/test_builtin.js
tests/test_language.js

index 1a7533b336027d6da314335bae10b0f2e87cb855..0c25b96f20d7804700bf82d667d719c8ee7b9d40 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,10 @@
+2020-11-08:
+
+- improved function parameter initializers
+- added std.setenv(), std.unsetenv() and std.getenviron()
+- added JS_EvalThis()
+- misc bug fixes
+
 2020-09-06:
 
 - added logical assignment operators
index 94c8e31e640d453854603b9d72b940ec7456e695..766a7e129e7424814810d59b87fb76c1c2af1898 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -28,9 +28,9 @@ endif
 # Windows cross compilation from Linux
 #CONFIG_WIN32=y
 # use link time optimization (smaller and faster executables but slower build)
-CONFIG_LTO=y
+#CONFIG_LTO=y
 # consider warnings as errors (for development)
-#CONFIG_WERROR=y
+CONFIG_WERROR=y
 # force 32 bit build for some utilities
 #CONFIG_M32=y
 
@@ -53,7 +53,11 @@ CONFIG_BIGNUM=y
 OBJDIR=.obj
 
 ifdef CONFIG_WIN32
-  CROSS_PREFIX=i686-w64-mingw32-
+  ifdef CONFIG_M32
+    CROSS_PREFIX=i686-w64-mingw32-
+  else
+    CROSS_PREFIX=x86_64-w64-mingw32-
+  endif
   EXE=.exe
 else
   CROSS_PREFIX=
@@ -281,15 +285,12 @@ $(OBJDIR)/%.check.o: %.c | $(OBJDIR)
 regexp_test: libregexp.c libunicode.c cutils.c
        $(CC) $(LDFLAGS) $(CFLAGS) -DTEST -o $@ libregexp.c libunicode.c cutils.c $(LIBS)
 
-jscompress: jscompress.c
-       $(CC) $(LDFLAGS) $(CFLAGS) -o $@ jscompress.c
-
 unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c unicode_gen_def.h
        $(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o
 
 clean:
        rm -f repl.c qjscalc.c out.c
-       rm -f *.a *.o *.d *~ jscompress unicode_gen regexp_test $(PROGS)
+       rm -f *.a *.o *.d *~ unicode_gen regexp_test $(PROGS)
        rm -f hello.c test_fib.c
        rm -f examples/*.so tests/*.so
        rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug
diff --git a/TODO b/TODO
index 0eec6d356a50aa12ae3f5126c4ad76c568fd9ec8..b5500c9c02d5613993a92ea2cc661ac45ee10477 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,13 +1,11 @@
-Misc:
-- use realpath in module name normalizer and put it in quickjs-libc
-- use custom printf to avoid C library compatibility issues
-- rename CONFIG_ALL_UNICODE, CONFIG_BIGNUM, CONFIG_ATOMICS, CONFIG_CHECK_JSVALUE ?
+Bugs:
+- modules: better error handling with cyclic module references
+
+Misc ideas:
+- use custom printf to avoid compatibility issues with floating point numbers
+- consistent naming for preprocessor defines
 - unify coding style and naming conventions
 - use names from the ECMA spec in library implementation
-- modules: if no ".", use a well known module loading path ?
-- use JSHoistedDef only for global variables (JSHoistedDef.var_name != JS_ATOM_NULL)
-- add index in JSVarDef and is_arg flag to merge args and vars in JSFunctionDef
-- replace most JSVarDef flags with var_type enumeration
 - use byte code emitters with typed arguments (for clarity)
 - use 2 bytecode DynBufs in JSFunctionDef, one for reading, one for writing
   and use the same wrappers in all phases
@@ -15,19 +13,36 @@ Misc:
 - use custom timezone support to avoid C library compatibility issues
 
 Memory:
+- use memory pools for objects, etc?
 - test border cases for max number of atoms, object properties, string length
 - add emergency malloc mode for out of memory exceptions.
 - test all DynBuf memory errors
 - test all js_realloc memory errors
-- bignum: handle memory errors
-- use memory pools for objects, etc?
 - improve JS_ComputeMemoryUsage() with more info
 
-Optimizations:
+Built-in standard library:
+- BSD sockets
+- modules: use realpath in module name normalizer and put it in quickjs-libc
+- modules: if no ".", use a well known module loading path ?
+- get rid of __loadScript, use more common name
+
+REPL:
+- debugger
+- readline: support MS Windows terminal
+- readline: handle dynamic terminal resizing
+- readline: handle double width unicode characters
+- multiline editing
+- runtime object and function inspectors
+- interactive object browser
+- use more generic approach to display evaluation results
+- improve directive handling: dispatch, colorize, completion...
+- save history
+- close all predefined methods in repl.js and jscalc.js
+
+Optimization ideas:
 - 64-bit atoms in 64-bit mode ?
-- use auto-init properties for more global objects
+- 64-bit small bigint in 64-bit mode ?
 - reuse stack slots for disjoint scopes, if strip
-- optimize `for of` iterator for built-in array objects
 - add heuristic to avoid some cycles in closures
 - small String (0-2 charcodes) with immediate storage
 - perform static string concatenation at compile time
@@ -36,43 +51,20 @@ Optimizations:
 - optimize `s += a + b`, `s += a.b` and similar simple expressions
 - ensure string canonical representation and optimise comparisons and hashes?
 - remove JSObject.first_weak_ref, use bit+context based hashed array for weak references
-- optimize function storage with length and name accessors?
 - property access optimization on the global object, functions,
   prototypes and special non extensible objects.
 - create object literals with the correct length by backpatching length argument
 - remove redundant set_loc_uninitialized/check_uninitialized opcodes
 - peephole optim: push_atom_value, to_propkey -> push_atom_value
 - peephole optim: put_loc x, get_loc_check x -> set_loc x
-- comparative performance benchmark
-- use variable name when throwing uninitialized exception if available
 - convert slow array to fast array when all properties != length are numeric
 - optimize destructuring assignments for global and local variables
 - implement some form of tail-call-optimization
 - optimize OP_apply
 - optimize f(...b)
 
-Extensions:
-- support more features in [features] section
-- add built-in preprocessor in compiler, get rid of jscompress
-  handle #if, #ifdef, #line, limited support for #define
-- get rid of __loadScript, use more common name
-- BSD sockets
-
-REPL:
-- debugger
-- readline: support MS Windows terminal
-- readline: handle dynamic terminal resizing
-- readline: handle double width unicode characters
-- multiline editing
-- runtime object and function inspectors
-- interactive object browser
-- use more generic approach to display evaluation results
-- improve directive handling: dispatch, colorize, completion...
-- save history
-- close all predefined methods in repl.js and jscalc.js
-
 Test262o:   0/11262 errors, 463 excluded
 Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
 
-Test262: 30/71748 errors, 868 excluded, 474 skipped
-Test262 commit: 24c67328062383079ada85f4d253eb0526fd209b
+Result: 51/75119 errors, 899 excluded, 570 skipped
+Test262 commit: 1c33fdb0ca60fb9d7392403be769ed0d26209132
diff --git a/VERSION b/VERSION
index c67790a7146b86d31b8f3a7d30c2d29b70b9b062..78749b0c7e8a2e4f3a0a32d287cdb562e2a09d8b 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2020-09-06
+2020-11-08
diff --git a/doc/jsbignum.html b/doc/jsbignum.html
deleted file mode 100644 (file)
index ab31612..0000000
+++ /dev/null
@@ -1,734 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->
-<head>
-<title>Javascript Bignum Extensions</title>
-
-<meta name="description" content="Javascript Bignum Extensions">
-<meta name="keywords" content="Javascript Bignum Extensions">
-<meta name="resource-type" content="document">
-<meta name="distribution" content="global">
-<meta name="Generator" content="makeinfo">
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<link href="#SEC_Contents" rel="contents" title="Table of Contents">
-<style type="text/css">
-<!--
-a.summary-letter {text-decoration: none}
-blockquote.indentedblock {margin-right: 0em}
-blockquote.smallindentedblock {margin-right: 0em; font-size: smaller}
-blockquote.smallquotation {font-size: smaller}
-div.display {margin-left: 3.2em}
-div.example {margin-left: 3.2em}
-div.lisp {margin-left: 3.2em}
-div.smalldisplay {margin-left: 3.2em}
-div.smallexample {margin-left: 3.2em}
-div.smalllisp {margin-left: 3.2em}
-kbd {font-style: oblique}
-pre.display {font-family: inherit}
-pre.format {font-family: inherit}
-pre.menu-comment {font-family: serif}
-pre.menu-preformatted {font-family: serif}
-pre.smalldisplay {font-family: inherit; font-size: smaller}
-pre.smallexample {font-size: smaller}
-pre.smallformat {font-family: inherit; font-size: smaller}
-pre.smalllisp {font-size: smaller}
-span.nolinebreak {white-space: nowrap}
-span.roman {font-family: initial; font-weight: normal}
-span.sansserif {font-family: sans-serif; font-weight: normal}
-ul.no-bullet {list-style: none}
--->
-</style>
-<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
-
-</head>
-
-<body lang="en">
-<h1 class="settitle" align="center">Javascript Bignum Extensions</h1>
-
-<a name="SEC_Contents"></a>
-<h2 class="contents-heading">Table of Contents</h2>
-
-<div class="contents">
-<ul class="no-bullet">
-<li><a name="toc-Introduction" href="#Introduction">1 Introduction</a></li>
-<li><a name="toc-Operator-overloading" href="#Operator-overloading">2 Operator overloading</a></li>
-<li><a name="toc-BigInt-extensions" href="#BigInt-extensions">3 BigInt extensions</a></li>
-<li><a name="toc-BigFloat" href="#BigFloat">4 BigFloat</a>
-<ul class="no-bullet">
-  <li><a name="toc-Introduction-1" href="#Introduction-1">4.1 Introduction</a></li>
-  <li><a name="toc-Floating-point-rounding" href="#Floating-point-rounding">4.2 Floating point rounding</a></li>
-  <li><a name="toc-Operators" href="#Operators">4.3 Operators</a></li>
-  <li><a name="toc-BigFloat-literals" href="#BigFloat-literals">4.4 BigFloat literals</a></li>
-  <li><a name="toc-Builtin-Object-changes" href="#Builtin-Object-changes">4.5 Builtin Object changes</a>
-  <ul class="no-bullet">
-    <li><a name="toc-BigFloat-function" href="#BigFloat-function">4.5.1 <code>BigFloat</code> function</a></li>
-    <li><a name="toc-BigFloat_002eprototype" href="#BigFloat_002eprototype">4.5.2 <code>BigFloat.prototype</code></a></li>
-    <li><a name="toc-BigFloatEnv-constructor" href="#BigFloatEnv-constructor">4.5.3 <code>BigFloatEnv</code> constructor</a></li>
-  </ul></li>
-</ul></li>
-<li><a name="toc-BigDecimal" href="#BigDecimal">5 BigDecimal</a>
-<ul class="no-bullet">
-  <li><a name="toc-Operators-1" href="#Operators-1">5.1 Operators</a></li>
-  <li><a name="toc-BigDecimal-literals" href="#BigDecimal-literals">5.2 BigDecimal literals</a></li>
-  <li><a name="toc-Builtin-Object-changes-1" href="#Builtin-Object-changes-1">5.3 Builtin Object changes</a>
-  <ul class="no-bullet">
-    <li><a name="toc-The-BigDecimal-function_002e" href="#The-BigDecimal-function_002e">5.3.1 The <code>BigDecimal</code> function.</a></li>
-    <li><a name="toc-Properties-of-the-BigDecimal-object" href="#Properties-of-the-BigDecimal-object">5.3.2 Properties of the <code>BigDecimal</code> object</a></li>
-    <li><a name="toc-Properties-of-the-BigDecimal_002eprototype-object" href="#Properties-of-the-BigDecimal_002eprototype-object">5.3.3 Properties of the <code>BigDecimal.prototype</code> object</a></li>
-  </ul></li>
-</ul></li>
-<li><a name="toc-Math-mode" href="#Math-mode">6 Math mode</a></li>
-
-</ul>
-</div>
-
-
-<a name="Introduction"></a>
-<h2 class="chapter">1 Introduction</h2>
-
-<p>The Bignum extensions add the following features to the Javascript
-language while being 100% backward compatible:
-</p>
-<ul>
-<li> Operator overloading with a dispatch logic inspired from the proposal available at <a href="https://github.com/tc39/proposal-operator-overloading/">https://github.com/tc39/proposal-operator-overloading/</a>.
-
-</li><li> Arbitrarily large floating point numbers (<code>BigFloat</code>) in base 2 using the IEEE 754 semantics.
-
-</li><li> Arbitrarily large floating point numbers (<code>BigDecimal</code>) in base 10 based on the proposal available at
-<a href="https://github.com/littledan/proposal-bigdecimal">https://github.com/littledan/proposal-bigdecimal</a>.
-
-</li><li> <code>math</code> mode: arbitrarily large integers and floating point numbers are available by default. The integer division and power can be overloaded for example to return a fraction. The modulo operator (<code>%</code>) is defined as the Euclidian
-remainder. <code>^</code> is an alias to the power operator
-(<code>**</code>). <code>^^</code> is used as the exclusive or operator.
-
-</li></ul>
-
-<p>The extensions are independent from each other except the <code>math</code>
-mode which relies on BigFloat and operator overloading.
-</p>
-<a name="Operator-overloading"></a>
-<h2 class="chapter">2 Operator overloading</h2>
-
-<p>Operator overloading is inspired from the proposal available at
-<a href="https://github.com/tc39/proposal-operator-overloading/">https://github.com/tc39/proposal-operator-overloading/</a>. It
-implements the same dispatch logic but finds the operator sets by
-looking at the <code>Symbol.operatorSet</code> property in the objects. The
-changes were done in order to simplify the implementation.
-</p>
-<p>More precisely, the following modifications were made:
-</p>
-<ul>
-<li> <code>with operators from</code> is not supported. Operator overloading is always enabled.
-
-</li><li> The dispatch is not based on a static <code>[[OperatorSet]]</code> field in all instances. Instead, a dynamic lookup of the <code>Symbol.operatorSet</code> property is done. This property is typically added in the prototype of each object.
-
-</li><li> <code>Operators.create(...dictionaries)</code> is used to create a new OperatorSet object. The <code>Operators</code> function is supported as an helper to be closer to the TC39 proposal.
-
-</li><li> <code>[]</code> cannot be overloaded.
-
-</li><li> In math mode, the BigInt division and power operators can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
-
-</li></ul>
-
-<a name="BigInt-extensions"></a>
-<h2 class="chapter">3 BigInt extensions</h2>
-
-<p>A few properties are added to the BigInt object:
-</p>
-<dl compact="compact">
-<dt><code>tdiv(a, b)</code></dt>
-<dd><p>Return <em>trunc(a/b)</em>. <code>b = 0</code> raises a RangeError
-exception.
-</p>
-</dd>
-<dt><code>fdiv(a, b)</code></dt>
-<dd><p>Return <em>\lfloor a/b \rfloor</em>. <code>b = 0</code> raises a RangeError
-exception.
-</p>
-</dd>
-<dt><code>cdiv(a, b)</code></dt>
-<dd><p>Return <em>\lceil a/b \rceil</em>. <code>b = 0</code> raises a RangeError
-exception.
-</p>
-</dd>
-<dt><code>ediv(a, b)</code></dt>
-<dd><p>Return <em>sgn(b) \lfloor a/{|b|} \rfloor</em> (Euclidian
-division). <code>b = 0</code> raises a RangeError exception.
-</p>
-</dd>
-<dt><code>tdivrem(a, b)</code></dt>
-<dt><code>fdivrem(a, b)</code></dt>
-<dt><code>cdivrem(a, b)</code></dt>
-<dt><code>edivrem(a, b)</code></dt>
-<dd><p>Return an array of two elements. The first element is the quotient,
-the second is the remainder. The same rounding is done as the
-corresponding division operation.
-</p>
-</dd>
-<dt><code>sqrt(a)</code></dt>
-<dd><p>Return <em>\lfloor \sqrt(a) \rfloor</em>. A RangeError exception is
-raised if <em>a &lt; 0</em>.
-</p>
-</dd>
-<dt><code>sqrtrem(a)</code></dt>
-<dd><p>Return an array of two elements. The first element is <em>\lfloor
-\sqrt{a} \rfloor</em>. The second element is <em>a-\lfloor \sqrt{a}
-\rfloor^2</em>. A RangeError exception is raised if <em>a &lt; 0</em>.
-</p>
-</dd>
-<dt><code>floorLog2(a)</code></dt>
-<dd><p>Return -1 if <em>a \leq 0</em> otherwise return <em>\lfloor \log2(a) \rfloor</em>.
-</p>
-</dd>
-<dt><code>ctz(a)</code></dt>
-<dd><p>Return the number of trailing zeros in the two&rsquo;s complement binary representation of a. Return -1 if <em>a=0</em>.
-</p>
-</dd>
-</dl>
-
-<a name="BigFloat"></a>
-<h2 class="chapter">4 BigFloat</h2>
-
-<a name="Introduction-1"></a>
-<h3 class="section">4.1 Introduction</h3>
-
-<p>This extension adds the <code>BigFloat</code> primitive type. The
-<code>BigFloat</code> type represents floating point numbers in base 2
-with the IEEE 754 semantics. A floating
-point number is represented as a sign, mantissa and exponent. The
-special values <code>NaN</code>, <code>+/-Infinity</code>, <code>+0</code> and <code>-0</code>
-are supported. The mantissa and exponent can have any bit length with
-an implementation specific minimum and maximum.
-</p>
-<a name="Floating-point-rounding"></a>
-<h3 class="section">4.2 Floating point rounding</h3>
-
-<p>Each floating point operation operates with infinite precision and
-then rounds the result according to the specified floating point
-environment (<code>BigFloatEnv</code> object). The status flags of the
-environment are also set according to the result of the operation.
-</p>
-<p>If no floating point environment is provided, the global floating
-point environment is used.
-</p>
-<p>The rounding mode of the global floating point environment is always
-<code>RNDN</code> (&ldquo;round to nearest with ties to even&rdquo;)<a name="DOCF1" href="#FOOT1"><sup>1</sup></a>. The status flags of the global environment cannot be
-read<a name="DOCF2" href="#FOOT2"><sup>2</sup></a>. The precision of the global environment is
-<code>BigFloatEnv.prec</code>. The number of exponent bits of the global
-environment is <code>BigFloatEnv.expBits</code>. The global environment
-subnormal flag is set to <code>true</code>.
-</p>
-<p>For example, <code>prec = 53</code> and <code> expBits = 11</code> exactly give
-the same precision as the IEEE 754 64 bit floating point format. The
-default precision is <code>prec = 113</code> and <code> expBits = 15</code> (IEEE
-754 128 bit floating point format).
-</p>
-<p>The global floating point environment can only be modified temporarily
-when calling a function (see <code>BigFloatEnv.setPrec</code>). Hence a
-function can change the global floating point environment for its
-callees but not for its caller.
-</p>
-<a name="Operators"></a>
-<h3 class="section">4.3 Operators</h3>
-
-<p>The builtin operators are extended so that a BigFloat is returned if
-at least one operand is a BigFloat. The computations are always done
-with infinite precision and rounded according to the global floating
-point environment.
-</p>
-<p><code>typeof</code> applied on a <code>BigFloat</code> returns <code>bigfloat</code>.
-</p>
-<p>BigFloat can be compared with all the other numeric types and the
-result follows the expected mathematical relations.
-</p>
-<p>However, since BigFloat and Number are different types they are never
-equal when using the strict comparison operators (e.g. <code>0.0 ===
-0.0l</code> is false).
-</p>
-<a name="BigFloat-literals"></a>
-<h3 class="section">4.4 BigFloat literals</h3>
-
-<p>BigFloat literals are floating point numbers with a trailing <code>l</code>
-suffix. BigFloat literals have an infinite precision. They are rounded
-according to the global floating point environment when they are
-evaluated.<a name="DOCF3" href="#FOOT3"><sup>3</sup></a>
-</p>
-<a name="Builtin-Object-changes"></a>
-<h3 class="section">4.5 Builtin Object changes</h3>
-
-<a name="BigFloat-function"></a>
-<h4 class="subsection">4.5.1 <code>BigFloat</code> function</h4>
-
-<p>The <code>BigFloat</code> function cannot be invoked as a constructor. When
-invoked as a function: the parameter is converted to a primitive
-type. If the result is a numeric type, it is converted to BigFloat
-without rounding. If the result is a string, it is converted to
-BigFloat using the precision of the global floating point environment.
-</p>
-<p><code>BigFloat</code> properties:
-</p>
-<dl compact="compact">
-<dt><code>LN2</code></dt>
-<dt><code>PI</code></dt>
-<dd><p>Getter. Return the value of the corresponding mathematical constant
-rounded to nearest, ties to even with the current global
-precision. The constant values are cached for small precisions.
-</p>
-</dd>
-<dt><code>MIN_VALUE</code></dt>
-<dt><code>MAX_VALUE</code></dt>
-<dt><code>EPSILON</code></dt>
-<dd><p>Getter. Return the minimum, maximum and epsilon <code>BigFloat</code> values
-(same definition as the corresponding <code>Number</code> constants).
-</p>
-</dd>
-<dt><code>fpRound(a[, e])</code></dt>
-<dd><p>Round the floating point number <code>a</code> according to the floating
-point environment <code>e</code> or the global environment if <code>e</code> is
-undefined.
-</p>
-</dd>
-<dt><code>parseFloat(a[, radix[, e]])</code></dt>
-<dd><p>Parse the string <code>a</code> as a floating point number in radix
-<code>radix</code>. The radix is 0 (default) or from 2 to 36. The radix 0
-means radix 10 unless there is a hexadecimal or binary prefix. The
-result is rounded according to the floating point environment <code>e</code>
-or the global environment if <code>e</code> is undefined.
-</p>
-</dd>
-<dt><code>isFinite(a)</code></dt>
-<dd><p>Return true if <code>a</code> is a finite bigfloat.
-</p>
-</dd>
-<dt><code>isNaN(a)</code></dt>
-<dd><p>Return true if <code>a</code> is a NaN bigfloat.
-</p>
-</dd>
-<dt><code>add(a, b[, e])</code></dt>
-<dt><code>sub(a, b[, e])</code></dt>
-<dt><code>mul(a, b[, e])</code></dt>
-<dt><code>div(a, b[, e])</code></dt>
-<dd><p>Perform the specified floating point operation and round the floating
-point number <code>a</code> according to the floating point environment
-<code>e</code> or the global environment if <code>e</code> is undefined. If
-<code>e</code> is specified, the floating point status flags are updated.
-</p>
-</dd>
-<dt><code>floor(x)</code></dt>
-<dt><code>ceil(x)</code></dt>
-<dt><code>round(x)</code></dt>
-<dt><code>trunc(x)</code></dt>
-<dd><p>Round to an integer. No additional rounding is performed.
-</p>
-</dd>
-<dt><code>abs(x)</code></dt>
-<dd><p>Return the absolute value of x. No additional rounding is performed.
-</p>
-</dd>
-<dt><code>fmod(x, y[, e])</code></dt>
-<dt><code>remainder(x, y[, e])</code></dt>
-<dd><p>Floating point remainder. The quotient is truncated to zero (fmod) or
-to the nearest integer with ties to even (remainder). <code>e</code> is an
-optional floating point environment.
-</p>
-</dd>
-<dt><code>sqrt(x[, e])</code></dt>
-<dd><p>Square root. Return a rounded floating point number. <code>e</code> is an
-optional floating point environment.
-</p>
-</dd>
-<dt><code>sin(x[, e])</code></dt>
-<dt><code>cos(x[, e])</code></dt>
-<dt><code>tan(x[, e])</code></dt>
-<dt><code>asin(x[, e])</code></dt>
-<dt><code>acos(x[, e])</code></dt>
-<dt><code>atan(x[, e])</code></dt>
-<dt><code>atan2(x, y[, e])</code></dt>
-<dt><code>exp(x[, e])</code></dt>
-<dt><code>log(x[, e])</code></dt>
-<dt><code>pow(x, y[, e])</code></dt>
-<dd><p>Transcendental operations. Return a rounded floating point
-number. <code>e</code> is an optional floating point environment.
-</p>
-</dd>
-</dl>
-
-<a name="BigFloat_002eprototype"></a>
-<h4 class="subsection">4.5.2 <code>BigFloat.prototype</code></h4>
-
-<p>The following properties are modified:
-</p>
-<dl compact="compact">
-<dt><code>valueOf()</code></dt>
-<dd><p>Return the bigfloat primitive value corresponding to <code>this</code>.
-</p>
-</dd>
-<dt><code>toString(radix)</code></dt>
-<dd>
-<p>For floating point numbers:
-</p>
-<ul>
-<li> If the radix is a power of two, the conversion is done with infinite
-precision.
-</li><li> Otherwise, the number is rounded to nearest with ties to even using
-the global precision. It is then converted to string using the minimum
-number of digits so that its conversion back to a floating point using
-the global precision and round to nearest gives the same number. 
-
-</li></ul>
-
-<p>The exponent letter is <code>e</code> for base 10, <code>p</code> for bases 2, 8,
-16 with a binary exponent and <code>@</code> for the other bases.
-</p>
-</dd>
-<dt><code>toPrecision(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)</code></dt>
-<dt><code>toFixed(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)</code></dt>
-<dt><code>toExponential(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)</code></dt>
-<dd><p>Same semantics as the corresponding <code>Number</code> functions with
-BigFloats. There is no limit on the accepted precision <code>p</code>. The
-rounding mode and radix can be optionally specified. The radix must be
-between 2 and 36.
-</p>
-</dd>
-</dl>
-
-<a name="BigFloatEnv-constructor"></a>
-<h4 class="subsection">4.5.3 <code>BigFloatEnv</code> constructor</h4>
-
-<p>The <code>BigFloatEnv([p, [,rndMode]]</code> constructor cannot be invoked as a
-function. The floating point environment contains:
-</p>
-<ul>
-<li> the mantissa precision in bits
-
-</li><li> the exponent size in bits assuming an IEEE 754 representation;
-
-</li><li> the subnormal flag (if true, subnormal floating point numbers can
-be generated by the floating point operations).
-
-</li><li> the rounding mode
-
-</li><li> the floating point status. The status flags can only be set by the floating point operations. They can be reset with <code>BigFloatEnv.prototype.clearStatus()</code> or with the various status flag setters.
-
-</li></ul>
-
-<p><code>new BigFloatEnv([p, [,rndMode]]</code> creates a new floating point
-environment. The status flags are reset. If no parameter is given the
-precision, exponent bits and subnormal flags are copied from the
-global floating point environment. Otherwise, the precision is set to
-<code>p</code>, the number of exponent bits is set to <code>expBitsMax</code> and the
-subnormal flags is set to <code>false</code>. If <code>rndMode</code> is
-<code>undefined</code>, the rounding mode is set to <code>RNDN</code>.
-</p>
-<p><code>BigFloatEnv</code> properties:
-</p>
-<dl compact="compact">
-<dt><code>prec</code></dt>
-<dd><p>Getter. Return the precision in bits of the global floating point
-environment. The initial value is <code>113</code>.
-</p>
-</dd>
-<dt><code>expBits</code></dt>
-<dd><p>Getter. Return the exponent size in bits of the global floating point
-environment assuming an IEEE 754 representation. The initial value is
-<code>15</code>.
-</p>
-</dd>
-<dt><code>setPrec(f, p[, e])</code></dt>
-<dd><p>Set the precision of the global floating point environment to <code>p</code>
-and the exponent size to <code>e</code> then call the function
-<code>f</code>. Then the Float precision and exponent size are reset to
-their precious value and the return value of <code>f</code> is returned (or
-an exception is raised if <code>f</code> raised an exception). If <code>e</code>
-is <code>undefined</code> it is set to <code>BigFloatEnv.expBitsMax</code>.
-</p>
-</dd>
-<dt><code>precMin</code></dt>
-<dd><p>Read-only integer. Return the minimum allowed precision. Must be at least 2.
-</p>
-</dd>
-<dt><code>precMax</code></dt>
-<dd><p>Read-only integer. Return the maximum allowed precision. Must be at least 113.
-</p>
-</dd>
-<dt><code>expBitsMin</code></dt>
-<dd><p>Read-only integer. Return the minimum allowed exponent size in
-bits. Must be at least 3.
-</p>
-</dd>
-<dt><code>expBitsMax</code></dt>
-<dd><p>Read-only integer. Return the maximum allowed exponent size in
-bits. Must be at least 15.
-</p>
-</dd>
-<dt><code>RNDN</code></dt>
-<dd><p>Read-only integer. Round to nearest, with ties to even rounding mode.
-</p>
-</dd>
-<dt><code>RNDZ</code></dt>
-<dd><p>Read-only integer. Round to zero rounding mode.
-</p>
-</dd>
-<dt><code>RNDD</code></dt>
-<dd><p>Read-only integer. Round to -Infinity rounding mode.
-</p>
-</dd>
-<dt><code>RNDU</code></dt>
-<dd><p>Read-only integer. Round to +Infinity rounding mode.
-</p>
-</dd>
-<dt><code>RNDNA</code></dt>
-<dd><p>Read-only integer. Round to nearest, with ties away from zero rounding mode.
-</p>
-</dd>
-<dt><code>RNDA</code></dt>
-<dd><p>Read-only integer. Round away from zero rounding mode.
-</p>
-</dd>
-<dt><code>RNDF<a name="DOCF4" href="#FOOT4"><sup>4</sup></a></code></dt>
-<dd><p>Read-only integer. Faithful rounding mode. The result is
-non-deterministically rounded to -Infinity or +Infinity. This rounding
-mode usually gives a faster and deterministic running time for the
-floating point operations.
-</p>
-</dd>
-</dl>
-
-<p><code>BigFloatEnv.prototype</code> properties:
-</p>
-<dl compact="compact">
-<dt><code>prec</code></dt>
-<dd><p>Getter and setter (Integer). Return or set the precision in bits.
-</p>
-</dd>
-<dt><code>expBits</code></dt>
-<dd><p>Getter and setter (Integer). Return or set the exponent size in bits
-assuming an IEEE 754 representation.
-</p>
-</dd>
-<dt><code>rndMode</code></dt>
-<dd><p>Getter and setter (Integer). Return or set the rounding mode.
-</p>
-</dd>
-<dt><code>subnormal</code></dt>
-<dd><p>Getter and setter (Boolean). subnormal flag. It is false when
-<code>expBits = expBitsMax</code>.
-</p>
-</dd>
-<dt><code>clearStatus()</code></dt>
-<dd><p>Clear the status flags.
-</p>
-</dd>
-<dt><code>invalidOperation</code></dt>
-<dt><code>divideByZero</code></dt>
-<dt><code>overflow</code></dt>
-<dt><code>underflow</code></dt>
-<dt><code>inexact</code></dt>
-<dd><p>Getter and setter (Boolean). Status flags.
-</p>
-</dd>
-</dl>
-
-<a name="BigDecimal"></a>
-<h2 class="chapter">5 BigDecimal</h2>
-
-<p>This extension adds the <code>BigDecimal</code> primitive type. The
-<code>BigDecimal</code> type represents floating point numbers in base
-10. It is inspired from the proposal available at
-<a href="https://github.com/littledan/proposal-bigdecimal">https://github.com/littledan/proposal-bigdecimal</a>.
-</p>
-<p>The <code>BigDecimal</code> floating point numbers are always normalized and
-finite. There is no concept of <code>-0</code>, <code>Infinity</code> or
-<code>NaN</code>. By default, all the computations are done with infinite
-precision.
-</p>
-<a name="Operators-1"></a>
-<h3 class="section">5.1 Operators</h3>
-
-<p>The following builtin operators support BigDecimal:
-</p>
-<dl compact="compact">
-<dt><code>+</code></dt>
-<dt><code>-</code></dt>
-<dt><code>*</code></dt>
-<dd><p>Both operands must be BigDecimal. The result is computed with infinite
-precision.
-</p></dd>
-<dt><code>%</code></dt>
-<dd><p>Both operands must be BigDecimal. The result is computed with infinite
-precision. A range error is throws in case of division by zero.
-</p>
-</dd>
-<dt><code>/</code></dt>
-<dd><p>Both operands must be BigDecimal. A range error is throws in case of
-division by zero or if the result cannot be represented with infinite
-precision (use <code>BigDecimal.div</code> to specify the rounding).
-</p>
-</dd>
-<dt><code>**</code></dt>
-<dd><p>Both operands must be BigDecimal. The exponent must be a positive
-integer. The result is computed with infinite precision.
-</p>
-</dd>
-<dt><code>===</code></dt>
-<dd><p>When one of the operand is a BigDecimal, return true if both operands
-are a BigDecimal and if they are equal.
-</p>
-</dd>
-<dt><code>==</code></dt>
-<dt><code>!=</code></dt>
-<dt><code>&lt;=</code></dt>
-<dt><code>&gt;=</code></dt>
-<dt><code>&lt;</code></dt>
-<dt><code>&gt;</code></dt>
-<dd>
-<p>Numerical comparison. When one of the operand is not a BigDecimal, it is
-converted to BigDecimal by using ToString(). Hence comparisons between
-Number and BigDecimal do not use the exact mathematical value of the
-Number value.
-</p>
-</dd>
-</dl>
-
-<a name="BigDecimal-literals"></a>
-<h3 class="section">5.2 BigDecimal literals</h3>
-
-<p>BigDecimal literals are decimal floating point numbers with a trailing
-<code>m</code> suffix.
-</p>
-<a name="Builtin-Object-changes-1"></a>
-<h3 class="section">5.3 Builtin Object changes</h3>
-
-<a name="The-BigDecimal-function_002e"></a>
-<h4 class="subsection">5.3.1 The <code>BigDecimal</code> function.</h4>
-
-<p>It returns <code>0m</code> if no parameter is provided. Otherwise the first
-parameter is converted to a bigdecimal by using ToString(). Hence
-Number values are not converted to their exact numerical value as
-BigDecimal.
-</p>
-<a name="Properties-of-the-BigDecimal-object"></a>
-<h4 class="subsection">5.3.2 Properties of the <code>BigDecimal</code> object</h4>
-
-<dl compact="compact">
-<dt><code>add(a, b[, e])</code></dt>
-<dt><code>sub(a, b[, e])</code></dt>
-<dt><code>mul(a, b[, e])</code></dt>
-<dt><code>div(a, b[, e])</code></dt>
-<dt><code>mod(a, b[, e])</code></dt>
-<dt><code>sqrt(a, e)</code></dt>
-<dt><code>round(a, e)</code></dt>
-<dd><p>Perform the specified floating point operation and round the floating
-point result according to the rounding object <code>e</code>. If the
-rounding object is not present, the operation is executed with
-infinite precision.
-</p>
-<p>For <code>div</code>, a <code>RangeError</code> exception is thrown in case of
-division by zero or if the result cannot be represented with infinite
-precision if no rounding object is present.
-</p>
-<p>For <code>sqrt</code>, a range error is thrown if <code>a</code> is less than
-zero.
-</p>
-<p>The rounding object must contain the following properties:
-<code>roundingMode</code> is a string specifying the rounding mode
-(<code>&quot;floor&quot;</code>, <code>&quot;ceiling&quot;</code>, <code>&quot;down&quot;</code>, <code>&quot;up&quot;</code>,
-<code>&quot;half-even&quot;</code>, <code>&quot;half-up&quot;</code>). Either
-<code>maximumSignificantDigits</code> or <code>maximumFractionDigits</code> must
-be present to specify respectively the number of significant digits
-(must be &gt;= 1) or the number of digits after the decimal point (must
-be &gt;= 0).
-</p>
-</dd>
-</dl>
-
-<a name="Properties-of-the-BigDecimal_002eprototype-object"></a>
-<h4 class="subsection">5.3.3 Properties of the <code>BigDecimal.prototype</code> object</h4>
-
-<dl compact="compact">
-<dt><code>valueOf()</code></dt>
-<dd><p>Return the bigdecimal primitive value corresponding to <code>this</code>.
-</p>
-</dd>
-<dt><code>toString()</code></dt>
-<dd><p>Convert <code>this</code> to a string with infinite precision in base 10.
-</p>
-</dd>
-<dt><code>toPrecision(p, rnd_mode = &quot;half-up&quot;)</code></dt>
-<dt><code>toFixed(p, rnd_mode = &quot;half-up&quot;)</code></dt>
-<dt><code>toExponential(p, rnd_mode = &quot;half-up&quot;)</code></dt>
-<dd><p>Convert the BigDecimal <code>this</code> to string with the specified
-precision <code>p</code>. There is no limit on the accepted precision
-<code>p</code>. The rounding mode can be optionally
-specified. <code>toPrecision</code> outputs either in decimal fixed notation
-or in decimal exponential notation with a <code>p</code> digits of
-precision.  <code>toExponential</code> outputs in decimal exponential
-notation with <code>p</code> digits after the decimal point. <code>toFixed</code>
-outputs in decimal notation with <code>p</code> digits after the decimal
-point.
-</p>
-</dd>
-</dl>
-
-<a name="Math-mode"></a>
-<h2 class="chapter">6 Math mode</h2>
-
-<p>A new <em>math mode</em> is enabled with the <code>&quot;use math&quot;</code>
-directive. It propagates the same way as the <em>strict mode</em>. It is
-designed so that arbitrarily large integers and floating point numbers
-are available by default. In order to minimize the number of changes
-in the Javascript semantics, integers are represented either as Number
-or BigInt depending on their magnitude. Floating point numbers are
-always represented as BigFloat.
-</p>
-<p>The following changes are made to the Javascript semantics:
-</p>
-<ul>
-<li> Floating point literals (i.e. number with a decimal point or an exponent) are <code>BigFloat</code> by default (i.e. a <code>l</code> suffix is implied). Hence <code>typeof 1.0 === &quot;bigfloat&quot;</code>.
-
-</li><li> Integer literals (i.e. numbers without a decimal point or an exponent) with or without the <code>n</code> suffix are <code>BigInt</code> if their value cannot be represented as a safe integer. A safe integer is defined as a integer whose absolute value is smaller or equal to <code>2**53-1</code>. Hence <code>typeof 1 === &quot;number &quot;</code>, <code>typeof 1n === &quot;number&quot;</code> but <code>typeof 9007199254740992 === &quot;bigint&quot; </code>.
-
-</li><li> All the bigint builtin operators and functions are modified so that their result is returned as a Number if it is a safe integer. Otherwise the result stays a BigInt.
-
-</li><li> The builtin operators are modified so that they return an exact result (which can be a BigInt) if their operands are safe integers. Operands between Number and BigInt are accepted provided the Number operand is a safe integer. The integer power with a negative exponent returns a BigFloat as result. The integer division returns a BigFloat as result.
-
-</li><li> The <code>^</code> operator is an alias to the power operator (<code>**</code>).
-
-</li><li> The power operator (both <code>^</code> and <code>**</code>) grammar is modified so that <code>-2^2</code> is allowed and yields <code>-4</code>.
-
-</li><li> The logical xor operator is still available with the <code>^^</code> operator.
-
-</li><li> The modulo operator (<code>%</code>) returns the Euclidian remainder (always positive) instead of the truncated remainder.
-
-</li><li> The integer division operator can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
-
-</li><li> The integer power operator with a non zero negative exponent can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
-
-</li></ul>
-
-<div class="footnote">
-<hr>
-<h4 class="footnotes-heading">Footnotes</h4>
-
-<h3><a name="FOOT1" href="#DOCF1">(1)</a></h3>
-<p>The
-rationale is that the rounding mode changes must always be
-explicit.</p>
-<h3><a name="FOOT2" href="#DOCF2">(2)</a></h3>
-<p>The rationale is to avoid side effects for the built-in
-operators.</p>
-<h3><a name="FOOT3" href="#DOCF3">(3)</a></h3>
-<p>Base 10 floating point literals cannot usually be
-exactly represented as base 2 floating point number. In order to
-ensure that the literal is represented accurately with the current
-precision, it must be evaluated at runtime.</p>
-<h3><a name="FOOT4" href="#DOCF4">(4)</a></h3>
-<p>Could be removed in case a deterministic behavior for floating point operations is required.</p>
-</div>
-<hr>
-
-
-
-</body>
-</html>
diff --git a/doc/jsbignum.pdf b/doc/jsbignum.pdf
deleted file mode 100644 (file)
index 442a8c0..0000000
Binary files a/doc/jsbignum.pdf and /dev/null differ
diff --git a/doc/quickjs.html b/doc/quickjs.html
deleted file mode 100644 (file)
index e8b3369..0000000
+++ /dev/null
@@ -1,1369 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->
-<head>
-<title>QuickJS Javascript Engine</title>
-
-<meta name="description" content="QuickJS Javascript Engine">
-<meta name="keywords" content="QuickJS Javascript Engine">
-<meta name="resource-type" content="document">
-<meta name="distribution" content="global">
-<meta name="Generator" content="makeinfo">
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<link href="#SEC_Contents" rel="contents" title="Table of Contents">
-<style type="text/css">
-<!--
-a.summary-letter {text-decoration: none}
-blockquote.indentedblock {margin-right: 0em}
-blockquote.smallindentedblock {margin-right: 0em; font-size: smaller}
-blockquote.smallquotation {font-size: smaller}
-div.display {margin-left: 3.2em}
-div.example {margin-left: 3.2em}
-div.lisp {margin-left: 3.2em}
-div.smalldisplay {margin-left: 3.2em}
-div.smallexample {margin-left: 3.2em}
-div.smalllisp {margin-left: 3.2em}
-kbd {font-style: oblique}
-pre.display {font-family: inherit}
-pre.format {font-family: inherit}
-pre.menu-comment {font-family: serif}
-pre.menu-preformatted {font-family: serif}
-pre.smalldisplay {font-family: inherit; font-size: smaller}
-pre.smallexample {font-size: smaller}
-pre.smallformat {font-family: inherit; font-size: smaller}
-pre.smalllisp {font-size: smaller}
-span.nolinebreak {white-space: nowrap}
-span.roman {font-family: initial; font-weight: normal}
-span.sansserif {font-family: sans-serif; font-weight: normal}
-ul.no-bullet {list-style: none}
--->
-</style>
-<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
-
-</head>
-
-<body lang="en">
-<h1 class="settitle" align="center">QuickJS Javascript Engine</h1>
-
-<a name="SEC_Contents"></a>
-<h2 class="contents-heading">Table of Contents</h2>
-
-<div class="contents">
-<ul class="no-bullet">
-<li><a name="toc-Introduction" href="#Introduction">1 Introduction</a>
-<ul class="no-bullet">
-  <li><a name="toc-Main-Features" href="#Main-Features">1.1 Main Features</a></li>
-</ul></li>
-<li><a name="toc-Usage" href="#Usage">2 Usage</a>
-<ul class="no-bullet">
-  <li><a name="toc-Installation" href="#Installation">2.1 Installation</a></li>
-  <li><a name="toc-Quick-start" href="#Quick-start">2.2 Quick start</a></li>
-  <li><a name="toc-Command-line-options" href="#Command-line-options">2.3 Command line options</a>
-  <ul class="no-bullet">
-    <li><a name="toc-qjs-interpreter" href="#qjs-interpreter">2.3.1 <code>qjs</code> interpreter</a></li>
-    <li><a name="toc-qjsc-compiler" href="#qjsc-compiler">2.3.2 <code>qjsc</code> compiler</a></li>
-  </ul></li>
-  <li><a name="toc-qjscalc-application" href="#qjscalc-application">2.4 <code>qjscalc</code> application</a></li>
-  <li><a name="toc-Built_002din-tests" href="#Built_002din-tests">2.5 Built-in tests</a></li>
-  <li><a name="toc-Test262-_0028ECMAScript-Test-Suite_0029" href="#Test262-_0028ECMAScript-Test-Suite_0029">2.6 Test262 (ECMAScript Test Suite)</a></li>
-</ul></li>
-<li><a name="toc-Specifications" href="#Specifications">3 Specifications</a>
-<ul class="no-bullet">
-  <li><a name="toc-Language-support" href="#Language-support">3.1 Language support</a>
-  <ul class="no-bullet">
-    <li><a name="toc-ES2020-support" href="#ES2020-support">3.1.1 ES2020 support</a></li>
-    <li><a name="toc-ECMA402" href="#ECMA402">3.1.2 ECMA402</a></li>
-    <li><a name="toc-Extensions" href="#Extensions">3.1.3 Extensions</a></li>
-    <li><a name="toc-Mathematical-extensions" href="#Mathematical-extensions">3.1.4 Mathematical extensions</a></li>
-  </ul></li>
-  <li><a name="toc-Modules" href="#Modules">3.2 Modules</a></li>
-  <li><a name="toc-Standard-library" href="#Standard-library">3.3 Standard library</a>
-  <ul class="no-bullet">
-    <li><a name="toc-Global-objects" href="#Global-objects">3.3.1 Global objects</a></li>
-    <li><a name="toc-std-module" href="#std-module">3.3.2 <code>std</code> module</a></li>
-    <li><a name="toc-os-module" href="#os-module">3.3.3 <code>os</code> module</a></li>
-  </ul></li>
-  <li><a name="toc-QuickJS-C-API" href="#QuickJS-C-API">3.4 QuickJS C API</a>
-  <ul class="no-bullet">
-    <li><a name="toc-Runtime-and-contexts" href="#Runtime-and-contexts">3.4.1 Runtime and contexts</a></li>
-    <li><a name="toc-JSValue" href="#JSValue">3.4.2 JSValue</a></li>
-    <li><a name="toc-C-functions" href="#C-functions">3.4.3 C functions</a></li>
-    <li><a name="toc-Exceptions" href="#Exceptions">3.4.4 Exceptions</a></li>
-    <li><a name="toc-Script-evaluation" href="#Script-evaluation">3.4.5 Script evaluation</a></li>
-    <li><a name="toc-JS-Classes" href="#JS-Classes">3.4.6 JS Classes</a></li>
-    <li><a name="toc-C-Modules" href="#C-Modules">3.4.7 C Modules</a></li>
-    <li><a name="toc-Memory-handling" href="#Memory-handling">3.4.8 Memory handling</a></li>
-    <li><a name="toc-Execution-timeout-and-interrupts" href="#Execution-timeout-and-interrupts">3.4.9 Execution timeout and interrupts</a></li>
-  </ul></li>
-</ul></li>
-<li><a name="toc-Internals" href="#Internals">4 Internals</a>
-<ul class="no-bullet">
-  <li><a name="toc-Bytecode" href="#Bytecode">4.1 Bytecode</a></li>
-  <li><a name="toc-Executable-generation" href="#Executable-generation">4.2 Executable generation</a>
-  <ul class="no-bullet">
-    <li><a name="toc-qjsc-compiler-1" href="#qjsc-compiler-1">4.2.1 <code>qjsc</code> compiler</a></li>
-    <li><a name="toc-Binary-JSON" href="#Binary-JSON">4.2.2 Binary JSON</a></li>
-  </ul></li>
-  <li><a name="toc-Runtime" href="#Runtime">4.3 Runtime</a>
-  <ul class="no-bullet">
-    <li><a name="toc-Strings" href="#Strings">4.3.1 Strings</a></li>
-    <li><a name="toc-Objects" href="#Objects">4.3.2 Objects</a></li>
-    <li><a name="toc-Atoms" href="#Atoms">4.3.3 Atoms</a></li>
-    <li><a name="toc-Numbers" href="#Numbers">4.3.4 Numbers</a></li>
-    <li><a name="toc-Garbage-collection" href="#Garbage-collection">4.3.5 Garbage collection</a></li>
-    <li><a name="toc-JSValue-1" href="#JSValue-1">4.3.6 JSValue</a></li>
-    <li><a name="toc-Function-call" href="#Function-call">4.3.7 Function call</a></li>
-  </ul></li>
-  <li><a name="toc-RegExp" href="#RegExp">4.4 RegExp</a></li>
-  <li><a name="toc-Unicode" href="#Unicode">4.5 Unicode</a></li>
-  <li><a name="toc-BigInt_002c-BigFloat_002c-BigDecimal" href="#BigInt_002c-BigFloat_002c-BigDecimal">4.6 BigInt, BigFloat, BigDecimal</a></li>
-</ul></li>
-<li><a name="toc-License" href="#License">5 License</a></li>
-
-</ul>
-</div>
-
-
-<a name="Introduction"></a>
-<h2 class="chapter">1 Introduction</h2>
-
-<p>QuickJS is a small and embeddable Javascript engine. It supports the
-ES2020 specification
-<a name="DOCF1" href="#FOOT1"><sup>1</sup></a>
-including modules, asynchronous generators, proxies and BigInt.
-</p>
-<p>It supports mathematical extensions such as big decimal float float
-numbers (BigDecimal), big binary floating point numbers (BigFloat),
-and operator overloading.
-</p>
-<a name="Main-Features"></a>
-<h3 class="section">1.1 Main Features</h3>
-
-<ul>
-<li> Small and easily embeddable: just a few C files, no external dependency, 210 KiB of x86 code for a simple &ldquo;hello world&rdquo; program.
-
-</li><li> Fast interpreter with very low startup time: runs the 69000 tests of the ECMAScript Test Suite<a name="DOCF2" href="#FOOT2"><sup>2</sup></a> in about 95 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
-
-</li><li> Almost complete ES2020 support including modules, asynchronous
-generators and full Annex B support (legacy web compatibility). Many
-features from the upcoming ES2021 specification
-<a name="DOCF3" href="#FOOT3"><sup>3</sup></a> are also supported.
-
-</li><li> Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2020 features.
-
-</li><li> Compile Javascript sources to executables with no external dependency.
-
-</li><li> Garbage collection using reference counting (to reduce memory usage and have deterministic behavior) with cycle removal.
-
-</li><li> Mathematical extensions: BigDecimal, BigFloat, operator overloading, bigint mode, math mode.
-
-</li><li> Command line interpreter with contextual colorization and completion implemented in Javascript.
-
-</li><li> Small built-in standard library with C library wrappers.
-
-</li></ul>
-
-<a name="Usage"></a>
-<h2 class="chapter">2 Usage</h2>
-
-<a name="Installation"></a>
-<h3 class="section">2.1 Installation</h3>
-
-<p>A Makefile is provided to compile the engine on Linux or MacOS/X.  A
-preliminary Windows support is available thru cross compilation on a
-Linux host with the MingGW tools.
-</p>
-<p>Edit the top of the <code>Makefile</code> if you wish to select specific
-options then run <code>make</code>.
-</p>
-<p>You can type <code>make install</code> as root if you wish to install the binaries and support files to
-<code>/usr/local</code> (this is not necessary to use QuickJS).
-</p>
-<a name="Quick-start"></a>
-<h3 class="section">2.2 Quick start</h3>
-
-<p><code>qjs</code> is the command line interpreter (Read-Eval-Print Loop). You can pass
-Javascript files and/or expressions as arguments to execute them:
-</p>
-<div class="example">
-<pre class="example">./qjs examples/hello.js
-</pre></div>
-
-<p><code>qjsc</code> is the command line compiler:
-</p>
-<div class="example">
-<pre class="example">./qjsc -o hello examples/hello.js
-./hello
-</pre></div>
-
-<p>generates a <code>hello</code> executable with no external dependency.
-</p>
-<a name="Command-line-options"></a>
-<h3 class="section">2.3 Command line options</h3>
-
-<a name="qjs-interpreter"></a>
-<h4 class="subsection">2.3.1 <code>qjs</code> interpreter</h4>
-
-<pre class="verbatim">usage: qjs [options] [file [args]]
-</pre>
-<p>Options are:
-</p><dl compact="compact">
-<dt><code>-h</code></dt>
-<dt><code>--help</code></dt>
-<dd><p>List options.
-</p>
-</dd>
-<dt><code>-e <code>EXPR</code></code></dt>
-<dt><code>--eval <code>EXPR</code></code></dt>
-<dd><p>Evaluate EXPR.
-</p>
-</dd>
-<dt><code>-i</code></dt>
-<dt><code>--interactive</code></dt>
-<dd><p>Go to interactive mode (it is not the default when files are provided on the command line).
-</p>
-</dd>
-<dt><code>-m</code></dt>
-<dt><code>--module</code></dt>
-<dd><p>Load as ES6 module (default=autodetect). A module is autodetected if
-the filename extension is <code>.mjs</code> or if the first keyword of the
-source is <code>import</code>.
-</p>
-</dd>
-<dt><code>--script</code></dt>
-<dd><p>Load as ES6 script (default=autodetect).
-</p>
-</dd>
-<dt><code>--bignum</code></dt>
-<dd><p>Enable the bignum extensions: BigDecimal object, BigFloat object and
-the <code>&quot;use math&quot;</code> directive.
-</p>
-</dd>
-<dt><code>-I file</code></dt>
-<dt><code>--include file</code></dt>
-<dd><p>Include an additional file.
-</p>
-</dd>
-</dl>
-
-<p>Advanced options are:
-</p>
-<dl compact="compact">
-<dt><code>--std</code></dt>
-<dd><p>Make the <code>std</code> and <code>os</code> modules available to the loaded
-script even if it is not a module.
-</p>
-</dd>
-<dt><code>-d</code></dt>
-<dt><code>--dump</code></dt>
-<dd><p>Dump the memory usage stats.
-</p>
-</dd>
-<dt><code>-q</code></dt>
-<dt><code>--quit</code></dt>
-<dd><p>just instantiate the interpreter and quit.
-</p>
-</dd>
-</dl>
-
-<a name="qjsc-compiler"></a>
-<h4 class="subsection">2.3.2 <code>qjsc</code> compiler</h4>
-
-<pre class="verbatim">usage: qjsc [options] [files]
-</pre>
-<p>Options are:
-</p><dl compact="compact">
-<dt><code>-c</code></dt>
-<dd><p>Only output bytecode in a C file. The default is to output an executable file.
-</p></dd>
-<dt><code>-e</code></dt>
-<dd><p>Output <code>main()</code> and bytecode in a C file. The default is to output an
-executable file.
-</p></dd>
-<dt><code>-o output</code></dt>
-<dd><p>Set the output filename (default = <samp>out.c</samp> or <samp>a.out</samp>).
-</p>
-</dd>
-<dt><code>-N cname</code></dt>
-<dd><p>Set the C name of the generated data.
-</p>
-</dd>
-<dt><code>-m</code></dt>
-<dd><p>Compile as Javascript module (default=autodetect).
-</p>
-</dd>
-<dt><code>-D module_name</code></dt>
-<dd><p>Compile a dynamically loaded module and its dependencies. This option
-is needed when your code uses the <code>import</code> keyword or the
-<code>os.Worker</code> constructor because the compiler cannot statically
-find the name of the dynamically loaded modules.
-</p>
-</dd>
-<dt><code>-M module_name[,cname]</code></dt>
-<dd><p>Add initialization code for an external C module. See the
-<code>c_module</code> example.
-</p>
-</dd>
-<dt><code>-x</code></dt>
-<dd><p>Byte swapped output (only used for cross compilation).
-</p>
-</dd>
-<dt><code>-flto</code></dt>
-<dd><p>Use link time optimization. The compilation is slower but the
-executable is smaller and faster. This option is automatically set
-when the <code>-fno-x</code> options are used.
-</p>
-</dd>
-<dt><code>-fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise|bigint]</code></dt>
-<dd><p>Disable selected language features to produce a smaller executable file.
-</p>
-</dd>
-<dt><code>-fbignum</code></dt>
-<dd><p>Enable the bignum extensions: BigDecimal object, BigFloat object and
-the <code>&quot;use math&quot;</code> directive.
-</p>
-</dd>
-</dl>
-
-<a name="qjscalc-application"></a>
-<h3 class="section">2.4 <code>qjscalc</code> application</h3>
-
-<p>The <code>qjscalc</code> application is a superset of the <code>qjs</code>
-command line interpreter implementing a Javascript calculator with
-arbitrarily large integer and floating point numbers, fractions,
-complex numbers, polynomials and matrices. The source code is in
-<samp>qjscalc.js</samp>. More documentation and a web version are available at
-<a href="http://numcalc.com">http://numcalc.com</a>.
-</p>
-<a name="Built_002din-tests"></a>
-<h3 class="section">2.5 Built-in tests</h3>
-
-<p>Run <code>make test</code> to run the few built-in tests included in the
-QuickJS archive.
-</p>
-<a name="Test262-_0028ECMAScript-Test-Suite_0029"></a>
-<h3 class="section">2.6 Test262 (ECMAScript Test Suite)</h3>
-
-<p>A test262 runner is included in the QuickJS archive. The test262 tests
-can be installed in the QuickJS source directory with:
-</p>
-<div class="example">
-<pre class="example">git clone https://github.com/tc39/test262.git test262
-cd test262
-patch -p1 &lt; ../tests/test262.patch
-cd ..
-</pre></div>
-
-<p>The patch adds the implementation specific <code>harness</code> functions
-and optimizes the inefficient RegExp character classes and Unicode
-property escapes tests (the tests themselves are not modified, only a
-slow string initialization function is optimized).
-</p>
-<p>The tests can be run with
-</p><div class="example">
-<pre class="example">make test2
-</pre></div>
-
-<p>The configuration files <code>test262.conf</code>
-(resp. <code>test262o.conf</code> for the old ES5.1 tests<a name="DOCF4" href="#FOOT4"><sup>4</sup></a>))
-contain the options to run the various tests. Tests can be excluded
-based on features or filename.
-</p>
-<p>The file <code>test262_errors.txt</code> contains the current list of
-errors. The runner displays a message when a new error appears or when
-an existing error is corrected or modified. Use the <code>-u</code> option
-to update the current list of errors (or <code>make test2-update</code>).
-</p>
-<p>The file <code>test262_report.txt</code> contains the logs of all the
-tests. It is useful to have a clearer analysis of a particular
-error. In case of crash, the last line corresponds to the failing
-test.
-</p>
-<p>Use the syntax <code>./run-test262 -c test262.conf -f filename.js</code> to
-run a single test. Use the syntax <code>./run-test262 -c test262.conf
-N</code> to start testing at test number <code>N</code>.
-</p>
-<p>For more information, run <code>./run-test262</code> to see the command line
-options of the test262 runner.
-</p>
-<p><code>run-test262</code> accepts the <code>-N</code> option to be invoked from
-<code>test262-harness</code><a name="DOCF5" href="#FOOT5"><sup>5</sup></a>
-thru <code>eshost</code>. Unless you want to compare QuickJS with other
-engines under the same conditions, we do not recommend to run the
-tests this way as it is much slower (typically half an hour instead of
-about 100 seconds).
-</p>
-<a name="Specifications"></a>
-<h2 class="chapter">3 Specifications</h2>
-
-<a name="Language-support"></a>
-<h3 class="section">3.1 Language support</h3>
-
-<a name="ES2020-support"></a>
-<h4 class="subsection">3.1.1 ES2020 support</h4>
-
-<p>The ES2020 specification is almost fully supported including the Annex
-B (legacy web compatibility) and the Unicode related features.
-</p>
-<p>The following features are not supported yet:
-</p>
-<ul>
-<li> Tail calls<a name="DOCF6" href="#FOOT6"><sup>6</sup></a>
-
-</li></ul>
-
-<a name="ECMA402"></a>
-<h4 class="subsection">3.1.2 ECMA402</h4>
-
-<p>ECMA402 (Internationalization API) is not supported.
-</p>
-<a name="Extensions"></a>
-<h4 class="subsection">3.1.3 Extensions</h4>
-
-<ul>
-<li> The directive <code>&quot;use strip&quot;</code> indicates that the debug information (including the source code of the functions) should not be retained to save memory. As <code>&quot;use strict&quot;</code>, the directive can be global to a script or local to a function.
-
-</li><li> The first line of a script beginning with <code>#!</code> is ignored.
-
-</li></ul>
-
-<a name="Mathematical-extensions"></a>
-<h4 class="subsection">3.1.4 Mathematical extensions</h4>
-
-<p>The mathematical extensions are fully backward compatible with
-standard Javascript. See <code>jsbignum.pdf</code> for more information.
-</p>
-<ul>
-<li> <code>BigDecimal</code> support: arbitrary large floating point numbers in base 10.
-
-</li><li> <code>BigFloat</code> support: arbitrary large floating point numbers in base 2.
-
-</li><li> Operator overloading.
-
-</li><li> The directive <code>&quot;use bigint&quot;</code> enables the bigint mode where integers are <code>BigInt</code> by default.
-
-</li><li> The directive <code>&quot;use math&quot;</code> enables the math mode where the division and power operators on integers produce fractions. Floating point literals are <code>BigFloat</code> by default and integers are <code>BigInt</code> by default.
-
-</li></ul>
-
-<a name="Modules"></a>
-<h3 class="section">3.2 Modules</h3>
-
-<p>ES6 modules are fully supported. The default name resolution is the
-following:
-</p>
-<ul>
-<li> Module names with a leading <code>.</code> or <code>..</code> are relative
-to the current module path.
-
-</li><li> Module names without a leading <code>.</code> or <code>..</code> are system
-modules, such as <code>std</code> or <code>os</code>.
-
-</li><li> Module names ending with <code>.so</code> are native modules using the
-QuickJS C API.
-
-</li></ul>
-
-<a name="Standard-library"></a>
-<h3 class="section">3.3 Standard library</h3>
-
-<p>The standard library is included by default in the command line
-interpreter. It contains the two modules <code>std</code> and <code>os</code> and
-a few global objects.
-</p>
-<a name="Global-objects"></a>
-<h4 class="subsection">3.3.1 Global objects</h4>
-
-<dl compact="compact">
-<dt><code>scriptArgs</code></dt>
-<dd><p>Provides the command line arguments. The first argument is the script name.
-</p></dd>
-<dt><code>print(...args)</code></dt>
-<dd><p>Print the arguments separated by spaces and a trailing newline.
-</p></dd>
-<dt><code>console.log(...args)</code></dt>
-<dd><p>Same as print().
-</p>
-</dd>
-</dl>
-
-<a name="std-module"></a>
-<h4 class="subsection">3.3.2 <code>std</code> module</h4>
-
-<p>The <code>std</code> module provides wrappers to the libc <samp>stdlib.h</samp>
-and <samp>stdio.h</samp> and a few other utilities.
-</p>
-<p>Available exports:
-</p>
-<dl compact="compact">
-<dt><code>exit(n)</code></dt>
-<dd><p>Exit the process.
-</p>
-</dd>
-<dt><code>evalScript(str, options = undefined)</code></dt>
-<dd><p>Evaluate the string <code>str</code> as a script (global
-eval). <code>options</code> is an optional object containing the following
-optional properties:
-</p>
-<dl compact="compact">
-<dt><code>backtrace_barrier</code></dt>
-<dd><p>Boolean (default = false). If true, error backtraces do not list the
-  stack frames below the evalScript.
-  </p></dd>
-</dl>
-
-</dd>
-<dt><code>loadScript(filename)</code></dt>
-<dd><p>Evaluate the file <code>filename</code> as a script (global eval).
-</p>
-</dd>
-<dt><code>loadFile(filename)</code></dt>
-<dd><p>Load the file <code>filename</code> and return it as a string assuming UTF-8
-encoding. Return <code>null</code> in case of I/O error.
-</p>
-</dd>
-<dt><code>open(filename, flags, errorObj = undefined)</code></dt>
-<dd><p>Open a file (wrapper to the libc <code>fopen()</code>). Return the FILE
-object or <code>null</code> in case of I/O error. If <code>errorObj</code> is not
-undefined, set its <code>errno</code> property to the error code or to 0 if
-no error occured.
-</p>
-</dd>
-<dt><code>popen(command, flags, errorObj = undefined)</code></dt>
-<dd><p>Open a process by creating a pipe (wrapper to the libc
-<code>popen()</code>). Return the FILE
-object or <code>null</code> in case of I/O error. If <code>errorObj</code> is not
-undefined, set its <code>errno</code> property to the error code or to 0 if
-no error occured.
-</p>
-</dd>
-<dt><code>fdopen(fd, flags, errorObj = undefined)</code></dt>
-<dd><p>Open a file from a file handle (wrapper to the libc
-<code>fdopen()</code>). Return the FILE
-object or <code>null</code> in case of I/O error. If <code>errorObj</code> is not
-undefined, set its <code>errno</code> property to the error code or to 0 if
-no error occured.
-</p>
-</dd>
-<dt><code>tmpfile(errorObj = undefined)</code></dt>
-<dd><p>Open a temporary file. Return the FILE
-object or <code>null</code> in case of I/O error. If <code>errorObj</code> is not
-undefined, set its <code>errno</code> property to the error code or to 0 if
-no error occured.
-</p>
-</dd>
-<dt><code>puts(str)</code></dt>
-<dd><p>Equivalent to <code>std.out.puts(str)</code>.
-</p>
-</dd>
-<dt><code>printf(fmt, ...args)</code></dt>
-<dd><p>Equivalent to <code>std.out.printf(fmt, ...args)</code>.
-</p>
-</dd>
-<dt><code>sprintf(fmt, ...args)</code></dt>
-<dd><p>Equivalent to the libc sprintf().
-</p>
-</dd>
-<dt><code>in</code></dt>
-<dt><code>out</code></dt>
-<dt><code>err</code></dt>
-<dd><p>Wrappers to the libc file <code>stdin</code>, <code>stdout</code>, <code>stderr</code>.
-</p>
-</dd>
-<dt><code>SEEK_SET</code></dt>
-<dt><code>SEEK_CUR</code></dt>
-<dt><code>SEEK_END</code></dt>
-<dd><p>Constants for seek().
-</p>
-</dd>
-<dt><code>Error</code></dt>
-<dd>
-<p>Enumeration object containing the integer value of common errors
-(additional error codes may be defined):
-</p>
-<dl compact="compact">
-<dt><code>EINVAL</code></dt>
-<dt><code>EIO</code></dt>
-<dt><code>EACCES</code></dt>
-<dt><code>EEXIST</code></dt>
-<dt><code>ENOSPC</code></dt>
-<dt><code>ENOSYS</code></dt>
-<dt><code>EBUSY</code></dt>
-<dt><code>ENOENT</code></dt>
-<dt><code>EPERM</code></dt>
-<dt><code>EPIPE</code></dt>
-</dl>
-
-</dd>
-<dt><code>strerror(errno)</code></dt>
-<dd><p>Return a string that describes the error <code>errno</code>.
-</p>
-</dd>
-<dt><code>gc()</code></dt>
-<dd><p>Manually invoke the cycle removal algorithm. The cycle removal
-algorithm is automatically started when needed, so this function is
-useful in case of specific memory constraints or for testing.
-</p>
-</dd>
-<dt><code>getenv(name)</code></dt>
-<dd><p>Return the value of the environment variable <code>name</code> or
-<code>undefined</code> if it is not defined.
-</p>
-</dd>
-<dt><code>urlGet(url, options = undefined)</code></dt>
-<dd>
-<p>Download <code>url</code> using the <samp>curl</samp> command line
-utility. <code>options</code> is an optional object containing the following
-optional properties:
-</p>
-<dl compact="compact">
-<dt><code>binary</code></dt>
-<dd><p>Boolean (default = false). If true, the response is an ArrayBuffer
-  instead of a string. When a string is returned, the data is assumed
-  to be UTF-8 encoded.
-</p>
-</dd>
-<dt><code>full</code></dt>
-<dd>  
-<p>Boolean (default = false). If true, return the an object contains
-  the properties <code>response</code> (response content),
-  <code>responseHeaders</code> (headers separated by CRLF), <code>status</code>
-  (status code). <code>response</code> is <code>null</code> is case of protocol or
-  network error. If <code>full</code> is false, only the response is
-  returned if the status is between 200 and 299. Otherwise <code>null</code>
-  is returned.
-</p>
-</dd>
-</dl>
-
-</dd>
-<dt><code>parseExtJSON(str)</code></dt>
-<dd>
-<p>Parse <code>str</code> using a superset of <code>JSON.parse</code>. The
-  following extensions are accepted:
-</p>
-<ul>
-<li> Single line and multiline comments
-  </li><li> unquoted properties (ASCII-only Javascript identifiers)
-  </li><li> trailing comma in array and object definitions
-  </li><li> single quoted strings
-  </li><li> <code>\f</code> and <code>\v</code> are accepted as space characters
-  </li><li> leading plus in numbers
-  </li><li> octal (<code>0o</code> prefix) and hexadecimal (<code>0x</code> prefix) numbers
-  </li></ul>
-</dd>
-</dl>
-
-<p>FILE prototype:
-</p>
-<dl compact="compact">
-<dt><code>close()</code></dt>
-<dd><p>Close the file. Return 0 if OK or <code>-errno</code> in case of I/O error.
-</p></dd>
-<dt><code>puts(str)</code></dt>
-<dd><p>Outputs the string with the UTF-8 encoding.
-</p></dd>
-<dt><code>printf(fmt, ...args)</code></dt>
-<dd><p>Formatted printf.
-</p>
-<p>The same formats as the standard C library <code>printf</code> are
-supported. Integer format types (e.g. <code>%d</code>) truncate the Numbers
-or BigInts to 32 bits. Use the <code>l</code> modifier (e.g. <code>%ld</code>) to
-truncate to 64 bits.
-</p>
-</dd>
-<dt><code>flush()</code></dt>
-<dd><p>Flush the buffered file.
-</p></dd>
-<dt><code>seek(offset, whence)</code></dt>
-<dd><p>Seek to a give file position (whence is
-<code>std.SEEK_*</code>). <code>offset</code> can be a number or a bigint. Return
-0 if OK or <code>-errno</code> in case of I/O error.
-</p></dd>
-<dt><code>tell()</code></dt>
-<dd><p>Return the current file position.
-</p></dd>
-<dt><code>tello()</code></dt>
-<dd><p>Return the current file position as a bigint.
-</p></dd>
-<dt><code>eof()</code></dt>
-<dd><p>Return true if end of file.
-</p></dd>
-<dt><code>fileno()</code></dt>
-<dd><p>Return the associated OS handle.
-</p></dd>
-<dt><code>error()</code></dt>
-<dd><p>Return true if there was an error.
-</p></dd>
-<dt><code>clearerr()</code></dt>
-<dd><p>Clear the error indication.
-</p>
-</dd>
-<dt><code>read(buffer, position, length)</code></dt>
-<dd><p>Read <code>length</code> bytes from the file to the ArrayBuffer <code>buffer</code> at byte
-position <code>position</code> (wrapper to the libc <code>fread</code>).
-</p>
-</dd>
-<dt><code>write(buffer, position, length)</code></dt>
-<dd><p>Write <code>length</code> bytes to the file from the ArrayBuffer <code>buffer</code> at byte
-position <code>position</code> (wrapper to the libc <code>fread</code>).
-</p>
-</dd>
-<dt><code>getline()</code></dt>
-<dd><p>Return the next line from the file, assuming UTF-8 encoding, excluding
-the trailing line feed.
-</p>
-</dd>
-<dt><code>readAsString(max_size = undefined)</code></dt>
-<dd><p>Read <code>max_size</code> bytes from the file and return them as a string
-assuming UTF-8 encoding. If <code>max_size</code> is not present, the file
-is read up its end.
-</p>
-</dd>
-<dt><code>getByte()</code></dt>
-<dd><p>Return the next byte from the file. Return -1 if the end of file is reached.
-</p>
-</dd>
-<dt><code>putByte(c)</code></dt>
-<dd><p>Write one byte to the file.
-</p></dd>
-</dl>
-
-<a name="os-module"></a>
-<h4 class="subsection">3.3.3 <code>os</code> module</h4>
-
-<p>The <code>os</code> module provides Operating System specific functions:
-</p>
-<ul>
-<li> low level file access
-</li><li> signals
-</li><li> timers
-</li><li> asynchronous I/O
-</li><li> workers (threads)
-</li></ul>
-
-<p>The OS functions usually return 0 if OK or an OS specific negative
-error code.
-</p>
-<p>Available exports:
-</p>
-<dl compact="compact">
-<dt><code>open(filename, flags, mode = 0o666)</code></dt>
-<dd><p>Open a file. Return a handle or &lt; 0 if error.
-</p>
-</dd>
-<dt><code>O_RDONLY</code></dt>
-<dt><code>O_WRONLY</code></dt>
-<dt><code>O_RDWR</code></dt>
-<dt><code>O_APPEND</code></dt>
-<dt><code>O_CREAT</code></dt>
-<dt><code>O_EXCL</code></dt>
-<dt><code>O_TRUNC</code></dt>
-<dd><p>POSIX open flags.
-</p>
-</dd>
-<dt><code>O_TEXT</code></dt>
-<dd><p>(Windows specific). Open the file in text mode. The default is binary mode.
-</p>
-</dd>
-<dt><code>close(fd)</code></dt>
-<dd><p>Close the file handle <code>fd</code>.
-</p>
-</dd>
-<dt><code>seek(fd, offset, whence)</code></dt>
-<dd><p>Seek in the file. Use <code>std.SEEK_*</code> for
-<code>whence</code>. <code>offset</code> is either a number or a bigint. If
-<code>offset</code> is a bigint, a bigint is returned too.
-</p>
-</dd>
-<dt><code>read(fd, buffer, offset, length)</code></dt>
-<dd><p>Read <code>length</code> bytes from the file handle <code>fd</code> to the
-ArrayBuffer <code>buffer</code> at byte position <code>offset</code>.
-Return the number of read bytes or &lt; 0 if error.
-</p>
-</dd>
-<dt><code>write(fd, buffer, offset, length)</code></dt>
-<dd><p>Write <code>length</code> bytes to the file handle <code>fd</code> from the
-ArrayBuffer <code>buffer</code> at byte position <code>offset</code>.
-Return the number of written bytes or &lt; 0 if error.
-</p>
-</dd>
-<dt><code>isatty(fd)</code></dt>
-<dd><p>Return <code>true</code> is <code>fd</code> is a TTY (terminal) handle.
-</p>
-</dd>
-<dt><code>ttyGetWinSize(fd)</code></dt>
-<dd><p>Return the TTY size as <code>[width, height]</code> or <code>null</code> if not available.
-</p>
-</dd>
-<dt><code>ttySetRaw(fd)</code></dt>
-<dd><p>Set the TTY in raw mode.
-</p>
-</dd>
-<dt><code>remove(filename)</code></dt>
-<dd><p>Remove a file. Return 0 if OK or <code>-errno</code>.
-</p>
-</dd>
-<dt><code>rename(oldname, newname)</code></dt>
-<dd><p>Rename a file. Return 0 if OK or <code>-errno</code>.
-</p>
-</dd>
-<dt><code>realpath(path)</code></dt>
-<dd><p>Return <code>[str, err]</code> where <code>str</code> is the canonicalized absolute
-pathname of <code>path</code> and <code>err</code> the error code.
-</p>
-</dd>
-<dt><code>getcwd()</code></dt>
-<dd><p>Return <code>[str, err]</code> where <code>str</code> is the current working directory
-and <code>err</code> the error code.
-</p>
-</dd>
-<dt><code>chdir(path)</code></dt>
-<dd><p>Change the current directory. Return 0 if OK or <code>-errno</code>.
-</p>
-</dd>
-<dt><code>mkdir(path, mode = 0o777)</code></dt>
-<dd><p>Create a directory at <code>path</code>. Return 0 if OK or <code>-errno</code>.
-</p>
-</dd>
-<dt><code>stat(path)</code></dt>
-<dt><code>lstat(path)</code></dt>
-<dd>
-<p>Return <code>[obj, err]</code> where <code>obj</code> is an object containing the
-file status of <code>path</code>. <code>err</code> is the error code. The
-following fields are defined in <code>obj</code>: dev, ino, mode, nlink,
-uid, gid, rdev, size, blocks, atime, mtime, ctime. The times are
-specified in milliseconds since 1970. <code>lstat()</code> is the same as
-<code>stat()</code> excepts that it returns information about the link
-itself.
-</p>
-</dd>
-<dt><code>S_IFMT</code></dt>
-<dt><code>S_IFIFO</code></dt>
-<dt><code>S_IFCHR</code></dt>
-<dt><code>S_IFDIR</code></dt>
-<dt><code>S_IFBLK</code></dt>
-<dt><code>S_IFREG</code></dt>
-<dt><code>S_IFSOCK</code></dt>
-<dt><code>S_IFLNK</code></dt>
-<dt><code>S_ISGID</code></dt>
-<dt><code>S_ISUID</code></dt>
-<dd><p>Constants to interpret the <code>mode</code> property returned by
-<code>stat()</code>. They have the same value as in the C system header
-<samp>sys/stat.h</samp>.
-</p>
-</dd>
-<dt><code>utimes(path, atime, mtime)</code></dt>
-<dd><p>Change the access and modification times of the file <code>path</code>. The
-times are specified in milliseconds since 1970. Return 0 if OK or <code>-errno</code>.
-</p>
-</dd>
-<dt><code>symlink(target, linkpath)</code></dt>
-<dd><p>Create a link at <code>linkpath</code> containing the string <code>target</code>. Return 0 if OK or <code>-errno</code>.
-</p>
-</dd>
-<dt><code>readlink(path)</code></dt>
-<dd><p>Return <code>[str, err]</code> where <code>str</code> is the link target and <code>err</code>
-the error code.
-</p>
-</dd>
-<dt><code>readdir(path)</code></dt>
-<dd><p>Return <code>[array, err]</code> where <code>array</code> is an array of strings
-containing the filenames of the directory <code>path</code>. <code>err</code> is
-the error code.
-</p>
-</dd>
-<dt><code>setReadHandler(fd, func)</code></dt>
-<dd><p>Add a read handler to the file handle <code>fd</code>. <code>func</code> is called
-each time there is data pending for <code>fd</code>. A single read handler
-per file handle is supported. Use <code>func = null</code> to remove the
-handler.
-</p>
-</dd>
-<dt><code>setWriteHandler(fd, func)</code></dt>
-<dd><p>Add a write handler to the file handle <code>fd</code>. <code>func</code> is
-called each time data can be written to <code>fd</code>. A single write
-handler per file handle is supported. Use <code>func = null</code> to remove
-the handler.
-</p>
-</dd>
-<dt><code>signal(signal, func)</code></dt>
-<dd><p>Call the function <code>func</code> when the signal <code>signal</code>
-happens. Only a single handler per signal number is supported. Use
-<code>null</code> to set the default handler or <code>undefined</code> to ignore
-the signal. Signal handlers can only be defined in the main thread.
-</p>
-</dd>
-<dt><code>SIGINT</code></dt>
-<dt><code>SIGABRT</code></dt>
-<dt><code>SIGFPE</code></dt>
-<dt><code>SIGILL</code></dt>
-<dt><code>SIGSEGV</code></dt>
-<dt><code>SIGTERM</code></dt>
-<dd><p>POSIX signal numbers.
-</p>
-</dd>
-<dt><code>kill(pid, sig)</code></dt>
-<dd><p>Send the signal <code>sig</code> to the process <code>pid</code>.
-</p>
-</dd>
-<dt><code>exec(args[, options])</code></dt>
-<dd><p>Execute a process with the arguments <code>args</code>. <code>options</code> is an
-object containing optional parameters:
-</p>
-<dl compact="compact">
-<dt><code>block</code></dt>
-<dd><p>Boolean (default = true). If true, wait until the process is
-  terminated. In this case, <code>exec</code> return the exit code if positive
-  or the negated signal number if the process was interrupted by a
-  signal. If false, do not block and return the process id of the child.
-</p>  
-</dd>
-<dt><code>usePath</code></dt>
-<dd><p>Boolean (default = true). If true, the file is searched in the
-  <code>PATH</code> environment variable.
-</p>
-</dd>
-<dt><code>file</code></dt>
-<dd><p>String (default = <code>args[0]</code>). Set the file to be executed.
-</p>
-</dd>
-<dt><code>cwd</code></dt>
-<dd><p>String. If present, set the working directory of the new process.
-</p>
-</dd>
-<dt><code>stdin</code></dt>
-<dt><code>stdout</code></dt>
-<dt><code>stderr</code></dt>
-<dd><p>If present, set the handle in the child for stdin, stdout or stderr.
-</p>
-</dd>
-<dt><code>env</code></dt>
-<dd><p>Object. If present, set the process environment from the object
-  key-value pairs. Otherwise use the same environment as the current
-  process.
-</p>
-</dd>
-<dt><code>uid</code></dt>
-<dd><p>Integer. If present, the process uid with <code>setuid</code>.
-</p>
-</dd>
-<dt><code>gid</code></dt>
-<dd><p>Integer. If present, the process gid with <code>setgid</code>.
-</p>
-</dd>
-</dl>
-
-</dd>
-<dt><code>waitpid(pid, options)</code></dt>
-<dd><p><code>waitpid</code> Unix system call. Return the array <code>[ret,
-status]</code>. <code>ret</code> contains <code>-errno</code> in case of error.
-</p>
-</dd>
-<dt><code>WNOHANG</code></dt>
-<dd><p>Constant for the <code>options</code> argument of <code>waitpid</code>.
-</p>
-</dd>
-<dt><code>dup(fd)</code></dt>
-<dd><p><code>dup</code> Unix system call.
-</p>
-</dd>
-<dt><code>dup2(oldfd, newfd)</code></dt>
-<dd><p><code>dup2</code> Unix system call.
-</p>
-</dd>
-<dt><code>pipe()</code></dt>
-<dd><p><code>pipe</code> Unix system call. Return two handles as <code>[read_fd,
-write_fd]</code> or null in case of error.
-</p>
-</dd>
-<dt><code>sleep(delay_ms)</code></dt>
-<dd><p>Sleep during <code>delay_ms</code> milliseconds.
-</p>
-</dd>
-<dt><code>setTimeout(func, delay)</code></dt>
-<dd><p>Call the function <code>func</code> after <code>delay</code> ms. Return a handle
-to the timer.
-</p>
-</dd>
-<dt><code>clearTimeout(handle)</code></dt>
-<dd><p>Cancel a timer.
-</p>
-</dd>
-<dt><code>platform</code></dt>
-<dd><p>Return a string representing the platform: <code>&quot;linux&quot;</code>, <code>&quot;darwin&quot;</code>,
-<code>&quot;win32&quot;</code> or <code>&quot;js&quot;</code>.
-</p>
-</dd>
-<dt><code>Worker(module_filename)</code></dt>
-<dd><p>Constructor to create a new thread (worker) with an API close to the
-<code>WebWorkers</code>. <code>module_filename</code> is a string specifying the
-module filename which is executed in the newly created thread. As for
-dynamically imported module, it is relative to the current script or
-module path. Threads normally don&rsquo;t share any data and communicate
-between each other with messages. Nested workers are not supported. An
-example is available in <samp>tests/test_worker.js</samp>.
-</p>
-<p>The worker class has the following static properties:
-</p>
-<dl compact="compact">
-<dt><code>parent</code></dt>
-<dd><p>In the created worker, <code>Worker.parent</code> represents the parent
-  worker and is used to send or receive messages.
-  </p></dd>
-</dl>
-
-<p>The worker instances have the following properties:
-</p>
-<dl compact="compact">
-<dt><code>postMessage(msg)</code></dt>
-<dd>  
-<p>Send a message to the corresponding worker. <code>msg</code> is cloned in
-  the destination worker using an algorithm similar to the <code>HTML</code>
-  structured clone algorithm. <code>SharedArrayBuffer</code> are shared
-  between workers.
-</p>
-<p>Current limitations: <code>Map</code> and <code>Set</code> are not supported
-  yet.
-</p>
-</dd>
-<dt><code>onmessage</code></dt>
-<dd>
-<p>Getter and setter. Set a function which is called each time a
-  message is received. The function is called with a single
-  argument. It is an object with a <code>data</code> property containing the
-  received message. The thread is not terminated if there is at least
-  one non <code>null</code> <code>onmessage</code> handler.
-</p>
-</dd>
-</dl>
-
-</dd>
-</dl>
-
-<a name="QuickJS-C-API"></a>
-<h3 class="section">3.4 QuickJS C API</h3>
-
-<p>The C API was designed to be simple and efficient. The C API is
-defined in the header <code>quickjs.h</code>.
-</p>
-<a name="Runtime-and-contexts"></a>
-<h4 class="subsection">3.4.1 Runtime and contexts</h4>
-
-<p><code>JSRuntime</code> represents a Javascript runtime corresponding to an
-object heap. Several runtimes can exist at the same time but they
-cannot exchange objects. Inside a given runtime, no multi-threading is
-supported.
-</p>
-<p><code>JSContext</code> represents a Javascript context (or Realm). Each
-JSContext has its own global objects and system objects. There can be
-several JSContexts per JSRuntime and they can share objects, similar
-to frames of the same origin sharing Javascript objects in a
-web browser.
-</p>
-<a name="JSValue"></a>
-<h4 class="subsection">3.4.2 JSValue</h4>
-
-<p><code>JSValue</code> represents a Javascript value which can be a primitive
-type or an object. Reference counting is used, so it is important to
-explicitly duplicate (<code>JS_DupValue()</code>, increment the reference
-count) or free (<code>JS_FreeValue()</code>, decrement the reference count)
-JSValues.
-</p>
-<a name="C-functions"></a>
-<h4 class="subsection">3.4.3 C functions</h4>
-
-<p>C functions can be created with
-<code>JS_NewCFunction()</code>. <code>JS_SetPropertyFunctionList()</code> is a
-shortcut to easily add functions, setters and getters properties to a
-given object.
-</p>
-<p>Unlike other embedded Javascript engines, there is no implicit stack,
-so C functions get their parameters as normal C parameters. As a
-general rule, C functions take constant <code>JSValue</code>s as parameters
-(so they don&rsquo;t need to free them) and return a newly allocated (=live)
-<code>JSValue</code>.
-</p>
-<a name="Exceptions"></a>
-<h4 class="subsection">3.4.4 Exceptions</h4>
-
-<p>Exceptions: most C functions can return a Javascript exception. It
-must be explicitly tested and handled by the C code. The specific
-<code>JSValue</code> <code>JS_EXCEPTION</code> indicates that an exception
-occurred. The actual exception object is stored in the
-<code>JSContext</code> and can be retrieved with <code>JS_GetException()</code>.
-</p>
-<a name="Script-evaluation"></a>
-<h4 class="subsection">3.4.5 Script evaluation</h4>
-
-<p>Use <code>JS_Eval()</code> to evaluate a script or module source.
-</p>
-<p>If the script or module was compiled to bytecode with <code>qjsc</code>, it
-can be evaluated by calling <code>js_std_eval_binary()</code>. The advantage
-is that no compilation is needed so it is faster and smaller because
-the compiler can be removed from the executable if no <code>eval</code> is
-required.
-</p>
-<p>Note: the bytecode format is linked to a given QuickJS
-version. Moreover, no security check is done before its
-execution. Hence the bytecode should not be loaded from untrusted
-sources. That&rsquo;s why there is no option to output the bytecode to a
-binary file in <code>qjsc</code>.
-</p>
-<a name="JS-Classes"></a>
-<h4 class="subsection">3.4.6 JS Classes</h4>
-
-<p>C opaque data can be attached to a Javascript object. The type of the
-C opaque data is determined with the class ID (<code>JSClassID</code>) of
-the object. Hence the first step is to register a new class ID and JS
-class (<code>JS_NewClassID()</code>, <code>JS_NewClass()</code>). Then you can
-create objects of this class with <code>JS_NewObjectClass()</code> and get or
-set the C opaque point with
-<code>JS_GetOpaque()</code>/<code>JS_SetOpaque()</code>.
-</p>
-<p>When defining a new JS class, it is possible to declare a finalizer
-which is called when the object is destroyed. A <code>gc_mark</code> method
-can be provided so that the cycle removal algorithm can find the other
-objects referenced by this object. Other methods are available to
-define exotic object behaviors.
-</p>
-<p>The Class ID are globally allocated (i.e. for all runtimes). The
-JSClass are allocated per <code>JSRuntime</code>. <code>JS_SetClassProto()</code>
-is used to define a prototype for a given class in a given
-JSContext. <code>JS_NewObjectClass()</code> sets this prototype in the
-created object.
-</p>
-<p>Examples are available in <samp>quickjs-libc.c</samp>.
-</p>
-<a name="C-Modules"></a>
-<h4 class="subsection">3.4.7 C Modules</h4>
-
-<p>Native ES6 modules are supported and can be dynamically or statically
-linked. Look at the <samp>test_bjson</samp> and <samp>bjson.so</samp>
-examples. The standard library <samp>quickjs-libc.c</samp> is also a good example
-of a native module.
-</p>
-<a name="Memory-handling"></a>
-<h4 class="subsection">3.4.8 Memory handling</h4>
-
-<p>Use <code>JS_SetMemoryLimit()</code> to set a global memory allocation limit
-to a given JSRuntime.
-</p>
-<p>Custom memory allocation functions can be provided with
-<code>JS_NewRuntime2()</code>.
-</p>
-<p>The maximum system stack size can be set with <code>JS_SetMaxStackSize()</code>.
-</p>
-<a name="Execution-timeout-and-interrupts"></a>
-<h4 class="subsection">3.4.9 Execution timeout and interrupts</h4>
-
-<p>Use <code>JS_SetInterruptHandler()</code> to set a callback which is
-regularly called by the engine when it is executing code. This
-callback can be used to implement an execution timeout.
-</p>
-<p>It is used by the command line interpreter to implement a
-<code>Ctrl-C</code> handler.
-</p>
-<a name="Internals"></a>
-<h2 class="chapter">4 Internals</h2>
-
-<a name="Bytecode"></a>
-<h3 class="section">4.1 Bytecode</h3>
-
-<p>The compiler generates bytecode directly with no intermediate
-representation such as a parse tree, hence it is very fast. Several
-optimizations passes are done over the generated bytecode.
-</p>
-<p>A stack-based bytecode was chosen because it is simple and generates 
-compact code.
-</p>
-<p>For each function, the maximum stack size is computed at compile time so that
-no runtime stack overflow tests are needed.
-</p>
-<p>A separate compressed line number table is maintained for the debug
-information.
-</p>
-<p>Access to closure variables is optimized and is almost as fast as local
-variables.
-</p>
-<p>Direct <code>eval</code> in strict mode is optimized.
-</p>
-<a name="Executable-generation"></a>
-<h3 class="section">4.2 Executable generation</h3>
-
-<a name="qjsc-compiler-1"></a>
-<h4 class="subsection">4.2.1 <code>qjsc</code> compiler</h4>
-
-<p>The <code>qjsc</code> compiler generates C sources from Javascript files. By
-default the C sources are compiled with the system compiler
-(<code>gcc</code> or <code>clang</code>).
-</p>
-<p>The generated C source contains the bytecode of the compiled functions
-or modules. If a full complete executable is needed, it also
-contains a <code>main()</code> function with the necessary C code to initialize the
-Javascript engine and to load and execute the compiled functions and
-modules.
-</p>
-<p>Javascript code can be mixed with C modules.
-</p>
-<p>In order to have smaller executables, specific Javascript features can
-be disabled, in particular <code>eval</code> or the regular expressions. The
-code removal relies on the Link Time Optimization of the system
-compiler.
-</p>
-<a name="Binary-JSON"></a>
-<h4 class="subsection">4.2.2 Binary JSON</h4>
-
-<p><code>qjsc</code> works by compiling scripts or modules and then serializing
-them to a binary format. A subset of this format (without functions or
-modules) can be used as binary JSON. The example <samp>test_bjson.js</samp>
-shows how to use it.
-</p>
-<p>Warning: the binary JSON format may change without notice, so it
-should not be used to store persistent data. The <samp>test_bjson.js</samp>
-example is only used to test the binary object format functions.
-</p>
-<a name="Runtime"></a>
-<h3 class="section">4.3 Runtime</h3>
-
-<a name="Strings"></a>
-<h4 class="subsection">4.3.1 Strings</h4>
-
-<p>Strings are stored either as an 8 bit or a 16 bit array of
-characters. Hence random access to characters is always fast.
-</p>
-<p>The C API provides functions to convert Javascript Strings to C UTF-8 encoded
-strings. The most common case where the Javascript string contains
-only ASCII characters involves no copying.
-</p>
-<a name="Objects"></a>
-<h4 class="subsection">4.3.2 Objects</h4>
-
-<p>The object shapes (object prototype, property names and flags) are shared
-between objects to save memory.
-</p>
-<p>Arrays with no holes (except at the end of the array) are optimized.
-</p>
-<p>TypedArray accesses are optimized.
-</p>
-<a name="Atoms"></a>
-<h4 class="subsection">4.3.3 Atoms</h4>
-
-<p>Object property names and some strings are stored as Atoms (unique
-strings) to save memory and allow fast comparison. Atoms are
-represented as a 32 bit integer. Half of the atom range is reserved for
-immediate integer literals from <em>0</em> to <em>2^{31}-1</em>.
-</p>
-<a name="Numbers"></a>
-<h4 class="subsection">4.3.4 Numbers</h4>
-
-<p>Numbers are represented either as 32-bit signed integers or 64-bit IEEE-754
-floating point values. Most operations have fast paths for the 32-bit
-integer case.
-</p>
-<a name="Garbage-collection"></a>
-<h4 class="subsection">4.3.5 Garbage collection</h4>
-
-<p>Reference counting is used to free objects automatically and
-deterministically. A separate cycle removal pass is done when the allocated
-memory becomes too large. The cycle removal algorithm only uses the
-reference counts and the object content, so no explicit garbage
-collection roots need to be manipulated in the C code.
-</p>
-<a name="JSValue-1"></a>
-<h4 class="subsection">4.3.6 JSValue</h4>
-
-<p>It is a Javascript value which can be a primitive type (such as
-Number, String, ...) or an Object. NaN boxing is used in the 32-bit version
-to store 64-bit floating point numbers. The representation is
-optimized so that 32-bit integers and reference counted values can be
-efficiently tested.
-</p>
-<p>In 64-bit code, JSValue are 128-bit large and no NaN boxing is used. The
-rationale is that in 64-bit code memory usage is less critical.
-</p>
-<p>In both cases (32 or 64 bits), JSValue exactly fits two CPU registers,
-so it can be efficiently returned by C functions.
-</p>
-<a name="Function-call"></a>
-<h4 class="subsection">4.3.7 Function call</h4>
-
-<p>The engine is optimized so that function calls are fast. The system
-stack holds the Javascript parameters and local variables.
-</p>
-<a name="RegExp"></a>
-<h3 class="section">4.4 RegExp</h3>
-
-<p>A specific regular expression engine was developed. It is both small
-and efficient and supports all the ES2020 features including the
-Unicode properties. As the Javascript compiler, it directly generates
-bytecode without a parse tree.
-</p>
-<p>Backtracking with an explicit stack is used so that there is no
-recursion on the system stack. Simple quantifiers are specifically
-optimized to avoid recursions.
-</p>
-<p>Infinite recursions coming from quantifiers with empty terms are
-avoided.
-</p>
-<p>The full regexp library weights about 15 KiB (x86 code), excluding the
-Unicode library.
-</p>
-<a name="Unicode"></a>
-<h3 class="section">4.5 Unicode</h3>
-
-<p>A specific Unicode library was developed so that there is no
-dependency on an external large Unicode library such as ICU. All the
-Unicode tables are compressed while keeping a reasonable access
-speed.
-</p>
-<p>The library supports case conversion, Unicode normalization, Unicode
-script queries, Unicode general category queries and all Unicode
-binary properties.
-</p>
-<p>The full Unicode library weights about 45 KiB (x86 code).
-</p>
-<a name="BigInt_002c-BigFloat_002c-BigDecimal"></a>
-<h3 class="section">4.6 BigInt, BigFloat, BigDecimal</h3>
-
-<p>BigInt, BigFloat and BigDecimal are implemented with the <code>libbf</code>
-library<a name="DOCF7" href="#FOOT7"><sup>7</sup></a>. It weights about 90
-KiB (x86 code) and provides arbitrary precision IEEE 754 floating
-point operations and transcendental functions with exact rounding.
-</p>
-<a name="License"></a>
-<h2 class="chapter">5 License</h2>
-
-<p>QuickJS is released under the MIT license.
-</p>
-<p>Unless otherwise specified, the QuickJS sources are copyright Fabrice
-Bellard and Charlie Gordon.
-</p>
-<div class="footnote">
-<hr>
-<h4 class="footnotes-heading">Footnotes</h4>
-
-<h3><a name="FOOT1" href="#DOCF1">(1)</a></h3>
-<p><a href="https://tc39.es/ecma262/">https://tc39.es/ecma262/</a></p>
-<h3><a name="FOOT2" href="#DOCF2">(2)</a></h3>
-<p><a href="https://github.com/tc39/test262">https://github.com/tc39/test262</a></p>
-<h3><a name="FOOT3" href="#DOCF3">(3)</a></h3>
-<p><a href="https://tc39.github.io/ecma262/">https://tc39.github.io/ecma262/</a></p>
-<h3><a name="FOOT4" href="#DOCF4">(4)</a></h3>
-<p>The old
-ES5.1 tests can be extracted with <code>git clone --single-branch
---branch es5-tests https://github.com/tc39/test262.git test262o</code></p>
-<h3><a name="FOOT5" href="#DOCF5">(5)</a></h3>
-<p><a href="https://github.com/bterlson/test262-harness">https://github.com/bterlson/test262-harness</a></p>
-<h3><a name="FOOT6" href="#DOCF6">(6)</a></h3>
-<p>We believe the current specification of tails calls is too complicated and presents limited practical interests.</p>
-<h3><a name="FOOT7" href="#DOCF7">(7)</a></h3>
-<p><a href="https://bellard.org/libbf">https://bellard.org/libbf</a></p>
-</div>
-<hr>
-
-
-
-</body>
-</html>
diff --git a/doc/quickjs.pdf b/doc/quickjs.pdf
deleted file mode 100644 (file)
index 497964b..0000000
Binary files a/doc/quickjs.pdf and /dev/null differ
index 57d13e64cd954a04bda5f3de3115050d2160f6ce..40c0bb51ca847889c76a0b0288702773a45d2d64 100644 (file)
@@ -452,6 +452,16 @@ useful in case of specific memory constraints or for testing.
 Return the value of the environment variable @code{name} or
 @code{undefined} if it is not defined.
 
+@item setenv(name, value)
+Set the value of the environment variable @code{name} to the string
+@code{value}.
+
+@item unsetenv(name)
+Delete the environment variable @code{name}.
+
+@item getenviron()
+Return an object containing the environment variables as key-value pairs.
+
 @item urlGet(url, options = undefined)
 
 Download @code{url} using the @file{curl} command line
@@ -532,7 +542,7 @@ position @code{position} (wrapper to the libc @code{fread}).
 
 @item write(buffer, position, length)
 Write @code{length} bytes to the file from the ArrayBuffer @code{buffer} at byte
-position @code{position} (wrapper to the libc @code{fread}).
+position @code{position} (wrapper to the libc @code{fwrite}).
 
 @item getline()
 Return the next line from the file, assuming UTF-8 encoding, excluding
diff --git a/jscompress.c b/jscompress.c
deleted file mode 100644 (file)
index a68c0e8..0000000
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * Javascript Compressor
- * 
- * Copyright (c) 2008-2018 Fabrice Bellard
- * Copyright (c) 2017-2018 Charlie Gordon
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <stdarg.h>
-#include <string.h>
-#include <inttypes.h>
-#include <unistd.h>
-
-#include "cutils.h"
-
-typedef struct JSToken {
-    int tok;
-    char buf[20];
-    char *str;
-    int len;
-    int size;
-    int line_num;  /* line number for start of token */
-    int lines;     /* number of embedded linefeeds in token */
-} JSToken;
-
-enum {
-    TOK_EOF = 256,
-    TOK_IDENT,
-    TOK_STR1,
-    TOK_STR2,
-    TOK_STR3,
-    TOK_NUM,
-    TOK_COM,
-    TOK_LCOM,
-};
-
-void tok_reset(JSToken *tt)
-{
-    if (tt->str != tt->buf) {
-        free(tt->str);
-        tt->str = tt->buf;
-        tt->size = sizeof(tt->buf);
-    }
-    tt->len = 0;
-}
-
-void tok_add_ch(JSToken *tt, int c)
-{
-    if (tt->len + 1 > tt->size) {
-        tt->size *= 2;
-        if (tt->str == tt->buf) {
-            tt->str = malloc(tt->size);
-            memcpy(tt->str, tt->buf, tt->len);
-        } else {
-            tt->str = realloc(tt->str, tt->size);
-        }
-    }
-    tt->str[tt->len++] = c;
-}
-
-FILE *infile;
-const char *filename;
-int output_line_num;
-int line_num;
-int ch;
-JSToken tokc;
-
-int skip_mask;
-#define DEFINE_MAX 20
-char *define_tab[DEFINE_MAX];
-int define_len;
-
-void error(const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    if (filename) {
-        fprintf(stderr, "%s:%d: ", filename, line_num);
-    } else {
-        fprintf(stderr, "jscompress: ");
-    }
-    vfprintf(stderr, fmt, ap);
-    fprintf(stderr, "\n");
-    va_end(ap);
-    exit(1);
-}
-
-void define_symbol(const char *def)
-{
-    int i;
-    for (i = 0; i < define_len; i++) {
-        if (!strcmp(tokc.str, define_tab[i]))
-            return;
-    }
-    if (define_len >= DEFINE_MAX)
-        error("too many defines");
-    define_tab[define_len++] = strdup(def);
-}
-
-void undefine_symbol(const char *def)
-{
-    int i, j;
-    for (i = j = 0; i < define_len; i++) {
-        if (!strcmp(tokc.str, define_tab[i])) {
-            free(define_tab[i]);
-        } else {
-            define_tab[j++] = define_tab[i];
-        }
-    }
-    define_len = j;
-}
-
-const char *find_symbol(const char *def)
-{
-    int i;
-    for (i = 0; i < define_len; i++) {
-        if (!strcmp(tokc.str, define_tab[i]))
-            return "1";
-    }
-    return NULL;
-}
-
-void next(void);
-
-void nextch(void)
-{
-    ch = fgetc(infile);
-    if (ch == '\n')
-        line_num++;
-}
-
-int skip_blanks(void)
-{
-    for (;;) {
-        next();
-        if (tokc.tok != ' ' && tokc.tok != '\t' &&
-            tokc.tok != TOK_COM && tokc.tok != TOK_LCOM)
-            return tokc.tok;
-    }
-}
-
-void parse_directive(void)
-{
-    int ifdef, mask = skip_mask;
-    /* simplistic preprocessor:
-       #define / #undef / #ifdef / #ifndef / #else / #endif
-       no symbol substitution.
-     */
-    skip_mask = 0;  /* disable skipping to parse preprocessor line */
-    nextch();
-    if (skip_blanks() != TOK_IDENT)
-        error("expected preprocessing directive after #");
-
-    if (!strcmp(tokc.str, "define")) {
-        if (skip_blanks() != TOK_IDENT)
-            error("expected identifier after #define");
-        define_symbol(tokc.str);
-    } else if (!strcmp(tokc.str, "undef")) {
-        if (skip_blanks() != TOK_IDENT)
-            error("expected identifier after #undef");
-        undefine_symbol(tokc.str);
-    } else if ((ifdef = 1, !strcmp(tokc.str, "ifdef")) ||
-               (ifdef = 0, !strcmp(tokc.str, "ifndef"))) {
-        if (skip_blanks() != TOK_IDENT)
-            error("expected identifier after #ifdef/#ifndef");
-        mask = (mask << 2) | 2 | ifdef;
-        if (find_symbol(tokc.str))
-            mask ^= 1;
-    } else if (!strcmp(tokc.str, "else")) {
-        if (!(mask & 2))
-            error("#else without a #if");
-        mask ^= 1;
-    } else if (!strcmp(tokc.str, "endif")) {
-        if (!(mask & 2))
-            error("#endif without a #if");
-        mask >>= 2;
-    } else {
-        error("unsupported preprocessing directive");
-    }
-    if (skip_blanks() != '\n')
-        error("extra characters on preprocessing line");
-    skip_mask = mask;
-}
-
-/* return -1 if invalid char */
-static int hex_to_num(int ch)
-{
-    if (ch >= 'a' && ch <= 'f')
-        return ch - 'a' + 10;
-    else if (ch >= 'A' && ch <= 'F')
-        return ch - 'A' + 10;
-    else if (ch >= '0' && ch <= '9')
-        return ch - '0';
-    else
-        return -1;
-}
-
-void next(void)
-{
-again:    
-    tok_reset(&tokc);
-    tokc.line_num = line_num;
-    tokc.lines = 0;
-    switch(ch) {
-    case EOF:
-        tokc.tok = TOK_EOF;
-        if (skip_mask)
-            error("missing #endif");
-        break;
-    case 'a' ... 'z':
-    case 'A' ... 'Z':
-    case '_':
-    case '$':
-        tok_add_ch(&tokc, ch);
-        nextch();
-        while ((ch >= 'a' && ch <= 'z') ||
-               (ch >= 'A' && ch <= 'Z') ||
-               (ch >= '0' && ch <= '9') ||
-               (ch == '_' || ch == '$')) {
-            tok_add_ch(&tokc, ch);
-            nextch();
-        }
-        tok_add_ch(&tokc, '\0');
-        tokc.tok = TOK_IDENT;
-        break;
-    case '.':
-        nextch();
-        if (ch >= '0' && ch <= '9') {
-            tok_add_ch(&tokc, '.');
-            goto has_dot;
-        }
-        tokc.tok = '.';
-        break;
-    case '0':
-        tok_add_ch(&tokc, ch);
-        nextch();
-        if (ch == 'x' || ch == 'X') {
-            /* hexa */
-            tok_add_ch(&tokc, ch);
-            nextch();
-            while ((ch >= 'a' && ch <= 'f') ||
-                   (ch >= 'A' && ch <= 'F') ||
-                   (ch >= '0' && ch <= '9')) {
-                tok_add_ch(&tokc, ch);
-                nextch();
-            }
-            tok_add_ch(&tokc, '\0');
-            tokc.tok = TOK_NUM;
-            break;
-        }
-        goto has_digit;
-
-    case '1' ... '9':
-        tok_add_ch(&tokc, ch);
-        nextch();
-    has_digit:
-        /* decimal */
-        while (ch >= '0' && ch <= '9') {
-            tok_add_ch(&tokc, ch);
-            nextch();
-        }
-        if (ch == '.') {
-            tok_add_ch(&tokc, ch);
-            nextch();
-        has_dot:
-            while (ch >= '0' && ch <= '9') {
-                tok_add_ch(&tokc, ch);
-                nextch();
-            }
-        }
-        if (ch == 'e' || ch == 'E') {
-            tok_add_ch(&tokc, ch);
-            nextch();
-            if (ch == '+' || ch == '-') {
-                tok_add_ch(&tokc, ch);
-                nextch();
-            }
-            while (ch >= '0' && ch <= '9') {
-                tok_add_ch(&tokc, ch);
-                nextch();
-            }
-        }
-        tok_add_ch(&tokc, '\0');
-        tokc.tok = TOK_NUM;
-        break;
-    case '`':
-        {
-            nextch();
-            while (ch != '`' && ch != EOF) {
-                if (ch == '\\') {
-                    tok_add_ch(&tokc, ch);
-                    nextch();
-                    if (ch == EOF) {
-                        error("unexpected char after '\\'");
-                    }
-                    tok_add_ch(&tokc, ch);
-                } else {
-                    tok_add_ch(&tokc, ch);
-                    nextch();
-                }
-            }
-            nextch();
-            tok_add_ch(&tokc, 0);
-            tokc.tok = TOK_STR3;
-        }
-        break;
-    case '\"':
-    case '\'':
-        {
-            int n, i, c, hex_digit_count;
-            int quote_ch;
-            quote_ch = ch;
-            nextch();
-            while (ch != quote_ch && ch != EOF) {
-                if (ch == '\\') {
-                    nextch();
-                    switch(ch) {
-                    case 'n':
-                        tok_add_ch(&tokc, '\n');
-                        nextch();
-                        break;
-                    case 'r':
-                        tok_add_ch(&tokc, '\r');
-                        nextch();
-                        break;
-                    case 't':
-                        tok_add_ch(&tokc, '\t');
-                        nextch();
-                        break;
-                    case 'v':
-                        tok_add_ch(&tokc, '\v');
-                        nextch();
-                        break;
-                    case '\"':
-                    case '\'':
-                    case '\\':
-                        tok_add_ch(&tokc, ch);
-                        nextch();
-                        break;
-                    case '0' ... '7':
-                        n = 0;
-                        while (ch >= '0' && ch <= '7') {
-                            n = n * 8 + (ch - '0');
-                            nextch();
-                        }
-                        tok_add_ch(&tokc, n);
-                        break;
-                    case 'x':
-                    case 'u':
-                        if (ch == 'x')
-                            hex_digit_count = 2;
-                        else
-                            hex_digit_count = 4;
-                        nextch();
-                        n = 0;
-                        for(i = 0; i < hex_digit_count; i++) {
-                            c = hex_to_num(ch);
-                            if (c < 0) 
-                                error("unexpected char after '\\x'");
-                            n = n * 16 + c;
-                            nextch();
-                        }
-                        if (n >= 256)
-                            error("unicode is currently unsupported");
-                        tok_add_ch(&tokc, n);
-                        break;
-
-                    default:
-                        error("unexpected char after '\\'");
-                    }
-                } else {
-                    /* XXX: should refuse embedded newlines */
-                    tok_add_ch(&tokc, ch);
-                    nextch();
-                }
-            }
-            nextch();
-            tok_add_ch(&tokc, 0);
-            if (quote_ch == '\'')
-                tokc.tok = TOK_STR1;
-            else
-                tokc.tok = TOK_STR2;
-        }
-        break;
-    case '/':
-        nextch();
-        if (ch == '/') {
-            tok_add_ch(&tokc, '/');
-            tok_add_ch(&tokc, ch);
-            nextch();
-            while (ch != '\n' && ch != EOF) {
-                tok_add_ch(&tokc, ch);
-                nextch();
-            }
-            tok_add_ch(&tokc, '\0');
-            tokc.tok = TOK_LCOM;
-        } else if (ch == '*') {
-            int last;
-            tok_add_ch(&tokc, '/');
-            tok_add_ch(&tokc, ch);
-            last = 0;
-            for(;;) {
-                nextch();
-                if (ch == EOF)
-                    error("unterminated comment");
-                if (ch == '\n')
-                    tokc.lines++;
-                tok_add_ch(&tokc, ch);
-                if (last == '*' && ch == '/')
-                    break;
-                last = ch;
-            }
-            nextch();
-            tok_add_ch(&tokc, '\0');
-            tokc.tok = TOK_COM;
-        } else {
-            tokc.tok = '/';
-        }
-        break;
-    case '#':
-        parse_directive();
-        goto again;
-    case '\n':
-        /* adjust line number */
-        tokc.line_num--;
-        tokc.lines++;
-        /* fall thru */
-    default:
-        tokc.tok = ch;
-        nextch();
-        break;
-    }
-    if (skip_mask & 1)
-        goto again;
-}
-
-void print_tok(FILE *f, JSToken *tt)
-{
-    /* keep output lines in sync with input lines */
-    while (output_line_num < tt->line_num) {
-        putc('\n', f);
-        output_line_num++;
-    }
-
-    switch(tt->tok) {
-    case TOK_IDENT:
-    case TOK_COM:
-    case TOK_LCOM:
-        fprintf(f, "%s", tt->str);
-        break;
-    case TOK_NUM:
-        {
-            unsigned long a;
-            char *p;
-            a = strtoul(tt->str, &p, 0);
-            if (*p == '\0' && a <= 0x7fffffff) {
-                /* must be an integer */
-                fprintf(f, "%d", (int)a);
-            } else {
-                fprintf(f, "%s", tt->str);
-            }
-        }
-        break;
-    case TOK_STR3:
-        fprintf(f, "`%s`", tt->str);
-        break;
-    case TOK_STR1:
-    case TOK_STR2:
-        {
-            int i, c, quote_ch;
-            if (tt->tok == TOK_STR1)
-                quote_ch = '\'';
-            else
-                quote_ch = '\"';
-            fprintf(f, "%c", quote_ch);
-            for(i = 0; i < tt->len - 1; i++) {
-                c = (uint8_t)tt->str[i];
-                switch(c) {
-                case '\r':
-                    fprintf(f, "\\r");
-                    break;
-                case '\n':
-                    fprintf(f, "\\n");
-                    break;
-                case '\t':
-                    fprintf(f, "\\t");
-                    break;
-                case '\v':
-                    fprintf(f, "\\v");
-                    break;
-                case '\"':
-                case '\'':
-                    if (c == quote_ch)
-                        fprintf(f, "\\%c", c);
-                    else
-                        fprintf(f, "%c", c);
-                    break;
-                case '\\':
-                    fprintf(f, "\\\\");
-                    break;
-                default:
-                    /* XXX: no utf-8 support! */
-                    if (c >= 32 && c <= 255) {
-                        fprintf(f, "%c", c);
-                    } else if (c <= 255) 
-                        fprintf(f, "\\x%02x", c);
-                    else
-                        fprintf(f, "\\u%04x", c);
-                    break;
-                }
-            }
-            fprintf(f, "%c", quote_ch);
-        }
-        break;
-    default:
-        if (tokc.tok >= 256)
-            error("unsupported token in print_tok: %d", tt->tok);
-        fprintf(f, "%c", tt->tok);
-        break;
-    }
-    output_line_num += tt->lines;
-}
-
-/* check if token pasting could occur */                    
-static BOOL compat_token(int c1, int c2)
-{
-    if ((c1 == TOK_IDENT || c1 == TOK_NUM) &&
-        (c2 == TOK_IDENT || c2 == TOK_NUM))
-        return FALSE;
-
-    if ((c1 == c2 && strchr("+-<>&|=*/.", c1))
-    ||  (c2 == '=' && strchr("+-<>&|!*/^%", c1))
-    ||  (c1 == '=' && c2 == '>')
-    ||  (c1 == '/' && c2 == '*')
-    ||  (c1 == '.' && c2 == TOK_NUM)
-    ||  (c1 == TOK_NUM && c2 == '.'))
-        return FALSE;
-
-    return TRUE;
-}
-
-void js_compress(const char *filename, const char *outfilename,
-                 BOOL do_strip, BOOL keep_header)
-{
-    FILE *outfile;
-    int ltok, seen_space;
-    
-    line_num = 1;
-    infile = fopen(filename, "rb");
-    if (!infile) {
-        perror(filename);
-        exit(1);
-    }
-    
-    output_line_num = 1;
-    outfile = fopen(outfilename, "wb");
-    if (!outfile) {
-        perror(outfilename);
-        exit(1);
-    }
-        
-    nextch();
-    next();
-    ltok = 0;
-    seen_space = 0;
-    if (do_strip) {
-        if (keep_header) {
-            while (tokc.tok == ' ' ||
-                   tokc.tok == '\n' ||
-                   tokc.tok == '\t' ||
-                   tokc.tok == '\v' ||
-                   tokc.tok == '\b' ||
-                   tokc.tok == '\f') {
-                seen_space = 1;
-                next();
-            }
-            if (tokc.tok == TOK_COM) {
-                print_tok(outfile, &tokc);
-                //fprintf(outfile, "\n");
-                ltok = tokc.tok;
-                seen_space = 0;
-                next();
-            }
-        }
-
-        for(;;) {
-            if (tokc.tok == TOK_EOF)
-                break;
-            if (tokc.tok == ' ' ||
-                tokc.tok == '\r' ||
-                tokc.tok == '\t' ||
-                tokc.tok == '\v' ||
-                tokc.tok == '\b' ||
-                tokc.tok == '\f' ||
-                tokc.tok == TOK_LCOM ||
-                tokc.tok == TOK_COM) {
-                /* don't print spaces or comments */
-                seen_space = 1;
-            } else if (tokc.tok == TOK_STR3) {
-                print_tok(outfile, &tokc);
-                ltok = tokc.tok;
-                seen_space = 0;
-            } else if (tokc.tok == TOK_STR1 || tokc.tok == TOK_STR2) {
-                int count, i;
-                /* find the optimal quote char */
-                count = 0;
-                for(i = 0; i < tokc.len; i++) {
-                    if (tokc.str[i] == '\'')
-                        count++;
-                    else if (tokc.str[i] == '\"')
-                        count--;
-                }
-                if (count > 0)
-                    tokc.tok = TOK_STR2;
-                else if (count < 0)
-                    tokc.tok = TOK_STR1;
-                print_tok(outfile, &tokc);
-                ltok = tokc.tok;
-                seen_space = 0;
-            } else {
-                if (seen_space && !compat_token(ltok, tokc.tok)) {
-                    fprintf(outfile, " ");
-                }
-                print_tok(outfile, &tokc);
-                ltok = tokc.tok;
-                seen_space = 0;
-            }
-            next();
-        }
-    } else {
-        /* just handle preprocessing */
-        while (tokc.tok != TOK_EOF) {
-            print_tok(outfile, &tokc);
-            next();
-        }
-    }
-
-    fclose(outfile);
-    fclose(infile);
-}
-
-#define HASH_SIZE 30011
-#define MATCH_LEN_MIN 3
-#define MATCH_LEN_MAX (4 + 63)
-#define DIST_MAX 65535
-
-static int find_longest_match(int *pdist, const uint8_t *src, int src_len,
-                              const int *hash_next, int cur_pos)
-{
-    int pos, i, match_len, match_pos, pos_min, len_max;
-
-    len_max = min_int(src_len - cur_pos, MATCH_LEN_MAX);
-    match_len = 0;
-    match_pos = 0;
-    pos_min = max_int(cur_pos - DIST_MAX - 1, 0);
-    pos = hash_next[cur_pos];
-    while (pos >= pos_min) {
-        for(i = 0; i < len_max; i++) {
-            if (src[cur_pos + i] != src[pos + i])
-                break;
-        }
-        if (i > match_len) {
-            match_len = i;
-            match_pos = pos;
-        }
-        pos = hash_next[pos];
-    }
-    *pdist = cur_pos - match_pos - 1;
-    return match_len;
-}
-
-int lz_compress(uint8_t **pdst, const uint8_t *src, int src_len)
-{
-    int *hash_table, *hash_next;
-    uint32_t h, v;
-    int i, dist, len, len1, dist1;
-    uint8_t *dst, *q;
-    
-    /* build the hash table */
-    
-    hash_table = malloc(sizeof(hash_table[0]) * HASH_SIZE);
-    for(i = 0; i < HASH_SIZE; i++)
-        hash_table[i] = -1;
-    hash_next = malloc(sizeof(hash_next[0]) * src_len);
-    for(i = 0; i < src_len; i++)
-        hash_next[i] = -1;
-
-    for(i = 0; i < src_len - MATCH_LEN_MIN + 1; i++) {
-        h = ((src[i] << 16) | (src[i + 1] << 8) | src[i + 2]) % HASH_SIZE;
-        hash_next[i] = hash_table[h];
-        hash_table[h] = i;
-    }
-    for(;i < src_len; i++) {
-        hash_next[i] = -1;
-    }
-    free(hash_table);
-
-    dst = malloc(src_len + 4); /* never larger than the source */
-    q = dst;
-    *q++ = src_len >> 24;
-    *q++ = src_len >> 16;
-    *q++ = src_len >> 8;
-    *q++ = src_len >> 0;
-    /* compress */
-    i = 0;
-    while (i < src_len) {
-        if (src[i] >= 128)
-            return -1;
-        len = find_longest_match(&dist, src, src_len, hash_next, i);
-        if (len >= MATCH_LEN_MIN) {
-            /* heuristic: see if better length just after */
-            len1 = find_longest_match(&dist1, src, src_len, hash_next, i + 1);
-            if (len1 > len)
-                goto no_match;
-        }
-        if (len < MATCH_LEN_MIN) {
-        no_match:
-            *q++ = src[i];
-            i++;
-        } else if (len <= (3 + 15) && dist < (1 << 10)) {
-            v = 0x8000 | ((len - 3) << 10) | dist;
-            *q++ = v >> 8;
-            *q++ = v;
-            i += len;
-        } else if (len >= 4 && len <= (4 + 63) && dist < (1 << 16)) {
-            v = 0xc00000 | ((len - 4) << 16) | dist;
-            *q++ = v >> 16;
-            *q++ = v >> 8;
-            *q++ = v;
-            i += len;
-        } else {
-            goto no_match;
-        }
-    }
-    free(hash_next);
-    *pdst = dst;
-    return q - dst;
-}
-
-static int load_file(uint8_t **pbuf, const char *filename)
-{
-    FILE *f;
-    uint8_t *buf;
-    int buf_len;
-
-    f = fopen(filename, "rb");
-    if (!f) {
-        perror(filename);
-        exit(1);
-    }
-    fseek(f, 0, SEEK_END);
-    buf_len = ftell(f);
-    fseek(f, 0, SEEK_SET);
-    buf = malloc(buf_len + 1);
-    fread(buf, 1, buf_len, f);
-    buf[buf_len] = '\0';
-    fclose(f);
-    *pbuf = buf;
-    return buf_len;
-}
-
-static void save_file(const char *filename, const uint8_t *buf, int buf_len)
-{
-    FILE *f;
-    
-    f = fopen(filename, "wb");
-    if (!f) {
-        perror(filename);
-        exit(1);
-    }
-    fwrite(buf, 1, buf_len, f);
-    fclose(f);
-}
-
-static void save_c_source(const char *filename, const uint8_t *buf, int buf_len,
-                          const char *var_name)
-{
-    FILE *f;
-    int i;
-    
-    f = fopen(filename, "wb");
-    if (!f) {
-        perror(filename);
-        exit(1);
-    }
-    fprintf(f, "/* This file is automatically generated - do not edit */\n\n");
-    fprintf(f, "const uint8_t %s[] = {\n", var_name);
-    for(i = 0; i < buf_len; i++) {
-        fprintf(f, " 0x%02x,", buf[i]);
-        if ((i % 8) == 7 || (i == buf_len - 1))
-            fprintf(f, "\n");
-    }
-    fprintf(f, "};\n");
-    fclose(f);
-}
-
-#define DEFAULT_OUTPUT_FILENAME "out.js"
-
-void help(void)
-{
-    printf("jscompress version 1.0 Copyright (c) 2008-2018 Fabrice Bellard\n"
-           "usage: jscompress [options] filename\n"
-           "Javascript compressor\n"
-           "\n"
-           "-h          print this help\n"
-           "-n          do not compress spaces\n"
-           "-H          keep the first comment\n"
-           "-c          compress to file\n"
-           "-C name     compress to C source ('name' is the variable name)\n"
-           "-D symbol   define preprocessor symbol\n"
-           "-U symbol   undefine preprocessor symbol\n"
-           "-o outfile  set the output filename (default=%s)\n",
-           DEFAULT_OUTPUT_FILENAME);
-    exit(1);
-}
-
-int main(int argc, char **argv)
-{
-    int c, do_strip, keep_header, compress;
-    const char *out_filename, *c_var, *fname;
-    char tmpfilename[1024];
-
-    do_strip = 1;
-    keep_header = 0;
-    out_filename = DEFAULT_OUTPUT_FILENAME;
-    compress = 0;
-    c_var = NULL;
-    for(;;) {
-        c = getopt(argc, argv, "hno:HcC:D:U:");
-        if (c == -1)
-            break;
-        switch(c) {
-        case 'h':
-            help();
-            break;
-        case 'n':
-            do_strip = 0;
-            break;
-        case 'o':
-            out_filename = optarg;
-            break;
-        case 'H':
-            keep_header = 1;
-            break;
-        case 'c':
-            compress = 1;
-            break;
-        case 'C':
-            c_var = optarg;
-            compress = 1;
-            break;
-        case 'D':
-            define_symbol(optarg);
-            break;
-        case 'U':
-            undefine_symbol(optarg);
-            break;
-        }
-    }
-    if (optind >= argc)
-        help();
-
-    filename = argv[optind++];
-
-    if (compress) {
-#if defined(__ANDROID__)
-        /* XXX: use another directory ? */
-        snprintf(tmpfilename, sizeof(tmpfilename), "out.%d", getpid());
-#else
-        snprintf(tmpfilename, sizeof(tmpfilename), "/tmp/out.%d", getpid());
-#endif
-        fname = tmpfilename;
-    } else {
-        fname = out_filename;
-    }
-    js_compress(filename, fname, do_strip, keep_header);
-    
-    if (compress) {
-        uint8_t *buf1, *buf2; 
-        int buf1_len, buf2_len;
-        
-        buf1_len = load_file(&buf1, fname);
-        unlink(fname);
-        buf2_len = lz_compress(&buf2, buf1, buf1_len);
-        if (buf2_len < 0) {
-            fprintf(stderr, "Could not compress file (UTF8 chars are forbidden)\n");
-            exit(1);
-        }
-        
-        if (c_var) {
-            save_c_source(out_filename, buf2, buf2_len, c_var);
-        } else {
-            save_file(out_filename, buf2, buf2_len);
-        }
-        free(buf1);
-        free(buf2);
-    }
-    return 0;
-}
diff --git a/libbf.h b/libbf.h
index 6749b35c6907aa46c7ad9e225afdde5905fe82d1..4576bf8854f088d1414c6fc404f78ebf7148486f 100644 (file)
--- a/libbf.h
+++ b/libbf.h
@@ -27,7 +27,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#if defined(__x86_64__)
+#if INTPTR_MAX >= INT64_MAX
 #define LIMB_LOG2_BITS 6
 #else
 #define LIMB_LOG2_BITS 5
index bbb5e9d70169b593be175163f3e560f550a9c2b0..379bfc7a95d25aa40564bae81cbdbe6084ebb639 100644 (file)
@@ -75,7 +75,7 @@ typedef struct {
     int capture_count;
     int total_capture_count; /* -1 = not computed yet */
     int has_named_captures; /* -1 = don't know, 0 = no, 1 = yes */
-    void *mem_opaque;
+    void *opaque;
     DynBuf group_names;
     union {
         char error_msg[TMP_BUF_SIZE];
@@ -230,7 +230,7 @@ static int cr_init_char_range(REParseState *s, CharRange *cr, uint32_t c)
     invert = c & 1;
     c_pt = char_range_table[c >> 1];
     len = *c_pt++;
-    cr_init(cr, s->mem_opaque, lre_realloc);
+    cr_init(cr, s->opaque, lre_realloc);
     for(i = 0; i < len * 2; i++) {
         if (cr_add_point(cr, c_pt[i]))
             goto fail;
@@ -625,7 +625,7 @@ static int parse_unicode_property(REParseState *s, CharRange *cr,
     p++;
     q = name;
     while (is_unicode_char(*p)) {
-        if ((q - name) > sizeof(name) - 1)
+        if ((q - name) >= sizeof(name) - 1)
             goto unknown_property_name;
         *q++ = *p++;
     }
@@ -634,7 +634,7 @@ static int parse_unicode_property(REParseState *s, CharRange *cr,
     if (*p == '=') {
         p++;
         while (is_unicode_char(*p)) {
-            if ((q - value) > sizeof(value) - 1)
+            if ((q - value) >= sizeof(value) - 1)
                 return re_parse_error(s, "unknown unicode property value");
             *q++ = *p++;
         }
@@ -651,7 +651,7 @@ static int parse_unicode_property(REParseState *s, CharRange *cr,
     } else if (!strcmp(name, "Script_Extensions") || !strcmp(name, "scx")) {
         script_ext = TRUE;
     do_script:
-        cr_init(cr, s->mem_opaque, lre_realloc);
+        cr_init(cr, s->opaque, lre_realloc);
         ret = unicode_script(cr, value, script_ext);
         if (ret) {
             cr_free(cr);
@@ -661,7 +661,7 @@ static int parse_unicode_property(REParseState *s, CharRange *cr,
                 goto out_of_memory;
         }
     } else if (!strcmp(name, "General_Category") || !strcmp(name, "gc")) {
-        cr_init(cr, s->mem_opaque, lre_realloc);
+        cr_init(cr, s->opaque, lre_realloc);
         ret = unicode_general_category(cr, value);
         if (ret) {
             cr_free(cr);
@@ -671,7 +671,7 @@ static int parse_unicode_property(REParseState *s, CharRange *cr,
                 goto out_of_memory;
         }
     } else if (value[0] == '\0') {
-        cr_init(cr, s->mem_opaque, lre_realloc);
+        cr_init(cr, s->opaque, lre_realloc);
         ret = unicode_general_category(cr, name);
         if (ret == -1) {
             cr_free(cr);
@@ -864,7 +864,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
     CharRange cr1_s, *cr1 = &cr1_s;
     BOOL invert;
     
-    cr_init(cr, s->mem_opaque, lre_realloc);
+    cr_init(cr, s->opaque, lre_realloc);
     p = *pp;
     p++;    /* skip '[' */
     invert = FALSE;
@@ -1147,9 +1147,13 @@ static int re_parse_captures(REParseState *s, int *phas_named_captures,
                         }
                     }
                     capture_index++;
+                    if (capture_index >= CAPTURE_COUNT_MAX)
+                        goto done;
                 }
             } else {
                 capture_index++;
+                if (capture_index >= CAPTURE_COUNT_MAX)
+                    goto done;
             }
             break;
         case '\\':
@@ -1163,6 +1167,7 @@ static int re_parse_captures(REParseState *s, int *phas_named_captures,
             break;
         }
     }
+ done:
     if (capture_name)
         return -1;
     else
@@ -1734,6 +1739,9 @@ static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir)
 {
     int start, len, pos;
 
+    if (lre_check_stack_overflow(s->opaque, 0))
+        return re_parse_error(s, "stack overflow");
+    
     start = s->byte_code.size;
     if (re_parse_alternative(s, is_backward_dir))
         return -1;
@@ -1819,7 +1827,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
     BOOL is_sticky;
     
     memset(s, 0, sizeof(*s));
-    s->mem_opaque = opaque;
+    s->opaque = opaque;
     s->buf_ptr = (const uint8_t *)buf;
     s->buf_end = s->buf_ptr + buf_len;
     s->buf_start = s->buf_ptr;
index 493869e306d90d10b0317ca5d74298e1f22d705c..b7c5001a30fcff72816f90e0362469e5bfd51933 100644 (file)
@@ -2625,6 +2625,17 @@ function atanh(a)
     return 0.5 * log((1 + x) / (1 - x));
 }
 
+function sigmoid(x)
+{
+    x = Float(x);
+    return 1 / (1 + exp(-x));
+}
+
+function lerp(a, b, t)
+{
+    return a + (b - a) * t;
+}
+
 var idn = Matrix.idn;
 var diag = Matrix.diag;
 var trans = Matrix.trans;
index a353ad4426b83bcd6c05fd7c8debd5640225a82a..4c2279452ac730fc78bd163e91b9525097e29f02 100644 (file)
@@ -113,6 +113,7 @@ DEF(caller, "caller")
 DEF(_eval_, "<eval>")
 DEF(_ret_, "<ret>")
 DEF(_var_, "<var>")
+DEF(_arg_var_, "<arg_var>")
 DEF(_with_, "<with>")
 DEF(lastIndex, "lastIndex")
 DEF(target, "target")
index 00a7536d7774f6cb0b2e13848173000adfef146b..e8b81e910c325fefc8f4943e0444c9eb3730dd14 100644 (file)
@@ -623,6 +623,97 @@ static JSValue js_std_getenv(JSContext *ctx, JSValueConst this_val,
         return JS_NewString(ctx, str);
 }
 
+#if defined(_WIN32)
+static void setenv(const char *name, const char *value, int overwrite)
+{
+    char *str;
+    size_t name_len, value_len;
+    name_len = strlen(name);
+    value_len = strlen(value);
+    str = malloc(name_len + 1 + value_len + 1);
+    memcpy(str, name, name_len);
+    str[name_len] = '=';
+    memcpy(str + name_len + 1, value, value_len);
+    str[name_len + 1 + value_len] = '\0';
+    _putenv(str);
+    free(str);
+}
+
+static void unsetenv(const char *name)
+{
+    setenv(name, "", TRUE);
+}
+#endif /* _WIN32 */
+
+static JSValue js_std_setenv(JSContext *ctx, JSValueConst this_val,
+                           int argc, JSValueConst *argv)
+{
+    const char *name, *value;
+    name = JS_ToCString(ctx, argv[0]);
+    if (!name)
+        return JS_EXCEPTION;
+    value = JS_ToCString(ctx, argv[1]);
+    if (!value) {
+        JS_FreeCString(ctx, name);
+        return JS_EXCEPTION;
+    }
+    setenv(name, value, TRUE);
+    JS_FreeCString(ctx, name);
+    JS_FreeCString(ctx, value);
+    return JS_UNDEFINED;
+}
+
+static JSValue js_std_unsetenv(JSContext *ctx, JSValueConst this_val,
+                               int argc, JSValueConst *argv)
+{
+    const char *name;
+    name = JS_ToCString(ctx, argv[0]);
+    if (!name)
+        return JS_EXCEPTION;
+    unsetenv(name);
+    JS_FreeCString(ctx, name);
+    return JS_UNDEFINED;
+}
+
+/* return an object containing the list of the available environment
+   variables. */
+static JSValue js_std_getenviron(JSContext *ctx, JSValueConst this_val,
+                                 int argc, JSValueConst *argv)
+{
+    char **envp;
+    const char *name, *p, *value;
+    JSValue obj;
+    uint32_t idx;
+    size_t name_len;
+    JSAtom atom;
+    int ret;
+
+    obj = JS_NewObject(ctx);
+    if (JS_IsException(obj))
+        return JS_EXCEPTION;
+    envp = environ;
+    for(idx = 0; envp[idx] != NULL; idx++) {
+        name = envp[idx];
+        p = strchr(name, '=');
+        name_len = p - name;
+        if (!p)
+            continue;
+        value = p + 1;
+        atom = JS_NewAtomLen(ctx, name, name_len);
+        if (atom == JS_ATOM_NULL)
+            goto fail;
+        ret = JS_DefinePropertyValue(ctx, obj, atom, JS_NewString(ctx, value),
+                                     JS_PROP_C_W_E);
+        JS_FreeAtom(ctx, atom);
+        if (ret < 0)
+            goto fail;
+    }
+    return obj;
+ fail:
+    JS_FreeValue(ctx, obj);
+    return JS_EXCEPTION;
+}
+
 static JSValue js_std_gc(JSContext *ctx, JSValueConst this_val,
                          int argc, JSValueConst *argv)
 {
@@ -1395,6 +1486,9 @@ static const JSCFunctionListEntry js_std_funcs[] = {
     JS_CFUNC_DEF("evalScript", 1, js_evalScript ),
     JS_CFUNC_DEF("loadScript", 1, js_loadScript ),
     JS_CFUNC_DEF("getenv", 1, js_std_getenv ),
+    JS_CFUNC_DEF("setenv", 1, js_std_setenv ),
+    JS_CFUNC_DEF("unsetenv", 1, js_std_unsetenv ),
+    JS_CFUNC_DEF("getenviron", 1, js_std_getenviron ),
     JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ),
     JS_CFUNC_DEF("loadFile", 1, js_std_loadFile ),
     JS_CFUNC_DEF("strerror", 1, js_std_strerror ),
@@ -1412,7 +1506,6 @@ static const JSCFunctionListEntry js_std_funcs[] = {
     JS_PROP_INT32_DEF("SEEK_CUR", SEEK_CUR, JS_PROP_CONFIGURABLE ),
     JS_PROP_INT32_DEF("SEEK_END", SEEK_END, JS_PROP_CONFIGURABLE ),
     JS_OBJECT_DEF("Error", js_std_error_props, countof(js_std_error_props), JS_PROP_CONFIGURABLE),
-    /* setenv, ... */
 };
     
 static const JSCFunctionListEntry js_std_file_proto_funcs[] = {
index 387363c370eac3770449a5869316767aa26661c9..c731a14a9cefe9f24d0b33278bb7f095efc80b8f 100644 (file)
@@ -114,7 +114,7 @@ DEF(    check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */
 DEF(      add_brand, 1, 2, 0, none) /* this_obj home_obj -> */
 DEF(   return_async, 1, 1, 0, none)
 DEF(          throw, 1, 1, 0, none)
-DEF(      throw_var, 6, 0, 0, atom_u8)
+DEF(    throw_error, 6, 0, 0, atom_u8)
 DEF(           eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */
 DEF(     apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */
 DEF(         regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
@@ -205,16 +205,15 @@ DEF(   for_of_start, 1, 1, 3, none)
 DEF(for_await_of_start, 1, 1, 3, none)
 DEF(    for_in_next, 1, 1, 3, none)
 DEF(    for_of_next, 2, 3, 5, u8)
-DEF(for_await_of_next, 1, 3, 4, none)
+DEF(iterator_check_object, 1, 1, 1, none)
 DEF(iterator_get_value_done, 1, 1, 2, none)
 DEF( iterator_close, 1, 3, 0, none)
 DEF(iterator_close_return, 1, 4, 4, none)
-DEF(async_iterator_close, 1, 3, 2, none)
-DEF(async_iterator_next, 1, 4, 4, none)
-DEF(async_iterator_get, 2, 4, 5, u8)
+DEF(  iterator_next, 1, 4, 4, none)
+DEF(  iterator_call, 2, 4, 5, u8)
 DEF(  initial_yield, 1, 0, 0, none)
 DEF(          yield, 1, 1, 2, none)
-DEF(     yield_star, 1, 2, 2, none)
+DEF(     yield_star, 1, 1, 2, none)
 DEF(async_yield_star, 1, 1, 2, none)
 DEF(          await, 1, 1, 1, none)
 
@@ -266,8 +265,6 @@ DEF(            nop, 1, 0, 0, none)
 
 /* temporary opcodes: never emitted in the final bytecode */
 
-def(set_arg_valid_upto, 3, 0, 0, arg) /* emitted in phase 1, removed in phase 2 */
-
 def(    enter_scope, 3, 0, 0, u16)  /* emitted in phase 1, removed in phase 2 */
 def(    leave_scope, 3, 0, 0, u16)  /* emitted in phase 1, removed in phase 2 */
 
index efc1d54aad5db7e3a75d6e204c5abb39af30d24d..a39ff8f66cfcbc35f787b29b269136c8b1a85893 100644 (file)
--- a/quickjs.c
+++ b/quickjs.c
@@ -199,7 +199,7 @@ typedef enum JSErrorEnum {
 } JSErrorEnum;
 
 #define JS_MAX_LOCAL_VARS 65536
-#define JS_STACK_SIZE_MAX 65536
+#define JS_STACK_SIZE_MAX 65534
 #define JS_STRING_LEN_MAX ((1 << 30) - 1)
 
 #define __exception __attribute__((warn_unused_result))
@@ -506,14 +506,17 @@ typedef struct JSClosureVar {
     uint8_t is_arg : 1;
     uint8_t is_const : 1;
     uint8_t is_lexical : 1;
-    uint8_t var_kind : 3; /* see JSVarKindEnum */
-    /* 9 bits available */
+    uint8_t var_kind : 4; /* see JSVarKindEnum */
+    /* 8 bits available */
     uint16_t var_idx; /* is_local = TRUE: index to a normal variable of the
                     parent function. otherwise: index to a closure
                     variable of the parent function */
     JSAtom var_name;
 } JSClosureVar;
 
+#define ARG_SCOPE_INDEX 1
+#define ARG_SCOPE_END (-2)
+
 typedef struct JSVarScope {
     int parent;  /* index into fd->scopes of the enclosing scope */
     int first;   /* index into fd->vars of the last variable in this scope */
@@ -526,6 +529,7 @@ typedef enum {
     JS_VAR_NEW_FUNCTION_DECL, /* lexical var with async/generator
                                  function declaration */
     JS_VAR_CATCH,
+    JS_VAR_FUNCTION_NAME, /* function expression name */
     JS_VAR_PRIVATE_FIELD,
     JS_VAR_PRIVATE_METHOD,
     JS_VAR_PRIVATE_GETTER,
@@ -533,12 +537,21 @@ typedef enum {
     JS_VAR_PRIVATE_GETTER_SETTER, /* must come after JS_VAR_PRIVATE_SETTER */
 } JSVarKindEnum;
 
+/* XXX: could use a different structure in bytecode functions to save
+   memory */
 typedef struct JSVarDef {
     JSAtom var_name;
-    int scope_level;   /* index into fd->scopes of this variable lexical scope */
-    int scope_next;    /* index into fd->vars of the next variable in the
-                        * same or enclosing lexical scope */
-    uint8_t is_func_var : 1; /* used for the function self reference */
+    /* index into fd->scopes of this variable lexical scope */
+    int scope_level;
+    /* during compilation: 
+        - if scope_level = 0: scope in which the variable is defined
+        - if scope_level != 0: index into fd->vars of the next
+          variable in the same or enclosing lexical scope
+       in a bytecode function:
+       index into fd->vars of the next
+       variable in the same or enclosing lexical scope
+    */
+    int scope_next;    
     uint8_t is_const : 1;
     uint8_t is_lexical : 1;
     uint8_t is_captured : 1;
@@ -548,7 +561,9 @@ typedef struct JSVarDef {
        JS_VAR_FUNCTION_DECL/JS_VAR_NEW_FUNCTION_DECL or scope level of
        the definition of the 'var' variables (they have scope_level =
        0) */
-    int func_pool_or_scope_idx : 24; /* only used during compilation */
+    int func_pool_idx : 24; /* only used during compilation : index in
+                               the constant pool for hoisted function
+                               definition */
 } JSVarDef;
 
 /* for the encoding of the pc2line table */
@@ -855,7 +870,7 @@ struct JSObject {
             uint8_t extensible : 1;
             uint8_t free_mark : 1; /* only used when freeing objects with cycles */
             uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */
-            uint8_t fast_array : 1; /* TRUE if u.array is used for get/put */
+            uint8_t fast_array : 1; /* TRUE if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */
             uint8_t is_constructor : 1; /* TRUE if object is a constructor function */
             uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */
             uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */
@@ -1000,7 +1015,7 @@ static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_o
 static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
                              int argc, JSValueConst *argv);
 static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
-                                            JSValue val);
+                                            JSValue val, BOOL is_array_ctor);
 static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
                              JSValueConst val, int flags, int scope_idx);
 JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
@@ -1226,11 +1241,11 @@ static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,
                           JSGCObjectTypeEnum type);
 static void remove_gc_object(JSGCObjectHeader *h);
 static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s);
-static int js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);
-static int js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,
+static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);
+static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,
                                  void *opaque);
-static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,
-                                          JSAtom atom, void *opaque);
+static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p,
+                                               JSAtom atom, void *opaque);
 void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag);
 
 static const JSClassExoticMethods js_arguments_exotic_methods;
@@ -6710,6 +6725,21 @@ static JSValue JS_ThrowReferenceErrorUninitialized(JSContext *ctx, JSAtom name)
                                   JS_AtomGetStr(ctx, buf, sizeof(buf), name));
 }
 
+static JSValue JS_ThrowReferenceErrorUninitialized2(JSContext *ctx,
+                                                    JSFunctionBytecode *b,
+                                                    int idx, BOOL is_ref)
+{
+    JSAtom atom = JS_ATOM_NULL;
+    if (is_ref) {
+        atom = b->closure_var[idx].var_name;
+    } else {
+        /* not present if the function is stripped and contains no eval() */
+        if (b->vardefs)
+            atom = b->vardefs[b->arg_count + idx].var_name;
+    }
+    return JS_ThrowReferenceErrorUninitialized(ctx, atom);
+}
+
 static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id)
 {
     JSRuntime *rt = ctx->rt;
@@ -6986,25 +7016,37 @@ int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj)
     return JS_OrdinaryIsInstanceOf(ctx, val, obj);
 }
 
-typedef int JSAutoInitFunc(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);
+/* return the value associated to the autoinit property or an exception */
+typedef JSValue JSAutoInitFunc(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);
 
 static JSAutoInitFunc *js_autoinit_func_table[] = {
     js_instantiate_prototype, /* JS_AUTOINIT_ID_PROTOTYPE */
     js_module_ns_autoinit, /* JS_AUTOINIT_ID_MODULE_NS */
-    JS_InstantiateFunctionListItem, /* JS_AUTOINIT_ID_PROP */
+    JS_InstantiateFunctionListItem2, /* JS_AUTOINIT_ID_PROP */
 };
 
+/* warning: 'prs' is reallocated after it */
 static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop,
-                               JSProperty *pr)
+                               JSProperty *pr, JSShapeProperty *prs)
 {
-    int ret;
+    JSValue val;
     JSContext *realm;
     JSAutoInitFunc *func;
-    
+
+    if (js_shape_prepare_update(ctx, p, &prs))
+        return -1;
+
     realm = js_autoinit_get_realm(pr);
     func = js_autoinit_func_table[js_autoinit_get_id(pr)];
-    ret = func(realm, p, prop, pr->u.init.opaque);
-    return ret;
+    /* 'func' shall not modify the object properties 'pr' */
+    val = func(realm, p, prop, pr->u.init.opaque);
+    js_autoinit_free(ctx->rt, pr);
+    prs->flags &= ~JS_PROP_TMASK;
+    pr->u.value = JS_UNDEFINED;
+    if (JS_IsException(val))
+        return -1;
+    pr->u.value = val;
+    return 0;
 }
 
 JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
@@ -7075,7 +7117,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
                     return JS_DupValue(ctx, val);
                 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
                     /* Instantiate property and retry */
-                    if (JS_AutoInitProperty(ctx, p, prop, pr))
+                    if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
                         return JS_EXCEPTION;
                     continue;
                 }
@@ -7093,7 +7135,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
                         return JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);
                     } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
                                p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
-                        goto typed_array_oob;
+                        return JS_UNDEFINED;
                     }
                 } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
                            p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
@@ -7102,9 +7144,6 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
                     if (ret != 0) {
                         if (ret < 0)
                             return JS_EXCEPTION;
-                    typed_array_oob:
-                        if (typed_array_is_detached(ctx, p))
-                            return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
                         return JS_UNDEFINED;
                     }
                 }
@@ -7337,6 +7376,22 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
     return 0;
 }
 
+static uint32_t js_string_obj_get_length(JSContext *ctx,
+                                         JSValueConst obj)
+{
+    JSObject *p;
+    JSString *p1;
+    uint32_t len = 0;
+
+    /* This is a class exotic method: obj class_id is JS_CLASS_STRING */
+    p = JS_VALUE_GET_OBJ(obj);
+    if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {
+        p1 = JS_VALUE_GET_STRING(p->u.object_data);
+        len = p1->len;
+    }
+    return len;
+}
+
 static int num_keys_cmp(const void *p1, const void *p2, void *opaque)
 {
     JSContext *ctx = opaque;
@@ -7379,7 +7434,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
     JSPropertyEnum *tab_atom, *tab_exotic;
     JSAtom atom;
     uint32_t num_keys_count, str_keys_count, sym_keys_count, atom_count;
-    uint32_t num_index, str_index, sym_index, exotic_count;
+    uint32_t num_index, str_index, sym_index, exotic_count, exotic_keys_count;
     BOOL is_enumerable, num_sorted;
     uint32_t num_key;
     JSAtomKindEnum kind;
@@ -7392,6 +7447,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
     num_keys_count = 0;
     str_keys_count = 0;
     sym_keys_count = 0;
+    exotic_keys_count = 0;
     exotic_count = 0;
     tab_exotic = NULL;
     sh = p->shape;
@@ -7425,19 +7481,13 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
 
     if (p->is_exotic) {
         if (p->fast_array) {
-            /* the implicit GetOwnProperty raises an exception if the
-               typed array is detached */
-            if ((flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY)) &&
-                 (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
-                  p->class_id <= JS_CLASS_FLOAT64_ARRAY) &&
-                 typed_array_is_detached(ctx, p) &&
-                typed_array_get_length(ctx, p) != 0) {
-                JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
-                return -1;
-            }
             if (flags & JS_GPN_STRING_MASK) {
                 num_keys_count += p->u.array.count;
             }
+        } else if (p->class_id == JS_CLASS_STRING) {
+            if (flags & JS_GPN_STRING_MASK) {
+                num_keys_count += js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
+            }
         } else {
             const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
             if (em && em->get_own_property_names) {
@@ -7466,13 +7516,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
                             tab_exotic[i].is_enumerable = is_enumerable;
                         }
                         if (!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) {
-                            if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) {
-                                num_keys_count++;
-                            } else if (kind == JS_ATOM_KIND_STRING) {
-                                str_keys_count++;
-                            } else {
-                                sym_keys_count++;
-                            }
+                            exotic_keys_count++;
                         }
                     }
                 }
@@ -7482,7 +7526,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
 
     /* fill them */
 
-    atom_count = num_keys_count + str_keys_count + sym_keys_count;
+    atom_count = num_keys_count + str_keys_count + sym_keys_count + exotic_keys_count;
     /* avoid allocating 0 bytes */
     tab_atom = js_malloc(ctx, sizeof(tab_atom[0]) * max_int(atom_count, 1));
     if (!tab_atom) {
@@ -7518,12 +7562,19 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
     }
 
     if (p->is_exotic) {
+        int len;
         if (p->fast_array) {
             if (flags & JS_GPN_STRING_MASK) {
-                for(i = 0; i < p->u.array.count; i++) {
+                len = p->u.array.count;
+                goto add_array_keys;
+            }
+        } else if (p->class_id == JS_CLASS_STRING) {
+            if (flags & JS_GPN_STRING_MASK) {
+                len = js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
+            add_array_keys:
+                for(i = 0; i < len; i++) {
                     tab_atom[num_index].atom = __JS_AtomFromUInt32(i);
                     if (tab_atom[num_index].atom == JS_ATOM_NULL) {
-                        js_free_prop_enum(ctx, tab_exotic, exotic_count);
                         js_free_prop_enum(ctx, tab_atom, num_index);
                         return -1;
                     }
@@ -7531,30 +7582,23 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
                     num_index++;
                 }
             }
-        }
-        if (exotic_count > 0) {
+        } else {
+            /* Note: exotic keys are not reordered and comes after the object own properties. */
             for(i = 0; i < exotic_count; i++) {
                 atom = tab_exotic[i].atom;
                 is_enumerable = tab_exotic[i].is_enumerable;
                 kind = JS_AtomGetKind(ctx, atom);
                 if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) &&
                     ((flags >> kind) & 1) != 0) {
-                    if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) {
-                        j = num_index++;
-                        num_sorted = FALSE;
-                    } else if (kind == JS_ATOM_KIND_STRING) {
-                        j = str_index++;
-                    } else {
-                        j = sym_index++;
-                    }
-                    tab_atom[j].atom = atom;
-                    tab_atom[j].is_enumerable = is_enumerable;
+                    tab_atom[sym_index].atom = atom;
+                    tab_atom[sym_index].is_enumerable = is_enumerable;
+                    sym_index++;
                 } else {
                     JS_FreeAtom(ctx, atom);
                 }
             }
+            js_free(ctx, tab_exotic);
         }
-        js_free(ctx, tab_exotic);
     }
 
     assert(num_index == num_keys_count);
@@ -7614,7 +7658,7 @@ retry:
                     desc->value = JS_DupValue(ctx, val);
                 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
                     /* Instantiate property and retry */
-                    if (JS_AutoInitProperty(ctx, p, prop, pr))
+                    if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
                         return -1;
                     goto retry;
                 }
@@ -7642,10 +7686,8 @@ retry:
                 idx = __JS_AtomToUInt32(prop);
                 if (idx < p->u.array.count) {
                     if (desc) {
-                        desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE;
-                        if (p->class_id == JS_CLASS_ARRAY ||
-                            p->class_id == JS_CLASS_ARGUMENTS)
-                            desc->flags |= JS_PROP_CONFIGURABLE;
+                        desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE |
+                            JS_PROP_CONFIGURABLE;
                         desc->getter = JS_UNDEFINED;
                         desc->setter = JS_UNDEFINED;
                         desc->value = JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);
@@ -7653,19 +7695,6 @@ retry:
                     return TRUE;
                 }
             }
-            if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
-                p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
-                int ret;
-                ret = JS_AtomIsNumericIndex(ctx, prop);
-                if (ret != 0) {
-                    if (ret < 0)
-                        return -1;
-                    if (typed_array_is_detached(ctx, p)) {
-                        JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
-                        return -1;
-                    }
-                }
-            }
         } else {
             const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
             if (em && em->get_own_property) {
@@ -7748,8 +7777,6 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop)
             if (ret != 0) {
                 if (ret < 0)
                     return -1;
-                /* the detached array test was done in
-                   JS_GetOwnPropertyInternal() */
                 return FALSE;
             }
         }
@@ -8074,7 +8101,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom)
                         return -1;
                     goto redo;
                 } else {
-                    return FALSE; /* not configurable */
+                    return FALSE;
                 }
             }
         } else {
@@ -8114,15 +8141,19 @@ static int call_setter(JSContext *ctx, JSObject *setter,
 }
 
 /* set the array length and remove the array elements if necessary. */
-static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, int flags)
+static int set_array_length(JSContext *ctx, JSObject *p, JSValue val,
+                            int flags)
 {
     uint32_t len, idx, cur_len;
     int i, ret;
 
     /* Note: this call can reallocate the properties of 'p' */
-    ret = JS_ToArrayLengthFree(ctx, &len, val);
+    ret = JS_ToArrayLengthFree(ctx, &len, val, FALSE);
     if (ret)
         return -1;
+    /* JS_ToArrayLengthFree() must be done before the read-only test */
+    if (unlikely(!(p->shape->prop[0].flags & JS_PROP_WRITABLE)))
+        return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length);
 
     if (likely(p->fast_array)) {
         uint32_t old_len = p->u.array.count;
@@ -8382,8 +8413,7 @@ retry:
             /* fast case */
             set_value(ctx, &pr->u.value, val);
             return TRUE;
-        } else if ((prs->flags & (JS_PROP_LENGTH | JS_PROP_WRITABLE)) ==
-                   (JS_PROP_LENGTH | JS_PROP_WRITABLE)) {
+        } else if (prs->flags & JS_PROP_LENGTH) {
             assert(p->class_id == JS_CLASS_ARRAY);
             assert(prop == JS_ATOM_length);
             return set_array_length(ctx, p, val, flags);
@@ -8399,7 +8429,7 @@ retry:
             return TRUE;
         } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
             /* Instantiate property and retry (potentially useless) */
-            if (JS_AutoInitProperty(ctx, p, prop, pr)) {
+            if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) {
                 JS_FreeValue(ctx, val);
                 return -1;
             }
@@ -8437,10 +8467,6 @@ retry:
                         JS_FreeValue(ctx, val);
                         if (JS_IsException(val))
                             return -1;
-                        if (typed_array_is_detached(ctx, p1)) {
-                            JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
-                            return -1;
-                        }
                         return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");
                     }
                 }
@@ -8509,7 +8535,7 @@ retry:
                 return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags);
             } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
                 /* Instantiate property and retry (potentially useless) */
-                if (JS_AutoInitProperty(ctx, p1, prop, pr))
+                if (JS_AutoInitProperty(ctx, p1, prop, pr, prs))
                     return -1;
                 goto retry2;
             } else if (!(prs->flags & JS_PROP_WRITABLE)) {
@@ -8677,12 +8703,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
                 return -1;
             if (unlikely(idx >= (uint32_t)p->u.array.count)) {
             ta_out_of_bound:
-                if (typed_array_is_detached(ctx, p)) {
-                    JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
-                    return -1;
-                } else {
-                    return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");
-                }
+                return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");
             }
             p->u.array.u.double_ptr[idx] = d;
             break;
@@ -8967,13 +8988,32 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
  redo_prop_update:
     prs = find_own_property(&pr, p, prop);
     if (prs) {
+        /* the range of the Array length property is always tested before */
+        if ((prs->flags & JS_PROP_LENGTH) && (flags & JS_PROP_HAS_VALUE)) {
+            uint32_t array_length;
+            if (JS_ToArrayLengthFree(ctx, &array_length,
+                                     JS_DupValue(ctx, val), FALSE)) {
+                return -1;
+            }
+            /* this code relies on the fact that Uint32 are never allocated */
+            val = (JSValueConst)JS_NewUint32(ctx, array_length);
+            /* prs may have been modified */
+            prs = find_own_property(&pr, p, prop);
+            assert(prs != NULL);
+        }
         /* property already exists */
         if (!check_define_prop_flags(prs->flags, flags)) {
         not_configurable:
             return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable");
         }
 
-    retry:
+        if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
+            /* Instantiate property and retry */
+            if (JS_AutoInitProperty(ctx, p, prop, pr, prs))
+                return -1;
+            goto redo_prop_update;
+        }
+
         if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE |
                      JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {
             if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {
@@ -8996,14 +9036,6 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
                     /* convert to getset */
                     if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
                         free_var_ref(ctx->rt, pr->u.var_ref);
-                    } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
-                        /* clear property and update */
-                        if (js_shape_prepare_update(ctx, p, &prs))
-                            return -1;
-                        js_autoinit_free(ctx->rt, pr);
-                        prs->flags &= ~JS_PROP_TMASK;
-                        pr->u.value = JS_UNDEFINED;
-                        goto retry;
                     } else {
                         JS_FreeValue(ctx, pr->u.value);
                     }
@@ -9051,39 +9083,17 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
                     pr->u.value = JS_UNDEFINED;
                 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
                     /* Note: JS_PROP_VARREF is always writable */
-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
-                    /* clear property and update */
-                    if (js_shape_prepare_update(ctx, p, &prs))
-                        return -1;
-                    js_autoinit_free(ctx->rt, pr);
-                    prs->flags &= ~JS_PROP_TMASK;
-                    pr->u.value = JS_UNDEFINED;
                 } else {
                     if ((prs->flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0 &&
-                        (flags & JS_PROP_HAS_VALUE) &&
-                        !js_same_value(ctx, val, pr->u.value)) {
-                        goto not_configurable;
+                        (flags & JS_PROP_HAS_VALUE)) {
+                        if (!js_same_value(ctx, val, pr->u.value)) {
+                            goto not_configurable;
+                        } else {
+                            return TRUE;
+                        }
                     }
                 }
-                if (prs->flags & JS_PROP_LENGTH) {
-                    if (flags & JS_PROP_HAS_VALUE) {
-                        res = set_array_length(ctx, p, JS_DupValue(ctx, val),
-                                               flags);
-                    } else {
-                        res = TRUE;
-                    }
-                    /* still need to reset the writable flag if needed.
-                       The JS_PROP_LENGTH is reset to have the correct
-                       read-only behavior in JS_SetProperty(). */
-                    if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) ==
-                        JS_PROP_HAS_WRITABLE) {
-                        prs = get_shape_prop(p->shape);
-                        if (js_update_property_flags(ctx, p, &prs,
-                                                     prs->flags & ~(JS_PROP_WRITABLE | JS_PROP_LENGTH)))
-                            return -1;
-                    }
-                    return res;
-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
+                if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
                     if (flags & JS_PROP_HAS_VALUE) {
                         if (p->class_id == JS_CLASS_MODULE_NS) {
                             /* JS_PROP_WRITABLE is always true for variable
@@ -9107,9 +9117,27 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
                         pr->u.value = val1;
                         prs->flags &= ~(JS_PROP_TMASK | JS_PROP_WRITABLE);
                     }
-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
-                    /* XXX: should never happen, type was reset above */
-                    abort();
+                } else if (prs->flags & JS_PROP_LENGTH) {
+                    if (flags & JS_PROP_HAS_VALUE) {
+                        /* Note: no JS code is executable because
+                           'val' is guaranted to be a Uint32 */
+                        res = set_array_length(ctx, p, JS_DupValue(ctx, val),
+                                               flags);
+                    } else {
+                        res = TRUE;
+                    }
+                    /* still need to reset the writable flag if
+                       needed.  The JS_PROP_LENGTH is kept because the
+                       Uint32 test is still done if the length
+                       property is read-only. */
+                    if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) ==
+                        JS_PROP_HAS_WRITABLE) {
+                        prs = get_shape_prop(p->shape);
+                        if (js_update_property_flags(ctx, p, &prs,
+                                                     prs->flags & ~JS_PROP_WRITABLE))
+                            return -1;
+                    }
+                    return res;
                 } else {
                     if (flags & JS_PROP_HAS_VALUE) {
                         JS_FreeValue(ctx, pr->u.value);
@@ -9194,9 +9222,9 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
             typed_array_oob:
                 return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound index in typed array");
             }
-            prop_flags = get_prop_flags(flags, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE);
+            prop_flags = get_prop_flags(flags, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
             if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET) ||
-                prop_flags != (JS_PROP_ENUMERABLE | JS_PROP_WRITABLE)) {
+                prop_flags != (JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE)) {
                 return JS_ThrowTypeErrorOrFalse(ctx, flags, "invalid descriptor flags");
             }
             if (flags & JS_PROP_HAS_VALUE) {
@@ -9581,9 +9609,8 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,
         set_value(ctx, &pr->u.value, val);
         return 0;
     }
-
     flags = JS_PROP_THROW_STRICT;
-    if (flag != 2 && is_strict_mode(ctx))
+    if (is_strict_mode(ctx)) 
         flags |= JS_PROP_NO_ADD;
     return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags);
 }
@@ -10918,11 +10945,10 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val)
 }
 
 static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
-                                            JSValue val)
+                                            JSValue val, BOOL is_array_ctor)
 {
     uint32_t tag, len;
 
- redo:
     tag = JS_VALUE_GET_TAG(val);
     switch(tag) {
     case JS_TAG_INT:
@@ -10959,16 +10985,36 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
             double d;
             d = JS_VALUE_GET_FLOAT64(val);
             len = (uint32_t)d;
-            if (len != d) {
-            fail:
-                JS_ThrowRangeError(ctx, "invalid array length");
-                return -1;
-            }
+            if (len != d)
+                goto fail;
         } else {
-            val = JS_ToNumberFree(ctx, val);
-            if (JS_IsException(val))
-                return -1;
-            goto redo;
+            uint32_t len1;
+
+            if (is_array_ctor) {
+                val = JS_ToNumberFree(ctx, val);
+                if (JS_IsException(val))
+                    return -1;
+                /* cannot recurse because val is a number */
+                if (JS_ToArrayLengthFree(ctx, &len, val, TRUE))
+                    return -1;
+            } else {
+                /* legacy behavior: must do the conversion twice and compare */
+                if (JS_ToUint32(ctx, &len, val)) {
+                    JS_FreeValue(ctx, val);
+                    return -1;
+                }
+                val = JS_ToNumberFree(ctx, val);
+                if (JS_IsException(val))
+                    return -1;
+                /* cannot recurse because val is a number */
+                if (JS_ToArrayLengthFree(ctx, &len1, val, FALSE))
+                    return -1;
+                if (len1 != len) {
+                fail:
+                    JS_ThrowRangeError(ctx, "invalid array length");
+                    return -1;
+                }
+            }
         }
         break;
     }
@@ -15031,15 +15077,6 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
             if (prs->flags & JS_PROP_ENUMERABLE)
                 goto normal_case;
         }
-        /* the implicit GetOwnProperty raises an exception if the
-           typed array is detached */
-        if ((p->class_id >= JS_CLASS_UINT8C_ARRAY &&
-             p->class_id <= JS_CLASS_FLOAT64_ARRAY) &&
-            typed_array_is_detached(ctx, p) &&
-            typed_array_get_length(ctx, p) != 0) {
-            JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
-            goto fail;
-        }
         /* for fast arrays, we only store the number of elements */
         it->is_array = TRUE;
         it->array_length = p->u.array.count;
@@ -15349,16 +15386,6 @@ static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
     return 0;
 }
 
-static __exception int js_for_await_of_next(JSContext *ctx, JSValue *sp)
-{
-    JSValue result;
-    result = JS_Call(ctx, sp[-2], sp[-3], 0, NULL);
-    if (JS_IsException(result))
-        return -1;
-    sp[0] = result;
-    return 0;
-}
-
 static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValueConst obj,
                                            BOOL *pdone)
 {
@@ -15663,7 +15690,7 @@ static JSValue js_closure2(JSContext *ctx, JSValue func_obj,
     return JS_EXCEPTION;
 }
 
-static int js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque)
+static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque)
 {
     JSValue obj, this_val;
     int ret;
@@ -15671,15 +15698,17 @@ static int js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, vo
     this_val = JS_MKPTR(JS_TAG_OBJECT, p);
     obj = JS_NewObject(ctx);
     if (JS_IsException(obj))
-        return -1;
+        return JS_EXCEPTION;
     set_cycle_flag(ctx, obj);
     set_cycle_flag(ctx, this_val);
     ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_constructor,
                                  JS_DupValue(ctx, this_val),
                                  JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
-    if (JS_DefinePropertyValue(ctx, this_val, atom, obj, JS_PROP_WRITABLE) < 0 || ret < 0)
-        return -1;
-    return 0;
+    if (ret < 0) {
+        JS_FreeValue(ctx, obj);
+        return JS_EXCEPTION;
+    }
+    return obj;
 }
 
 static const uint16_t func_kind_to_class_id[] = {
@@ -16645,11 +16674,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
             JS_Throw(ctx, *--sp);
             goto exception;
 
-        CASE(OP_throw_var):
+        CASE(OP_throw_error):
 #define JS_THROW_VAR_RO             0
 #define JS_THROW_VAR_REDECL         1
 #define JS_THROW_VAR_UNINITIALIZED  2
-#define JS_THROW_VAR_DELETE_SUPER   3
+#define JS_THROW_ERROR_DELETE_SUPER   3
+#define JS_THROW_ERROR_ITERATOR_THROW 4
             {
                 JSAtom atom;
                 int type;
@@ -16665,8 +16695,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
                 if (type == JS_THROW_VAR_UNINITIALIZED)
                     JS_ThrowReferenceErrorUninitialized(ctx, atom);
                 else
-                if (type == JS_THROW_VAR_DELETE_SUPER)
+                if (type == JS_THROW_ERROR_DELETE_SUPER)
                     JS_ThrowReferenceError(ctx, "unsupported reference to 'super'");
+                else
+                if (type == JS_THROW_ERROR_ITERATOR_THROW)
+                    JS_ThrowTypeError(ctx, "iterator does not have a throw method");
                 else
                     JS_ThrowInternalError(ctx, "invalid throw var type %d", type);
             }
@@ -16995,7 +17028,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
                 pc += 2;
                 val = *var_refs[idx]->pvalue;
                 if (unlikely(JS_IsUninitialized(val))) {
-                    JS_ThrowReferenceErrorUninitialized(ctx, JS_ATOM_NULL);
+                    JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE);
                     goto exception;
                 }
                 sp[0] = JS_DupValue(ctx, val);
@@ -17008,7 +17041,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
                 idx = get_u16(pc);
                 pc += 2;
                 if (unlikely(JS_IsUninitialized(*var_refs[idx]->pvalue))) {
-                    JS_ThrowReferenceErrorUninitialized(ctx, JS_ATOM_NULL);
+                    JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE);
                     goto exception;
                 }
                 set_value(ctx, var_refs[idx]->pvalue, sp[-1]);
@@ -17021,7 +17054,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
                 idx = get_u16(pc);
                 pc += 2;
                 if (unlikely(!JS_IsUninitialized(*var_refs[idx]->pvalue))) {
-                    JS_ThrowReferenceErrorUninitialized(ctx, JS_ATOM_NULL);
+                    JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE);
                     goto exception;
                 }
                 set_value(ctx, var_refs[idx]->pvalue, sp[-1]);
@@ -17042,7 +17075,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
                 idx = get_u16(pc);
                 pc += 2;
                 if (unlikely(JS_IsUninitialized(var_buf[idx]))) {
-                    JS_ThrowReferenceErrorUninitialized(ctx, JS_ATOM_NULL);
+                    JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, FALSE);
                     goto exception;
                 }
                 sp[0] = JS_DupValue(ctx, var_buf[idx]);
@@ -17055,7 +17088,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
                 idx = get_u16(pc);
                 pc += 2;
                 if (unlikely(JS_IsUninitialized(var_buf[idx]))) {
-                    JS_ThrowReferenceErrorUninitialized(ctx, JS_ATOM_NULL);
+                    JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, FALSE);
                     goto exception;
                 }
                 set_value(ctx, &var_buf[idx], sp[-1]);
@@ -17294,16 +17327,17 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
             sp += 1;
             *sp++ = JS_NewCatchOffset(ctx, 0);
             BREAK;
-        CASE(OP_for_await_of_next):
-            if (js_for_await_of_next(ctx, sp))
-                goto exception;
-            sp += 1;
-            BREAK;
         CASE(OP_iterator_get_value_done):
             if (js_iterator_get_value_done(ctx, sp))
                 goto exception;
             sp += 1;
             BREAK;
+        CASE(OP_iterator_check_object):
+            if (unlikely(!JS_IsObject(sp[-1]))) {
+                JS_ThrowTypeError(ctx, "iterator must return an object");
+                goto exception;
+            }
+            BREAK;
 
         CASE(OP_iterator_close):
             /* iter_obj next catch_offset -> */
@@ -17340,37 +17374,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
             }
             BREAK;
 
-        CASE(OP_async_iterator_close):
-            /* iter_obj next catch_offset -> value flag */
-            {
-                JSValue ret, method;
-                int ret_flag;
-                sp--; /* remove the catch offset */
-                method = JS_GetProperty(ctx, sp[-2], JS_ATOM_return);
-                if (JS_IsException(method))
-                    goto exception;
-                if (JS_IsUndefined(method) || JS_IsNull(method)) {
-                    ret = JS_UNDEFINED;
-                    ret_flag = TRUE;
-                } else {
-                    ret = JS_CallFree(ctx, method, sp[-2], 0, NULL);
-                    if (JS_IsException(ret))
-                        goto exception;
-                    if (!JS_IsObject(ret)) {
-                        JS_FreeValue(ctx, ret);
-                        JS_ThrowTypeErrorNotAnObject(ctx);
-                        goto exception;
-                    }
-                    ret_flag = FALSE;
-                }
-                JS_FreeValue(ctx, sp[-2]);
-                JS_FreeValue(ctx, sp[-1]);
-                sp[-2] = ret;
-                sp[-1] = JS_NewBool(ctx, ret_flag);
-            }
-            BREAK;
-
-        CASE(OP_async_iterator_next):
+        CASE(OP_iterator_next):
             /* stack: iter_obj next catch_offset val */
             {
                 JSValue ret;
@@ -17383,26 +17387,28 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
             }
             BREAK;
 
-        CASE(OP_async_iterator_get):
+        CASE(OP_iterator_call):
             /* stack: iter_obj next catch_offset val */
             {
                 JSValue method, ret;
                 BOOL ret_flag;
                 int flags;
                 flags = *pc++;
-                /* XXX: use another opcode such as OP_throw_var */
-                if (flags == 2) {
-                    JS_ThrowTypeError(ctx, "iterator does not have a throw method");
-                    goto exception;
-                }
-                method = JS_GetProperty(ctx, sp[-4], flags ? JS_ATOM_throw : JS_ATOM_return);
+                method = JS_GetProperty(ctx, sp[-4], (flags & 1) ?
+                                        JS_ATOM_throw : JS_ATOM_return);
                 if (JS_IsException(method))
                     goto exception;
                 if (JS_IsUndefined(method) || JS_IsNull(method)) {
                     ret_flag = TRUE;
                 } else {
-                    ret = JS_CallFree(ctx, method, sp[-4],
-                                      1, (JSValueConst *)(sp - 1));
+                    if (flags & 2) {
+                        /* no argument */
+                        ret = JS_CallFree(ctx, method, sp[-4],
+                                          0, NULL);
+                    } else {
+                        ret = JS_CallFree(ctx, method, sp[-4],
+                                          1, (JSValueConst *)(sp - 1));
+                    }
                     if (JS_IsException(ret))
                         goto exception;
                     JS_FreeValue(ctx, sp[-1]);
@@ -17728,7 +17734,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
 
         CASE(OP_put_ref_value):
             {
-                int ret;
+                int ret, flags;
+                flags = JS_PROP_THROW_STRICT;
                 if (unlikely(JS_IsUndefined(sp[-3]))) {
                     if (is_strict_mode(ctx)) {
                         JSAtom atom = JS_ValueToAtom(ctx, sp[-2]);
@@ -17740,8 +17747,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
                     } else {
                         sp[-3] = JS_DupValue(ctx, ctx->global_obj);
                     }
+                } else {
+                    if (is_strict_mode(ctx))
+                        flags |= JS_PROP_NO_ADD;
                 }
-                ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT);
+                ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], flags);
                 JS_FreeValue(ctx, sp[-3]);
                 sp -= 3;
                 if (unlikely(ret < 0))
@@ -18084,8 +18094,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
                     var_buf[idx] = JS_NewInt32(ctx, val + 1);
                 } else {
                 inc_loc_slow:
-                    if (js_unary_arith_slow(ctx, var_buf + idx + 1, OP_inc))
+                    /* must duplicate otherwise the variable value may
+                       be destroyed before JS code accesses it */
+                    op1 = JS_DupValue(ctx, op1);
+                    if (js_unary_arith_slow(ctx, &op1 + 1, OP_inc))
                         goto exception;
+                    set_value(ctx, &var_buf[idx], op1);
                 }
             }
             BREAK;
@@ -18105,8 +18119,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
                     var_buf[idx] = JS_NewInt32(ctx, val - 1);
                 } else {
                 dec_loc_slow:
-                    if (js_unary_arith_slow(ctx, var_buf + idx + 1, OP_dec))
+                    /* must duplicate otherwise the variable value may
+                       be destroyed before JS code accesses it */
+                    op1 = JS_DupValue(ctx, op1);
+                    if (js_unary_arith_slow(ctx, &op1 + 1, OP_dec))
                         goto exception;
+                    set_value(ctx, &var_buf[idx], op1);
                 }
             }
             BREAK;
@@ -18432,6 +18450,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
                         set_value(ctx, &sp[-1], val);
                         break;
                     case OP_with_put_var:
+                        /* XXX: check if strict mode */
                         ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2],
                                                      JS_PROP_THROW_STRICT);
                         JS_FreeValue(ctx, sp[-1]);
@@ -18922,13 +18941,11 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
     JSGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_GENERATOR);
     JSStackFrame *sf;
     JSValue ret, func_ret;
-    JSValueConst iter_args[1];
 
     *pdone = TRUE;
     if (!s)
         return JS_ThrowTypeError(ctx, "not a generator");
     sf = &s->func_state.frame;
- redo:
     switch(s->state) {
     default:
     case JS_GENERATOR_STATE_SUSPENDED_START:
@@ -18940,85 +18957,16 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
         }
         break;
     case JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR:
-        {
-            int done;
-            JSValue method, iter_obj;
-
-            iter_obj = sf->cur_sp[-2];
-            if (magic == GEN_MAGIC_NEXT) {
-                method = JS_DupValue(ctx, sf->cur_sp[-1]);
-            } else {
-                method = JS_GetProperty(ctx, iter_obj,
-                                        magic == GEN_MAGIC_RETURN ?
-                                        JS_ATOM_return : JS_ATOM_throw);
-                if (JS_IsException(method))
-                    goto iter_exception;
-            }
-            if (magic != GEN_MAGIC_NEXT &&
-                (JS_IsUndefined(method) || JS_IsNull(method))) {
-                /* default action */
-                if (magic == GEN_MAGIC_RETURN) {
-                    ret = JS_DupValue(ctx, argv[0]);
-                    goto iter_done;
-                } else {
-                    if (JS_IteratorClose(ctx, iter_obj, FALSE))
-                        goto iter_exception;
-                    JS_ThrowTypeError(ctx, "iterator does not have a throw method");
-                    goto iter_exception;
-                }
-            }
-            ret = JS_IteratorNext2(ctx, iter_obj, method, argc, argv, &done);
-            JS_FreeValue(ctx, method);
-            if (JS_IsException(ret)) {
-            iter_exception:
-                goto exec_throw;
-            }
-            /* if not done, the iterator returns the exact object
-               returned by 'method' */
-            if (done == 2) {
-                JSValue done_val, value;
-                done_val = JS_GetProperty(ctx, ret, JS_ATOM_done);
-                if (JS_IsException(done_val)) {
-                    JS_FreeValue(ctx, ret);
-                    goto iter_exception;
-                }
-                done = JS_ToBoolFree(ctx, done_val);
-                if (done) {
-                    value = JS_GetProperty(ctx, ret, JS_ATOM_value);
-                    JS_FreeValue(ctx, ret);
-                    if (JS_IsException(value))
-                        goto iter_exception;
-                    ret = value;
-                    goto iter_done;
-                } else {
-                    *pdone = 2;
-                }
-            } else {
-                if (done) {
-                    /* 'yield *' returns the value associated to done = true */
-                iter_done:
-                    JS_FreeValue(ctx, sf->cur_sp[-2]);
-                    JS_FreeValue(ctx, sf->cur_sp[-1]);
-                    sf->cur_sp--;
-                    goto exec_arg;
-                } else {
-                    *pdone = FALSE;
-                }
-            }
-            break;
-        }
-        break;
     case JS_GENERATOR_STATE_SUSPENDED_YIELD:
         /* cur_sp[-1] was set to JS_UNDEFINED in the previous call */
         ret = JS_DupValue(ctx, argv[0]);
-        if (magic == GEN_MAGIC_THROW) {
+        if (magic == GEN_MAGIC_THROW &&
+            s->state == JS_GENERATOR_STATE_SUSPENDED_YIELD) {
             JS_Throw(ctx, ret);
-        exec_throw:
             s->func_state.throw_flag = TRUE;
         } else {
-        exec_arg:
             sf->cur_sp[-1] = ret;
-            sf->cur_sp[0] = JS_NewBool(ctx, (magic == GEN_MAGIC_RETURN));
+            sf->cur_sp[0] = JS_NewInt32(ctx, magic);
             sf->cur_sp++;
         exec_no_arg:
             s->func_state.throw_flag = FALSE;
@@ -19032,17 +18980,14 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
             return func_ret;
         }
         if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {
+            /* get the returned yield value at the top of the stack */
+            ret = sf->cur_sp[-1];
+            sf->cur_sp[-1] = JS_UNDEFINED;
             if (JS_VALUE_GET_INT(func_ret) == FUNC_RET_YIELD_STAR) {
-                /* 'yield *' */
                 s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR;
-                iter_args[0] = JS_UNDEFINED;
-                argc = 1;
-                argv = iter_args;
-                goto redo;
+                /* return (value, done) object */
+                *pdone = 2;
             } else {
-                /* get the return the yield value at the top of the stack */
-                ret = sf->cur_sp[-1];
-                sf->cur_sp[-1] = JS_UNDEFINED;
                 *pdone = FALSE;
             }
         } else {
@@ -19853,15 +19798,15 @@ typedef struct BlockEnv {
     int has_iterator;
 } BlockEnv;
 
-typedef struct JSHoistedDef {
-    int cpool_idx; /* -1 means variable global definition */
-    uint8_t force_init : 1; /* initialize to undefined */
+typedef struct JSGlobalVar {
+    int cpool_idx; /* if >= 0, index in the constant pool for hoisted
+                      function defintion*/
+    uint8_t force_init : 1; /* force initialization to undefined */
     uint8_t is_lexical : 1; /* global let/const definition */
     uint8_t is_const   : 1; /* const definition */
-    int var_idx;   /* function object index if cpool_idx >= 0 */
     int scope_level;    /* scope of definition */
-    JSAtom var_name;  /* variable name if cpool_idx < 0 */
-} JSHoistedDef;
+    JSAtom var_name;  /* variable name */
+} JSGlobalVar;
 
 typedef struct RelocEntry {
     struct RelocEntry *next;
@@ -19924,6 +19869,7 @@ typedef struct JSFunctionDef {
     BOOL has_home_object; /* TRUE if the home object is available */
     BOOL has_prototype; /* true if a prototype field is necessary */
     BOOL has_simple_parameter_list;
+    BOOL has_parameter_expressions; /* if true, an argument scope is created */
     BOOL has_use_strict; /* to reject directive in special cases */
     BOOL has_eval_call; /* true if the function contains a call to eval() */
     BOOL has_arguments_binding; /* true if the 'arguments' binding is
@@ -19951,7 +19897,10 @@ typedef struct JSFunctionDef {
     int arg_count; /* number of arguments */
     int defined_arg_count;
     int var_object_idx; /* -1 if none */
+    int arg_var_object_idx; /* -1 if none (var object for the argument scope) */
     int arguments_var_idx; /* -1 if none */
+    int arguments_arg_idx; /* argument variable definition in argument scope, 
+                              -1 if none */
     int func_var_idx; /* variable containing the current function (-1
                          if none, only used if is_func_expr is true) */
     int eval_ret_idx; /* variable containing the return value of the eval, -1 if none */
@@ -19967,10 +19916,11 @@ typedef struct JSFunctionDef {
     int scope_count;    /* number of entries used in the fd->scopes array */
     JSVarScope *scopes;
     JSVarScope def_scope_array[4];
+    int body_scope; /* scope of the body of the function or eval */
 
-    int hoisted_def_count;
-    int hoisted_def_size;
-    JSHoistedDef *hoisted_def;
+    int global_var_count;
+    int global_var_size;
+    JSGlobalVar *global_vars;
 
     DynBuf byte_code;
     int last_opcode_pos; /* -1 if no last opcode */
@@ -21475,7 +21425,7 @@ static BOOL js_is_live_code(JSParseState *s) {
     case OP_return_undef:
     case OP_return_async:
     case OP_throw:
-    case OP_throw_var:
+    case OP_throw_error:
     case OP_goto:
 #if SHORT_OPCODES
     case OP_goto8:
@@ -21647,6 +21597,21 @@ static int find_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
     return find_arg(ctx, fd, name);
 }
 
+/* find a variable declaration in a given scope */
+static int find_var_in_scope(JSContext *ctx, JSFunctionDef *fd,
+                             JSAtom name, int scope_level)
+{
+    int scope_idx;
+    for(scope_idx = fd->scopes[scope_level].first; scope_idx >= 0;
+        scope_idx = fd->vars[scope_idx].scope_next) {
+        if (fd->vars[scope_idx].scope_level != scope_level)
+            break;
+        if (fd->vars[scope_idx].var_name == name)
+            return scope_idx;
+    }
+    return -1;
+}
+
 /* return true if scope == parent_scope or if scope is a child of
    parent_scope */
 static BOOL is_child_scope(JSContext *ctx, JSFunctionDef *fd,
@@ -21668,7 +21633,7 @@ static int find_var_in_child_scope(JSContext *ctx, JSFunctionDef *fd,
     for(i = 0; i < fd->var_count; i++) {
         JSVarDef *vd = &fd->vars[i];
         if (vd->var_name == name && vd->scope_level == 0) {
-            if (is_child_scope(ctx, fd, vd->func_pool_or_scope_idx,
+            if (is_child_scope(ctx, fd, vd->scope_next,
                                scope_level))
                 return i;
         }
@@ -21677,11 +21642,11 @@ static int find_var_in_child_scope(JSContext *ctx, JSFunctionDef *fd,
 }
 
 
-static JSHoistedDef *find_hoisted_def(JSFunctionDef *fd, JSAtom name)
+static JSGlobalVar *find_global_var(JSFunctionDef *fd, JSAtom name)
 {
     int i;
-    for(i = 0; i < fd->hoisted_def_count; i++) {
-        JSHoistedDef *hf = &fd->hoisted_def[i];
+    for(i = 0; i < fd->global_var_count; i++) {
+        JSGlobalVar *hf = &fd->global_vars[i];
         if (hf->var_name == name)
             return hf;
     }
@@ -21689,9 +21654,9 @@ static JSHoistedDef *find_hoisted_def(JSFunctionDef *fd, JSAtom name)
 
 }
 
-static JSHoistedDef *find_lexical_hoisted_def(JSFunctionDef *fd, JSAtom name)
+static JSGlobalVar *find_lexical_global_var(JSFunctionDef *fd, JSAtom name)
 {
-    JSHoistedDef *hf = find_hoisted_def(fd, name);
+    JSGlobalVar *hf = find_global_var(fd, name);
     if (hf && hf->is_lexical)
         return hf;
     else
@@ -21711,7 +21676,7 @@ static int find_lexical_decl(JSContext *ctx, JSFunctionDef *fd, JSAtom name,
     }
 
     if (fd->is_eval && fd->eval_type == JS_EVAL_TYPE_GLOBAL) {
-        if (find_lexical_hoisted_def(fd, name))
+        if (find_lexical_global_var(fd, name))
             return GLOBAL_VAR_OFFSET;
     }
     return -1;
@@ -21800,6 +21765,7 @@ static int add_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
     vd = &fd->vars[fd->var_count++];
     memset(vd, 0, sizeof(*vd));
     vd->var_name = JS_DupAtom(ctx, name);
+    vd->func_pool_idx = -1;
     return fd->var_count - 1;
 }
 
@@ -21823,22 +21789,47 @@ static int add_func_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
     int idx = fd->func_var_idx;
     if (idx < 0 && (idx = add_var(ctx, fd, name)) >= 0) {
         fd->func_var_idx = idx;
-        fd->vars[idx].is_func_var = TRUE;
+        fd->vars[idx].var_kind = JS_VAR_FUNCTION_NAME;
         if (fd->js_mode & JS_MODE_STRICT)
             fd->vars[idx].is_const = TRUE;
     }
     return idx;
 }
 
-static int add_arguments_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
+static int add_arguments_var(JSContext *ctx, JSFunctionDef *fd)
 {
     int idx = fd->arguments_var_idx;
-    if (idx < 0 && (idx = add_var(ctx, fd, name)) >= 0) {
+    if (idx < 0 && (idx = add_var(ctx, fd, JS_ATOM_arguments)) >= 0) {
         fd->arguments_var_idx = idx;
     }
     return idx;
 }
 
+/* add an argument definition in the argument scope. Only needed when
+   "eval()" may be called in the argument scope. Return 0 if OK. */
+static int add_arguments_arg(JSContext *ctx, JSFunctionDef *fd)
+{
+    int idx;
+    if (fd->arguments_arg_idx < 0) {
+        idx = find_var_in_scope(ctx, fd, JS_ATOM_arguments, ARG_SCOPE_INDEX);
+        if (idx < 0) {
+            /* XXX: the scope links are not fully updated. May be an
+               issue if there are child scopes of the argument
+               scope */
+            idx = add_var(ctx, fd, JS_ATOM_arguments);
+            if (idx < 0)
+                return -1;
+            fd->vars[idx].scope_next = fd->scopes[ARG_SCOPE_INDEX].first;
+            fd->scopes[ARG_SCOPE_INDEX].first = idx;
+            fd->vars[idx].scope_level = ARG_SCOPE_INDEX;
+            fd->vars[idx].is_lexical = TRUE;
+
+            fd->arguments_arg_idx = idx;
+        }
+    }
+    return 0;
+}
+
 static int add_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
 {
     JSVarDef *vd;
@@ -21854,32 +21845,27 @@ static int add_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name)
     vd = &fd->args[fd->arg_count++];
     memset(vd, 0, sizeof(*vd));
     vd->var_name = JS_DupAtom(ctx, name);
+    vd->func_pool_idx = -1;
     return fd->arg_count - 1;
 }
 
-/* add a Hoisted definition for a function (cpool_idx >= 0) or a
-   global variable (cpool_idx = -1) */
-static JSHoistedDef *add_hoisted_def(JSContext *ctx,
-                                     JSFunctionDef *s, int cpool_idx,
-                                     JSAtom name, int var_idx, BOOL is_lexical)
+/* add a global variable definition */
+static JSGlobalVar *add_global_var(JSContext *ctx, JSFunctionDef *s,
+                                     JSAtom name)
 {
-    JSHoistedDef *hf;
+    JSGlobalVar *hf;
 
-    if (js_resize_array(ctx, (void **)&s->hoisted_def,
-                        sizeof(s->hoisted_def[0]),
-                        &s->hoisted_def_size, s->hoisted_def_count + 1))
+    if (js_resize_array(ctx, (void **)&s->global_vars,
+                        sizeof(s->global_vars[0]),
+                        &s->global_var_size, s->global_var_count + 1))
         return NULL;
-    hf = &s->hoisted_def[s->hoisted_def_count++];
-    hf->cpool_idx = cpool_idx;
-    hf->force_init = 0;
-    hf->is_lexical = is_lexical;
+    hf = &s->global_vars[s->global_var_count++];
+    hf->cpool_idx = -1;
+    hf->force_init = FALSE;
+    hf->is_lexical = FALSE;
     hf->is_const = FALSE;
-    hf->var_idx = var_idx;
     hf->scope_level = s->scope_level;
-    hf->var_name = JS_ATOM_NULL;
-    if (name != JS_ATOM_NULL) {
-        hf->var_name = JS_DupAtom(ctx, name);
-    }
+    hf->var_name = JS_DupAtom(ctx, name);
     return hf;
 }
 
@@ -21924,7 +21910,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
                     goto redef_lex_error;
                 }
             } else {
-                if (fd->scope_level == 1) {
+                if (fd->scope_level == fd->body_scope) {
                 redef_lex_error:
                     /* redefining a scoped var in the same scope: error */
                     return js_parse_error(s, "invalid redefinition of lexical identifier");
@@ -21933,7 +21919,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
         }
         if (var_def_type != JS_VAR_DEF_FUNCTION_DECL &&
             var_def_type != JS_VAR_DEF_NEW_FUNCTION_DECL &&
-            fd->scope_level == 1 &&
+            fd->scope_level == fd->body_scope &&
             find_arg(ctx, fd, name) >= 0) {
             /* lexical variable redefines a parameter name */
             return js_parse_error(s, "invalid redefinition of parameter name");
@@ -21944,8 +21930,8 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
         }
         
         if (fd->is_global_var) {
-            JSHoistedDef *hf;
-            hf = find_hoisted_def(fd, name);
+            JSGlobalVar *hf;
+            hf = find_global_var(fd, name);
             if (hf && is_child_scope(ctx, fd, hf->scope_level,
                                      fd->scope_level)) {
                 return js_parse_error(s, "invalid redefinition of global identifier");
@@ -21955,11 +21941,12 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
         if (fd->is_eval &&
             (fd->eval_type == JS_EVAL_TYPE_GLOBAL ||
              fd->eval_type == JS_EVAL_TYPE_MODULE) &&
-            fd->scope_level == 1) {
-            JSHoistedDef *hf;
-            hf = add_hoisted_def(s->ctx, fd, -1, name, -1, TRUE);
+            fd->scope_level == fd->body_scope) {
+            JSGlobalVar *hf;
+            hf = add_global_var(s->ctx, fd, name);
             if (!hf)
                 return -1;
+            hf->is_lexical = TRUE;
             hf->is_const = (var_def_type == JS_VAR_DEF_CONST);
             idx = GLOBAL_VAR_OFFSET;
         } else {
@@ -21991,13 +21978,13 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
             return js_parse_error(s, "invalid redefinition of lexical identifier");
         }
         if (fd->is_global_var) {
-            JSHoistedDef *hf;
-            hf = find_hoisted_def(fd, name);
+            JSGlobalVar *hf;
+            hf = find_global_var(fd, name);
             if (hf && hf->is_lexical && hf->scope_level == fd->scope_level &&
                 fd->eval_type == JS_EVAL_TYPE_MODULE) {
                 goto invalid_lexical_redefinition;
             }
-            hf = add_hoisted_def(s->ctx, fd, -1, name, -1, FALSE);
+            hf = add_global_var(s->ctx, fd, name);
             if (!hf)
                 return -1;
             idx = GLOBAL_VAR_OFFSET;
@@ -22010,7 +21997,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
             if (idx >= 0) {
                 if (name == JS_ATOM_arguments && fd->has_arguments_binding)
                     fd->arguments_var_idx = idx;
-                fd->vars[idx].func_pool_or_scope_idx = fd->scope_level;
+                fd->vars[idx].scope_next = fd->scope_level;
             }
         }
         break;
@@ -22052,8 +22039,9 @@ static __exception int js_parse_function_decl2(JSParseState *s,
                                                int function_line_num,
                                                JSParseExportEnum export_flag,
                                                JSFunctionDef **pfd);
-static __exception int js_parse_assign_expr(JSParseState *s, int in_accepted);
-static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag);
+static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags);
+static __exception int js_parse_assign_expr(JSParseState *s);
+static __exception int js_parse_unary(JSParseState *s, int parse_flags);
 static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,
                              JSAtom label_name,
                              int label_break, int label_cont,
@@ -22385,8 +22373,9 @@ static BOOL is_regexp_allowed(int tok)
     }
 }
 
-#define SKIP_HAS_SEMI      (1 << 0)
-#define SKIP_HAS_ELLIPSIS  (1 << 1)
+#define SKIP_HAS_SEMI       (1 << 0)
+#define SKIP_HAS_ELLIPSIS   (1 << 1)
+#define SKIP_HAS_ASSIGNMENT (1 << 2)
 
 /* XXX: improve speed with early bailout */
 /* XXX: no longer works if regexps are present. Could use previous
@@ -22459,7 +22448,10 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_
                 bits |= SKIP_HAS_ELLIPSIS;
             }
             break;
-
+        case '=':
+            bits |= SKIP_HAS_ASSIGNMENT;
+            break;
+            
         case TOK_DIV_ASSIGN:
             tok_len = 2;
             goto parse_regexp;
@@ -22574,7 +22566,7 @@ static __exception int js_parse_object_literal(JSParseState *s)
         if (s->token.val == TOK_ELLIPSIS) {
             if (next_token(s))
                 return -1;
-            if (js_parse_assign_expr(s, TRUE))
+            if (js_parse_assign_expr(s))
                 return -1;
             emit_op(s, OP_null);  /* dummy excludeList */
             emit_op(s, OP_copy_data_properties);
@@ -22633,7 +22625,7 @@ static __exception int js_parse_object_literal(JSParseState *s)
         } else {
             if (js_parse_expect(s, ':'))
                 goto fail;
-            if (js_parse_assign_expr(s, TRUE))
+            if (js_parse_assign_expr(s))
                 goto fail;
             if (name == JS_ATOM_NULL) {
                 set_object_name_computed(s);
@@ -22668,8 +22660,23 @@ static __exception int js_parse_object_literal(JSParseState *s)
     return -1;
 }
 
-static __exception int js_parse_postfix_expr(JSParseState *s,
-                                             BOOL accept_lparen);
+/* allow the 'in' binary operator */
+#define PF_IN_ACCEPTED  (1 << 0) 
+/* allow function calls parsing in js_parse_postfix_expr() */
+#define PF_POSTFIX_CALL (1 << 1) 
+/* allow arrow functions parsing in js_parse_postfix_expr() */
+#define PF_ARROW_FUNC   (1 << 2) 
+/* allow the exponentiation operator in js_parse_unary() */
+#define PF_POW_ALLOWED  (1 << 3) 
+/* forbid the exponentiation operator in js_parse_unary() */
+#define PF_POW_FORBIDDEN (1 << 4) 
+
+static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags);
+
+static __exception int js_parse_left_hand_side_expr(JSParseState *s)
+{
+    return js_parse_postfix_expr(s, PF_POSTFIX_CALL);
+}
 
 /* XXX: is there is nicer solution ? */
 static __exception int js_parse_class_default_ctor(JSParseState *s,
@@ -22873,8 +22880,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
         class_flags = JS_DEFINE_CLASS_HAS_HERITAGE;
         if (next_token(s))
             goto fail;
-        /* XXX: the grammar only allows LeftHandSideExpression */
-        if (js_parse_postfix_expr(s, TRUE))
+        if (js_parse_left_hand_side_expr(s))
             goto fail;
     } else {
         emit_op(s, OP_undefined);
@@ -23081,7 +23087,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
             if (s->token.val == '=') {
                 if (next_token(s))
                     goto fail;
-                if (js_parse_assign_expr(s, TRUE))
+                if (js_parse_assign_expr(s))
                     goto fail;
             } else {
                 emit_op(s, OP_undefined);
@@ -23285,7 +23291,7 @@ static __exception int js_parse_array_literal(JSParseState *s)
     while (s->token.val != ']' && idx < 32) {
         if (s->token.val == ',' || s->token.val == TOK_ELLIPSIS)
             break;
-        if (js_parse_assign_expr(s, TRUE))
+        if (js_parse_assign_expr(s))
             return -1;
         idx++;
         /* accept trailing comma */
@@ -23306,7 +23312,7 @@ static __exception int js_parse_array_literal(JSParseState *s)
             break;
         need_length = TRUE;
         if (s->token.val != ',') {
-            if (js_parse_assign_expr(s, TRUE))
+            if (js_parse_assign_expr(s))
                 return -1;
             emit_op(s, OP_define_field);
             emit_u32(s, __JS_AtomFromUInt32(idx));
@@ -23341,7 +23347,7 @@ static __exception int js_parse_array_literal(JSParseState *s)
         if (s->token.val == TOK_ELLIPSIS) {
             if (next_token(s))
                 return -1;
-            if (js_parse_assign_expr(s, TRUE))
+            if (js_parse_assign_expr(s))
                 return -1;
 #if 1
             emit_op(s, OP_append);
@@ -23373,7 +23379,7 @@ static __exception int js_parse_array_literal(JSParseState *s)
         } else {
             need_length = TRUE;
             if (s->token.val != ',') {
-                if (js_parse_assign_expr(s, TRUE))
+                if (js_parse_assign_expr(s))
                     return -1;
                 /* a idx val */
                 emit_op(s, OP_define_array_el);
@@ -23781,6 +23787,8 @@ fail:
     return JS_ATOM_NULL;
 }
 
+/* Return -1 if error, 0 if no initializer, 1 if an initializer is
+   present at the top level. */
 static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
                                         int hasval, int has_ellipsis,
                                         BOOL allow_initializer)
@@ -23789,7 +23797,8 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
     int start_addr, assign_addr;
     JSAtom prop_name, var_name;
     int opcode, scope, tok1, skip_bits;
-
+    BOOL has_initializer;
+    
     if (has_ellipsis < 0) {
         /* pre-parse destructuration target for spread detection */
         js_parse_skip_parens_token(s, &skip_bits, FALSE);
@@ -23842,7 +23851,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
                     label_lvalue = -1;
                     depth_lvalue = 0;
                 } else {
-                    if (js_parse_postfix_expr(s, TRUE))
+                    if (js_parse_left_hand_side_expr(s))
                         return -1;
 
                     if (get_lvalue(s, &opcode, &scope, &var_name,
@@ -23898,7 +23907,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
                         emit_op(s, OP_get_field2);
                         emit_u32(s, prop_name);
                     }
-                    if (js_parse_destructuring_element(s, tok, is_arg, TRUE, -1, TRUE))
+                    if (js_parse_destructuring_element(s, tok, is_arg, TRUE, -1, TRUE) < 0)
                         return -1;
                     if (s->token.val == '}')
                         break;
@@ -23935,7 +23944,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
                     if (var_name == JS_ATOM_NULL)
                         goto prop_error;
                 } else {
-                    if (js_parse_postfix_expr(s, TRUE))
+                    if (js_parse_left_hand_side_expr(s))
                         goto prop_error;
                 lvalue:
                     if (get_lvalue(s, &opcode, &scope, &var_name,
@@ -24033,7 +24042,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
                 if (next_token(s))
                     goto var_error;
                 emit_op(s, OP_drop);
-                if (js_parse_assign_expr(s, TRUE))
+                if (js_parse_assign_expr(s))
                     goto var_error;
                 if (opcode == OP_scope_get_var || opcode == OP_get_ref_value)
                     set_object_name(s, var_name);
@@ -24097,7 +24106,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
                     emit_u8(s, 0);
                     emit_op(s, OP_drop);
                 }
-                if (js_parse_destructuring_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
+                if (js_parse_destructuring_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)
                     return -1;
             } else {
                 var_name = JS_ATOM_NULL;
@@ -24111,7 +24120,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
                     opcode = OP_scope_get_var;
                     scope = s->cur_func->scope_level;
                 } else {
-                    if (js_parse_postfix_expr(s, TRUE))
+                    if (js_parse_left_hand_side_expr(s))
                         return -1;
                     if (get_lvalue(s, &opcode, &scope, &var_name,
                                    &label_lvalue, &enum_depth, FALSE, '[')) {
@@ -24135,7 +24144,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
                     if (next_token(s))
                         goto var_error;
                     emit_op(s, OP_drop);
-                    if (js_parse_assign_expr(s, TRUE))
+                    if (js_parse_assign_expr(s))
                         goto var_error;
                     if (opcode == OP_scope_get_var || opcode == OP_get_ref_value)
                         set_object_name(s, var_name);
@@ -24170,10 +24179,11 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
         emit_label(s, label_parse);
         if (hasval)
             emit_op(s, OP_drop);
-        if (js_parse_assign_expr(s, TRUE))
+        if (js_parse_assign_expr(s))
             return -1;
         emit_goto(s, OP_goto, label_assign);
         emit_label(s, label_done);
+        has_initializer = TRUE;
     } else {
         /* normally hasval is true except if
            js_parse_skip_parens_token() was wrong in the parsing */
@@ -24186,8 +24196,9 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
         memset(s->cur_func->byte_code.buf + start_addr, OP_nop,
                assign_addr - start_addr);
         s->cur_func->label_slots[label_parse].ref_count--;
+        has_initializer = FALSE;
     }
-    return 0;
+    return has_initializer;
 
  prop_error:
     JS_FreeAtom(s->ctx, prop_name);
@@ -24220,10 +24231,12 @@ static void optional_chain_test(JSParseState *s, int *poptional_chaining_label,
     emit_label(s, label_next);
 }
 
-static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen)
+/* allowed parse_flags: PF_POSTFIX_CALL, PF_ARROW_FUNC */
+static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
 {
     FuncCallType call_type;
     int optional_chaining_label;
+    BOOL accept_lparen = (parse_flags & PF_POSTFIX_CALL) != 0;
     
     call_type = FUNC_CALL_NORMAL;
     switch(s->token.val) {
@@ -24321,7 +24334,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
         }
         break;
     case '(':
-        if (js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {
+        if ((parse_flags & PF_ARROW_FUNC) &&
+            js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {
             if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
                                        JS_FUNC_NORMAL, JS_ATOM_NULL,
                                        s->token.ptr, s->token.line_num))
@@ -24369,7 +24383,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
             if (s->token.u.ident.is_reserved) {
                 return js_parse_error_reserved_identifier(s);
             }
-            if (peek_token(s, TRUE) == TOK_ARROW) {
+            if ((parse_flags & PF_ARROW_FUNC) &&
+                peek_token(s, TRUE) == TOK_ARROW) {
                 if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
                                            JS_FUNC_NORMAL, JS_ATOM_NULL,
                                            s->token.ptr, s->token.line_num))
@@ -24388,10 +24403,11 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
                                                JS_FUNC_ASYNC, JS_ATOM_NULL,
                                                source_ptr, source_line_num))
                         return -1;
-                } else if ((s->token.val == '(' &&
-                            js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) ||
-                           (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&
-                            peek_token(s, TRUE) == TOK_ARROW)) {
+                } else if ((parse_flags & PF_ARROW_FUNC) &&
+                           ((s->token.val == '(' &&
+                             js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) ||
+                            (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&
+                             peek_token(s, TRUE) == TOK_ARROW))) {
                     if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
                                                JS_FUNC_ASYNC, JS_ATOM_NULL,
                                                source_ptr, source_line_num))
@@ -24421,7 +24437,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
         {
             int skip_bits;
             if (js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') {
-                if (js_parse_destructuring_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
+                if (js_parse_destructuring_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)
                     return -1;
             } else {
                 if (s->token.val == '{') {
@@ -24450,7 +24466,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
             emit_atom(s, JS_ATOM_new_target);
             emit_u16(s, 0);
         } else {
-            if (js_parse_postfix_expr(s, FALSE))
+            if (js_parse_postfix_expr(s, 0))
                 return -1;
             accept_lparen = TRUE;
             if (s->token.val != '(') {
@@ -24503,7 +24519,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
                 return -1;
             if (!accept_lparen)
                 return js_parse_error(s, "invalid use of 'import()'");
-            if (js_parse_assign_expr(s, TRUE))
+            if (js_parse_assign_expr(s))
                 return -1;
             if (js_parse_expect(s, ')'))
                 return -1;
@@ -24636,7 +24652,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
                 }
                 if (s->token.val == TOK_ELLIPSIS)
                     break;
-                if (js_parse_assign_expr(s, TRUE))
+                if (js_parse_assign_expr(s))
                     return -1;
                 arg_count++;
                 if (s->token.val == ')')
@@ -24656,7 +24672,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
                     if (s->token.val == TOK_ELLIPSIS) {
                         if (next_token(s))
                             return -1;
-                        if (js_parse_assign_expr(s, TRUE))
+                        if (js_parse_assign_expr(s))
                             return -1;
 #if 1
                         /* XXX: could pass is_last indicator? */
@@ -24687,7 +24703,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
                         emit_op(s, OP_nip1);
 #endif
                     } else {
-                        if (js_parse_assign_expr(s, TRUE))
+                        if (js_parse_assign_expr(s))
                             return -1;
                         /* array idx val */
                         emit_op(s, OP_define_array_el);
@@ -24789,16 +24805,19 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
         } else if (s->token.val == '.') {
             if (next_token(s))
                 return -1;
+        parse_property:
             if (s->token.val == TOK_PRIVATE_NAME) {
                 /* private class field */
                 if (get_prev_opcode(fd) == OP_get_super) {
                     return js_parse_error(s, "private class field forbidden after super");
                 }
+                if (has_optional_chain) {
+                    optional_chain_test(s, &optional_chaining_label, 1);
+                }
                 emit_op(s, OP_scope_get_private_field);
                 emit_atom(s, s->token.u.ident.atom);
                 emit_u16(s, s->cur_func->scope_level);
             } else {
-            parse_property:
                 if (!token_is_ident(s->token.val)) {
                     return js_parse_error(s, "expecting field name");
                 }
@@ -24857,7 +24876,7 @@ static __exception int js_parse_delete(JSParseState *s)
 
     if (next_token(s))
         return -1;
-    if (js_parse_unary(s, -1))
+    if (js_parse_unary(s, PF_POW_FORBIDDEN))
         return -1;
     switch(opcode = get_prev_opcode(fd)) {
     case OP_get_field:
@@ -24896,9 +24915,9 @@ static __exception int js_parse_delete(JSParseState *s)
     case OP_scope_get_private_field:
         return js_parse_error(s, "cannot delete a private class field");
     case OP_get_super_value:
-        emit_op(s, OP_throw_var);
+        emit_op(s, OP_throw_error);
         emit_atom(s, JS_ATOM_NULL);
-        emit_u8(s, JS_THROW_VAR_DELETE_SUPER);
+        emit_u8(s, JS_THROW_ERROR_DELETE_SUPER);
         break;
     default:
     ret_true:
@@ -24909,7 +24928,8 @@ static __exception int js_parse_delete(JSParseState *s)
     return 0;
 }
 
-static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag)
+/* allowed parse_flags: PF_ARROW_FUNC, PF_POW_ALLOWED, PF_POW_FORBIDDEN */
+static __exception int js_parse_unary(JSParseState *s, int parse_flags)
 {
     int op;
 
@@ -24922,7 +24942,7 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag)
         op = s->token.val;
         if (next_token(s))
             return -1;
-        if (js_parse_unary(s, -1))
+        if (js_parse_unary(s, PF_POW_FORBIDDEN))
             return -1;
         switch(op) {
         case '-':
@@ -24944,7 +24964,7 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag)
         default:
             abort();
         }
-        exponentiation_flag = 0;
+        parse_flags = 0;
         break;
     case TOK_DEC:
     case TOK_INC:
@@ -24954,7 +24974,6 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag)
             op = s->token.val;
             if (next_token(s))
                 return -1;
-            /* XXX: should parse LeftHandSideExpression */
             if (js_parse_unary(s, 0))
                 return -1;
             if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))
@@ -24969,7 +24988,7 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag)
             JSFunctionDef *fd;
             if (next_token(s))
                 return -1;
-            if (js_parse_unary(s, -1))
+            if (js_parse_unary(s, PF_POW_FORBIDDEN))
                 return -1;
             /* reference access should not return an exception, so we
                patch the get_var */
@@ -24978,13 +24997,13 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag)
                 fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_get_var_undef;
             }
             emit_op(s, OP_typeof);
-            exponentiation_flag = 0;
+            parse_flags = 0;
         }
         break;
     case TOK_DELETE:
         if (js_parse_delete(s))
             return -1;
-        exponentiation_flag = 0;
+        parse_flags = 0;
         break;
     case TOK_AWAIT:
         if (!(s->cur_func->func_kind & JS_FUNC_ASYNC))
@@ -24993,13 +25012,14 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag)
             return js_parse_error(s, "await in default expression");
         if (next_token(s))
             return -1;
-        if (js_parse_unary(s, -1))
+        if (js_parse_unary(s, PF_POW_FORBIDDEN))
             return -1;
         emit_op(s, OP_await);
-        exponentiation_flag = 0;
+        parse_flags = 0;
         break;
     default:
-        if (js_parse_postfix_expr(s, TRUE))
+        if (js_parse_postfix_expr(s, (parse_flags & PF_ARROW_FUNC) |
+                                  PF_POSTFIX_CALL))
             return -1;
         if (!s->got_lf &&
             (s->token.val == TOK_DEC || s->token.val == TOK_INC)) {
@@ -25016,21 +25036,21 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag)
         }
         break;
     }
-    if (exponentiation_flag) {
+    if (parse_flags & (PF_POW_ALLOWED | PF_POW_FORBIDDEN)) {
 #ifdef CONFIG_BIGNUM
         if (s->token.val == TOK_POW || s->token.val == TOK_MATH_POW) {
             /* Extended exponentiation syntax rules: we extend the ES7
                grammar in order to have more intuitive semantics:
                -2**2 evaluates to -4. */
             if (!(s->cur_func->js_mode & JS_MODE_MATH)) {
-                if (exponentiation_flag < 0) {
+                if (parse_flags & PF_POW_FORBIDDEN) {
                     JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'");
                     return -1;
                 }
             }
             if (next_token(s))
                 return -1;
-            if (js_parse_unary(s, 1))
+            if (js_parse_unary(s, PF_POW_ALLOWED))
                 return -1;
             emit_op(s, OP_pow);
         }
@@ -25041,13 +25061,13 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag)
                regarding the precedence of prefix operators and the
                postifx exponential, ES7 specifies that -2**2 is a
                syntax error. */
-            if (exponentiation_flag < 0) {
+            if (parse_flags & PF_POW_FORBIDDEN) {
                 JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'");
                 return -1;
             }
             if (next_token(s))
                 return -1;
-            if (js_parse_unary(s, 1))
+            if (js_parse_unary(s, PF_POW_ALLOWED))
                 return -1;
             emit_op(s, OP_pow);
         }
@@ -25056,15 +25076,17 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag)
     return 0;
 }
 
+/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
 static __exception int js_parse_expr_binary(JSParseState *s, int level,
-                                            BOOL in_accepted)
+                                            int parse_flags)
 {
     int op, opcode;
 
     if (level == 0) {
-        return js_parse_unary(s, 1);
+        return js_parse_unary(s, (parse_flags & PF_ARROW_FUNC) |
+                              PF_POW_ALLOWED);
     }
-    if (js_parse_expr_binary(s, level - 1, in_accepted))
+    if (js_parse_expr_binary(s, level - 1, parse_flags))
         return -1;
     for(;;) {
         op = s->token.val;
@@ -25134,7 +25156,7 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level,
                 opcode = OP_instanceof;
                 break;
             case TOK_IN:
-                if (in_accepted) {
+                if (parse_flags & PF_IN_ACCEPTED) {
                     opcode = OP_in;
                 } else {
                     return 0;
@@ -25194,23 +25216,24 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level,
         }
         if (next_token(s))
             return -1;
-        if (js_parse_expr_binary(s, level - 1, in_accepted))
+        if (js_parse_expr_binary(s, level - 1, parse_flags & ~PF_ARROW_FUNC))
             return -1;
         emit_op(s, opcode);
     }
     return 0;
 }
 
+/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
 static __exception int js_parse_logical_and_or(JSParseState *s, int op,
-                                               BOOL in_accepted)
+                                               int parse_flags)
 {
     int label1;
 
     if (op == TOK_LAND) {
-        if (js_parse_expr_binary(s, 8, in_accepted))
+        if (js_parse_expr_binary(s, 8, parse_flags))
             return -1;
     } else {
-        if (js_parse_logical_and_or(s, TOK_LAND, in_accepted))
+        if (js_parse_logical_and_or(s, TOK_LAND, parse_flags))
             return -1;
     }
     if (s->token.val == op) {
@@ -25224,10 +25247,11 @@ static __exception int js_parse_logical_and_or(JSParseState *s, int op,
             emit_op(s, OP_drop);
 
             if (op == TOK_LAND) {
-                if (js_parse_expr_binary(s, 8, in_accepted))
+                if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC))
                     return -1;
             } else {
-                if (js_parse_logical_and_or(s, TOK_LAND, in_accepted))
+                if (js_parse_logical_and_or(s, TOK_LAND,
+                                            parse_flags & ~PF_ARROW_FUNC))
                     return -1;
             }
             if (s->token.val != op) {
@@ -25242,11 +25266,11 @@ static __exception int js_parse_logical_and_or(JSParseState *s, int op,
     return 0;
 }
 
-static __exception int js_parse_coalesce_expr(JSParseState *s, BOOL in_accepted)
+static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
 {
     int label1;
     
-    if (js_parse_logical_and_or(s, TOK_LOR, in_accepted))
+    if (js_parse_logical_and_or(s, TOK_LOR, parse_flags))
         return -1;
     if (s->token.val == TOK_DOUBLE_QUESTION_MARK) {
         label1 = new_label(s);
@@ -25259,7 +25283,7 @@ static __exception int js_parse_coalesce_expr(JSParseState *s, BOOL in_accepted)
             emit_goto(s, OP_if_false, label1);
             emit_op(s, OP_drop);
             
-            if (js_parse_expr_binary(s, 8, in_accepted))
+            if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC))
                 return -1;
             if (s->token.val != TOK_DOUBLE_QUESTION_MARK)
                 break;
@@ -25269,18 +25293,19 @@ static __exception int js_parse_coalesce_expr(JSParseState *s, BOOL in_accepted)
     return 0;
 }
 
-static __exception int js_parse_cond_expr(JSParseState *s, BOOL in_accepted)
+/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
+static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)
 {
     int label1, label2;
 
-    if (js_parse_coalesce_expr(s, in_accepted))
+    if (js_parse_coalesce_expr(s, parse_flags))
         return -1;
     if (s->token.val == '?') {
         if (next_token(s))
             return -1;
         label1 = emit_goto(s, OP_if_false, -1);
 
-        if (js_parse_assign_expr(s, TRUE))
+        if (js_parse_assign_expr(s))
             return -1;
         if (js_parse_expect(s, ':'))
             return -1;
@@ -25289,7 +25314,7 @@ static __exception int js_parse_cond_expr(JSParseState *s, BOOL in_accepted)
 
         emit_label(s, label1);
 
-        if (js_parse_assign_expr(s, in_accepted))
+        if (js_parse_assign_expr2(s, parse_flags & PF_IN_ACCEPTED))
             return -1;
 
         emit_label(s, label2);
@@ -25299,14 +25324,16 @@ static __exception int js_parse_cond_expr(JSParseState *s, BOOL in_accepted)
 
 static void emit_return(JSParseState *s, BOOL hasval);
 
-static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted)
+/* allowed parse_flags: PF_IN_ACCEPTED */
+static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
 {
     int opcode, op, scope;
     JSAtom name0 = JS_ATOM_NULL;
     JSAtom name;
 
     if (s->token.val == TOK_YIELD) {
-        BOOL is_star = FALSE;
+        BOOL is_star = FALSE, is_async;
+        
         if (!(s->cur_func->func_kind & JS_FUNC_GENERATOR))
             return js_parse_error(s, "unexpected 'yield' keyword");
         if (!s->cur_func->in_function_body)
@@ -25323,109 +25350,120 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted)
                 if (next_token(s))
                     return -1;
             }
-            if (js_parse_assign_expr(s, in_accepted))
+            if (js_parse_assign_expr2(s, parse_flags))
                 return -1;
         } else {
             emit_op(s, OP_undefined);
         }
-        if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
+        is_async = (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR);
+
+        if (is_star) {
             int label_loop, label_return, label_next;
             int label_return1, label_yield, label_throw, label_throw1;
             int label_throw2;
 
-            if (is_star) {
-                label_loop = new_label(s);
-                label_yield = new_label(s);
-
-                emit_op(s, OP_for_await_of_start);
+            label_loop = new_label(s);
+            label_yield = new_label(s);
 
-                /* remove the catch offset (XXX: could avoid pushing back
-                   undefined) */
-                emit_op(s, OP_drop);
-                emit_op(s, OP_undefined);
+            emit_op(s, is_async ? OP_for_await_of_start : OP_for_of_start);
 
-                emit_op(s, OP_undefined); /* initial value */
-
-                emit_label(s, label_loop);
-                emit_op(s, OP_async_iterator_next);
+            /* remove the catch offset (XXX: could avoid pushing back
+               undefined) */
+            emit_op(s, OP_drop);
+            emit_op(s, OP_undefined);
+            
+            emit_op(s, OP_undefined); /* initial value */
+            
+            emit_label(s, label_loop);
+            emit_op(s, OP_iterator_next);
+            if (is_async)
                 emit_op(s, OP_await);
-                emit_op(s, OP_iterator_get_value_done);
-                label_next = emit_goto(s, OP_if_true, -1); /* end of loop */
+            emit_op(s, OP_iterator_check_object);
+            emit_op(s, OP_get_field2);
+            emit_atom(s, JS_ATOM_done);
+            label_next = emit_goto(s, OP_if_true, -1); /* end of loop */
+            emit_label(s, label_yield);
+            if (is_async) {
+                /* OP_async_yield_star takes the value as parameter */
+                emit_op(s, OP_get_field);
+                emit_atom(s, JS_ATOM_value);
                 emit_op(s, OP_await);
-                emit_label(s, label_yield);
                 emit_op(s, OP_async_yield_star);
-                emit_op(s, OP_dup);
-                label_return = emit_goto(s, OP_if_true, -1);
-                emit_op(s, OP_drop);
-                emit_goto(s, OP_goto, label_loop);
-
-                emit_label(s, label_return);
-                emit_op(s, OP_push_i32);
-                emit_u32(s, 2);
-                emit_op(s, OP_strict_eq);
-                label_throw = emit_goto(s, OP_if_true, -1);
-
-                /* return handling */
-                emit_op(s, OP_await);
-                emit_op(s, OP_async_iterator_get);
-                emit_u8(s, 0);
-                label_return1 = emit_goto(s, OP_if_true, -1);
+            } else {
+                /* OP_yield_star takes (value, done) as parameter */
+                emit_op(s, OP_yield_star);
+            }
+            emit_op(s, OP_dup);
+            label_return = emit_goto(s, OP_if_true, -1);
+            emit_op(s, OP_drop);
+            emit_goto(s, OP_goto, label_loop);
+            
+            emit_label(s, label_return);
+            emit_op(s, OP_push_i32);
+            emit_u32(s, 2);
+            emit_op(s, OP_strict_eq);
+            label_throw = emit_goto(s, OP_if_true, -1);
+            
+            /* return handling */
+            if (is_async)
                 emit_op(s, OP_await);
-                emit_op(s, OP_iterator_get_value_done);
-                /* XXX: the spec does not indicate that an await should be
-                   performed in case done = true, but the tests assume it */
-                emit_goto(s, OP_if_false, label_yield);
-
-                emit_label(s, label_return1);
-                emit_op(s, OP_nip);
-                emit_op(s, OP_nip);
-                emit_op(s, OP_nip);
-                emit_return(s, TRUE);
-
-                /* throw handling */
-                emit_label(s, label_throw);
-                emit_op(s, OP_async_iterator_get);
-                emit_u8(s, 1);
-                label_throw1 = emit_goto(s, OP_if_true, -1);
+            emit_op(s, OP_iterator_call);
+            emit_u8(s, 0);
+            label_return1 = emit_goto(s, OP_if_true, -1);
+            if (is_async)
                 emit_op(s, OP_await);
-                emit_op(s, OP_iterator_get_value_done);
-                emit_goto(s, OP_if_false, label_yield);
-                /* XXX: the spec does not indicate that an await should be
-                   performed in case done = true, but the tests assume it */
+            emit_op(s, OP_iterator_check_object);
+            emit_op(s, OP_get_field2);
+            emit_atom(s, JS_ATOM_done);
+            emit_goto(s, OP_if_false, label_yield);
+
+            emit_op(s, OP_get_field);
+            emit_atom(s, JS_ATOM_value);
+            
+            emit_label(s, label_return1);
+            emit_op(s, OP_nip);
+            emit_op(s, OP_nip);
+            emit_op(s, OP_nip);
+            emit_return(s, TRUE);
+            
+            /* throw handling */
+            emit_label(s, label_throw);
+            emit_op(s, OP_iterator_call);
+            emit_u8(s, 1);
+            label_throw1 = emit_goto(s, OP_if_true, -1);
+            if (is_async)
                 emit_op(s, OP_await);
-                emit_goto(s, OP_goto, label_next);
-                /* close the iterator and throw a type error exception */
-                emit_label(s, label_throw1);
-                emit_op(s, OP_async_iterator_get);
-                emit_u8(s, 0);
-                label_throw2 = emit_goto(s, OP_if_true, -1);
+            emit_op(s, OP_iterator_check_object);
+            emit_op(s, OP_get_field2);
+            emit_atom(s, JS_ATOM_done);
+            emit_goto(s, OP_if_false, label_yield);
+            emit_goto(s, OP_goto, label_next);
+            /* close the iterator and throw a type error exception */
+            emit_label(s, label_throw1);
+            emit_op(s, OP_iterator_call);
+            emit_u8(s, 2);
+            label_throw2 = emit_goto(s, OP_if_true, -1);
+            if (is_async)
                 emit_op(s, OP_await);
-                emit_label(s, label_throw2);
-                emit_op(s, OP_async_iterator_get);
-                emit_u8(s, 2); /* throw the type error exception */
-                emit_op(s, OP_drop); /* never reached */
+            emit_label(s, label_throw2);
 
-                emit_label(s, label_next);
-                emit_op(s, OP_nip); /* keep the value associated with
-                                       done = true */
-                emit_op(s, OP_nip);
-                emit_op(s, OP_nip);
-            } else {
-                emit_op(s, OP_await);
-                emit_op(s, OP_yield);
-                label_next = emit_goto(s, OP_if_false, -1);
-                emit_return(s, TRUE);
-                emit_label(s, label_next);
-            }
+            emit_op(s, OP_throw_error);
+            emit_atom(s, JS_ATOM_NULL);
+            emit_u8(s, JS_THROW_ERROR_ITERATOR_THROW);
+            
+            emit_label(s, label_next);
+            emit_op(s, OP_get_field);
+            emit_atom(s, JS_ATOM_value);
+            emit_op(s, OP_nip); /* keep the value associated with
+                                   done = true */
+            emit_op(s, OP_nip);
+            emit_op(s, OP_nip);
         } else {
             int label_next;
-            if (is_star) {
-                emit_op(s, OP_for_of_start);
-                emit_op(s, OP_drop);    /* drop the catch offset */
-                emit_op(s, OP_yield_star);
-            } else {
-                emit_op(s, OP_yield);
-            }
+            
+            if (is_async)
+                emit_op(s, OP_await);
+            emit_op(s, OP_yield);
             label_next = emit_goto(s, OP_if_false, -1);
             emit_return(s, TRUE);
             emit_label(s, label_next);
@@ -25436,7 +25474,7 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted)
         /* name0 is used to check for OP_set_name pattern, not duplicated */
         name0 = s->token.u.ident.atom;
     }
-    if (js_parse_cond_expr(s, in_accepted))
+    if (js_parse_cond_expr(s, parse_flags | PF_ARROW_FUNC))
         return -1;
 
     op = s->token.val;
@@ -25447,7 +25485,7 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted)
         if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, (op != '='), op) < 0)
             return -1;
 
-        if (js_parse_assign_expr(s, in_accepted)) {
+        if (js_parse_assign_expr2(s, parse_flags)) {
             JS_FreeAtom(s->ctx, name);
             return -1;
         }
@@ -25491,7 +25529,7 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted)
                            -1);
         emit_op(s, OP_drop);
         
-        if (js_parse_assign_expr(s, in_accepted)) {
+        if (js_parse_assign_expr2(s, parse_flags)) {
             JS_FreeAtom(s->ctx, name);
             return -1;
         }
@@ -25533,11 +25571,17 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted)
     return 0;
 }
 
-static __exception int js_parse_expr2(JSParseState *s, BOOL in_accepted)
+static __exception int js_parse_assign_expr(JSParseState *s)
+{
+    return js_parse_assign_expr2(s, PF_IN_ACCEPTED);
+}
+
+/* allowed parse_flags: PF_IN_ACCEPTED */
+static __exception int js_parse_expr2(JSParseState *s, int parse_flags)
 {
     BOOL comma = FALSE;
     for(;;) {
-        if (js_parse_assign_expr(s, in_accepted))
+        if (js_parse_assign_expr2(s, parse_flags))
             return -1;
         if (comma) {
             /* prevent get_lvalue from using the last expression
@@ -25559,7 +25603,7 @@ static __exception int js_parse_expr2(JSParseState *s, BOOL in_accepted)
 
 static __exception int js_parse_expr(JSParseState *s)
 {
-    return js_parse_expr2(s, TRUE);
+    return js_parse_expr2(s, PF_IN_ACCEPTED);
 }
 
 static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,
@@ -25655,12 +25699,25 @@ static void emit_return(JSParseState *s, BOOL hasval)
             }
             emit_op(s, OP_iterator_close_return);
             if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
-                int label_next;
-                emit_op(s, OP_async_iterator_close);
+                int label_next, label_next2;
+
+                emit_op(s, OP_drop); /* catch offset */
+                emit_op(s, OP_drop); /* next */
+                emit_op(s, OP_get_field2);
+                emit_atom(s, JS_ATOM_return);
+                /* stack: iter_obj return_func */
+                emit_op(s, OP_dup);
+                emit_op(s, OP_is_undefined_or_null);
                 label_next = emit_goto(s, OP_if_true, -1);
+                emit_op(s, OP_call_method);
+                emit_u16(s, 0);
+                emit_op(s, OP_iterator_check_object);
                 emit_op(s, OP_await);
+                label_next2 = emit_goto(s, OP_goto, -1);
                 emit_label(s, label_next);
                 emit_op(s, OP_drop);
+                emit_label(s, label_next2);
+                emit_op(s, OP_drop);
             } else {
                 emit_op(s, OP_iterator_close);
             }
@@ -25748,7 +25805,8 @@ static __exception int js_parse_block(JSParseState *s)
     return 0;
 }
 
-static __exception int js_parse_var(JSParseState *s, BOOL in_accepted, int tok,
+/* allowed parse_flags: PF_IN_ACCEPTED */
+static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
                                     BOOL export_flag)
 {
     JSContext *ctx = s->ctx;
@@ -25788,7 +25846,7 @@ static __exception int js_parse_var(JSParseState *s, BOOL in_accepted, int tok,
                     emit_u16(s, fd->scope_level);
                     if (get_lvalue(s, &opcode, &scope, &name1, &label, NULL, FALSE, '=') < 0)
                         goto var_error;
-                    if (js_parse_assign_expr(s, in_accepted)) {
+                    if (js_parse_assign_expr2(s, parse_flags)) {
                         JS_FreeAtom(ctx, name1);
                         goto var_error;
                     }
@@ -25796,7 +25854,7 @@ static __exception int js_parse_var(JSParseState *s, BOOL in_accepted, int tok,
                     put_lvalue(s, opcode, scope, name1, label,
                                PUT_LVALUE_NOKEEP, FALSE);
                 } else {
-                    if (js_parse_assign_expr(s, in_accepted))
+                    if (js_parse_assign_expr2(s, parse_flags))
                         goto var_error;
                     set_object_name(s, name);
                     emit_op(s, (tok == TOK_CONST || tok == TOK_LET) ?
@@ -25823,7 +25881,7 @@ static __exception int js_parse_var(JSParseState *s, BOOL in_accepted, int tok,
             if ((s->token.val == '[' || s->token.val == '{')
             &&  js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') {
                 emit_op(s, OP_undefined);
-                if (js_parse_destructuring_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
+                if (js_parse_destructuring_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)
                     return -1;
             } else {
                 return js_parse_error(s, "variable name expected");
@@ -25952,7 +26010,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
 
         if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {
             if (s->token.val == '[' || s->token.val == '{') {
-                if (js_parse_destructuring_element(s, tok, 0, TRUE, -1, FALSE))
+                if (js_parse_destructuring_element(s, tok, 0, TRUE, -1, FALSE) < 0)
                     return -1;
                 has_destructuring = TRUE;
             } else {
@@ -25978,11 +26036,11 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
         int skip_bits;
         if ((s->token.val == '[' || s->token.val == '{')
         &&  ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == TOK_IN || tok1 == TOK_OF)) {
-            if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
+            if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)
                 return -1;
         } else {
             int lvalue_label;
-            if (js_parse_postfix_expr(s, TRUE))
+            if (js_parse_left_hand_side_expr(s))
                 return -1;
             if (get_lvalue(s, &opcode, &scope, &var_name, &lvalue_label,
                            NULL, FALSE, TOK_FOR))
@@ -26002,7 +26060,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
         /* parse and evaluate initializer prior to evaluating the
            object (only used with "for in" with a non lexical variable
            in non strict mode */
-        if (next_token(s) || js_parse_assign_expr(s, FALSE)) {
+        if (next_token(s) || js_parse_assign_expr2(s, 0)) {
             JS_FreeAtom(ctx, var_name);
             return -1;
         }
@@ -26035,7 +26093,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
     if (next_token(s))
         return -1;
     if (is_for_of) {
-        if (js_parse_assign_expr(s, TRUE))
+        if (js_parse_assign_expr(s))
             return -1;
     } else {
         if (js_parse_expr(s))
@@ -26088,7 +26146,11 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
     if (is_for_of) {
         if (is_async) {
             /* call the next method */
-            emit_op(s, OP_for_await_of_next);
+            /* stack: iter_obj next catch_offset */
+            emit_op(s, OP_dup3);
+            emit_op(s, OP_drop);
+            emit_op(s, OP_call_method);
+            emit_u16(s, 0);
             /* get the result of the promise */
             emit_op(s, OP_await);
             /* unwrap the value and done values */
@@ -26646,7 +26708,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
                     if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {
                         if (s->token.val == '[' || s->token.val == '{') {
                             /* XXX: TOK_LET is not completely correct */
-                            if (js_parse_destructuring_element(s, TOK_LET, 0, TRUE, -1, TRUE))
+                            if (js_parse_destructuring_element(s, TOK_LET, 0, TRUE, -1, TRUE) < 0)
                                 goto fail;
                         } else {
                             js_parse_error(s, "identifier expected");
@@ -26712,18 +26774,37 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
             }
             emit_label(s, label_finally);
             if (s->token.val == TOK_FINALLY) {
-                int saved_eval_ret_idx;
+                int saved_eval_ret_idx = 0; /* avoid warning */
+                
                 if (next_token(s))
                     goto fail;
                 /* on the stack: ret_value gosub_ret_value */
                 push_break_entry(s->cur_func, &block_env, JS_ATOM_NULL,
                                  -1, -1, 2);
-                saved_eval_ret_idx = s->cur_func->eval_ret_idx;
-                s->cur_func->eval_ret_idx = -1;
-                /* 'finally' does not update eval_ret */
+
+                if (s->cur_func->eval_ret_idx >= 0) {
+                    /* 'finally' updates eval_ret only if not a normal
+                       termination */
+                    saved_eval_ret_idx =
+                        add_var(s->ctx, s->cur_func, JS_ATOM__ret_);
+                    if (saved_eval_ret_idx < 0)
+                        goto fail;
+                    emit_op(s, OP_get_loc);
+                    emit_u16(s, s->cur_func->eval_ret_idx);
+                    emit_op(s, OP_put_loc);
+                    emit_u16(s, saved_eval_ret_idx);
+                    set_eval_ret_undefined(s);
+                }
+                
                 if (js_parse_block(s))
                     goto fail;
-                s->cur_func->eval_ret_idx = saved_eval_ret_idx;
+
+                if (s->cur_func->eval_ret_idx >= 0) {
+                    emit_op(s, OP_get_loc);
+                    emit_u16(s, saved_eval_ret_idx);
+                    emit_op(s, OP_put_loc);
+                    emit_u16(s, s->cur_func->eval_ret_idx);
+                }
                 pop_break_entry(s->cur_func);
             }
             emit_op(s, OP_ret);
@@ -27511,19 +27592,11 @@ static int exported_names_cmp(const void *p1, const void *p2, void *opaque)
 
 static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m);
 
-static int js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,
-                                 void *opaque)
+static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,
+                                     void *opaque)
 {
     JSModuleDef *m = opaque;
-    JSValue val, this_val = JS_MKPTR(JS_TAG_OBJECT, p);
-    
-    val = js_get_module_ns(ctx, m);
-    if (JS_IsException(val))
-        return -1;
-    if (JS_DefinePropertyValue(ctx, this_val, atom, val,
-                               JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0)
-        return -1;
-    return 0;
+    return js_get_module_ns(ctx, m);
 }
 
 static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
@@ -27741,7 +27814,7 @@ static int js_create_module_bytecode_function(JSContext *ctx, JSModuleDef *m)
     return -1;
 }
 
-/* must be done before js_instantiate_module() because of cyclic references */
+/* must be done before js_link_module() because of cyclic references */
 static int js_create_module_function(JSContext *ctx, JSModuleDef *m)
 {
     BOOL is_c_module;
@@ -27784,7 +27857,7 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m)
     
 /* Prepare a module to be executed by resolving all the imported
    variables. */
-static int js_instantiate_module(JSContext *ctx, JSModuleDef *m)
+static int js_link_module(JSContext *ctx, JSModuleDef *m)
 {
     int i;
     JSImportEntry *mi;
@@ -27792,7 +27865,8 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m)
     JSVarRef **var_refs, *var_ref;
     JSObject *p;
     BOOL is_c_module;
-
+    JSValue ret_val;
+    
     if (m->instantiated)
         return 0;
     m->instantiated = TRUE;
@@ -27806,7 +27880,7 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m)
 
     for(i = 0; i < m->req_module_entries_count; i++) {
         JSReqModuleEntry *rme = &m->req_module_entries[i];
-        if (js_instantiate_module(ctx, rme->module) < 0)
+        if (js_link_module(ctx, rme->module) < 0)
             goto fail;
     }
 
@@ -27925,6 +27999,12 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m)
                 me->u.local.var_ref = var_ref;
             }
         }
+
+        /* initialize the global variables */
+        ret_val = JS_Call(ctx, m->func_obj, JS_TRUE, 0, NULL);
+        if (JS_IsException(ret_val))
+            goto fail;
+        JS_FreeValue(ctx, ret_val);
     }
 
 #ifdef DUMP_MODULE_RESOLVE
@@ -28324,7 +28404,7 @@ static __exception int js_parse_export(JSParseState *s)
                                            s->token.ptr, s->token.line_num,
                                            JS_PARSE_EXPORT_DEFAULT, NULL);
         } else {
-            if (js_parse_assign_expr(s, TRUE))
+            if (js_parse_assign_expr(s))
                 return -1;
         }
         /* set the name of anonymous functions */
@@ -28567,7 +28647,9 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx,
     fd->last_opcode_pos = -1;
     fd->func_name = JS_ATOM_NULL;
     fd->var_object_idx = -1;
+    fd->arg_var_object_idx = -1;
     fd->arguments_var_idx = -1;
+    fd->arguments_arg_idx = -1;
     fd->func_var_idx = -1;
     fd->eval_ret_idx = -1;
     fd->this_var_idx = -1;
@@ -28576,13 +28658,14 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx,
     fd->home_object_var_idx = -1;
 
     /* XXX: should distinguish arg, var and var object and body scopes */
-    fd->scope_level = 0;  /* 0: var/arg scope, 1:body scope */
-    fd->scope_first = -1;
     fd->scopes = fd->def_scope_array;
     fd->scope_size = countof(fd->def_scope_array);
     fd->scope_count = 1;
     fd->scopes[0].first = -1;
     fd->scopes[0].parent = -1;
+    fd->scope_level = 0;  /* 0: var/arg scope */
+    fd->scope_first = -1;
+    fd->body_scope = -1;
 
     fd->filename = JS_NewAtom(ctx, filename);
     fd->line_num = line_num;
@@ -28663,10 +28746,10 @@ static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd)
     }
     js_free(ctx, fd->args);
 
-    for(i = 0; i < fd->hoisted_def_count; i++) {
-        JS_FreeAtom(ctx, fd->hoisted_def[i].var_name);
+    for(i = 0; i < fd->global_var_count; i++) {
+        JS_FreeAtom(ctx, fd->global_vars[i].var_name);
     }
-    js_free(ctx, fd->hoisted_def);
+    js_free(ctx, fd->global_vars);
 
     for(i = 0; i < fd->closure_var_count; i++) {
         JSClosureVar *cv = &fd->closure_var[i];
@@ -29350,19 +29433,27 @@ static int resolve_pseudo_var(JSContext *ctx, JSFunctionDef *s,
     switch(var_name) {
     case JS_ATOM_home_object:
         /* 'home_object' pseudo variable */
-        var_idx = s->home_object_var_idx = add_var(ctx, s, var_name);
+        if (s->home_object_var_idx < 0)
+            s->home_object_var_idx = add_var(ctx, s, var_name);
+        var_idx = s->home_object_var_idx;
         break;
     case JS_ATOM_this_active_func:
         /* 'this.active_func' pseudo variable */
-        var_idx = s->this_active_func_var_idx = add_var(ctx, s, var_name);
+        if (s->this_active_func_var_idx < 0)
+            s->this_active_func_var_idx = add_var(ctx, s, var_name);
+        var_idx = s->this_active_func_var_idx;
         break;
     case JS_ATOM_new_target:
         /* 'new.target' pseudo variable */
-        var_idx = s->new_target_var_idx = add_var(ctx, s, var_name);
+        if (s->new_target_var_idx < 0)
+            s->new_target_var_idx = add_var(ctx, s, var_name);
+        var_idx = s->new_target_var_idx;
         break;
     case JS_ATOM_this:
         /* 'this' pseudo variable */
-        var_idx = s->this_var_idx = add_var_this(ctx, s);
+        if (s->this_var_idx < 0)
+            s->this_var_idx = add_var_this(ctx, s);
+        var_idx = s->this_var_idx;
         break;
     default:
         var_idx = -1;
@@ -29371,18 +29462,32 @@ static int resolve_pseudo_var(JSContext *ctx, JSFunctionDef *s,
     return var_idx;
 }
 
+/* test if 'var_name' is in the variable object on the stack. If is it
+   the case, handle it and jump to 'label_done' */
+static void var_object_test(JSContext *ctx, JSFunctionDef *s,
+                            JSAtom var_name, int op, DynBuf *bc,
+                            int *plabel_done, BOOL is_with)
+{
+    dbuf_putc(bc, get_with_scope_opcode(op));
+    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
+    *plabel_done = new_label_fd(s, *plabel_done);
+    dbuf_put_u32(bc, *plabel_done);
+    dbuf_putc(bc, is_with);
+    update_label(s, *plabel_done, 1);
+    s->jump_size++;
+}
+    
 /* return the position of the next opcode */
 static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
                              JSAtom var_name, int scope_level, int op,
                              DynBuf *bc, uint8_t *bc_buf,
-                             LabelSlot *ls, int pos_next, int arg_valid)
+                             LabelSlot *ls, int pos_next)
 {
     int idx, var_idx, is_put;
     int label_done;
-    BOOL is_func_var = FALSE;
     JSFunctionDef *fd;
     JSVarDef *vd;
-    BOOL is_pseudo_var;
+    BOOL is_pseudo_var, is_arg_scope;
 
     label_done = -1;
 
@@ -29400,12 +29505,11 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
         if (vd->var_name == var_name) {
             if (op == OP_scope_put_var || op == OP_scope_make_ref) {
                 if (vd->is_const) {
-                    dbuf_putc(bc, OP_throw_var);
+                    dbuf_putc(bc, OP_throw_error);
                     dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
                     dbuf_putc(bc, JS_THROW_VAR_RO);
                     goto done;
                 }
-                is_func_var = vd->is_func_var;
             }
             var_idx = idx;
             break;
@@ -29413,33 +29517,16 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
         if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {
             dbuf_putc(bc, OP_get_loc);
             dbuf_put_u16(bc, idx);
-            dbuf_putc(bc, get_with_scope_opcode(op));
-            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
-            label_done = new_label_fd(s, label_done);
-            dbuf_put_u32(bc, label_done);
-            dbuf_putc(bc, 1);
-            update_label(s, label_done, 1);
-            s->jump_size++;
+            var_object_test(ctx, s, var_name, op, bc, &label_done, 1);
         }
         idx = vd->scope_next;
     }
+    is_arg_scope = (idx == ARG_SCOPE_END);
     if (var_idx < 0) {
-        /* XXX: scoping issues:
-           should not resolve vars from the function body during argument parse,
-           `arguments` and function-name should not be hidden by later vars.
-         */
-        var_idx = find_var(ctx, s, var_name);
-        if (var_idx >= 0) {
-            if (scope_level == 0
-            &&  (var_idx & ARGUMENT_VAR_OFFSET)
-            &&  (var_idx - ARGUMENT_VAR_OFFSET) >= arg_valid) {
-                /* referring to an uninitialized argument */
-                dbuf_putc(bc, OP_throw_var);
-                dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
-                dbuf_putc(bc, JS_THROW_VAR_UNINITIALIZED);
-            }
-            if (!(var_idx & ARGUMENT_VAR_OFFSET))
-                is_func_var = s->vars[var_idx].is_func_var;
+        /* argument scope: variables are not visible but pseudo
+           variables are visible */
+        if (!is_arg_scope) {
+            var_idx = find_var(ctx, s, var_name);
         }
 
         if (var_idx < 0 && is_pseudo_var)
@@ -29448,21 +29535,31 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
         if (var_idx < 0 && var_name == JS_ATOM_arguments &&
             s->has_arguments_binding) {
             /* 'arguments' pseudo variable */
-            var_idx = add_arguments_var(ctx, s, var_name);
+            var_idx = add_arguments_var(ctx, s);
         }
         if (var_idx < 0 && s->is_func_expr && var_name == s->func_name) {
             /* add a new variable with the function name */
             var_idx = add_func_var(ctx, s, var_name);
-            is_func_var = TRUE;
         }
     }
     if (var_idx >= 0) {
+        if ((op == OP_scope_put_var || op == OP_scope_make_ref) &&
+            !(var_idx & ARGUMENT_VAR_OFFSET) &&
+            s->vars[var_idx].is_const) {
+            /* only happens when assigning a function expression name
+               in strict mode */
+            dbuf_putc(bc, OP_throw_error);
+            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
+            dbuf_putc(bc, JS_THROW_VAR_RO);
+            goto done;
+        }
         /* OP_scope_put_var_init is only used to initialize a
            lexical variable, so it is never used in a with or var object. It
            can be used with a closure (module global variable case). */
         switch (op) {
         case OP_scope_make_ref:
-            if (is_func_var) {
+            if (!(var_idx & ARGUMENT_VAR_OFFSET) &&
+                s->vars[var_idx].var_kind == JS_VAR_FUNCTION_NAME) {
                 /* Create a dummy object reference for the func_var */
                 dbuf_putc(bc, OP_object);
                 dbuf_putc(bc, OP_get_loc);
@@ -29510,7 +29607,6 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
             if (var_idx & ARGUMENT_VAR_OFFSET) {
                 dbuf_putc(bc, OP_get_arg + is_put);
                 dbuf_put_u16(bc, var_idx - ARGUMENT_VAR_OFFSET);
-                /* XXX: should test if argument reference needs TDZ check */
             } else {
                 if (is_put) {
                     if (s->vars[var_idx].is_lexical) {
@@ -29543,41 +29639,32 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
         goto done;
     }
     /* check eval object */
-    if (s->var_object_idx >= 0 && !is_pseudo_var) {
+    if (!is_arg_scope && s->var_object_idx >= 0 && !is_pseudo_var) {
         dbuf_putc(bc, OP_get_loc);
         dbuf_put_u16(bc, s->var_object_idx);
-        dbuf_putc(bc, get_with_scope_opcode(op));
-        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
-        label_done = new_label_fd(s, label_done);
-        dbuf_put_u32(bc, label_done);
-        dbuf_putc(bc, 0);
-        update_label(s, label_done, 1);
-        s->jump_size++;
+        var_object_test(ctx, s, var_name, op, bc, &label_done, 0);
+    }
+    /* check eval object in argument scope */
+    if (s->arg_var_object_idx >= 0 && !is_pseudo_var) {
+        dbuf_putc(bc, OP_get_loc);
+        dbuf_put_u16(bc, s->arg_var_object_idx);
+        var_object_test(ctx, s, var_name, op, bc, &label_done, 0);
     }
+
     /* check parent scopes */
     for (fd = s; fd->parent;) {
         scope_level = fd->parent_scope_level;
         fd = fd->parent;
-        if (scope_level == 0) {
-            /* function is defined as part of the argument parsing: hide vars
-               from the function body.
-               XXX: variables created from argument destructuring might need
-               to be visible, should refine this method.
-             */
-            var_idx = find_arg(ctx, fd, var_name);
-            goto check_idx;
-        }
         for (idx = fd->scopes[scope_level].first; idx >= 0;) {
             vd = &fd->vars[idx];
             if (vd->var_name == var_name) {
                 if (op == OP_scope_put_var || op == OP_scope_make_ref) {
                     if (vd->is_const) {
-                        dbuf_putc(bc, OP_throw_var);
+                        dbuf_putc(bc, OP_throw_error);
                         dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
                         dbuf_putc(bc, JS_THROW_VAR_RO);
                         goto done;
                     }
-                    is_func_var = vd->is_func_var;
                 }
                 var_idx = idx;
                 break;
@@ -29587,26 +29674,19 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
                 if (idx >= 0) {
                     dbuf_putc(bc, OP_get_var_ref);
                     dbuf_put_u16(bc, idx);
-                    dbuf_putc(bc, get_with_scope_opcode(op));
-                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
-                    label_done = new_label_fd(s, label_done);
-                    dbuf_put_u32(bc, label_done);
-                    dbuf_putc(bc, 1);
-                    update_label(s, label_done, 1);
-                    s->jump_size++;
+                    var_object_test(ctx, s, var_name, op, bc, &label_done, 1);
                 }
             }
             idx = vd->scope_next;
         }
+        is_arg_scope = (idx == ARG_SCOPE_END);
         if (var_idx >= 0)
             break;
-
-        var_idx = find_var(ctx, fd, var_name);
-    check_idx:
-        if (var_idx >= 0) {
-            if (!(var_idx & ARGUMENT_VAR_OFFSET))
-                is_func_var = fd->vars[var_idx].is_func_var;
-            break;
+        
+        if (!is_arg_scope) {
+            var_idx = find_var(ctx, fd, var_name);
+            if (var_idx >= 0)
+                break;
         }
         if (is_pseudo_var) {
             var_idx = resolve_pseudo_var(ctx, fd, var_name);
@@ -29614,33 +29694,39 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
                 break;
         }
         if (var_name == JS_ATOM_arguments && fd->has_arguments_binding) {
-            var_idx = add_arguments_var(ctx, fd, var_name);
+            var_idx = add_arguments_var(ctx, fd);
             break;
         }
         if (fd->is_func_expr && fd->func_name == var_name) {
             /* add a new variable with the function name */
             var_idx = add_func_var(ctx, fd, var_name);
-            is_func_var = TRUE;
             break;
         }
 
         /* check eval object */
-        if (fd->var_object_idx >= 0 && !is_pseudo_var) {
-            fd->vars[fd->var_object_idx].is_captured = 1;
+        if (!is_arg_scope && fd->var_object_idx >= 0 && !is_pseudo_var) {
+            vd = &fd->vars[fd->var_object_idx];
+            vd->is_captured = 1;
             idx = get_closure_var(ctx, s, fd, FALSE,
-                                  fd->var_object_idx, JS_ATOM__var_,
+                                  fd->var_object_idx, vd->var_name,
                                   FALSE, FALSE, JS_VAR_NORMAL);
             dbuf_putc(bc, OP_get_var_ref);
             dbuf_put_u16(bc, idx);
-            dbuf_putc(bc, get_with_scope_opcode(op));
-            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
-            label_done = new_label_fd(s, label_done);
-            dbuf_put_u32(bc, label_done);
-            dbuf_putc(bc, 0);
-            update_label(s, label_done, 1);
-            s->jump_size++;
+            var_object_test(ctx, s, var_name, op, bc, &label_done, 0);
         }
 
+        /* check eval object in argument scope */
+        if (fd->arg_var_object_idx >= 0 && !is_pseudo_var) {
+            vd = &fd->vars[fd->arg_var_object_idx];
+            vd->is_captured = 1;
+            idx = get_closure_var(ctx, s, fd, FALSE,
+                                  fd->arg_var_object_idx, vd->var_name,
+                                  FALSE, FALSE, JS_VAR_NORMAL);
+            dbuf_putc(bc, OP_get_var_ref);
+            dbuf_put_u16(bc, idx);
+            var_object_test(ctx, s, var_name, op, bc, &label_done, 0);
+        }
+        
         if (fd->is_eval)
             break; /* it it necessarily the top level function */
     }
@@ -29665,6 +29751,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
                 }
                 goto has_idx;
             } else if ((cv->var_name == JS_ATOM__var_ ||
+                        cv->var_name == JS_ATOM__arg_var_ ||
                         cv->var_name == JS_ATOM__with_) && !is_pseudo_var) {
                 int is_with = (cv->var_name == JS_ATOM__with_);
                 if (fd != s) {
@@ -29678,13 +29765,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
                 }
                 dbuf_putc(bc, OP_get_var_ref);
                 dbuf_put_u16(bc, idx);
-                dbuf_putc(bc, get_with_scope_opcode(op));
-                dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
-                label_done = new_label_fd(s, label_done);
-                dbuf_put_u32(bc, label_done);
-                dbuf_putc(bc, is_with);
-                update_label(s, label_done, 1);
-                s->jump_size++;
+                var_object_test(ctx, s, var_name, op, bc, &label_done, is_with);
             }
         }
     }
@@ -29709,14 +29790,14 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
         has_idx:
             if ((op == OP_scope_put_var || op == OP_scope_make_ref) &&
                 s->closure_var[idx].is_const) {
-                dbuf_putc(bc, OP_throw_var);
+                dbuf_putc(bc, OP_throw_error);
                 dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
                 dbuf_putc(bc, JS_THROW_VAR_RO);
                 goto done;
             }
             switch (op) {
             case OP_scope_make_ref:
-                if (is_func_var) {
+                if (s->closure_var[idx].var_kind == JS_VAR_FUNCTION_NAME) {
                     /* Create a dummy object reference for the func_var */
                     dbuf_putc(bc, OP_object);
                     dbuf_putc(bc, OP_get_var_ref);
@@ -29956,7 +30037,7 @@ static int resolve_scope_private_field(JSContext *ctx, JSFunctionDef *s,
             break;
         case JS_VAR_PRIVATE_SETTER:
             /* XXX: add clearer error message */
-            dbuf_putc(bc, OP_throw_var);
+            dbuf_putc(bc, OP_throw_error);
             dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
             dbuf_putc(bc, JS_THROW_VAR_RO);
             break;
@@ -29973,7 +30054,7 @@ static int resolve_scope_private_field(JSContext *ctx, JSFunctionDef *s,
         case JS_VAR_PRIVATE_METHOD:
         case JS_VAR_PRIVATE_GETTER:
             /* XXX: add clearer error message */
-            dbuf_putc(bc, OP_throw_var);
+            dbuf_putc(bc, OP_throw_error);
             dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
             dbuf_putc(bc, JS_THROW_VAR_RO);
             break;
@@ -30025,17 +30106,33 @@ static void mark_eval_captured_variables(JSContext *ctx, JSFunctionDef *s,
     }
 }
 
+/* XXX: should handle the argument scope generically */
+static BOOL is_var_in_arg_scope(const JSVarDef *vd)
+{
+    return (vd->var_name == JS_ATOM_home_object ||
+            vd->var_name == JS_ATOM_this_active_func ||
+            vd->var_name == JS_ATOM_new_target ||
+            vd->var_name == JS_ATOM_this ||
+            vd->var_name == JS_ATOM__arg_var_ ||
+            vd->var_kind == JS_VAR_FUNCTION_NAME);
+}
+
 static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
 {
     JSFunctionDef *fd;
     JSVarDef *vd;
     int i, scope_level, scope_idx;
-    BOOL has_arguments_binding, has_this_binding;
+    BOOL has_arguments_binding, has_this_binding, is_arg_scope;
 
     /* in non strict mode, variables are created in the caller's
        environment object */
     if (!s->is_eval && !(s->js_mode & JS_MODE_STRICT)) {
         s->var_object_idx = add_var(ctx, s, JS_ATOM__var_);
+        if (s->has_parameter_expressions) {
+            /* an additional variable object is needed for the
+               argument scope */
+            s->arg_var_object_idx = add_var(ctx, s, JS_ATOM__arg_var_);
+        }
     }
 
     /* eval can potentially use 'arguments' so we must define it */
@@ -30051,8 +30148,14 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
             s->home_object_var_idx = add_var(ctx, s, JS_ATOM_home_object);
     }
     has_arguments_binding = s->has_arguments_binding;
-    if (has_arguments_binding)
-        add_arguments_var(ctx, s, JS_ATOM_arguments);
+    if (has_arguments_binding) {
+        add_arguments_var(ctx, s);
+        /* also add an arguments binding in the argument scope to
+           raise an error if a direct eval in the argument scope tries
+           to redefine it */
+        if (s->has_parameter_expressions && !(s->js_mode & JS_MODE_STRICT))
+            add_arguments_arg(ctx, s);
+    }
     if (s->is_func_expr && s->func_name != JS_ATOM_NULL)
         add_func_var(ctx, s, s->func_name);
 
@@ -30069,7 +30172,6 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
         fd = fd->parent;
         if (!fd)
             break;
-        scope_idx = fd->scopes[scope_level].first;
         /* add 'this' if it was not previously added */
         if (!has_this_binding && fd->has_this_binding) {
             if (fd->this_var_idx < 0)
@@ -30084,7 +30186,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
         }
         /* add 'arguments' if it was not previously added */
         if (!has_arguments_binding && fd->has_arguments_binding) {
-            add_arguments_var(ctx, fd, JS_ATOM_arguments);
+            add_arguments_var(ctx, fd);
             has_arguments_binding = TRUE;
         }
         /* add function name */
@@ -30092,6 +30194,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
             add_func_var(ctx, fd, fd->func_name);
 
         /* add lexical variables */
+        scope_idx = fd->scopes[scope_level].first;
         while (scope_idx >= 0) {
             vd = &fd->vars[scope_idx];
             vd->is_captured = 1;
@@ -30099,24 +30202,37 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
                             vd->var_name, vd->is_const, vd->is_lexical, vd->var_kind);
             scope_idx = vd->scope_next;
         }
-        /* add unscoped variables */
-        for(i = 0; i < fd->arg_count; i++) {
-            vd = &fd->args[i];
-            if (vd->var_name != JS_ATOM_NULL) {
-                get_closure_var(ctx, s, fd,
-                                TRUE, i, vd->var_name, FALSE, FALSE,
-                                JS_VAR_NORMAL);
+        is_arg_scope = (scope_idx == ARG_SCOPE_END);
+        if (!is_arg_scope) {
+            /* add unscoped variables */
+            for(i = 0; i < fd->arg_count; i++) {
+                vd = &fd->args[i];
+                if (vd->var_name != JS_ATOM_NULL) {
+                    get_closure_var(ctx, s, fd,
+                                    TRUE, i, vd->var_name, FALSE, FALSE,
+                                    JS_VAR_NORMAL);
+                }
             }
-        }
-        for(i = 0; i < fd->var_count; i++) {
-            vd = &fd->vars[i];
-            /* do not close top level last result */
-            if (vd->scope_level == 0 &&
-                vd->var_name != JS_ATOM__ret_ &&
-                vd->var_name != JS_ATOM_NULL) {
-                get_closure_var(ctx, s, fd,
-                                FALSE, i, vd->var_name, FALSE, FALSE,
-                                JS_VAR_NORMAL);
+            for(i = 0; i < fd->var_count; i++) {
+                vd = &fd->vars[i];
+                /* do not close top level last result */
+                if (vd->scope_level == 0 &&
+                    vd->var_name != JS_ATOM__ret_ &&
+                    vd->var_name != JS_ATOM_NULL) {
+                    get_closure_var(ctx, s, fd,
+                                    FALSE, i, vd->var_name, FALSE, FALSE,
+                                    JS_VAR_NORMAL);
+                }
+            }
+        } else {
+            for(i = 0; i < fd->var_count; i++) {
+                vd = &fd->vars[i];
+                /* do not close top level last result */
+                if (vd->scope_level == 0 && is_var_in_arg_scope(vd)) {
+                    get_closure_var(ctx, s, fd,
+                                    FALSE, i, vd->var_name, FALSE, FALSE,
+                                    JS_VAR_NORMAL);
+                }
             }
         }
         if (fd->is_eval) {
@@ -30134,6 +30250,18 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
     }
 }
 
+static void set_closure_from_var(JSContext *ctx, JSClosureVar *cv,
+                                 JSVarDef *vd, int var_idx)
+{
+    cv->is_local = TRUE;
+    cv->is_arg = FALSE;
+    cv->is_const = vd->is_const;
+    cv->is_lexical = vd->is_lexical;
+    cv->var_kind = vd->var_kind;
+    cv->var_idx = var_idx;
+    cv->var_name = JS_DupAtom(ctx, vd->var_name);
+}
+
 /* for direct eval compilation: add references to the variables of the
    calling function */
 static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
@@ -30141,7 +30269,8 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
 {
     int i, count;
     JSVarDef *vd;
-
+    BOOL is_arg_scope;
+    
     count = b->arg_count + b->var_count + b->closure_var_count;
     s->closure_var = NULL;
     s->closure_var_count = 0;
@@ -30156,41 +30285,41 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
         vd = &b->vardefs[b->arg_count + i];
         if (vd->scope_level > 0) {
             JSClosureVar *cv = &s->closure_var[s->closure_var_count++];
-            cv->is_local = TRUE;
-            cv->is_arg = FALSE;
-            cv->is_const = vd->is_const;
-            cv->is_lexical = vd->is_lexical;
-            cv->var_kind = vd->var_kind;
-            cv->var_idx = i;
-            cv->var_name = JS_DupAtom(ctx, vd->var_name);
+            set_closure_from_var(ctx, cv, vd, i);
         }
         i = vd->scope_next;
     }
-    /* Add argument variables */
-    for(i = 0; i < b->arg_count; i++) {
-        JSClosureVar *cv = &s->closure_var[s->closure_var_count++];
-        vd = &b->vardefs[i];
-        cv->is_local = TRUE;
-        cv->is_arg = TRUE;
-        cv->is_const = FALSE;
-        cv->is_lexical = FALSE;
-        cv->var_kind = JS_VAR_NORMAL;
-        cv->var_idx = i;
-        cv->var_name = JS_DupAtom(ctx, vd->var_name);
-    }
-    /* Add local non lexical variables */
-    for(i = 0; i < b->var_count; i++) {
-        vd = &b->vardefs[b->arg_count + i];
-        if (vd->scope_level == 0 && vd->var_name != JS_ATOM__ret_) {
+    is_arg_scope = (i == ARG_SCOPE_END);
+    if (!is_arg_scope) {
+        /* Add argument variables */
+        for(i = 0; i < b->arg_count; i++) {
             JSClosureVar *cv = &s->closure_var[s->closure_var_count++];
+            vd = &b->vardefs[i];
             cv->is_local = TRUE;
-            cv->is_arg = FALSE;
+            cv->is_arg = TRUE;
             cv->is_const = FALSE;
             cv->is_lexical = FALSE;
             cv->var_kind = JS_VAR_NORMAL;
             cv->var_idx = i;
             cv->var_name = JS_DupAtom(ctx, vd->var_name);
         }
+        /* Add local non lexical variables */
+        for(i = 0; i < b->var_count; i++) {
+            vd = &b->vardefs[b->arg_count + i];
+            if (vd->scope_level == 0 && vd->var_name != JS_ATOM__ret_) {
+                JSClosureVar *cv = &s->closure_var[s->closure_var_count++];
+                set_closure_from_var(ctx, cv, vd, i);
+            }
+        }
+    } else {
+        /* only add pseudo variables */
+        for(i = 0; i < b->var_count; i++) {
+            vd = &b->vardefs[b->arg_count + i];
+            if (vd->scope_level == 0 && is_var_in_arg_scope(vd)) {
+                JSClosureVar *cv = &s->closure_var[s->closure_var_count++];
+                set_closure_from_var(ctx, cv, vd, i);
+            }
+        }
     }
     for(i = 0; i < b->closure_var_count; i++) {
         JSClosureVar *cv0 = &b->closure_var[i];
@@ -30348,59 +30477,93 @@ static BOOL code_match(CodeContext *s, int pos, ...)
 
 static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, DynBuf *bc)
 {
-    int i, idx, var_idx;
+    int i, idx, label_next = -1;
+
+    /* add the hoisted functions in arguments and local variables */
+    for(i = 0; i < s->arg_count; i++) {
+        JSVarDef *vd = &s->args[i];
+        if (vd->func_pool_idx >= 0) {
+            dbuf_putc(bc, OP_fclosure);
+            dbuf_put_u32(bc, vd->func_pool_idx);
+            dbuf_putc(bc, OP_put_arg);
+            dbuf_put_u16(bc, i);
+        }
+    }
+    for(i = 0; i < s->var_count; i++) {
+        JSVarDef *vd = &s->vars[i];
+        if (vd->scope_level == 0 && vd->func_pool_idx >= 0) {
+            dbuf_putc(bc, OP_fclosure);
+            dbuf_put_u32(bc, vd->func_pool_idx);
+            dbuf_putc(bc, OP_put_loc);
+            dbuf_put_u16(bc, i);
+        }
+    }
 
-    /* add the hoisted functions and variables */
-    for(i = 0; i < s->hoisted_def_count; i++) {
-        JSHoistedDef *hf = &s->hoisted_def[i];
+    /* the module global variables must be initialized before
+       evaluating the module so that the exported functions are
+       visible if there are cyclic module references */
+    if (s->module) {
+        label_next = new_label_fd(s, -1);
+        
+        /* if 'this' is true, initialize the global variables and return */
+        dbuf_putc(bc, OP_push_this);
+        dbuf_putc(bc, OP_if_false);
+        dbuf_put_u32(bc, label_next);
+        update_label(s, label_next, 1);
+        s->jump_size++;
+    }
+    
+    /* add the global variables (only happens if s->is_global_var is
+       true) */
+    for(i = 0; i < s->global_var_count; i++) {
+        JSGlobalVar *hf = &s->global_vars[i];
         int has_closure = 0;
         BOOL force_init = hf->force_init;
-        if (s->is_global_var && hf->var_name != JS_ATOM_NULL) {
-            /* we are in an eval, so the closure contains all the
-               enclosing variables */
-            /* If the outer function has a variable environment,
-               create a property for the variable there */
-            for(idx = 0; idx < s->closure_var_count; idx++) {
-                JSClosureVar *cv = &s->closure_var[idx];
-                if (cv->var_name == hf->var_name) {
-                    has_closure = 2;
-                    force_init = FALSE;
-                    break;
-                }
-                if (cv->var_name == JS_ATOM__var_) {
-                    dbuf_putc(bc, OP_get_var_ref);
-                    dbuf_put_u16(bc, idx);
-                    has_closure = 1;
-                    force_init = TRUE;
-                    break;
-                }
+        /* we are in an eval, so the closure contains all the
+           enclosing variables */
+        /* If the outer function has a variable environment,
+           create a property for the variable there */
+        for(idx = 0; idx < s->closure_var_count; idx++) {
+            JSClosureVar *cv = &s->closure_var[idx];
+            if (cv->var_name == hf->var_name) {
+                has_closure = 2;
+                force_init = FALSE;
+                break;
             }
-            if (!has_closure) {
-                int flags;
-
-                flags = 0;
-                if (s->eval_type != JS_EVAL_TYPE_GLOBAL)
-                    flags |= JS_PROP_CONFIGURABLE;
-                if (hf->cpool_idx >= 0 && !hf->is_lexical) {
-                    /* global function definitions need a specific handling */
-                    dbuf_putc(bc, OP_fclosure);
-                    dbuf_put_u32(bc, hf->cpool_idx);
-
-                    dbuf_putc(bc, OP_define_func);
-                    dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));
-                    dbuf_putc(bc, flags);
-
-                    goto done_hoisted_def;
-                } else {
-                    if (hf->is_lexical) {
-                        flags |= DEFINE_GLOBAL_LEX_VAR;
-                        if (!hf->is_const)
-                            flags |= JS_PROP_WRITABLE;
-                    }
-                    dbuf_putc(bc, OP_define_var);
-                    dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));
-                    dbuf_putc(bc, flags);
+            if (cv->var_name == JS_ATOM__var_ ||
+                cv->var_name == JS_ATOM__arg_var_) {
+                dbuf_putc(bc, OP_get_var_ref);
+                dbuf_put_u16(bc, idx);
+                has_closure = 1;
+                force_init = TRUE;
+                break;
+            }
+        }
+        if (!has_closure) {
+            int flags;
+            
+            flags = 0;
+            if (s->eval_type != JS_EVAL_TYPE_GLOBAL)
+                flags |= JS_PROP_CONFIGURABLE;
+            if (hf->cpool_idx >= 0 && !hf->is_lexical) {
+                /* global function definitions need a specific handling */
+                dbuf_putc(bc, OP_fclosure);
+                dbuf_put_u32(bc, hf->cpool_idx);
+                
+                dbuf_putc(bc, OP_define_func);
+                dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));
+                dbuf_putc(bc, flags);
+                
+                goto done_global_var;
+            } else {
+                if (hf->is_lexical) {
+                    flags |= DEFINE_GLOBAL_LEX_VAR;
+                    if (!hf->is_const)
+                        flags |= JS_PROP_WRITABLE;
                 }
+                dbuf_putc(bc, OP_define_var);
+                dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));
+                dbuf_putc(bc, flags);
             }
         }
         if (hf->cpool_idx >= 0 || force_init) {
@@ -30415,37 +30578,35 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy
             } else {
                 dbuf_putc(bc, OP_undefined);
             }
-            if (s->is_global_var) {
-                if (has_closure == 2) {
-                    dbuf_putc(bc, OP_put_var_ref);
-                    dbuf_put_u16(bc, idx);
-                } else if (has_closure == 1) {
-                    dbuf_putc(bc, OP_define_field);
-                    dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));
-                    dbuf_putc(bc, OP_drop);
-                } else {
-                    /* XXX: Check if variable is writable and enumerable */
-                    dbuf_putc(bc, OP_put_var);
-                    dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));
-                }
+            if (has_closure == 2) {
+                dbuf_putc(bc, OP_put_var_ref);
+                dbuf_put_u16(bc, idx);
+            } else if (has_closure == 1) {
+                dbuf_putc(bc, OP_define_field);
+                dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));
+                dbuf_putc(bc, OP_drop);
             } else {
-                var_idx = hf->var_idx;
-                if (var_idx & ARGUMENT_VAR_OFFSET) {
-                    dbuf_putc(bc, OP_put_arg);
-                    dbuf_put_u16(bc, var_idx - ARGUMENT_VAR_OFFSET);
-                } else {
-                    dbuf_putc(bc, OP_put_loc);
-                    dbuf_put_u16(bc, var_idx);
-                }
+                /* XXX: Check if variable is writable and enumerable */
+                dbuf_putc(bc, OP_put_var);
+                dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));
             }
         }
-    done_hoisted_def:
+    done_global_var:
         JS_FreeAtom(ctx, hf->var_name);
     }
-    js_free(ctx, s->hoisted_def);
-    s->hoisted_def = NULL;
-    s->hoisted_def_count = 0;
-    s->hoisted_def_size = 0;
+
+    if (s->module) {
+        dbuf_putc(bc, OP_return_undef);
+        
+        dbuf_putc(bc, OP_label);
+        dbuf_put_u32(bc, label_next);
+        s->label_slots[label_next].pos2 = bc->size;
+    }
+
+    js_free(ctx, s->global_vars);
+    s->global_vars = NULL;
+    s->global_var_count = 0;
+    s->global_var_size = 0;
 }
 
 static int skip_dead_code(JSFunctionDef *s, const uint8_t *bc_buf, int bc_len,
@@ -30525,7 +30686,7 @@ static int get_label_pos(JSFunctionDef *s, int label)
    variables when necessary */
 static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
 {
-    int pos, pos_next, bc_len, op, len, i, idx, arg_valid, line_num;
+    int pos, pos_next, bc_len, op, len, i, idx, line_num;
     uint8_t *bc_buf;
     JSAtom var_name;
     DynBuf bc_out;
@@ -30538,47 +30699,43 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
 
     /* first pass for runtime checks (must be done before the
        variables are created) */
-    if (s->is_global_var) {
-        for(i = 0; i < s->hoisted_def_count; i++) {
-            JSHoistedDef *hf = &s->hoisted_def[i];
-            int flags;
-
-            if (hf->var_name != JS_ATOM_NULL) {
-                /* check if global variable (XXX: simplify) */
-                for(idx = 0; idx < s->closure_var_count; idx++) {
-                    JSClosureVar *cv = &s->closure_var[idx];
-                    if (cv->var_name == hf->var_name) {
-                        if (s->eval_type == JS_EVAL_TYPE_DIRECT &&
-                            cv->is_lexical) {
-                            /* Check if a lexical variable is
-                               redefined as 'var'. XXX: Could abort
-                               compilation here, but for consistency
-                               with the other checks, we delay the
-                               error generation. */
-                            dbuf_putc(&bc_out, OP_throw_var);
-                            dbuf_put_u32(&bc_out, JS_DupAtom(ctx, hf->var_name));
-                            dbuf_putc(&bc_out, JS_THROW_VAR_REDECL);
-                        }
-                        goto next;
-                    }
-                    if (cv->var_name == JS_ATOM__var_)
-                        goto next;
+    for(i = 0; i < s->global_var_count; i++) {
+        JSGlobalVar *hf = &s->global_vars[i];
+        int flags;
+        
+        /* check if global variable (XXX: simplify) */
+        for(idx = 0; idx < s->closure_var_count; idx++) {
+            JSClosureVar *cv = &s->closure_var[idx];
+            if (cv->var_name == hf->var_name) {
+                if (s->eval_type == JS_EVAL_TYPE_DIRECT &&
+                    cv->is_lexical) {
+                    /* Check if a lexical variable is
+                       redefined as 'var'. XXX: Could abort
+                       compilation here, but for consistency
+                       with the other checks, we delay the
+                       error generation. */
+                    dbuf_putc(&bc_out, OP_throw_error);
+                    dbuf_put_u32(&bc_out, JS_DupAtom(ctx, hf->var_name));
+                    dbuf_putc(&bc_out, JS_THROW_VAR_REDECL);
                 }
-
-                dbuf_putc(&bc_out, OP_check_define_var);
-                dbuf_put_u32(&bc_out, JS_DupAtom(ctx, hf->var_name));
-                flags = 0;
-                if (hf->is_lexical)
-                    flags |= DEFINE_GLOBAL_LEX_VAR;
-                if (hf->cpool_idx >= 0)
-                    flags |= DEFINE_GLOBAL_FUNC_VAR;
-                dbuf_putc(&bc_out, flags);
+                goto next;
             }
-        next: ;
+            if (cv->var_name == JS_ATOM__var_ ||
+                cv->var_name == JS_ATOM__arg_var_)
+                goto next;
         }
+        
+        dbuf_putc(&bc_out, OP_check_define_var);
+        dbuf_put_u32(&bc_out, JS_DupAtom(ctx, hf->var_name));
+        flags = 0;
+        if (hf->is_lexical)
+            flags |= DEFINE_GLOBAL_LEX_VAR;
+        if (hf->cpool_idx >= 0)
+            flags |= DEFINE_GLOBAL_FUNC_VAR;
+        dbuf_putc(&bc_out, flags);
+    next: ;
     }
 
-    arg_valid = 0;
     line_num = 0; /* avoid warning */
     for (pos = 0; pos < bc_len; pos = pos_next) {
         op = bc_buf[pos];
@@ -30590,9 +30747,6 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
             s->line_number_size++;
             goto no_change;
 
-        case OP_set_arg_valid_upto:
-            arg_valid = get_u16(bc_buf + pos + 1);
-            break;
         case OP_eval: /* convert scope index to adjusted variable index */
             {
                 int call_argc = get_u16(bc_buf + pos + 1);
@@ -30618,7 +30772,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
             var_name = get_u32(bc_buf + pos + 1);
             scope = get_u16(bc_buf + pos + 5);
             pos_next = resolve_scope_var(ctx, s, var_name, scope, op, &bc_out,
-                                         NULL, NULL, pos_next, arg_valid);
+                                         NULL, NULL, pos_next);
             JS_FreeAtom(ctx, var_name);
             break;
         case OP_scope_make_ref:
@@ -30631,7 +30785,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
                 ls = &s->label_slots[label];
                 ls->ref_count--;  /* always remove label reference */
                 pos_next = resolve_scope_var(ctx, s, var_name, scope, op, &bc_out,
-                                             bc_buf, ls, pos_next, arg_valid);
+                                             bc_buf, ls, pos_next);
                 JS_FreeAtom(ctx, var_name);
             }
             break;
@@ -30712,7 +30866,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
         case OP_return:
         case OP_return_undef:
         case OP_throw:
-        case OP_throw_var:
+        case OP_throw_error:
         case OP_ret:
             if (OPTIMIZE) {
                 /* remove dead code */
@@ -30746,25 +30900,27 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
             {
                 int scope_idx, scope = get_u16(bc_buf + pos + 1);
 
-                if (scope == 1) {
+                if (scope == s->body_scope) {
                     instantiate_hoisted_definitions(ctx, s, &bc_out);
                 }
 
                 for(scope_idx = s->scopes[scope].first; scope_idx >= 0;) {
                     JSVarDef *vd = &s->vars[scope_idx];
                     if (vd->scope_level == scope) {
-                        if (vd->var_kind == JS_VAR_FUNCTION_DECL ||
-                            vd->var_kind == JS_VAR_NEW_FUNCTION_DECL) {
-                            /* Initialize lexical variable upon entering scope */
-                            dbuf_putc(&bc_out, OP_fclosure);
-                            dbuf_put_u32(&bc_out, vd->func_pool_or_scope_idx);
-                            dbuf_putc(&bc_out, OP_put_loc);
-                            dbuf_put_u16(&bc_out, scope_idx);
-                        } else {
-                            /* XXX: should check if variable can be used
-                               before initialization */
-                            dbuf_putc(&bc_out, OP_set_loc_uninitialized);
-                            dbuf_put_u16(&bc_out, scope_idx);
+                        if (scope_idx != s->arguments_arg_idx) {
+                            if (vd->var_kind == JS_VAR_FUNCTION_DECL ||
+                                vd->var_kind == JS_VAR_NEW_FUNCTION_DECL) {
+                                /* Initialize lexical variable upon entering scope */
+                                dbuf_putc(&bc_out, OP_fclosure);
+                                dbuf_put_u32(&bc_out, vd->func_pool_idx);
+                                dbuf_putc(&bc_out, OP_put_loc);
+                                dbuf_put_u16(&bc_out, scope_idx);
+                            } else {
+                                /* XXX: should check if variable can be used
+                                   before initialization */
+                                dbuf_putc(&bc_out, OP_set_loc_uninitialized);
+                                dbuf_put_u16(&bc_out, scope_idx);
+                            }
                         }
                         scope_idx = vd->scope_next;
                     } else {
@@ -31167,6 +31323,8 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
             dbuf_putc(&bc_out, OP_special_object);
             dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS);
         }
+        if (s->arguments_arg_idx >= 0)
+            put_short_code(&bc_out, OP_set_loc, s->arguments_arg_idx);
         put_short_code(&bc_out, OP_put_loc, s->arguments_var_idx);
     }
     /* initialize a reference to the current function if needed */
@@ -31181,6 +31339,11 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
         dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_VAR_OBJECT);
         put_short_code(&bc_out, OP_put_loc, s->var_object_idx);
     }
+    if (s->arg_var_object_idx >= 0) {
+        dbuf_putc(&bc_out, OP_special_object);
+        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_VAR_OBJECT);
+        put_short_code(&bc_out, OP_put_loc, s->arg_var_object_idx);
+    }
 
     for (pos = 0; pos < bc_len; pos = pos_next) {
         int val;
@@ -31248,7 +31411,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
         case OP_return_undef:
         case OP_return_async:
         case OP_throw:
-        case OP_throw_var:
+        case OP_throw_error:
             pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num);
             goto no_change;
 
@@ -31969,56 +32132,91 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
 /* compute the maximum stack size needed by the function */
 
 typedef struct StackSizeState {
+    int bc_len;
     int stack_len_max;
     uint16_t *stack_level_tab;
+    int *pc_stack;
+    int pc_stack_len;
+    int pc_stack_size;
 } StackSizeState;
 
-static __exception int compute_stack_size_rec(JSContext *ctx,
-                                              JSFunctionDef *fd,
-                                              StackSizeState *s,
-                                              int pos, int op, int stack_len)
+/* 'op' is only used for error indication */
+static __exception int ss_check(JSContext *ctx, StackSizeState *s,
+                                int pos, int op, int stack_len)
 {
-    int bc_len, diff, n_pop, pos_next;
-    const JSOpCode *oi;
-    const uint8_t *bc_buf;
-
+    if ((unsigned)pos >= s->bc_len) {
+        JS_ThrowInternalError(ctx, "bytecode buffer overflow (op=%d, pc=%d)", op, pos);
+        return -1;
+    }
     if (stack_len > s->stack_len_max) {
         s->stack_len_max = stack_len;
-        if (s->stack_len_max > JS_STACK_SIZE_MAX)
-            goto stack_overflow;
+        if (s->stack_len_max > JS_STACK_SIZE_MAX) {
+            JS_ThrowInternalError(ctx, "stack overflow (op=%d, pc=%d)", op, pos);
+            return -1;
+        }
     }
-    bc_buf = fd->byte_code.buf;
-    bc_len = fd->byte_code.size;
-    for(;;) {
-        if ((unsigned)pos >= bc_len)
-            goto buf_overflow;
-#if 0
-        printf("%5d: %d\n", pos, stack_len);
-#endif
-        if (s->stack_level_tab[pos] != 0xffff) {
-            /* already explored: check that the stack size is consistent */
-            if (s->stack_level_tab[pos] != stack_len) {
-                JS_ThrowInternalError(ctx, "unconsistent stack size: %d %d (pc=%d)",
-                                      s->stack_level_tab[pos], stack_len, pos);
-                return -1;
-            } else {
-                return 0;
-            }
+    if (s->stack_level_tab[pos] != 0xffff) {
+        /* already explored: check that the stack size is consistent */
+        if (s->stack_level_tab[pos] != stack_len) {
+            JS_ThrowInternalError(ctx, "unconsistent stack size: %d %d (pc=%d)",
+                                  s->stack_level_tab[pos], stack_len, pos);
+            return -1;
         } else {
-            s->stack_level_tab[pos] = stack_len;
+            return 0;
         }
+    }
+
+    /* mark as explored and store the stack size */
+    s->stack_level_tab[pos] = stack_len;
+
+    /* queue the new PC to explore */
+    if (js_resize_array(ctx, (void **)&s->pc_stack, sizeof(s->pc_stack[0]),
+                        &s->pc_stack_size, s->pc_stack_len + 1))
+        return -1;
+    s->pc_stack[s->pc_stack_len++] = pos;
+    return 0;
+}
+
+static __exception int compute_stack_size(JSContext *ctx,
+                                          JSFunctionDef *fd,
+                                          int *pstack_size)
+{
+    StackSizeState s_s, *s = &s_s;
+    int i, diff, n_pop, pos_next, stack_len, pos, op;
+    const JSOpCode *oi;
+    const uint8_t *bc_buf;
+
+    bc_buf = fd->byte_code.buf;
+    s->bc_len = fd->byte_code.size;
+    /* bc_len > 0 */
+    s->stack_level_tab = js_malloc(ctx, sizeof(s->stack_level_tab[0]) *
+                                   s->bc_len);
+    if (!s->stack_level_tab)
+        return -1;
+    for(i = 0; i < s->bc_len; i++)
+        s->stack_level_tab[i] = 0xffff;
+    s->stack_len_max = 0;
+    s->pc_stack = NULL;
+    s->pc_stack_len = 0;
+    s->pc_stack_size = 0;
 
+    /* breadth-first graph exploration */
+    if (ss_check(ctx, s, 0, OP_invalid, 0))
+        goto fail;
+
+    while (s->pc_stack_len > 0) {
+        pos = s->pc_stack[--s->pc_stack_len];
+        stack_len = s->stack_level_tab[pos];
         op = bc_buf[pos];
         if (op == 0 || op >= OP_COUNT) {
             JS_ThrowInternalError(ctx, "invalid opcode (op=%d, pc=%d)", op, pos);
-            return -1;
+            goto fail;
         }
         oi = &short_opcode_info(op);
         pos_next = pos + oi->size;
-        if (pos_next > bc_len) {
-        buf_overflow:
+        if (pos_next > s->bc_len) {
             JS_ThrowInternalError(ctx, "bytecode buffer overflow (op=%d, pc=%d)", op, pos);
-            return -1;
+            goto fail;
         }
         n_pop = oi->n_pop;
         /* call pops a variable number of arguments */
@@ -32034,13 +32232,15 @@ static __exception int compute_stack_size_rec(JSContext *ctx,
 
         if (stack_len < n_pop) {
             JS_ThrowInternalError(ctx, "stack underflow (op=%d, pc=%d)", op, pos);
-            return -1;
+            goto fail;
         }
         stack_len += oi->n_push - n_pop;
         if (stack_len > s->stack_len_max) {
             s->stack_len_max = stack_len;
-            if (s->stack_len_max > JS_STACK_SIZE_MAX)
-                goto stack_overflow;
+            if (s->stack_len_max > JS_STACK_SIZE_MAX) {
+                JS_ThrowInternalError(ctx, "stack overflow (op=%d, pc=%d)", op, pos);
+                goto fail;
+            }
         }
         switch(op) {
         case OP_tail_call:
@@ -32049,9 +32249,9 @@ static __exception int compute_stack_size_rec(JSContext *ctx,
         case OP_return_undef:
         case OP_return_async:
         case OP_throw:
-        case OP_throw_var:
+        case OP_throw_error:
         case OP_ret:
-            goto done;
+            goto done_insn;
         case OP_goto:
             diff = get_u32(bc_buf + pos + 1);
             pos_next = pos + 1 + diff;
@@ -32068,73 +32268,57 @@ static __exception int compute_stack_size_rec(JSContext *ctx,
         case OP_if_true8:
         case OP_if_false8:
             diff = (int8_t)bc_buf[pos + 1];
-            if (compute_stack_size_rec(ctx, fd, s, pos + 1 + diff, op, stack_len))
-                return -1;
+            if (ss_check(ctx, s, pos + 1 + diff, op, stack_len))
+                goto fail;
             break;
 #endif
         case OP_if_true:
         case OP_if_false:
         case OP_catch:
             diff = get_u32(bc_buf + pos + 1);
-            if (compute_stack_size_rec(ctx, fd, s, pos + 1 + diff, op, stack_len))
-                return -1;
+            if (ss_check(ctx, s, pos + 1 + diff, op, stack_len))
+                goto fail;
             break;
         case OP_gosub:
             diff = get_u32(bc_buf + pos + 1);
-            if (compute_stack_size_rec(ctx, fd, s, pos + 1 + diff, op, stack_len + 1))
-                return -1;
+            if (ss_check(ctx, s, pos + 1 + diff, op, stack_len + 1))
+                goto fail;
             break;
         case OP_with_get_var:
         case OP_with_delete_var:
             diff = get_u32(bc_buf + pos + 5);
-            if (compute_stack_size_rec(ctx, fd, s, pos + 5 + diff, op, stack_len + 1))
-                return -1;
+            if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 1))
+                goto fail;
             break;
         case OP_with_make_ref:
         case OP_with_get_ref:
         case OP_with_get_ref_undef:
             diff = get_u32(bc_buf + pos + 5);
-            if (compute_stack_size_rec(ctx, fd, s, pos + 5 + diff, op, stack_len + 2))
-                return -1;
+            if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 2))
+                goto fail;
             break;
         case OP_with_put_var:
             diff = get_u32(bc_buf + pos + 5);
-            if (compute_stack_size_rec(ctx, fd, s, pos + 5 + diff, op, stack_len - 1))
-                return -1;
+            if (ss_check(ctx, s, pos + 5 + diff, op, stack_len - 1))
+                goto fail;
             break;
 
         default:
             break;
         }
-        pos = pos_next;
+        if (ss_check(ctx, s, pos_next, op, stack_len))
+            goto fail;
+    done_insn: ;
     }
- done:
-    return 0;
-
- stack_overflow:
-    JS_ThrowInternalError(ctx, "stack overflow (op=%d, pc=%d)", op, pos);
-    return -1;
-}
-
-static __exception int compute_stack_size(JSContext *ctx,
-                                          JSFunctionDef *fd,
-                                          int *pstack_size)
-{
-    StackSizeState s_s, *s = &s_s;
-    int bc_len, i, ret;
-
-    bc_len = fd->byte_code.size;
-    /* bc_len > 0 */
-    s->stack_level_tab = js_malloc(ctx, sizeof(s->stack_level_tab[0]) * bc_len);
-    if (!s->stack_level_tab)
-        return -1;
-    for(i = 0; i < bc_len; i++)
-        s->stack_level_tab[i] = 0xffff;
-    s->stack_len_max = 0;
-    ret = compute_stack_size_rec(ctx, fd, s, 0, OP_invalid, 0);
     js_free(ctx, s->stack_level_tab);
+    js_free(ctx, s->pc_stack);
     *pstack_size = s->stack_len_max;
-    return ret;
+    return 0;
+ fail:
+    js_free(ctx, s->stack_level_tab);
+    js_free(ctx, s->pc_stack);
+    *pstack_size = 0;
+    return -1;
 }
 
 static int add_module_variables(JSContext *ctx, JSFunctionDef *fd)
@@ -32142,14 +32326,14 @@ static int add_module_variables(JSContext *ctx, JSFunctionDef *fd)
     int i, idx;
     JSModuleDef *m = fd->module;
     JSExportEntry *me;
-    JSHoistedDef *hf;
+    JSGlobalVar *hf;
 
     /* The imported global variables were added as closure variables
        in js_parse_import(). We add here the module global
        variables. */
 
-    for(i = 0; i < fd->hoisted_def_count; i++) {
-        hf = &fd->hoisted_def[i];
+    for(i = 0; i < fd->global_var_count; i++) {
+        hf = &fd->global_vars[i];
         if (add_closure_var(ctx, fd, TRUE, FALSE, i, hf->var_name, hf->is_const,
                             hf->is_lexical, FALSE) < 0)
             return -1;
@@ -32187,6 +32371,10 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
     for (scope = 0; scope < fd->scope_count; scope++) {
         fd->scopes[scope].first = -1;
     }
+    if (fd->has_parameter_expressions) {
+        /* special end of variable list marker for the argument scope */
+        fd->scopes[ARG_SCOPE_INDEX].first = ARG_SCOPE_END;
+    }
     for (idx = 0; idx < fd->var_count; idx++) {
         JSVarDef *vd = &fd->vars[idx];
         vd->scope_next = fd->scopes[vd->scope_level].first;
@@ -32194,12 +32382,12 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
     }
     for (scope = 2; scope < fd->scope_count; scope++) {
         JSVarScope *sd = &fd->scopes[scope];
-        if (sd->first == -1)
+        if (sd->first < 0)
             sd->first = fd->scopes[sd->parent].first;
     }
     for (idx = 0; idx < fd->var_count; idx++) {
         JSVarDef *vd = &fd->vars[idx];
-        if (vd->scope_next == -1 && vd->scope_level > 1) {
+        if (vd->scope_next < 0 && vd->scope_level > 1) {
             scope = fd->scopes[vd->scope_level].parent;
             vd->scope_next = fd->scopes[scope].first;
         }
@@ -32571,7 +32759,8 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,
                 /* Check if argument name duplicates a destructuring parameter */
                 /* XXX: should have a flag for such variables */
                 for (i = 0; i < fd->var_count; i++) {
-                    if (fd->vars[i].var_name == name)
+                    if (fd->vars[i].var_name == name &&
+                        fd->vars[i].scope_level == 0)
                         goto duplicate;
                 }
             }
@@ -32680,8 +32869,8 @@ static __exception int js_parse_function_decl2(JSParseState *s,
 
     if (fd->is_eval && fd->eval_type == JS_EVAL_TYPE_MODULE &&
         (func_type == JS_PARSE_FUNC_STATEMENT || func_type == JS_PARSE_FUNC_VAR)) {
-        JSHoistedDef *hf;
-        hf = find_hoisted_def(fd, func_name);
+        JSGlobalVar *hf;
+        hf = find_global_var(fd, func_name);
         /* XXX: should check scope chain */
         if (hf && hf->scope_level == fd->scope_level) {
             js_parse_error(s, "invalid redefinition of global identifier in module code");
@@ -32691,21 +32880,23 @@ static __exception int js_parse_function_decl2(JSParseState *s,
     }
 
     if (func_type == JS_PARSE_FUNC_VAR) {
-        /* Create lexical name here so function closure contains it */
         if (!(fd->js_mode & JS_MODE_STRICT)
+        && func_kind == JS_FUNC_NORMAL
         &&  find_lexical_decl(ctx, fd, func_name, fd->scope_first, FALSE) < 0
         &&  !((func_idx = find_var(ctx, fd, func_name)) >= 0 && (func_idx & ARGUMENT_VAR_OFFSET))
         &&  !(func_name == JS_ATOM_arguments && fd->has_arguments_binding)) {
             create_func_var = TRUE;
         }
+        /* Create the lexical name here so that the function closure
+           contains it */
         if (fd->is_eval &&
             (fd->eval_type == JS_EVAL_TYPE_GLOBAL ||
              fd->eval_type == JS_EVAL_TYPE_MODULE) &&
-            fd->scope_level == 1) {
+            fd->scope_level == fd->body_scope) {
             /* avoid creating a lexical variable in the global
                scope. XXX: check annex B */
-            JSHoistedDef *hf;
-            hf = find_hoisted_def(fd, func_name);
+            JSGlobalVar *hf;
+            hf = find_global_var(fd, func_name);
             /* XXX: should check scope chain */
             if (hf && hf->scope_level == fd->scope_level) {
                 js_parse_error(s, "invalid redefinition of global identifier");
@@ -32780,6 +32971,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
     
     /* parse arguments */
     fd->has_simple_parameter_list = TRUE;
+    fd->has_parameter_expressions = FALSE;
     has_opt_arg = FALSE;
     if (func_type == JS_PARSE_FUNC_ARROW && s->token.val == TOK_IDENT) {
         JSAtom name;
@@ -32792,13 +32984,30 @@ static __exception int js_parse_function_decl2(JSParseState *s,
             goto fail;
         fd->defined_arg_count = 1;
     } else {
-        if (js_parse_expect(s, '('))
-            goto fail;
+        if (s->token.val == '(') {
+            int skip_bits;
+            /* if there is an '=' inside the parameter list, we
+               consider there is a parameter expression inside */
+            js_parse_skip_parens_token(s, &skip_bits, FALSE);
+            if (skip_bits & SKIP_HAS_ASSIGNMENT)
+                fd->has_parameter_expressions = TRUE;
+            if (next_token(s))
+                goto fail;
+        } else {
+            if (js_parse_expect(s, '('))
+                goto fail;
+        }
 
+        if (fd->has_parameter_expressions) {
+            fd->scope_level = -1; /* force no parent scope */
+            if (push_scope(s) < 0)
+                return -1;
+        }
+        
         while (s->token.val != ')') {
             JSAtom name;
             BOOL rest = FALSE;
-            int idx;
+            int idx, has_initializer;
 
             if (s->token.val == TOK_ELLIPSIS) {
                 fd->has_simple_parameter_list = FALSE;
@@ -32817,8 +33026,13 @@ static __exception int js_parse_function_decl2(JSParseState *s,
                     emit_op(s, OP_get_arg);
                     emit_u16(s, idx);
                 }
-                if (js_parse_destructuring_element(s, TOK_VAR, 1, TRUE, -1, TRUE))
+                has_initializer = js_parse_destructuring_element(s, fd->has_parameter_expressions ? TOK_LET : TOK_VAR, 1, TRUE, -1, TRUE);
+                if (has_initializer < 0)
                     goto fail;
+                if (has_initializer)
+                    has_opt_arg = TRUE;
+                if (!has_opt_arg)
+                    fd->defined_arg_count++;
             } else if (s->token.val == TOK_IDENT) {
                 if (s->token.u.ident.is_reserved) {
                     js_parse_error_reserved_identifier(s);
@@ -32829,6 +33043,11 @@ static __exception int js_parse_function_decl2(JSParseState *s,
                     js_parse_error_reserved_identifier(s);
                     goto fail;
                 }
+                if (fd->has_parameter_expressions) {
+                    if (define_var(s, fd, name, JS_VAR_DEF_LET) < 0)
+                        goto fail;
+                }
+                /* XXX: could avoid allocating an argument if rest is true */
                 idx = add_arg(ctx, fd, name);
                 if (idx < 0)
                     goto fail;
@@ -32837,70 +33056,55 @@ static __exception int js_parse_function_decl2(JSParseState *s,
                 if (rest) {
                     emit_op(s, OP_rest);
                     emit_u16(s, idx);
+                    if (fd->has_parameter_expressions) {
+                        emit_op(s, OP_dup);
+                        emit_op(s, OP_scope_put_var_init);
+                        emit_atom(s, name);
+                        emit_u16(s, fd->scope_level);
+                    }
                     emit_op(s, OP_put_arg);
                     emit_u16(s, idx);
                     fd->has_simple_parameter_list = FALSE;
                     has_opt_arg = TRUE;
                 } else if (s->token.val == '=') {
+                    int label;
+                    
                     fd->has_simple_parameter_list = FALSE;
                     has_opt_arg = TRUE;
 
                     if (next_token(s))
                         goto fail;
 
-                    /* optimize `x = void 0` default value: no code needed */
-                    if (s->token.val == TOK_VOID) {
-                        JSParsePos pos;
-                        js_parse_get_pos(s, &pos);
-                        if (next_token(s))
-                            goto fail;
-                        if (s->token.val == TOK_NUMBER) {
-                            if (next_token(s))
-                                goto fail;
-                            if (s->token.val == ',') {
-                                if (next_token(s))
-                                    goto fail;
-                                continue;
-                            }
-                            if (s->token.val == ')') {
-                                continue;
-                            }
-                        }
-                        if (js_parse_seek_token(s, &pos))
-                            goto fail;
+                    label = new_label(s);
+                    emit_op(s, OP_get_arg);
+                    emit_u16(s, idx);
+                    emit_op(s, OP_dup);
+                    emit_op(s, OP_undefined);
+                    emit_op(s, OP_strict_eq);
+                    emit_goto(s, OP_if_false, label);
+                    emit_op(s, OP_drop);
+                    if (js_parse_assign_expr(s))
+                        goto fail;
+                    set_object_name(s, name);
+                    emit_op(s, OP_dup);
+                    emit_op(s, OP_put_arg);
+                    emit_u16(s, idx);
+                    emit_label(s, label);
+                    emit_op(s, OP_scope_put_var_init);
+                    emit_atom(s, name);
+                    emit_u16(s, fd->scope_level);
+                } else {
+                    if (!has_opt_arg) {
+                        fd->defined_arg_count++;
                     }
-#if 0
-                    /* XXX: not correct for eval code */
-                    /* Check for a default value of `undefined`
-                       to omit default argument processing */
-                    if (s->token.val == TOK_IDENT &&
-                        s->token.u.ident.atom == JS_ATOM_undefined &&
-                        fd->parent == NULL &&
-                        ((tok = peek_token(s, FALSE)) == ',' || tok == ')')) {
-                        if (next_token(s))  /* ignore undefined token */
-                            goto fail;
-                    } else
-#endif
-                    {
-                        int label = new_label(s);
-                        if (idx > 0) {
-                            emit_op(s, OP_set_arg_valid_upto);
-                            emit_u16(s, idx);
-                        }
+                    if (fd->has_parameter_expressions) {
+                        /* copy the argument to the argument scope */
                         emit_op(s, OP_get_arg);
                         emit_u16(s, idx);
-                        emit_op(s, OP_undefined);
-                        emit_op(s, OP_strict_eq);
-                        emit_goto(s, OP_if_false, label);
-                        if (js_parse_assign_expr(s, TRUE))
-                            goto fail;
-                        set_object_name(s, name);
-                        emit_op(s, OP_put_arg);
-                        emit_u16(s, idx);
-                        emit_label(s, label);
+                        emit_op(s, OP_scope_put_var_init);
+                        emit_atom(s, name);
+                        emit_u16(s, fd->scope_level);
                     }
-                } else if (!has_opt_arg) {
-                    fd->defined_arg_count++;
                 }
             } else {
                 js_parse_error(s, "missing formal parameter");
@@ -32922,6 +33126,41 @@ static __exception int js_parse_function_decl2(JSParseState *s,
         }
     }
 
+    if (fd->has_parameter_expressions) {
+        int idx;
+
+        /* Copy the variables in the argument scope to the variable
+           scope (see FunctionDeclarationInstantiation() in spec). The
+           normal arguments are already present, so no need to copy
+           them. */
+        idx = fd->scopes[fd->scope_level].first;
+        while (idx >= 0) {
+            JSVarDef *vd = &fd->vars[idx];
+            if (vd->scope_level != fd->scope_level)
+                break;
+            if (find_var(ctx, fd, vd->var_name) < 0) {
+                if (add_var(ctx, fd, vd->var_name) < 0)
+                    goto fail;
+                vd = &fd->vars[idx]; /* fd->vars may have been reallocated */
+                emit_op(s, OP_scope_get_var);
+                emit_atom(s, vd->var_name);
+                emit_u16(s, fd->scope_level);
+                emit_op(s, OP_scope_put_var);
+                emit_atom(s, vd->var_name);
+                emit_u16(s, 0);
+            }
+            idx = vd->scope_next;
+        }
+        
+        /* the argument scope has no parent, hence we don't use pop_scope(s) */
+        emit_op(s, OP_leave_scope);
+        emit_u16(s, fd->scope_level);
+
+        /* set the variable scope as the current scope */
+        fd->scope_level = 0;
+        fd->scope_first = fd->scopes[fd->scope_level].first;
+    }
+    
     if (next_token(s))
         goto fail;
 
@@ -32933,7 +33172,8 @@ static __exception int js_parse_function_decl2(JSParseState *s,
     /* in generators, yield expression is forbidden during the parsing
        of the arguments */
     fd->in_function_body = TRUE;
-    push_scope(s);  /* enter body scope: fd->scope_level = 1 */
+    push_scope(s);  /* enter body scope */
+    fd->body_scope = fd->scope_level;
 
     if (s->token.val == TOK_ARROW) {
         if (next_token(s))
@@ -32943,7 +33183,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
             if (js_parse_function_check_names(s, fd, func_name))
                 goto fail;
 
-            if (js_parse_assign_expr(s, TRUE))
+            if (js_parse_assign_expr(s))
                 goto fail;
 
             if (func_kind != JS_FUNC_NORMAL)
@@ -33025,10 +33265,10 @@ done:
             emit_u32(s, idx);
             if (create_func_var) {
                 if (s->cur_func->is_global_var) {
-                    JSHoistedDef *hf;
+                    JSGlobalVar *hf;
                     /* the global variable must be defined at the start of the
                        function */
-                    hf = add_hoisted_def(ctx, s->cur_func, -1, func_name, -1, FALSE);
+                    hf = add_global_var(ctx, s->cur_func, func_name);
                     if (!hf)
                         goto fail;
                     /* it is considered as defined at the top level
@@ -33058,7 +33298,7 @@ done:
             }
             if (lexical_func_idx >= 0) {
                 /* lexical variable will be initialized upon entering scope */
-                s->cur_func->vars[lexical_func_idx].func_pool_or_scope_idx = idx;
+                s->cur_func->vars[lexical_func_idx].func_pool_idx = idx;
                 emit_op(s, OP_drop);
             } else {
                 /* store function object into its lexical name */
@@ -33074,17 +33314,23 @@ done:
                 if (var_idx < 0)
                     goto fail;
                 /* the variable will be assigned at the top of the function */
-                if (!add_hoisted_def(ctx, s->cur_func, idx, JS_ATOM_NULL, var_idx, FALSE))
-                    goto fail;
+                if (var_idx & ARGUMENT_VAR_OFFSET) {
+                    s->cur_func->args[var_idx - ARGUMENT_VAR_OFFSET].func_pool_idx = idx;
+                } else {
+                    s->cur_func->vars[var_idx].func_pool_idx = idx;
+                }
             } else {
                 JSAtom func_var_name;
+                JSGlobalVar *hf;
                 if (func_name == JS_ATOM_NULL)
                     func_var_name = JS_ATOM__default_; /* export default */
                 else
                     func_var_name = func_name;
                 /* the variable will be assigned at the top of the function */
-                if (!add_hoisted_def(ctx, s->cur_func, idx, func_var_name, -1, FALSE))
+                hf = add_global_var(ctx, s->cur_func, func_var_name);
+                if (!hf)
                     goto fail;
+                hf->cpool_idx = idx;
                 if (export_flag != JS_PARSE_EXPORT_NONE) {
                     if (!add_export_entry(s, s->cur_func->module, func_var_name,
                                           export_flag == JS_PARSE_EXPORT_NAMED ? func_var_name : JS_ATOM_default, JS_EXPORT_TYPE_LOCAL))
@@ -33186,7 +33432,7 @@ static JSValue JS_EvalFunctionInternal(JSContext *ctx, JSValue fun_obj,
         JS_FreeValue(ctx, fun_obj);
         if (js_create_module_function(ctx, m) < 0)
             goto fail;
-        if (js_instantiate_module(ctx, m) < 0)
+        if (js_link_module(ctx, m) < 0)
             goto fail;
         ret_val = js_evaluate_module(ctx, m);
         if (JS_IsException(ret_val)) {
@@ -33308,7 +33554,8 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
     s->allow_html_comments = !s->is_module;
 
     push_scope(s); /* body scope */
-
+    fd->body_scope = fd->scope_level;
+    
     err = js_parse_program(s);
     if (err) {
     fail:
@@ -33371,19 +33618,27 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
 
 }
 
-JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
-                const char *filename, int eval_flags)
+JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
+                    const char *input, size_t input_len,
+                    const char *filename, int eval_flags)
 {
     int eval_type = eval_flags & JS_EVAL_TYPE_MASK;
     JSValue ret;
 
     assert(eval_type == JS_EVAL_TYPE_GLOBAL ||
            eval_type == JS_EVAL_TYPE_MODULE);
-    ret = JS_EvalInternal(ctx, ctx->global_obj, input, input_len, filename,
+    ret = JS_EvalInternal(ctx, this_obj, input, input_len, filename,
                           eval_flags, -1);
     return ret;
 }
 
+JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
+                const char *filename, int eval_flags)
+{
+    return JS_EvalThis(ctx, ctx->global_obj, input, input_len, filename,
+                       eval_flags);
+}
+
 int JS_ResolveModule(JSContext *ctx, JSValueConst obj)
 {
     if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) {
@@ -33980,7 +34235,6 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
             bc_put_leb128(s, vd->scope_next + 1);
             flags = idx = 0;
             bc_set_flags(&flags, &idx, vd->var_kind, 4);
-            bc_set_flags(&flags, &idx, vd->is_func_var, 1);
             bc_set_flags(&flags, &idx, vd->is_const, 1);
             bc_set_flags(&flags, &idx, vd->is_lexical, 1);
             bc_set_flags(&flags, &idx, vd->is_captured, 1);
@@ -34971,7 +35225,6 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
                 goto fail;
             idx = 0;
             vd->var_kind = bc_get_flags(v8, &idx, 4);
-            vd->is_func_var = bc_get_flags(v8, &idx, 1);
             vd->is_const = bc_get_flags(v8, &idx, 1);
             vd->is_lexical = bc_get_flags(v8, &idx, 1);
             vd->is_captured = bc_get_flags(v8, &idx, 1);
@@ -35628,16 +35881,39 @@ static JSAtom find_atom(JSContext *ctx, const char *name)
     return atom;
 }
 
-static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,
-                                          JSAtom atom, void *opaque)
+static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p,
+                                               JSAtom atom, void *opaque)
 {
     const JSCFunctionListEntry *e = opaque;
-    JSValueConst obj = JS_MKPTR(JS_TAG_OBJECT, p);
+    JSValue val;
+
+    switch(e->def_type) {
+    case JS_DEF_CFUNC:
+        val = JS_NewCFunction2(ctx, e->u.func.cfunc.generic,
+                               e->name, e->u.func.length, e->u.func.cproto, e->magic);
+        break;
+    case JS_DEF_PROP_STRING:
+        val = JS_NewAtomString(ctx, e->u.str);
+        break;
+    case JS_DEF_OBJECT:
+        val = JS_NewObject(ctx);
+        JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len);
+        break;
+    default:
+        abort();
+    }
+    return val;
+}
+
+static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
+                                          JSAtom atom,
+                                          const JSCFunctionListEntry *e)
+{
     JSValue val;
     int prop_flags = e->prop_flags;
 
     switch(e->def_type) {
-    case JS_DEF_ALIAS:
+    case JS_DEF_ALIAS: /* using autoinit for aliases is not safe */
         {
             JSAtom atom1 = find_atom(ctx, e->u.alias.name);
             switch (e->u.alias.base) {
@@ -35654,12 +35930,16 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,
                 abort();
             }
             JS_FreeAtom(ctx, atom1);
-            goto setval;
+            if (atom == JS_ATOM_Symbol_toPrimitive) {
+                /* Symbol.toPrimitive functions are not writable */
+                prop_flags = JS_PROP_CONFIGURABLE;
+            } else if (atom == JS_ATOM_Symbol_hasInstance) {
+                /* Function.prototype[Symbol.hasInstance] is not writable nor configurable */
+                prop_flags = 0;
+            }
         }
+        break;
     case JS_DEF_CFUNC:
-        val = JS_NewCFunction2(ctx, e->u.func.cfunc.generic,
-                               e->name, e->u.func.length, e->u.func.cproto, e->magic);
-    setval:
         if (atom == JS_ATOM_Symbol_toPrimitive) {
             /* Symbol.toPrimitive functions are not writable */
             prop_flags = JS_PROP_CONFIGURABLE;
@@ -35667,8 +35947,10 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,
             /* Function.prototype[Symbol.hasInstance] is not writable nor configurable */
             prop_flags = 0;
         }
-        break;
-    case JS_DEF_CGETSET:
+        JS_DefineAutoInitProperty(ctx, obj, atom, JS_AUTOINIT_ID_PROP,
+                                  (void *)e, prop_flags);
+        return 0;
+    case JS_DEF_CGETSET: /* XXX: use autoinit again ? */
     case JS_DEF_CGETSET_MAGIC:
         {
             JSValue getter, setter;
@@ -35692,9 +35974,6 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,
             return 0;
         }
         break;
-    case JS_DEF_PROP_STRING:
-        val = JS_NewAtomString(ctx, e->u.str);
-        break;
     case JS_DEF_PROP_INT32:
         val = JS_NewInt32(ctx, e->u.i32);
         break;
@@ -35707,10 +35986,11 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,
     case JS_DEF_PROP_UNDEFINED:
         val = JS_UNDEFINED;
         break;
+    case JS_DEF_PROP_STRING:
     case JS_DEF_OBJECT:
-        val = JS_NewObject(ctx);
-        JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len);
-        break;
+        JS_DefineAutoInitProperty(ctx, obj, atom, JS_AUTOINIT_ID_PROP,
+                                  (void *)e, prop_flags);
+        return 0;
     default:
         abort();
     }
@@ -35721,36 +36001,12 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,
 void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
                                 const JSCFunctionListEntry *tab, int len)
 {
-    int i, prop_flags;
+    int i;
 
     for (i = 0; i < len; i++) {
         const JSCFunctionListEntry *e = &tab[i];
         JSAtom atom = find_atom(ctx, e->name);
-
-        switch (e->def_type) {
-        case JS_DEF_CFUNC:
-        case JS_DEF_CGETSET:
-        case JS_DEF_CGETSET_MAGIC:
-        case JS_DEF_PROP_STRING:
-        case JS_DEF_ALIAS:
-        case JS_DEF_OBJECT:
-            prop_flags = JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE | (e->prop_flags & JS_PROP_ENUMERABLE);
-            JS_DefineAutoInitProperty(ctx, obj, atom,
-                                      JS_AUTOINIT_ID_PROP,
-                                      (void *)e, prop_flags);
-            break;
-        case JS_DEF_PROP_INT32:
-        case JS_DEF_PROP_INT64:
-        case JS_DEF_PROP_DOUBLE:
-        case JS_DEF_PROP_UNDEFINED:
-            {
-                JSObject *p = JS_VALUE_GET_OBJ(obj);
-                JS_InstantiateFunctionListItem(ctx, p, atom, (void *)e);
-            }
-            break;
-        default:
-            abort();
-        }
+        JS_InstantiateFunctionListItem(ctx, obj, atom, e);
         JS_FreeAtom(ctx, atom);
     }
 }
@@ -37262,6 +37518,8 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
     return tab;
 }
 
+/* magic value: 0 = normal apply, 1 = apply for constructor, 2 =
+   Reflect.apply */
 static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
                                  int argc, JSValueConst *argv, int magic)
 {
@@ -37273,14 +37531,14 @@ static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
         return JS_EXCEPTION;
     this_arg = argv[0];
     array_arg = argv[1];
-    if (JS_VALUE_GET_TAG(array_arg) == JS_TAG_UNDEFINED ||
-        JS_VALUE_GET_TAG(array_arg) == JS_TAG_NULL) {
+    if ((JS_VALUE_GET_TAG(array_arg) == JS_TAG_UNDEFINED ||
+         JS_VALUE_GET_TAG(array_arg) == JS_TAG_NULL) && magic != 2) {
         return JS_Call(ctx, this_val, this_arg, 0, NULL);
     }
     tab = build_arg_list(ctx, &len, array_arg);
     if (!tab)
         return JS_EXCEPTION;
-    if (magic) {
+    if (magic & 1) {
         ret = JS_CallConstructor2(ctx, this_val, this_arg, len, (JSValueConst *)tab);
     } else {
         ret = JS_Call(ctx, this_val, this_arg, len, (JSValueConst *)tab);
@@ -37650,7 +37908,7 @@ static JSValue js_array_constructor(JSContext *ctx, JSValueConst new_target,
         return obj;
     if (argc == 1 && JS_IsNumber(argv[0])) {
         uint32_t len;
-        if (JS_ToArrayLengthFree(ctx, &len, JS_DupValue(ctx, argv[0])))
+        if (JS_ToArrayLengthFree(ctx, &len, JS_DupValue(ctx, argv[0]), TRUE))
             goto fail;
         if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, len)) < 0)
             goto fail;
@@ -39659,46 +39917,6 @@ static int js_string_get_own_property(JSContext *ctx,
     return FALSE;
 }
 
-static uint32_t js_string_obj_get_length(JSContext *ctx,
-                                         JSValueConst obj)
-{
-    JSObject *p;
-    JSString *p1;
-    uint32_t len = 0;
-
-    /* This is a class exotic method: obj class_id is JS_CLASS_STRING */
-    p = JS_VALUE_GET_OBJ(obj);
-    if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {
-        p1 = JS_VALUE_GET_STRING(p->u.object_data);
-        len = p1->len;
-    }
-    return len;
-}
-
-static int js_string_get_own_property_names(JSContext *ctx,
-                                            JSPropertyEnum **ptab,
-                                            uint32_t *plen,
-                                            JSValueConst obj)
-{
-    JSPropertyEnum *tab;
-    uint32_t len, i;
-
-    len = js_string_obj_get_length(ctx, obj);
-    tab = NULL;
-    if (len > 0) {
-        /* do not allocate 0 bytes */
-        tab = js_malloc(ctx, sizeof(JSPropertyEnum) * len);
-        if (!tab)
-            return -1;
-        for(i = 0; i < len; i++) {
-            tab[i].atom = __JS_AtomFromUInt32(i);
-        }
-    }
-    *ptab = tab;
-    *plen = len;
-    return 0;
-}
-
 static int js_string_define_own_property(JSContext *ctx,
                                          JSValueConst this_obj,
                                          JSAtom prop, JSValueConst val,
@@ -39755,7 +39973,6 @@ static int js_string_delete_property(JSContext *ctx,
 
 static const JSClassExoticMethods js_string_exotic_methods = {
     .get_own_property = js_string_get_own_property,
-    .get_own_property_names = js_string_get_own_property_names,
     .define_own_property = js_string_define_own_property,
     .delete_property = js_string_delete_property,
 };
@@ -40359,15 +40576,17 @@ static JSValue js_string___GetSubstitution(JSContext *ctx, JSValueConst this_val
             string_buffer_concat(b, sp, position + matched_len, sp->len);
         } else if (c >= '0' && c <= '9') {
             k = c - '0';
-            c1 = string_get(rp, j);
-            if (c1 >= '0' && c1 <= '9') {
-                /* This behavior is specified in ES6 and refined in ECMA 2019 */
-                /* ECMA 2019 does not have the extra test, but
-                   Test262 S15.5.4.11_A3_T1..3 require this behavior */
-                k1 = k * 10 + c1 - '0';
-                if (k1 >= 1 && k1 < captures_len) {
-                    k = k1;
-                    j++;
+            if (j < len) {
+                c1 = string_get(rp, j);
+                if (c1 >= '0' && c1 <= '9') {
+                    /* This behavior is specified in ES6 and refined in ECMA 2019 */
+                    /* ECMA 2019 does not have the extra test, but
+                       Test262 S15.5.4.11_A3_T1..3 require this behavior */
+                    k1 = k * 10 + c1 - '0';
+                    if (k1 >= 1 && k1 < captures_len) {
+                        k = k1;
+                        j++;
+                    }
                 }
             }
             if (k >= 1 && k < captures_len) {
@@ -42805,7 +43024,8 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
         tab = JS_NewArray(ctx);
         if (JS_IsException(tab))
             goto exception;
-        if (JS_SetPropertyInt64(ctx, tab, 0, JS_DupValue(ctx, matched)) < 0)
+        if (JS_DefinePropertyValueInt64(ctx, tab, 0, JS_DupValue(ctx, matched),
+                                        JS_PROP_C_W_E | JS_PROP_THROW) < 0)
             goto exception;
         for(n = 1; n < nCaptures; n++) {
             JSValue capN;
@@ -42817,7 +43037,8 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
                 if (JS_IsException(capN))
                     goto exception;
             }
-            if (JS_SetPropertyInt64(ctx, tab, n, capN) < 0)
+            if (JS_DefinePropertyValueInt64(ctx, tab, n, capN,
+                                            JS_PROP_C_W_E | JS_PROP_THROW) < 0)
                 goto exception;
         }
         JS_FreeValue(ctx, namedCaptures);
@@ -42825,12 +43046,12 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
         if (JS_IsException(namedCaptures))
             goto exception;
         if (functionalReplace) {
-            if (JS_SetPropertyInt64(ctx, tab, n++, JS_NewInt32(ctx, position)) < 0)
+            if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_NewInt32(ctx, position), JS_PROP_C_W_E | JS_PROP_THROW) < 0)
                 goto exception;
-            if (JS_SetPropertyInt64(ctx, tab, n++, JS_DupValue(ctx, str)) < 0)
+            if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_DupValue(ctx, str), JS_PROP_C_W_E | JS_PROP_THROW) < 0)
                 goto exception;
             if (!JS_IsUndefined(namedCaptures)) {
-                if (JS_SetPropertyInt64(ctx, tab, n++, JS_DupValue(ctx, namedCaptures)) < 0)
+                if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_DupValue(ctx, namedCaptures), JS_PROP_C_W_E | JS_PROP_THROW) < 0)
                     goto exception;
             }
             args[0] = JS_UNDEFINED;
@@ -42917,8 +43138,10 @@ static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValueConst this_val,
     if (js_same_value(ctx, currentLastIndex, previousLastIndex)) {
         JS_FreeValue(ctx, previousLastIndex);
     } else {
-        if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, previousLastIndex) < 0)
+        if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, previousLastIndex) < 0) {
+            previousLastIndex = JS_UNDEFINED;
             goto exception;
+        }
     }
     JS_FreeValue(ctx, str);
     JS_FreeValue(ctx, currentLastIndex);
@@ -43023,7 +43246,8 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val,
                 sub = js_sub_string(ctx, strp, p, q);
                 if (JS_IsException(sub))
                     goto exception;
-                if (JS_SetPropertyInt64(ctx, A, lengthA++, sub) < 0)
+                if (JS_DefinePropertyValueInt64(ctx, A, lengthA++, sub,
+                                                JS_PROP_C_W_E | JS_PROP_THROW) < 0)
                     goto exception;
                 if (lengthA == lim)
                     goto done;
@@ -43034,7 +43258,7 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val,
                     sub = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, z, i));
                     if (JS_IsException(sub))
                         goto exception;
-                    if (JS_SetPropertyInt64(ctx, A, lengthA++, sub) < 0)
+                    if (JS_DefinePropertyValueInt64(ctx, A, lengthA++, sub, JS_PROP_C_W_E | JS_PROP_THROW) < 0)
                         goto exception;
                     if (lengthA == lim)
                         goto done;
@@ -43049,7 +43273,7 @@ add_tail:
     sub = js_sub_string(ctx, strp, p, size);
     if (JS_IsException(sub))
         goto exception;
-    if (JS_SetPropertyInt64(ctx, A, lengthA++, sub) < 0)
+    if (JS_DefinePropertyValueInt64(ctx, A, lengthA++, sub, JS_PROP_C_W_E | JS_PROP_THROW) < 0)
         goto exception;
     goto done;
 exception:
@@ -43829,7 +44053,7 @@ void JS_AddIntrinsicJSON(JSContext *ctx)
 static JSValue js_reflect_apply(JSContext *ctx, JSValueConst this_val,
                                 int argc, JSValueConst *argv)
 {
-    return js_function_apply(ctx, argv[0], max_int(0, argc - 1), argv + 1, 0);
+    return js_function_apply(ctx, argv[0], max_int(0, argc - 1), argv + 1, 2);
 }
 
 static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val,
@@ -46772,26 +46996,15 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va
 {
     JSValueConst ctor = func_data[0];
     JSValueConst onFinally = func_data[1];
-    JSValue res, promise, resolving_funcs[2], ret, then_func;
+    JSValue res, promise, ret, then_func;
 
     res = JS_Call(ctx, onFinally, JS_UNDEFINED, 0, NULL);
     if (JS_IsException(res))
         return res;
-    promise = js_new_promise_capability(ctx, resolving_funcs, ctor);
-    if (JS_IsException(promise)) {
-        JS_FreeValue(ctx, res);
-        return JS_EXCEPTION;
-    }
-    ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,
-                  1, (JSValueConst*)&res);
+    promise = js_promise_resolve(ctx, ctor, 1, (JSValueConst *)&res, 0);
     JS_FreeValue(ctx, res);
-    JS_FreeValue(ctx, resolving_funcs[0]);
-    JS_FreeValue(ctx, resolving_funcs[1]);
-    if (JS_IsException(ret)) {
-        JS_FreeValue(ctx, promise);
-        return ret;
-    }
-    JS_FreeValue(ctx, ret);
+    if (JS_IsException(promise))
+        return promise;
     if (magic == 0) {
         then_func = JS_NewCFunctionData(ctx, js_promise_finally_value_thunk, 0,
                                         0, 1, argv);
@@ -47503,7 +47716,7 @@ static JSValue JS_SetThisTimeValue(JSContext *ctx, JSValueConst this_val, double
         JSObject *p = JS_VALUE_GET_OBJ(this_val);
         if (p->class_id == JS_CLASS_DATE) {
             JS_FreeValue(ctx, p->u.object_data);
-            p->u.object_data = __JS_NewFloat64(ctx, v);
+            p->u.object_data = JS_NewFloat64(ctx, v);
             return JS_DupValue(ctx, p->u.object_data);
         }
     }
@@ -47547,7 +47760,7 @@ static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
 static char const day_names[] = "SunMonTueWedThuFriSat";
 
 static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,
-                                       int64_t fields[9], int is_local, int force)
+                                       double fields[9], int is_local, int force)
 {
     double dval;
     int64_t d, days, wd, y, i, md, h, m, s, ms, tz = 0;
@@ -47606,12 +47819,18 @@ static double time_clip(double t) {
         return NAN;
 }
 
-static double set_date_fields(int64_t fields[], int is_local) {
-    int64_t days, y, m, md, h, d, i;
-
-    i = fields[1];
-    m = math_mod(i, 12);
-    y = fields[0] + (i - m) / 12;
+/* The spec mandates the use of 'double' and it fixes the order
+   of the operations */
+static double set_date_fields(double fields[], int is_local) {
+    int64_t y;
+    double days, d, h, m1;
+    int i, m, md;
+    
+    m1 = fields[1];
+    m = fmod(m1, 12);
+    if (m < 0)
+        m += 12;
+    y = (int64_t)(fields[0] + floor(m1 / 12));
     days = days_from_year(y);
 
     for(i = 0; i < m; i++) {
@@ -47621,7 +47840,8 @@ static double set_date_fields(int64_t fields[], int is_local) {
         days += md;
     }
     days += fields[2] - 1;
-    h = ((fields[3] * 60 + fields[4]) * 60 + fields[5]) * 1000 + fields[6];
+    h = fields[3] * 3600000 + fields[4] * 60000 + 
+        fields[5] * 1000 + fields[6];
     d = days * 86400000 + h;
     if (is_local)
         d += getTimezoneOffset(d) * 60000;
@@ -47632,7 +47852,7 @@ static JSValue get_date_field(JSContext *ctx, JSValueConst this_val,
                               int argc, JSValueConst *argv, int magic)
 {
     // get_date_field(obj, n, is_local)
-    int64_t fields[9];
+    double fields[9];
     int res, n, is_local;
 
     is_local = magic & 0x0F;
@@ -47646,14 +47866,14 @@ static JSValue get_date_field(JSContext *ctx, JSValueConst this_val,
     if (magic & 0x100) {    // getYear
         fields[0] -= 1900;
     }
-    return JS_NewInt64(ctx, fields[n]);
+    return JS_NewFloat64(ctx, fields[n]);
 }
 
 static JSValue set_date_field(JSContext *ctx, JSValueConst this_val,
                               int argc, JSValueConst *argv, int magic)
 {
     // _field(obj, first_field, end_field, args, is_local)
-    int64_t fields[9];
+    double fields[9];
     int res, first_field, end_field, is_local, i, n;
     double d, a;
 
@@ -47695,7 +47915,7 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val,
 {
     // _string(obj, fmt, part)
     char buf[64];
-    int64_t fields[9];
+    double fields[9];
     int res, fmt, part, pos;
     int y, mon, d, h, m, s, ms, wd, tz;
 
@@ -47843,7 +48063,7 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,
         }
         val = time_clip(val);
     } else {
-        int64_t fields[] = { 0, 0, 1, 0, 0, 0, 0 };
+        double fields[] = { 0, 0, 1, 0, 0, 0, 0 };
         if (n > 7)
             n = 7;
         for(i = 0; i < n; i++) {
@@ -47862,12 +48082,12 @@ has_val:
     JSValueConst args[3];
     args[0] = new_target;
     args[1] = ctx->class_proto[JS_CLASS_DATE];
-    args[2] = __JS_NewFloat64(ctx, val);
+    args[2] = JS_NewFloat64(ctx, val);
     rv = js___date_create(ctx, JS_UNDEFINED, 3, args);
 #else
     rv = js_create_from_ctor(ctx, new_target, JS_CLASS_DATE);
     if (!JS_IsException(rv))
-        JS_SetObjectData(ctx, rv, __JS_NewFloat64(ctx, val));
+        JS_SetObjectData(ctx, rv, JS_NewFloat64(ctx, val));
 #endif
     if (!JS_IsException(rv) && JS_IsUndefined(new_target)) {
         /* invoked as a function, return (new Date()).toString(); */
@@ -47883,7 +48103,7 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val,
                            int argc, JSValueConst *argv)
 {
     // UTC(y, mon, d, h, m, s, ms)
-    int64_t fields[] = { 0, 0, 1, 0, 0, 0, 0 };
+    double fields[] = { 0, 0, 1, 0, 0, 0, 0 };
     int i, n;
     double a;
 
@@ -47901,7 +48121,7 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val,
         if (i == 0 && fields[0] >= 0 && fields[0] < 100)
             fields[0] += 1900;
     }
-    return __JS_NewFloat64(ctx, set_date_fields(fields, 0));
+    return JS_NewFloat64(ctx, set_date_fields(fields, 0));
 }
 
 static void string_skip_spaces(JSString *sp, int *pp) {
@@ -48011,6 +48231,7 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
     // parse(s)
     JSValue s, rv;
     int64_t fields[] = { 0, 1, 1, 0, 0, 0, 0 };
+    double fields1[7];
     int64_t tz, hh, mm;
     double d;
     int p, i, c, sgn;
@@ -48123,8 +48344,10 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
             }
         }
     }
-    d = set_date_fields(fields, is_local) - tz * 60000;
-    rv = __JS_NewFloat64(ctx, d);
+    for(i = 0; i < 7; i++)
+        fields1[i] = fields[i];
+    d = set_date_fields(fields1, is_local) - tz * 60000;
+    rv = JS_NewFloat64(ctx, d);
 
 done:
     JS_FreeValue(ctx, s);
@@ -48194,7 +48417,7 @@ static JSValue js_date_getTime(JSContext *ctx, JSValueConst this_val,
 
     if (JS_ThisTimeValue(ctx, &v, this_val))
         return JS_EXCEPTION;
-    return __JS_NewFloat64(ctx, v);
+    return JS_NewFloat64(ctx, v);
 }
 
 static JSValue js_date_setTime(JSContext *ctx, JSValueConst this_val,
@@ -48223,7 +48446,7 @@ static JSValue js_date_setYear(JSContext *ctx, JSValueConst this_val,
         if (y >= 0 && y < 100)
             y += 1900;
     }
-    args[0] = __JS_NewFloat64(ctx, y);
+    args[0] = JS_NewFloat64(ctx, y);
     return set_date_field(ctx, this_val, 1, args, 0x011);
 }
 
@@ -48714,9 +48937,11 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
 }
 
 static JSValue js_bigint_constructor(JSContext *ctx,
-                                     JSValueConst this_val,
+                                     JSValueConst new_target,
                                      int argc, JSValueConst *argv)
 {
+    if (!JS_IsUndefined(new_target))
+        return JS_ThrowTypeError(ctx, "not a constructor");
     return JS_ToBigIntCtorFree(ctx, JS_DupValue(ctx, argv[0]));
 }
 
@@ -48962,7 +49187,7 @@ static const JSCFunctionListEntry js_bigint_proto_funcs[] = {
 void JS_AddIntrinsicBigInt(JSContext *ctx)
 {
     JSRuntime *rt = ctx->rt;
-    JSValue obj1;
+    JSValueConst obj1;
 
     rt->bigint_ops.to_string = js_bigint_to_string;
     rt->bigint_ops.from_string = js_string_to_bigint;
@@ -48974,9 +49199,8 @@ void JS_AddIntrinsicBigInt(JSContext *ctx)
     JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_INT],
                                js_bigint_proto_funcs,
                                countof(js_bigint_proto_funcs));
-    obj1 = JS_NewCFunction(ctx, js_bigint_constructor, "BigInt", 1);
-    JS_NewGlobalCConstructor2(ctx, obj1, "BigInt",
-                              ctx->class_proto[JS_CLASS_BIG_INT]);
+    obj1 = JS_NewGlobalCConstructor(ctx, "BigInt", js_bigint_constructor, 1,
+                                    ctx->class_proto[JS_CLASS_BIG_INT]);
     JS_SetPropertyFunctionList(ctx, obj1, js_bigint_funcs,
                                countof(js_bigint_funcs));
 }
@@ -49194,10 +49418,12 @@ static const JSCFunctionListEntry js_bigfloat_proto_funcs[] = {
 };
 
 static JSValue js_bigfloat_constructor(JSContext *ctx,
-                                       JSValueConst this_val,
+                                       JSValueConst new_target,
                                        int argc, JSValueConst *argv)
 {
     JSValue val;
+    if (!JS_IsUndefined(new_target))
+        return JS_ThrowTypeError(ctx, "not a constructor");
     if (argc == 0) {
         bf_t *r;
         val = JS_NewBigFloat(ctx);
@@ -49858,8 +50084,7 @@ static const JSCFunctionListEntry js_float_env_proto_funcs[] = {
 void JS_AddIntrinsicBigFloat(JSContext *ctx)
 {
     JSRuntime *rt = ctx->rt;
-    JSValue obj1;
-    JSValueConst obj2;
+    JSValueConst obj1;
     
     rt->bigfloat_ops.to_string = js_bigfloat_to_string;
     rt->bigfloat_ops.from_string = js_string_to_bigfloat;
@@ -49873,9 +50098,8 @@ void JS_AddIntrinsicBigFloat(JSContext *ctx)
     JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT],
                                js_bigfloat_proto_funcs,
                                countof(js_bigfloat_proto_funcs));
-    obj1 = JS_NewCFunction(ctx, js_bigfloat_constructor, "BigFloat", 1);
-    JS_NewGlobalCConstructor2(ctx, obj1, "BigFloat",
-                              ctx->class_proto[JS_CLASS_BIG_FLOAT]);
+    obj1 = JS_NewGlobalCConstructor(ctx, "BigFloat", js_bigfloat_constructor, 1,
+                                    ctx->class_proto[JS_CLASS_BIG_FLOAT]);
     JS_SetPropertyFunctionList(ctx, obj1, js_bigfloat_funcs,
                                countof(js_bigfloat_funcs));
 
@@ -49883,10 +50107,10 @@ void JS_AddIntrinsicBigFloat(JSContext *ctx)
     JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_FLOAT_ENV],
                                js_float_env_proto_funcs,
                                countof(js_float_env_proto_funcs));
-    obj2 = JS_NewGlobalCConstructorOnly(ctx, "BigFloatEnv",
+    obj1 = JS_NewGlobalCConstructorOnly(ctx, "BigFloatEnv",
                                         js_float_env_constructor, 1,
                                         ctx->class_proto[JS_CLASS_FLOAT_ENV]);
-    JS_SetPropertyFunctionList(ctx, obj2, js_float_env_funcs,
+    JS_SetPropertyFunctionList(ctx, obj1, js_float_env_funcs,
                                countof(js_float_env_funcs));
 }
 
@@ -49989,10 +50213,12 @@ static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val,
 }
 
 static JSValue js_bigdecimal_constructor(JSContext *ctx,
-                                         JSValueConst this_val,
+                                         JSValueConst new_target,
                                          int argc, JSValueConst *argv)
 {
     JSValue val;
+    if (!JS_IsUndefined(new_target))
+        return JS_ThrowTypeError(ctx, "not a constructor");
     if (argc == 0) {
         bfdec_t *r;
         val = JS_NewBigDecimal(ctx);
@@ -50348,7 +50574,7 @@ static const JSCFunctionListEntry js_bigdecimal_funcs[] = {
 void JS_AddIntrinsicBigDecimal(JSContext *ctx)
 {
     JSRuntime *rt = ctx->rt;
-    JSValue obj1;
+    JSValueConst obj1;
 
     rt->bigdecimal_ops.to_string = js_bigdecimal_to_string;
     rt->bigdecimal_ops.from_string = js_string_to_bigdecimal;
@@ -50360,9 +50586,9 @@ void JS_AddIntrinsicBigDecimal(JSContext *ctx)
     JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_DECIMAL],
                                js_bigdecimal_proto_funcs,
                                countof(js_bigdecimal_proto_funcs));
-    obj1 = JS_NewCFunction(ctx, js_bigdecimal_constructor, "BigDecimal", 1);
-    JS_NewGlobalCConstructor2(ctx, obj1, "BigDecimal",
-                              ctx->class_proto[JS_CLASS_BIG_DECIMAL]);
+    obj1 = JS_NewGlobalCConstructor(ctx, "BigDecimal",
+                                    js_bigdecimal_constructor, 1,
+                                    ctx->class_proto[JS_CLASS_BIG_DECIMAL]);
     JS_SetPropertyFunctionList(ctx, obj1, js_bigdecimal_funcs,
                                countof(js_bigdecimal_funcs));
 }
@@ -50818,8 +51044,7 @@ static JSValue js_array_buffer_get_byteLength(JSContext *ctx,
     JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id);
     if (!abuf)
         return JS_EXCEPTION;
-    if (abuf->detached)
-        return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+    /* return 0 if detached */
     return JS_NewUint32(ctx, abuf->byte_length);
 }
 
index bb84829b966d2fbf2fa631e13d85445ccba5efe1..92457a2f5075e9720619abaeb35940d3ccabc952 100644 (file)
--- a/quickjs.h
+++ b/quickjs.h
@@ -776,7 +776,10 @@ JS_BOOL JS_DetectModule(const char *input, size_t input_len);
 /* 'input' must be zero terminated i.e. input[input_len] = '\0'. */
 JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
                 const char *filename, int eval_flags);
-JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj);
+/* same as JS_Eval() but with an explicit 'this_obj' parameter */
+JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
+                    const char *input, size_t input_len,
+                    const char *filename, int eval_flags);
 JSValue JS_GetGlobalObject(JSContext *ctx);
 int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj);
 int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
@@ -885,7 +888,9 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
 #define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */
 JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
                       int flags);
-
+/* instantiate and evaluate a bytecode function. Only used when
+   reading a script or module with JS_ReadObject() */
+JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj);
 /* load the dependencies of the module 'obj'. Useful when JS_ReadObject()
    returns a module. */
 int JS_ResolveModule(JSContext *ctx, JSValueConst obj);
index a0bd6ebfd51ec6b2b71de69abde9bb05fda6ec0a..6dc89fb05b07a132789c33dd88705caa084bfc60 100755 (executable)
@@ -6,30 +6,23 @@ set -e
 version=`cat VERSION`
 
 if [ "$1" = "-h" ] ; then
-    echo "release.sh [all]"
+    echo "release.sh [release_list]"
     echo ""
-    echo "all: build all the archives. Otherwise only build the quickjs source archive."
+    echo "release_list: extras binary win_binary quickjs"
+    
     exit 1
 fi
 
-extras="no"
-binary="no"
-quickjs="no"
-
-if [ "$1" = "all" ] ; then
-    extras="yes"
-    binary="yes"
-    quickjs="yes"
-elif [ "$1" = "binary" ] ; then
-    binary="yes"
-else
-    quickjs="yes"
+release_list="extras binary win_binary quickjs"
+
+if [ "$1" != "" ] ; then
+    release_list="$1"
 fi
 
 #################################################"
 # extras
 
-if [ "$extras" = "yes" ] ; then
+if echo $release_list | grep -w -q extras ; then
 
 d="quickjs-${version}"
 name="quickjs-extras-${version}"
@@ -46,10 +39,58 @@ cp -a tests/bench-v8 $outdir/tests
 fi
 
 #################################################"
-# binary release
+# Windows binary release
+
+if echo $release_list | grep -w -q win_binary ; then
+
+# win64
+
+dlldir=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
+cross_prefix="x86_64-w64-mingw32-"
+d="quickjs-win-x86_64-${version}"
+outdir="/tmp/${d}"
+
+rm -rf $outdir
+mkdir -p $outdir
+
+make CONFIG_WIN32=y qjs.exe
+cp qjs.exe $outdir
+${cross_prefix}strip $outdir/qjs.exe
+cp $dlldir/libwinpthread-1.dll $outdir
+
+( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
+
+make CONFIG_WIN32=y clean
+
+# win32
+
+dlldir=/usr/i686-w64-mingw32/sys-root/mingw/bin
+cross_prefix="i686-w64-mingw32-"
+d="quickjs-win-i686-${version}"
+outdir="/tmp/${d}"
+
+rm -rf $outdir
+mkdir -p $outdir
+
+make clean
+make CONFIG_WIN32=y clean
+
+make CONFIG_WIN32=y CONFIG_M32=y qjs.exe
+cp qjs.exe $outdir
+${cross_prefix}strip $outdir/qjs.exe
+cp $dlldir/libwinpthread-1.dll $outdir
+
+( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
+
+fi
+    
+#################################################"
+# Linux binary release
 
-if [ "$binary" = "yes" ] ; then
+if echo $release_list | grep -w -q binary ; then
 
+make clean
+make CONFIG_WIN32=y clean
 make -j4 qjs run-test262
 make -j4 CONFIG_M32=y qjs32 run-test262-32
 strip qjs run-test262 qjs32 run-test262-32
@@ -80,7 +121,7 @@ fi
 #################################################"
 # quickjs
 
-if [ "$quickjs" = "yes" ] ; then
+if echo $release_list | grep -w -q quickjs ; then
 
 make build_doc
 
@@ -98,7 +139,7 @@ cp Makefile VERSION TODO Changelog readme.txt release.sh unicode_download.sh \
    libregexp.c libregexp.h libregexp-opcode.h \
    libunicode.c libunicode.h libunicode-table.h \
    libbf.c libbf.h \
-   jscompress.c unicode_gen.c unicode_gen_def.h \
+   unicode_gen.c unicode_gen_def.h \
    run-test262.c test262o.conf test262.conf \
    test262o_errors.txt test262_errors.txt \
    $outdir
index e1eeb038688fd8bc8b0cf782d86a19e82dd9b312..f30a4ac5e890a119061ca443b7eba97a806ceb02 100644 (file)
@@ -49,9 +49,12 @@ testdir=test262/test
 # skipped features are tagged as such to avoid warnings
 
 AggregateError
+align-detached-buffer-semantics-with-web-reality
+arbitrary-module-namespace-names=skip
 Array.prototype.flat
 Array.prototype.flatMap
 Array.prototype.flatten
+Array.prototype.item=skip
 Array.prototype.values
 ArrayBuffer
 arrow-function
@@ -82,7 +85,6 @@ DataView.prototype.getInt8
 DataView.prototype.getUint16
 DataView.prototype.getUint32
 DataView.prototype.setUint8
-default-arg
 default-parameters
 destructuring-assignment
 destructuring-binding
@@ -90,6 +92,7 @@ dynamic-import
 export-star-as-namespace-from-module
 FinalizationGroup=skip
 FinalizationRegistry=skip
+FinalizationRegistry.prototype.cleanupSome=skip
 Float32Array
 Float64Array
 for-in-order
@@ -99,10 +102,12 @@ globalThis
 hashbang
 host-gc-required=skip
 import.meta
+Int16Array
 Int32Array
 Int8Array
 IsHTMLDDA
 json-superset
+legacy-regexp=skip
 let
 logical-assignment-operators
 Map
@@ -114,6 +119,7 @@ Object.fromEntries
 Object.is
 optional-catch-binding
 optional-chaining
+Promise
 Promise.allSettled
 Promise.any
 Promise.prototype.finally
@@ -135,6 +141,7 @@ string-trimming
 String.fromCodePoint
 String.prototype.endsWith
 String.prototype.includes
+String.prototype.item=skip
 String.prototype.matchAll
 String.prototype.replaceAll
 String.prototype.trimEnd
@@ -159,14 +166,19 @@ tail-call-optimization=skip
 template
 top-level-await=skip
 TypedArray
+TypedArray.prototype.item=skip
 u180e
 Uint16Array
+Uint32Array
 Uint8Array
 Uint8ClampedArray
 WeakMap
 WeakRef=skip
 WeakSet
 well-formed-json-stringify
+__getter__
+__proto__
+__setter__
 
 [exclude]
 # list excluded tests and directories here
@@ -183,8 +195,5 @@ test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js
 #test262/test/built-ins/RegExp/CharacterClassEscapes/
 #test262/test/built-ins/RegExp/property-escapes/
 
-# invalid tests
-test262/test/language/module-code/verify-dfs.js
-
 [tests]
 # list test files or use config.testdir
index d00d4f19b442da28bdec39449d23477467180d37..502a650c9e4fa1c57c1bc1abbfa1b018a1ea6be7 100644 (file)
@@ -1,30 +1,51 @@
 test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: Test262Error: Expected a ReferenceError but got a ReferenceError
 test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: strict mode: Test262Error: Expected a ReferenceError but got a ReferenceError
-test262/test/built-ins/Proxy/ownKeys/trap-is-undefined-target-is-proxy.js:29: Test262Error: Expected [0, length, foo, Symbol()] and [Symbol(), length, foo, 0] to have the same contents. 
-test262/test/built-ins/Proxy/ownKeys/trap-is-undefined-target-is-proxy.js:29: strict mode: Test262Error: Expected [0, length, foo, Symbol()] and [Symbol(), length, foo, 0] to have the same contents. 
 test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js:46: SyntaxError: invalid group name
 test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js:46: strict mode: SyntaxError: invalid group name
-test262/test/language/expressions/arrow-function/eval-var-scope-syntax-err.js:47: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/language/expressions/async-arrow-function/eval-var-scope-syntax-err.js:49: TypeError: $DONE() not called
-test262/test/language/expressions/async-function/named-eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called
-test262/test/language/expressions/async-function/nameless-eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called
-test262/test/language/expressions/async-generator/eval-var-scope-syntax-err.js:28: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/language/expressions/async-generator/named-eval-var-scope-syntax-err.js:28: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/language/expressions/class/elements/grammar-private-field-optional-chaining.js:26: SyntaxError: expecting field name
-test262/test/language/expressions/class/elements/grammar-private-field-optional-chaining.js:26: strict mode: SyntaxError: expecting field name
+test262/test/built-ins/TypedArray/prototype/every/BigInt/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/every/BigInt/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/every/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/every/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/filter/BigInt/callbackfn-detachbuffer.js:20: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/filter/BigInt/callbackfn-detachbuffer.js:20: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/filter/callbackfn-detachbuffer.js:20: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/filter/callbackfn-detachbuffer.js:20: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/findIndex/BigInt/predicate-may-detach-buffer.js:36: Test262Error: throws a TypeError getting a value from the detached buffer Expected a TypeError to be thrown but no exception was thrown at all (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/findIndex/BigInt/predicate-may-detach-buffer.js:36: strict mode: Test262Error: throws a TypeError getting a value from the detached buffer Expected a TypeError to be thrown but no exception was thrown at all (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/forEach/BigInt/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/forEach/BigInt/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/forEach/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/forEach/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/map/BigInt/callbackfn-detachbuffer.js:20: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/map/BigInt/callbackfn-detachbuffer.js:20: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/map/callbackfn-detachbuffer.js:20: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/map/callbackfn-detachbuffer.js:20: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/reduce/BigInt/callbackfn-detachbuffer.js:29: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/reduce/BigInt/callbackfn-detachbuffer.js:29: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/reduce/callbackfn-detachbuffer.js:29: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/reduce/callbackfn-detachbuffer.js:29: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/reduceRight/BigInt/callbackfn-detachbuffer.js:29: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/reduceRight/BigInt/callbackfn-detachbuffer.js:29: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/reduceRight/callbackfn-detachbuffer.js:29: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/reduceRight/callbackfn-detachbuffer.js:29: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/some/BigInt/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/some/BigInt/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArray/prototype/some/callbackfn-detachbuffer.js:28: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArray/prototype/some/callbackfn-detachbuffer.js:28: strict mode: Test262Error: Expected SameValue(«1», «2») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/detached-buffer.js:37: Test262Error:  (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/detached-buffer.js:37: strict mode: Test262Error:  (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/detached-buffer.js:38: Test262Error:  (Testing with Float64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/detached-buffer.js:38: strict mode: Test262Error:  (Testing with Float64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/GetOwnProperty/BigInt/index-prop-desc.js:21: Test262Error: Expected SameValue(«43», «42») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/GetOwnProperty/BigInt/index-prop-desc.js:21: strict mode: Test262Error: Expected SameValue(«43», «42») to be true (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/GetOwnProperty/index-prop-desc.js:22: Test262Error: Expected SameValue(«43», «42») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/GetOwnProperty/index-prop-desc.js:22: strict mode: Test262Error: Expected SameValue(«43», «42») to be true (Testing with Float64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer-realm.js:36: strict mode: TypeError: out-of-bound numeric index (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer.js:34: TypeError: cannot convert bigint to number (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer.js:32: strict mode: TypeError: out-of-bound numeric index (Testing with BigInt64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/Set/detached-buffer-realm.js:36: strict mode: TypeError: out-of-bound numeric index (Testing with Float64Array.)
+test262/test/built-ins/TypedArrayConstructors/internals/Set/detached-buffer.js:32: strict mode: TypeError: out-of-bound numeric index (Testing with Float64Array.)
 test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: TypeError: $DONE() not called
 test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: strict mode: TypeError: $DONE() not called
-test262/test/language/expressions/function/eval-var-scope-syntax-err.js:48: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/language/expressions/generators/eval-var-scope-syntax-err.js:49: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/language/expressions/object/method-definition/async-gen-meth-eval-var-scope-syntax-err.js:32: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/language/expressions/object/method-definition/async-meth-eval-var-scope-syntax-err.js:36: TypeError: $DONE() not called
-test262/test/language/expressions/object/method-definition/gen-meth-eval-var-scope-syntax-err.js:54: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/language/expressions/object/method-definition/meth-eval-var-scope-syntax-err.js:50: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
 test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:21: TypeError: cannot read property 'c' of undefined
 test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:15: strict mode: TypeError: cannot read property '_b' of undefined
-test262/test/language/statements/async-function/eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called
-test262/test/language/statements/async-generator/eval-var-scope-syntax-err.js:28: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/language/statements/class/elements/grammar-private-field-optional-chaining.js:26: SyntaxError: expecting field name
-test262/test/language/statements/class/elements/grammar-private-field-optional-chaining.js:26: strict mode: SyntaxError: expecting field name
-test262/test/language/statements/function/eval-var-scope-syntax-err.js:49: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/language/statements/generators/eval-var-scope-syntax-err.js:49: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
index 5650c528aba5d738b417a00a8a3f8f600868ebc9..c044b2c9dd4c27eaca1aba3efcf99e128c1ebfa7 100644 (file)
@@ -17,6 +17,22 @@ function assert(actual, expected, message) {
                 (message ? " (" + message + ")" : ""));
 }
 
+function assert_throws(expected_error, func)
+{
+    var err = false;
+    try {
+        func();
+    } catch(e) {
+        err = true;
+        if (!(e instanceof expected_error)) {
+            throw Error("unexpected exception type");
+        }
+    }
+    if (!err) {
+        throw Error("expected exception");
+    }
+}
+
 // load more elaborate version of assert if available
 try { __loadScript("test_assert.js"); } catch(e) {}
 
@@ -39,7 +55,7 @@ function test_function()
     function constructor1(a) {
         this.x = a;
     }
-    
+
     var r, g;
     
     r = my_func.call(null, 1, 2);
@@ -48,6 +64,13 @@ function test_function()
     r = my_func.apply(null, [1, 2]);
     assert(r, 3, "apply");
 
+    r = (function () { return 1; }).apply(null, undefined);
+    assert(r, 1);
+
+    assert_throws(TypeError, (function() {
+        Reflect.apply((function () { return 1; }), null, undefined);
+    }));
+    
     r = new Function("a", "b", "return a + b;");
     assert(r(2,3), 5, "function");
     
index 6b08467896c2018e35fcb062920386749fc0ec42..8d13deb94e7a04e5011ea2d6618f6cbcf0e1aac2 100644 (file)
@@ -15,6 +15,22 @@ function assert(actual, expected, message) {
                 (message ? " (" + message + ")" : ""));
 }
 
+function assert_throws(expected_error, func)
+{
+    var err = false;
+    try {
+        func();
+    } catch(e) {
+        err = true;
+        if (!(e instanceof expected_error)) {
+            throw Error("unexpected exception type");
+        }
+    }
+    if (!err) {
+        throw Error("expected exception");
+    }
+}
+
 // load more elaborate version of assert if available
 try { __loadScript("test_assert.js"); } catch(e) {}
 
@@ -233,8 +249,13 @@ function test_delete()
 
 function test_prototype()
 {
-    function f() { }
+    var f = function f() { };
     assert(f.prototype.constructor, f, "prototype");
+
+    var g = function g() { };
+    /* QuickJS bug */
+    Object.defineProperty(g, "prototype", { writable: false });
+    assert(g.prototype.constructor, g, "prototype");
 }
 
 function test_arguments()
@@ -376,6 +397,135 @@ function test_spread()
     assert(Object.getOwnPropertyNames(x).toString(), "0,length");
 }
 
+function test_function_length()
+{
+    assert( ((a, b = 1, c) => {}).length, 1);
+    assert( (([a,b]) => {}).length, 1);
+    assert( (({a,b}) => {}).length, 1);
+    assert( ((c, [a,b] = 1, d) => {}).length, 1);
+}
+
+function test_argument_scope()
+{
+    var f;
+    var c = "global";
+    
+    f = function(a = eval("var arguments")) {};
+    assert_throws(SyntaxError, f);
+
+    f = function(a = eval("1"), b = arguments[0]) { return b; };
+    assert(f(12), 12);
+
+    f = function(a, b = arguments[0]) { return b; };
+    assert(f(12), 12);
+
+    f = function(a, b = () => arguments) { return b; };
+    assert(f(12)()[0], 12);
+
+    f = function(a = eval("1"), b = () => arguments) { return b; };
+    assert(f(12)()[0], 12);
+
+    (function() {
+        "use strict";
+        f = function(a = this) { return a; };
+        assert(f.call(123), 123);
+
+        f = function f(a = f) { return a; };
+        assert(f(), f);
+
+        f = function f(a = eval("f")) { return a; };
+        assert(f(), f);
+    })();
+
+    f = (a = eval("var c = 1"), probe = () => c) => {
+        var c = 2;
+        assert(c, 2);
+        assert(probe(), 1);
+    }
+    f();
+
+    f = (a = eval("var arguments = 1"), probe = () => arguments) => {
+        var arguments = 2;
+        assert(arguments, 2);
+        assert(probe(), 1);
+    }
+    f();
+
+    f = function f(a = eval("var c = 1"), b = c, probe = () => c) {
+        assert(b, 1);
+        assert(c, 1);
+        assert(probe(), 1)
+    }
+    f();
+
+    assert(c, "global");
+    f = function f(a, b = c, probe = () => c) {
+        eval("var c = 1");
+        assert(c, 1);
+        assert(b, "global");
+        assert(probe(), "global")
+    }
+    f();
+    assert(c, "global");
+
+    f = function f(a = eval("var c = 1"), probe = (d = eval("c")) => d) {
+        assert(probe(), 1)
+    }
+    f();
+}
+
+function test_function_expr_name()
+{
+    var f;
+
+    /* non strict mode test : assignment to the function name silently
+       fails */
+    
+    f = function myfunc() {
+        myfunc = 1;
+        return myfunc;
+    };
+    assert(f(), f);
+
+    f = function myfunc() {
+        myfunc = 1;
+        (() => {
+            myfunc = 1;
+        })();
+        return myfunc;
+    };
+    assert(f(), f);
+
+    f = function myfunc() {
+        eval("myfunc = 1");
+        return myfunc;
+    };
+    assert(f(), f);
+    
+    /* strict mode test : assignment to the function name raises a
+       TypeError exception */
+
+    f = function myfunc() {
+        "use strict";
+        myfunc = 1;
+    };
+    assert_throws(TypeError, f);
+
+    f = function myfunc() {
+        "use strict";
+        (() => {
+            myfunc = 1;
+        })();
+    };
+    assert_throws(TypeError, f);
+
+    f = function myfunc() {
+        "use strict";
+        eval("myfunc = 1");
+    };
+    assert_throws(TypeError, f);
+}
+
 test_op1();
 test_cvt();
 test_eq();
@@ -392,3 +542,6 @@ test_regexp_skip();
 test_labels();
 test_destructuring();
 test_spread();
+test_function_length();
+test_argument_scope();
+test_function_expr_name();