History

2020-07-05 release

bellard committed 6 years ago

Commit 89007661 parent 172275830 files · +3715 −1669Browse files

Unified · Split

30 files
  1. Changelog +9 −0
  2. Makefile +17 −10
  3. TODO +4 −4
  4. VERSION +1 −1
  5. cutils.h +4 −0
  6. doc/jsbignum.html +2 −2
  7. doc/jsbignum.pdf +0 −0
  8. doc/quickjs.html +77 −18
  9. doc/quickjs.pdf +0 −0
  10. doc/quickjs.texi +63 −7
  11. examples/point.c +1 −1
  12. libbf.c +51 −24
  13. libregexp.c +36 −13
  14. qjs.c +14 −1
  15. qjsc.c +15 −2
  16. quickjs-atom.h +1 −0
  17. quickjs-libc.c +1036 −302
  18. quickjs-libc.h +9 −0
  19. quickjs.c +2058 −1253
  20. quickjs.h +25 −4
  21. repl.js +58 −14
  22. test262.conf +1 −0
  23. test262_errors.txt +4 −2
  24. tests/bjson.c +12 −4
  25. tests/microbench.js +14 −0
  26. tests/test_bjson.js +73 −7
  27. tests/test_builtin.js +4 −0
  28. tests/test_language.js +14 −2
  29. tests/test_std.js +21 −0
  30. tests/test_worker.js +93 −0
Changelog+9−0
@@ -1,3 +1,12 @@
12020-07-05:
2
3- modified JS_GetPrototype() to return a live value
4- REPL: support unicode characters larger than 16 bits
5- added os.Worker
6- improved object serialization
7- added std.parseExtJSON
8- misc bug fixes
9
12020-04-12:102020-04-12:
2 11
3- added cross realm support12- added cross realm support
Makefile+17−10
@@ -99,6 +99,10 @@ DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\" · 98 unmodified lines
99ifdef CONFIG_BIGNUM99ifdef CONFIG_BIGNUM
100DEFINES+=-DCONFIG_BIGNUM100DEFINES+=-DCONFIG_BIGNUM
101endif101endif
102ifdef CONFIG_WIN32
103DEFINES+=-D__USE_MINGW_ANSI_STDIO # for standard snprintf behavior
104endif
105
102CFLAGS+=$(DEFINES)106CFLAGS+=$(DEFINES)
103CFLAGS_DEBUG=$(CFLAGS) -O0107CFLAGS_DEBUG=$(CFLAGS) -O0
104CFLAGS_SMALL=$(CFLAGS) -Os108CFLAGS_SMALL=$(CFLAGS) -Os
@@ -115,8 +119,8 @@ CFLAGS+=-p · 10 unmodified lines
115LDFLAGS+=-p119LDFLAGS+=-p
116endif120endif
117ifdef CONFIG_ASAN121ifdef CONFIG_ASAN
118CFLAGS+=-fsanitize=address122CFLAGS+=-fsanitize=address -fno-omit-frame-pointer
119LDFLAGS+=-fsanitize=address123LDFLAGS+=-fsanitize=address -fno-omit-frame-pointer
120endif124endif
121ifdef CONFIG_WIN32125ifdef CONFIG_WIN32
122LDEXPORT=126LDEXPORT=
@@ -166,9 +170,10 @@ QJS_LIB_OBJS+=$(OBJDIR)/libbf.o · 43 unmodified lines
166QJS_OBJS+=$(OBJDIR)/qjscalc.o170QJS_OBJS+=$(OBJDIR)/qjscalc.o
167endif171endif
168 172
173HOST_LIBS=-lm -ldl -lpthread
169LIBS=-lm174LIBS=-lm
170ifndef CONFIG_WIN32175ifndef CONFIG_WIN32
171LIBS+=-ldl176LIBS+=-ldl -lpthread
172endif177endif
173 178
174$(OBJDIR):179$(OBJDIR):
@@ -187,7 +192,7 @@ ifneq ($(CROSS_PREFIX),) · 12 unmodified lines
187 192
188$(QJSC): $(OBJDIR)/qjsc.host.o \193$(QJSC): $(OBJDIR)/qjsc.host.o \
189 $(patsubst %.o, %.host.o, $(QJS_LIB_OBJS))194 $(patsubst %.o, %.host.o, $(QJS_LIB_OBJS))
190 $(HOST_CC) $(LDFLAGS) -o $@ $^ $(LIBS)195 $(HOST_CC) $(LDFLAGS) -o $@ $^ $(HOST_LIBS)
191 196
192endif #CROSS_PREFIX197endif #CROSS_PREFIX
193 198
@@ -239,13 +244,13 @@ libunicode-table.h: unicode_gen · 45 unmodified lines
239endif244endif
240 245
241run-test262: $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)246run-test262: $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)
242 $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread247 $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
243 248
244run-test262-debug: $(patsubst %.o, %.debug.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS))249run-test262-debug: $(patsubst %.o, %.debug.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS))
245 $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread250 $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
246 251
247run-test262-32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS))252run-test262-32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS))
248 $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS) -lpthread253 $(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
249 254
250# object suffix order: nolto, [m32|m32s]255# object suffix order: nolto, [m32|m32s]
251 256
@@ -285,7 +290,7 @@ unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c u · 33 unmodified lines
285clean:290clean:
286 rm -f repl.c qjscalc.c out.c291 rm -f repl.c qjscalc.c out.c
287 rm -f *.a *.o *.d *~ jscompress unicode_gen regexp_test $(PROGS)292 rm -f *.a *.o *.d *~ jscompress unicode_gen regexp_test $(PROGS)
288 rm -f hello.c hello_module.c test_fib.c293 rm -f hello.c test_fib.c
289 rm -f examples/*.so tests/*.so294 rm -f examples/*.so tests/*.so
290 rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug295 rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug
291 rm -rf run-test262-debug run-test262-32296 rm -rf run-test262-debug run-test262-32
@@ -379,10 +384,11 @@ endif · 87 unmodified lines
379 384
380test: qjs385test: qjs
381 ./qjs tests/test_closure.js386 ./qjs tests/test_closure.js
382 ./qjs tests/test_op.js387 ./qjs tests/test_language.js
383 ./qjs tests/test_builtin.js388 ./qjs tests/test_builtin.js
384 ./qjs tests/test_loop.js389 ./qjs tests/test_loop.js
385 ./qjs tests/test_std.js390 ./qjs tests/test_std.js
391 ./qjs tests/test_worker.js
386ifndef CONFIG_DARWIN392ifndef CONFIG_DARWIN
387ifdef CONFIG_BIGNUM393ifdef CONFIG_BIGNUM
388 ./qjs --bignum tests/test_bjson.js394 ./qjs --bignum tests/test_bjson.js
@@ -398,10 +404,11 @@ ifdef CONFIG_BIGNUM · 9 unmodified lines
398endif404endif
399ifdef CONFIG_M32405ifdef CONFIG_M32
400 ./qjs32 tests/test_closure.js406 ./qjs32 tests/test_closure.js
401 ./qjs32 tests/test_op.js407 ./qjs32 tests/test_language.js
402 ./qjs32 tests/test_builtin.js408 ./qjs32 tests/test_builtin.js
403 ./qjs32 tests/test_loop.js409 ./qjs32 tests/test_loop.js
404 ./qjs32 tests/test_std.js410 ./qjs32 tests/test_std.js
411 ./qjs32 tests/test_worker.js
405ifdef CONFIG_BIGNUM412ifdef CONFIG_BIGNUM
406 ./qjs32 --bignum tests/test_op_overloading.js413 ./qjs32 --bignum tests/test_op_overloading.js
407 ./qjs32 --bignum tests/test_bignum.js414 ./qjs32 --bignum tests/test_bignum.js
TODO+4−4
@@ -1,4 +1,5 @@
1Misc:1Misc:
2- use realpath in module name normalizer and put it in quickjs-libc
2- use custom printf to avoid C library compatibility issues3- use custom printf to avoid C library compatibility issues
3- rename CONFIG_ALL_UNICODE, CONFIG_BIGNUM, CONFIG_ATOMICS, CONFIG_CHECK_JSVALUE ?4- rename CONFIG_ALL_UNICODE, CONFIG_BIGNUM, CONFIG_ATOMICS, CONFIG_CHECK_JSVALUE ?
4- unify coding style and naming conventions5- unify coding style and naming conventions
@@ -56,12 +57,12 @@ Extensions: · 51 unmodified lines
56 handle #if, #ifdef, #line, limited support for #define57 handle #if, #ifdef, #line, limited support for #define
57- get rid of __loadScript, use more common name58- get rid of __loadScript, use more common name
58- BSD sockets59- BSD sockets
59- Workers
60 60
61REPL:61REPL:
62- debugger62- debugger
63- readline: support MS Windows terminal63- readline: support MS Windows terminal
64- readline: handle dynamic terminal resizing64- readline: handle dynamic terminal resizing
65- readline: handle double width unicode characters
65- multiline editing66- multiline editing
66- runtime object and function inspectors67- runtime object and function inspectors
67- interactive object browser68- interactive object browser
@@ -73,6 +74,5 @@ REPL: · 5 unmodified lines
73Test262o: 0/11262 errors, 463 excluded74Test262o: 0/11262 errors, 463 excluded
74Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)75Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
75 76
76Test262: 28/70829 errors, 877 excluded, 425 skipped77Test262: 30/71095 errors, 870 excluded, 549 skipped
77Test262 commit: 4a8e49b3ca7f9f74a4cafe6621ff9ba548ccc35378Test262 commit: 281eb10b2844929a7c0ac04527f5b42ce56509fd
78
VERSION+1−1
@@ -1 +1 @@
12020-04-1212020-07-05
cutils.h+4−0
@@ -268,6 +268,10 @@ void dbuf_free(DynBuf *s); · 267 unmodified lines
268static inline BOOL dbuf_error(DynBuf *s) {268static inline BOOL dbuf_error(DynBuf *s) {
269 return s->error;269 return s->error;
270}270}
271static inline void dbuf_set_error(DynBuf *s)
272{
273 s->error = TRUE;
274}
271 275
272#define UTF8_CHAR_LEN_MAX 6276#define UTF8_CHAR_LEN_MAX 6
273 277
doc/jsbignum.html+2−2
@@ -1,7 +1,8 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2<html>2<html>
3<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->3<!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ -->
4<head>4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5<title>Javascript Bignum Extensions</title>6<title>Javascript Bignum Extensions</title>
6 7
7<meta name="description" content="Javascript Bignum Extensions">8<meta name="description" content="Javascript Bignum Extensions">
@@ -9,7 +10,6 @@ · 1 unmodified line
9<meta name="resource-type" content="document">10<meta name="resource-type" content="document">
10<meta name="distribution" content="global">11<meta name="distribution" content="global">
11<meta name="Generator" content="makeinfo">12<meta name="Generator" content="makeinfo">
12<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
13<link href="#SEC_Contents" rel="contents" title="Table of Contents">13<link href="#SEC_Contents" rel="contents" title="Table of Contents">
14<style type="text/css">14<style type="text/css">
15<!--15<!--
doc/jsbignum.pdf+0−0

Binary file not shown.

doc/quickjs.html+77−18
@@ -1,7 +1,8 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2<html>2<html>
3<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->3<!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ -->
4<head>4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5<title>QuickJS Javascript Engine</title>6<title>QuickJS Javascript Engine</title>
6 7
7<meta name="description" content="QuickJS Javascript Engine">8<meta name="description" content="QuickJS Javascript Engine">
@@ -9,7 +10,6 @@ · 1 unmodified line
9<meta name="resource-type" content="document">10<meta name="resource-type" content="document">
10<meta name="distribution" content="global">11<meta name="distribution" content="global">
11<meta name="Generator" content="makeinfo">12<meta name="Generator" content="makeinfo">
12<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
13<link href="#SEC_Contents" rel="contents" title="Table of Contents">13<link href="#SEC_Contents" rel="contents" title="Table of Contents">
14<style type="text/css">14<style type="text/css">
15<!--15<!--
@@ -73,10 +73,9 @@ ul.no-bullet {list-style: none} · 57 unmodified lines
73 <li><a name="toc-Language-support" href="#Language-support">3.1 Language support</a>73 <li><a name="toc-Language-support" href="#Language-support">3.1 Language support</a>
74 <ul class="no-bullet">74 <ul class="no-bullet">
75 <li><a name="toc-ES2020-support" href="#ES2020-support">3.1.1 ES2020 support</a></li>75 <li><a name="toc-ES2020-support" href="#ES2020-support">3.1.1 ES2020 support</a></li>
76 <li><a name="toc-JSON" href="#JSON">3.1.2 JSON</a></li>76 <li><a name="toc-ECMA402" href="#ECMA402">3.1.2 ECMA402</a></li>
77 <li><a name="toc-ECMA402" href="#ECMA402">3.1.3 ECMA402</a></li>77 <li><a name="toc-Extensions" href="#Extensions">3.1.3 Extensions</a></li>
78 <li><a name="toc-Extensions" href="#Extensions">3.1.4 Extensions</a></li>78 <li><a name="toc-Mathematical-extensions" href="#Mathematical-extensions">3.1.4 Mathematical extensions</a></li>
79 <li><a name="toc-Mathematical-extensions" href="#Mathematical-extensions">3.1.5 Mathematical extensions</a></li>
80 </ul></li>79 </ul></li>
81 <li><a name="toc-Modules" href="#Modules">3.2 Modules</a></li>80 <li><a name="toc-Modules" href="#Modules">3.2 Modules</a></li>
82 <li><a name="toc-Standard-library" href="#Standard-library">3.3 Standard library</a>81 <li><a name="toc-Standard-library" href="#Standard-library">3.3 Standard library</a>
@@ -407,18 +406,13 @@ B (legacy web compatibility) and the Unicode related features. · 324 unmodified lines
407 406
408</li></ul>407</li></ul>
409 408
410<a name="JSON"></a>
411<h4 class="subsection">3.1.2 JSON</h4>
412
413<p>The JSON parser is currently more tolerant than the specification.
414</p>
415<a name="ECMA402"></a>409<a name="ECMA402"></a>
416<h4 class="subsection">3.1.3 ECMA402</h4>410<h4 class="subsection">3.1.2 ECMA402</h4>
417 411
418<p>ECMA402 (Internationalization API) is not supported.412<p>ECMA402 (Internationalization API) is not supported.
419</p>413</p>
420<a name="Extensions"></a>414<a name="Extensions"></a>
421<h4 class="subsection">3.1.4 Extensions</h4>415<h4 class="subsection">3.1.3 Extensions</h4>
422 416
423<ul>417<ul>
424<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.418<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.
@@ -428,7 +422,7 @@ B (legacy web compatibility) and the Unicode related features. · 3 unmodified lines
428</li></ul>422</li></ul>
429 423
430<a name="Mathematical-extensions"></a>424<a name="Mathematical-extensions"></a>
431<h4 class="subsection">3.1.5 Mathematical extensions</h4>425<h4 class="subsection">3.1.4 Mathematical extensions</h4>
432 426
433<p>The mathematical extensions are fully backward compatible with427<p>The mathematical extensions are fully backward compatible with
434standard Javascript. See <code>jsbignum.pdf</code> for more information.428standard Javascript. See <code>jsbignum.pdf</code> for more information.
@@ -557,7 +551,7 @@ no error occured. · 122 unmodified lines
557</p>551</p>
558</dd>552</dd>
559<dt><code>printf(fmt, ...args)</code></dt>553<dt><code>printf(fmt, ...args)</code></dt>
560<dd><p>Equivalent to <code>std.out.printf(fmt, ...args)</code>554<dd><p>Equivalent to <code>std.out.printf(fmt, ...args)</code>.
561</p>555</p>
562</dd>556</dd>
563<dt><code>sprintf(fmt, ...args)</code></dt>557<dt><code>sprintf(fmt, ...args)</code></dt>
@@ -636,6 +630,21 @@ optional properties: · 72 unmodified lines
636</dd>630</dd>
637</dl>631</dl>
638 632
633</dd>
634<dt><code>parseExtJSON(str)</code></dt>
635<dd>
636<p>Parse <code>str</code> using a superset of <code>JSON.parse</code>. The
637 following extensions are accepted:
638</p>
639<ul>
640<li> Single line and multiline comments
641 </li><li> unquoted properties (ASCII-only Javascript identifiers)
642 </li><li> trailing comma in array and object definitions
643 </li><li> single quoted strings
644 </li><li> <code>\f</code> and <code>\v</code> are accepted as space characters
645 </li><li> leading plus in numbers
646 </li><li> octal (<code>0o</code> prefix) and hexadecimal (<code>0x</code> prefix) numbers
647 </li></ul>
639</dd>648</dd>
640</dl>649</dl>
641 650
@@ -649,8 +658,14 @@ optional properties: · 7 unmodified lines
649<dd><p>Outputs the string with the UTF-8 encoding.658<dd><p>Outputs the string with the UTF-8 encoding.
650</p></dd>659</p></dd>
651<dt><code>printf(fmt, ...args)</code></dt>660<dt><code>printf(fmt, ...args)</code></dt>
652<dd><p>Formatted printf, same formats as the libc printf.661<dd><p>Formatted printf.
653</p></dd>662</p>
663<p>The same formats as the standard C library <code>printf</code> are
664supported. Integer format types (e.g. <code>%d</code>) truncate the Numbers
665or BigInts to 32 bits. Use the <code>l</code> modifier (e.g. <code>%ld</code>) to
666truncate to 64 bits.
667</p>
668</dd>
654<dt><code>flush()</code></dt>669<dt><code>flush()</code></dt>
655<dd><p>Flush the buffered file.670<dd><p>Flush the buffered file.
656</p></dd>671</p></dd>
@@ -718,6 +733,7 @@ is read up its end. · 61 unmodified lines
718</li><li> signals733</li><li> signals
719</li><li> timers734</li><li> timers
720</li><li> asynchronous I/O735</li><li> asynchronous I/O
736</li><li> workers (threads)
721</li></ul>737</li></ul>
722 738
723<p>The OS functions usually return 0 if OK or an OS specific negative739<p>The OS functions usually return 0 if OK or an OS specific negative
@@ -869,7 +885,7 @@ the handler. · 145 unmodified lines
869<dd><p>Call the function <code>func</code> when the signal <code>signal</code>885<dd><p>Call the function <code>func</code> when the signal <code>signal</code>
870happens. Only a single handler per signal number is supported. Use886happens. Only a single handler per signal number is supported. Use
871<code>null</code> to set the default handler or <code>undefined</code> to ignore887<code>null</code> to set the default handler or <code>undefined</code> to ignore
872the signal.888the signal. Signal handlers can only be defined in the main thread.
873</p>889</p>
874</dd>890</dd>
875<dt><code>SIGINT</code></dt>891<dt><code>SIGINT</code></dt>
@@ -972,6 +988,49 @@ to the timer. · 96 unmodified lines
972<dd><p>Return a string representing the platform: <code>&quot;linux&quot;</code>, <code>&quot;darwin&quot;</code>,988<dd><p>Return a string representing the platform: <code>&quot;linux&quot;</code>, <code>&quot;darwin&quot;</code>,
973<code>&quot;win32&quot;</code> or <code>&quot;js&quot;</code>.989<code>&quot;win32&quot;</code> or <code>&quot;js&quot;</code>.
974</p>990</p>
991</dd>
992<dt><code>Worker(source)</code></dt>
993<dd><p>Constructor to create a new thread (worker) with an API close to the
994<code>WebWorkers</code>. <code>source</code> is a string containing the module
995source which is executed in the newly created thread. Threads normally
996don&rsquo;t share any data and communicate between each other with
997messages. Nested workers are not supported. An example is available in
998<samp>tests/test_worker.js</samp>.
999</p>
1000<p>The worker class has the following static properties:
1001</p>
1002<dl compact="compact">
1003<dt><code>parent</code></dt>
1004<dd><p>In the created worker, <code>Worker.parent</code> represents the parent
1005 worker and is used to send or receive messages.
1006 </p></dd>
1007</dl>
1008
1009<p>The worker instances have the following properties:
1010</p>
1011<dl compact="compact">
1012<dt><code>postMessage(msg)</code></dt>
1013<dd>
1014<p>Send a message to the corresponding worker. <code>msg</code> is cloned in
1015 the destination worker using an algorithm similar to the <code>HTML</code>
1016 structured clone algorithm. <code>SharedArrayBuffer</code> are shared
1017 between workers.
1018</p>
1019<p>Current limitations: <code>Map</code> and <code>Set</code> are not supported
1020 yet.
1021</p>
1022</dd>
1023<dt><code>onmessage</code></dt>
1024<dd>
1025<p>Getter and setter. Set a function which is called each time a
1026 message is received. The function is called with a single
1027 argument. It is an object with a <code>data</code> property containing the
1028 received message. The thread is not terminated if there is at least
1029 one non <code>null</code> <code>onmessage</code> handler.
1030</p>
1031</dd>
1032</dl>
1033
975</dd>1034</dd>
976</dl>1035</dl>
977 1036
doc/quickjs.pdf+0−0

Binary file not shown.

doc/quickjs.texi+63−7
@@ -272,10 +272,6 @@ The following features are not supported yet: · 271 unmodified lines
272 272
273@end itemize273@end itemize
274 274
275@subsection JSON
276
277The JSON parser is currently more tolerant than the specification.
278
279@subsection ECMA402275@subsection ECMA402
280 276
281ECMA402 (Internationalization API) is not supported.277ECMA402 (Internationalization API) is not supported.
@@ -405,7 +401,7 @@ no error occured. · 123 unmodified lines
405Equivalent to @code{std.out.puts(str)}.401Equivalent to @code{std.out.puts(str)}.
406 402
407@item printf(fmt, ...args)403@item printf(fmt, ...args)
408Equivalent to @code{std.out.printf(fmt, ...args)}404Equivalent to @code{std.out.printf(fmt, ...args)}.
409 405
410@item sprintf(fmt, ...args)406@item sprintf(fmt, ...args)
411Equivalent to the libc sprintf().407Equivalent to the libc sprintf().
@@ -474,6 +470,20 @@ optional properties: · 62 unmodified lines
474 470
475 @end table471 @end table
476 472
473@item parseExtJSON(str)
474
475 Parse @code{str} using a superset of @code{JSON.parse}. The
476 following extensions are accepted:
477
478 @itemize
479 @item Single line and multiline comments
480 @item unquoted properties (ASCII-only Javascript identifiers)
481 @item trailing comma in array and object definitions
482 @item single quoted strings
483 @item @code{\f} and @code{\v} are accepted as space characters
484 @item leading plus in numbers
485 @item octal (@code{0o} prefix) and hexadecimal (@code{0x} prefix) numbers
486 @end itemize
477@end table487@end table
478 488
479FILE prototype:489FILE prototype:
@@ -484,7 +494,13 @@ Close the file. Return 0 if OK or @code{-errno} in case of I/O error. · 4 unmodified lines
484@item puts(str)494@item puts(str)
485Outputs the string with the UTF-8 encoding.495Outputs the string with the UTF-8 encoding.
486@item printf(fmt, ...args)496@item printf(fmt, ...args)
487Formatted printf, same formats as the libc printf.497Formatted printf.
498
499The same formats as the standard C library @code{printf} are
500supported. Integer format types (e.g. @code{%d}) truncate the Numbers
501or BigInts to 32 bits. Use the @code{l} modifier (e.g. @code{%ld}) to
502truncate to 64 bits.
503
488@item flush()504@item flush()
489Flush the buffered file.505Flush the buffered file.
490@item seek(offset, whence)506@item seek(offset, whence)
@@ -537,6 +553,7 @@ The @code{os} module provides Operating System specific functions: · 46 unmodified lines
537@item signals553@item signals
538@item timers554@item timers
539@item asynchronous I/O555@item asynchronous I/O
556@item workers (threads)
540@end itemize557@end itemize
541 558
542The OS functions usually return 0 if OK or an OS specific negative559The OS functions usually return 0 if OK or an OS specific negative
@@ -664,7 +681,7 @@ the handler. · 121 unmodified lines
664Call the function @code{func} when the signal @code{signal}681Call the function @code{func} when the signal @code{signal}
665happens. Only a single handler per signal number is supported. Use682happens. Only a single handler per signal number is supported. Use
666@code{null} to set the default handler or @code{undefined} to ignore683@code{null} to set the default handler or @code{undefined} to ignore
667the signal.684the signal. Signal handlers can only be defined in the main thread.
668 685
669@item SIGINT686@item SIGINT
670@item SIGABRT687@item SIGABRT
@@ -747,6 +764,45 @@ Cancel a timer. · 76 unmodified lines
747Return a string representing the platform: @code{"linux"}, @code{"darwin"},764Return a string representing the platform: @code{"linux"}, @code{"darwin"},
748@code{"win32"} or @code{"js"}.765@code{"win32"} or @code{"js"}.
749 766
767@item Worker(source)
768Constructor to create a new thread (worker) with an API close to the
769@code{WebWorkers}. @code{source} is a string containing the module
770source which is executed in the newly created thread. Threads normally
771don't share any data and communicate between each other with
772messages. Nested workers are not supported. An example is available in
773@file{tests/test_worker.js}.
774
775The worker class has the following static properties:
776
777 @table @code
778 @item parent
779 In the created worker, @code{Worker.parent} represents the parent
780 worker and is used to send or receive messages.
781 @end table
782
783The worker instances have the following properties:
784
785 @table @code
786 @item postMessage(msg)
787
788 Send a message to the corresponding worker. @code{msg} is cloned in
789 the destination worker using an algorithm similar to the @code{HTML}
790 structured clone algorithm. @code{SharedArrayBuffer} are shared
791 between workers.
792
793 Current limitations: @code{Map} and @code{Set} are not supported
794 yet.
795
796 @item onmessage
797
798 Getter and setter. Set a function which is called each time a
799 message is received. The function is called with a single
800 argument. It is an object with a @code{data} property containing the
801 received message. The thread is not terminated if there is at least
802 one non @code{null} @code{onmessage} handler.
803
804 @end table
805
750@end table806@end table
751 807
752@section QuickJS C API808@section QuickJS C API
examples/point.c+1−1
@@ -130,11 +130,11 @@ static int js_point_init(JSContext *ctx, JSModuleDef *m) · 129 unmodified lines
130 130
131 point_proto = JS_NewObject(ctx);131 point_proto = JS_NewObject(ctx);
132 JS_SetPropertyFunctionList(ctx, point_proto, js_point_proto_funcs, countof(js_point_proto_funcs));132 JS_SetPropertyFunctionList(ctx, point_proto, js_point_proto_funcs, countof(js_point_proto_funcs));
133 JS_SetClassProto(ctx, js_point_class_id, point_proto);
134 133
135 point_class = JS_NewCFunction2(ctx, js_point_ctor, "Point", 2, JS_CFUNC_constructor, 0);134 point_class = JS_NewCFunction2(ctx, js_point_ctor, "Point", 2, JS_CFUNC_constructor, 0);
136 /* set proto.constructor and ctor.prototype */135 /* set proto.constructor and ctor.prototype */
137 JS_SetConstructor(ctx, point_class, point_proto);136 JS_SetConstructor(ctx, point_class, point_proto);
137 JS_SetClassProto(ctx, js_point_class_id, point_proto);
138 138
139 JS_SetModuleExport(ctx, m, "Point", point_class);139 JS_SetModuleExport(ctx, m, "Point", point_class);
140 return 0;140 return 0;
libbf.c+51−24
@@ -3370,12 +3370,14 @@ slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv, · 3369 unmodified lines
3370}3370}
3371 3371
3372/* 'n' is the number of output limbs */3372/* 'n' is the number of output limbs */
3373static void bf_integer_to_radix_rec(bf_t *pow_tab,3373static int bf_integer_to_radix_rec(bf_t *pow_tab,
3374 limb_t *out, const bf_t *a, limb_t n,3374 limb_t *out, const bf_t *a, limb_t n,
3375 int level, limb_t n0, limb_t radixl,3375 int level, limb_t n0, limb_t radixl,
3376 unsigned int radixl_bits)3376 unsigned int radixl_bits)
3377{3377{
3378 limb_t n1, n2, q_prec;3378 limb_t n1, n2, q_prec;
3379 int ret;
3380
3379 assert(n >= 1);3381 assert(n >= 1);
3380 if (n == 1) {3382 if (n == 1) {
3381 out[0] = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn);3383 out[0] = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn);
@@ -3402,63 +3404,81 @@ static void bf_integer_to_radix_rec(bf_t *pow_tab, · 20 unmodified lines
3402 n1 = n - n2;3404 n1 = n - n2;
3403 B = &pow_tab[2 * level];3405 B = &pow_tab[2 * level];
3404 B_inv = &pow_tab[2 * level + 1];3406 B_inv = &pow_tab[2 * level + 1];
3407 ret = 0;
3405 if (B->len == 0) {3408 if (B->len == 0) {
3406 /* compute BASE^n2 */3409 /* compute BASE^n2 */
3407 bf_pow_ui_ui(B, radixl, n2, BF_PREC_INF, BF_RNDZ);3410 ret |= bf_pow_ui_ui(B, radixl, n2, BF_PREC_INF, BF_RNDZ);
3408 /* we use enough bits for the maximum possible 'n1' value,3411 /* we use enough bits for the maximum possible 'n1' value,
3409 i.e. n2 + 1 */3412 i.e. n2 + 1 */
3410 bf_set_ui(&R, 1);3413 ret |= bf_set_ui(&R, 1);
3411 bf_div(B_inv, &R, B, (n2 + 1) * radixl_bits + 2, BF_RNDN);3414 ret |= bf_div(B_inv, &R, B, (n2 + 1) * radixl_bits + 2, BF_RNDN);
3412 }3415 }
3413 // printf("%d: n1=% " PRId64 " n2=%" PRId64 "\n", level, n1, n2);3416 // printf("%d: n1=% " PRId64 " n2=%" PRId64 "\n", level, n1, n2);
3414 q_prec = n1 * radixl_bits;3417 q_prec = n1 * radixl_bits;
3415 bf_mul(&Q, a, B_inv, q_prec, BF_RNDN);3418 ret |= bf_mul(&Q, a, B_inv, q_prec, BF_RNDN);
3416 bf_rint(&Q, BF_RNDZ);3419 ret |= bf_rint(&Q, BF_RNDZ);
3417 3420
3418 bf_mul(&R, &Q, B, BF_PREC_INF, BF_RNDZ);3421 ret |= bf_mul(&R, &Q, B, BF_PREC_INF, BF_RNDZ);
3419 bf_sub(&R, a, &R, BF_PREC_INF, BF_RNDZ);3422 ret |= bf_sub(&R, a, &R, BF_PREC_INF, BF_RNDZ);
3423
3424 if (ret & BF_ST_MEM_ERROR)
3425 goto fail;
3420 /* adjust if necessary */3426 /* adjust if necessary */
3421 q_add = 0;3427 q_add = 0;
3422 while (R.sign && R.len != 0) {3428 while (R.sign && R.len != 0) {
3423 bf_add(&R, &R, B, BF_PREC_INF, BF_RNDZ);3429 if (bf_add(&R, &R, B, BF_PREC_INF, BF_RNDZ))
3430 goto fail;
3424 q_add--;3431 q_add--;
3425 }3432 }
3426 while (bf_cmpu(&R, B) >= 0) {3433 while (bf_cmpu(&R, B) >= 0) {
3427 bf_sub(&R, &R, B, BF_PREC_INF, BF_RNDZ);3434 if (bf_sub(&R, &R, B, BF_PREC_INF, BF_RNDZ))
3435 goto fail;
3428 q_add++;3436 q_add++;
3429 }3437 }
3430 if (q_add != 0) {3438 if (q_add != 0) {
3431 bf_add_si(&Q, &Q, q_add, BF_PREC_INF, BF_RNDZ);3439 if (bf_add_si(&Q, &Q, q_add, BF_PREC_INF, BF_RNDZ))
3440 goto fail;
3441 }
3442 if (bf_integer_to_radix_rec(pow_tab, out + n2, &Q, n1, level + 1, n0,
3443 radixl, radixl_bits))
3444 goto fail;
3445 if (bf_integer_to_radix_rec(pow_tab, out, &R, n2, level + 1, n0,
3446 radixl, radixl_bits)) {
3447 fail:
3448 bf_delete(&Q);
3449 bf_delete(&R);
3450 return -1;
3432 }3451 }
3433 bf_integer_to_radix_rec(pow_tab, out + n2, &Q, n1, level + 1, n0,
3434 radixl, radixl_bits);
3435 bf_integer_to_radix_rec(pow_tab, out, &R, n2, level + 1, n0,
3436 radixl, radixl_bits);
3437 bf_delete(&Q);3452 bf_delete(&Q);
3438 bf_delete(&R);3453 bf_delete(&R);
3439 }3454 }
3455 return 0;
3440}3456}
3441 3457
3442static void bf_integer_to_radix(bf_t *r, const bf_t *a, limb_t radixl)3458/* return 0 if OK != 0 if memory error */
3459static int bf_integer_to_radix(bf_t *r, const bf_t *a, limb_t radixl)
3443{3460{
3444 bf_context_t *s = r->ctx;3461 bf_context_t *s = r->ctx;
3445 limb_t r_len;3462 limb_t r_len;
3446 bf_t *pow_tab;3463 bf_t *pow_tab;
3447 int i, pow_tab_len;3464 int i, pow_tab_len, ret;
3448 3465
3449 r_len = r->len;3466 r_len = r->len;
3450 pow_tab_len = (ceil_log2(r_len) + 2) * 2; /* XXX: check */3467 pow_tab_len = (ceil_log2(r_len) + 2) * 2; /* XXX: check */
3451 pow_tab = bf_malloc(s, sizeof(pow_tab[0]) * pow_tab_len);3468 pow_tab = bf_malloc(s, sizeof(pow_tab[0]) * pow_tab_len);
3469 if (!pow_tab)
3470 return -1;
3452 for(i = 0; i < pow_tab_len; i++)3471 for(i = 0; i < pow_tab_len; i++)
3453 bf_init(r->ctx, &pow_tab[i]);3472 bf_init(r->ctx, &pow_tab[i]);
3454 3473
3455 bf_integer_to_radix_rec(pow_tab, r->tab, a, r_len, 0, r_len, radixl,3474 ret = bf_integer_to_radix_rec(pow_tab, r->tab, a, r_len, 0, r_len, radixl,
3456 ceil_log2(radixl));3475 ceil_log2(radixl));
3457 3476
3458 for(i = 0; i < pow_tab_len; i++) {3477 for(i = 0; i < pow_tab_len; i++) {
3459 bf_delete(&pow_tab[i]);3478 bf_delete(&pow_tab[i]);
3460 }3479 }
3461 bf_free(s, pow_tab);3480 bf_free(s, pow_tab);
3481 return ret;
3462}3482}
3463 3483
3464/* a must be >= 0. 'P' is the wanted number of digits in radix3484/* a must be >= 0. 'P' is the wanted number of digits in radix
@@ -3625,8 +3645,14 @@ static void output_digits(DynBuf *s, const bf_t *a1, int radix, limb_t n_digits, · 160 unmodified lines
3625 a = &a_s;3645 a = &a_s;
3626 bf_init(a1->ctx, a);3646 bf_init(a1->ctx, a);
3627 n = (n_digits + digits_per_limb - 1) / digits_per_limb;3647 n = (n_digits + digits_per_limb - 1) / digits_per_limb;
3628 bf_resize(a, n);3648 if (bf_resize(a, n)) {
3629 bf_integer_to_radix(a, a1, radixl);3649 dbuf_set_error(s);
3650 goto done;
3651 }
3652 if (bf_integer_to_radix(a, a1, radixl)) {
3653 dbuf_set_error(s);
3654 goto done;
3655 }
3630 radix_bits = 0;3656 radix_bits = 0;
3631 pos = n;3657 pos = n;
3632 pos_incr = 1;3658 pos_incr = 1;
@@ -3659,6 +3685,7 @@ static void output_digits(DynBuf *s, const bf_t *a1, int radix, limb_t n_digits, · 26 unmodified lines
3659 buf_pos += l;3685 buf_pos += l;
3660 i += l;3686 i += l;
3661 }3687 }
3688 done:
3662 if (a != a1)3689 if (a != a1)
3663 bf_delete(a);3690 bf_delete(a);
3664}3691}
libregexp.c+36−13
@@ -110,12 +110,14 @@ static inline int is_digit(int c) { · 109 unmodified lines
110 return c >= '0' && c <= '9';110 return c >= '0' && c <= '9';
111}111}
112 112
113/* insert 'len' bytes at position 'pos' */113/* insert 'len' bytes at position 'pos'. Return < 0 if error. */
114static void dbuf_insert(DynBuf *s, int pos, int len)114static int dbuf_insert(DynBuf *s, int pos, int len)
115{115{
116 dbuf_realloc(s, s->size + len);116 if (dbuf_realloc(s, s->size + len))
117 return -1;
117 memmove(s->buf + pos + len, s->buf + pos, s->size - pos);118 memmove(s->buf + pos + len, s->buf + pos, s->size - pos);
118 s->size += len;119 s->size += len;
120 return 0;
119}121}
120 122
121/* canonicalize with the specific JS regexp rules */123/* canonicalize with the specific JS regexp rules */
@@ -434,6 +436,11 @@ static int __attribute__((format(printf, 2, 3))) re_parse_error(REParseState *s, · 312 unmodified lines
434 return -1;436 return -1;
435}437}
436 438
439static int re_parse_out_of_memory(REParseState *s)
440{
441 return re_parse_error(s, "out of memory");
442}
443
437/* If allow_overflow is false, return -1 in case of444/* If allow_overflow is false, return -1 in case of
438 overflow. Otherwise return INT32_MAX. */445 overflow. Otherwise return INT32_MAX. */
439static int parse_digits(const uint8_t **pp, BOOL allow_overflow)446static int parse_digits(const uint8_t **pp, BOOL allow_overflow)
@@ -693,7 +700,7 @@ static int parse_unicode_property(REParseState *s, CharRange *cr, · 253 unmodified lines
693 *pp = p;700 *pp = p;
694 return 0;701 return 0;
695 out_of_memory:702 out_of_memory:
696 return re_parse_error(s, "out of memory");703 return re_parse_out_of_memory(s);
697}704}
698#endif /* CONFIG_ALL_UNICODE */705#endif /* CONFIG_ALL_UNICODE */
699 706
@@ -928,7 +935,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp) · 228 unmodified lines
928 *pp = p;935 *pp = p;
929 return 0;936 return 0;
930 memory_error:937 memory_error:
931 re_parse_error(s, "out of memory");938 re_parse_out_of_memory(s);
932 fail:939 fail:
933 cr_free(cr);940 cr_free(cr);
934 return -1;941 return -1;
@@ -1295,6 +1302,8 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) · 360 unmodified lines
1295 return -1;1302 return -1;
1296 re_emit_op(s, REOP_match);1303 re_emit_op(s, REOP_match);
1297 /* jump after the 'match' after the lookahead is successful */1304 /* jump after the 'match' after the lookahead is successful */
1305 if (dbuf_error(&s->byte_code))
1306 return -1;
1298 put_u32(s->byte_code.buf + pos, s->byte_code.size - (pos + 4));1307 put_u32(s->byte_code.buf + pos, s->byte_code.size - (pos + 4));
1299 } else if (p[2] == '<') {1308 } else if (p[2] == '<') {
1300 p += 3;1309 p += 3;
@@ -1548,12 +1557,15 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) · 247 unmodified lines
1548 1557
1549 if (quant_max > 0) {1558 if (quant_max > 0) {
1550 /* specific optimization for simple quantifiers */1559 /* specific optimization for simple quantifiers */
1560 if (dbuf_error(&s->byte_code))
1561 goto out_of_memory;
1551 len = re_is_simple_quantifier(s->byte_code.buf + last_atom_start,1562 len = re_is_simple_quantifier(s->byte_code.buf + last_atom_start,
1552 s->byte_code.size - last_atom_start);1563 s->byte_code.size - last_atom_start);
1553 if (len > 0) {1564 if (len > 0) {
1554 re_emit_op(s, REOP_match);1565 re_emit_op(s, REOP_match);
1555 1566
1556 dbuf_insert(&s->byte_code, last_atom_start, 17);1567 if (dbuf_insert(&s->byte_code, last_atom_start, 17))
1568 goto out_of_memory;
1557 pos = last_atom_start;1569 pos = last_atom_start;
1558 s->byte_code.buf[pos++] = REOP_simple_greedy_quant;1570 s->byte_code.buf[pos++] = REOP_simple_greedy_quant;
1559 put_u32(&s->byte_code.buf[pos],1571 put_u32(&s->byte_code.buf[pos],
@@ -1569,6 +1581,8 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) · 9 unmodified lines
1569 }1581 }
1570 }1582 }
1571 1583
1584 if (dbuf_error(&s->byte_code))
1585 goto out_of_memory;
1572 add_zero_advance_check = (re_check_advance(s->byte_code.buf + last_atom_start,1586 add_zero_advance_check = (re_check_advance(s->byte_code.buf + last_atom_start,
1573 s->byte_code.size - last_atom_start) == 0);1587 s->byte_code.size - last_atom_start) == 0);
1574 } else {1588 } else {
@@ -1582,7 +1596,8 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) · 7 unmodified lines
1582 /* need to reset the capture in case the atom is1596 /* need to reset the capture in case the atom is
1583 not executed */1597 not executed */
1584 if (last_capture_count != s->capture_count) {1598 if (last_capture_count != s->capture_count) {
1585 dbuf_insert(&s->byte_code, last_atom_start, 3);1599 if (dbuf_insert(&s->byte_code, last_atom_start, 3))
1600 goto out_of_memory;
1586 s->byte_code.buf[last_atom_start++] = REOP_save_reset;1601 s->byte_code.buf[last_atom_start++] = REOP_save_reset;
1587 s->byte_code.buf[last_atom_start++] = last_capture_count;1602 s->byte_code.buf[last_atom_start++] = last_capture_count;
1588 s->byte_code.buf[last_atom_start++] = s->capture_count - 1;1603 s->byte_code.buf[last_atom_start++] = s->capture_count - 1;
@@ -1590,12 +1605,14 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) · 1 unmodified line
1590 if (quant_max == 0) {1605 if (quant_max == 0) {
1591 s->byte_code.size = last_atom_start;1606 s->byte_code.size = last_atom_start;
1592 } else if (quant_max == 1) {1607 } else if (quant_max == 1) {
1593 dbuf_insert(&s->byte_code, last_atom_start, 5);1608 if (dbuf_insert(&s->byte_code, last_atom_start, 5))
1609 goto out_of_memory;
1594 s->byte_code.buf[last_atom_start] = REOP_split_goto_first +1610 s->byte_code.buf[last_atom_start] = REOP_split_goto_first +
1595 greedy;1611 greedy;
1596 put_u32(s->byte_code.buf + last_atom_start + 1, len);1612 put_u32(s->byte_code.buf + last_atom_start + 1, len);
1597 } else if (quant_max == INT32_MAX) {1613 } else if (quant_max == INT32_MAX) {
1598 dbuf_insert(&s->byte_code, last_atom_start, 5 + add_zero_advance_check);1614 if (dbuf_insert(&s->byte_code, last_atom_start, 5 + add_zero_advance_check))
1615 goto out_of_memory;
1599 s->byte_code.buf[last_atom_start] = REOP_split_goto_first +1616 s->byte_code.buf[last_atom_start] = REOP_split_goto_first +
1600 greedy;1617 greedy;
1601 put_u32(s->byte_code.buf + last_atom_start + 1,1618 put_u32(s->byte_code.buf + last_atom_start + 1,
@@ -1611,7 +1628,8 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) · 9 unmodified lines
1611 re_emit_goto(s, REOP_goto, last_atom_start);1628 re_emit_goto(s, REOP_goto, last_atom_start);
1612 }1629 }
1613 } else {1630 } else {
1614 dbuf_insert(&s->byte_code, last_atom_start, 10);1631 if (dbuf_insert(&s->byte_code, last_atom_start, 10))
1632 goto out_of_memory;
1615 pos = last_atom_start;1633 pos = last_atom_start;
1616 s->byte_code.buf[pos++] = REOP_push_i32;1634 s->byte_code.buf[pos++] = REOP_push_i32;
1617 put_u32(s->byte_code.buf + pos, quant_max);1635 put_u32(s->byte_code.buf + pos, quant_max);
@@ -1629,7 +1647,8 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) · 11 unmodified lines
1629 if (quant_min == 1) {1647 if (quant_min == 1) {
1630 /* nothing to add */1648 /* nothing to add */
1631 } else {1649 } else {
1632 dbuf_insert(&s->byte_code, last_atom_start, 5);1650 if (dbuf_insert(&s->byte_code, last_atom_start, 5))
1651 goto out_of_memory;
1633 s->byte_code.buf[last_atom_start] = REOP_push_i32;1652 s->byte_code.buf[last_atom_start] = REOP_push_i32;
1634 put_u32(s->byte_code.buf + last_atom_start + 1,1653 put_u32(s->byte_code.buf + last_atom_start + 1,
1635 quant_min);1654 quant_min);
@@ -1670,6 +1689,8 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) · 34 unmodified lines
1670 done:1689 done:
1671 s->buf_ptr = p;1690 s->buf_ptr = p;
1672 return 0;1691 return 0;
1692 out_of_memory:
1693 return re_parse_out_of_memory(s);
1673}1694}
1674 1695
1675static int re_parse_alternative(REParseState *s, BOOL is_backward_dir)1696static int re_parse_alternative(REParseState *s, BOOL is_backward_dir)
@@ -1719,7 +1740,9 @@ static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir) · 43 unmodified lines
1719 len = s->byte_code.size - start;1740 len = s->byte_code.size - start;
1720 1741
1721 /* insert a split before the first alternative */1742 /* insert a split before the first alternative */
1722 dbuf_insert(&s->byte_code, start, 5);1743 if (dbuf_insert(&s->byte_code, start, 5)) {
1744 return re_parse_out_of_memory(s);
1745 }
1723 s->byte_code.buf[start] = REOP_split_next_first;1746 s->byte_code.buf[start] = REOP_split_next_first;
1724 put_u32(s->byte_code.buf + start + 1, len + 5);1747 put_u32(s->byte_code.buf + start + 1, len + 5);
1725 1748
@@ -1844,7 +1867,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, · 118 unmodified lines
1844 }1867 }
1845 1868
1846 if (dbuf_error(&s->byte_code)) {1869 if (dbuf_error(&s->byte_code)) {
1847 re_parse_error(s, "out of memory");1870 re_parse_out_of_memory(s);
1848 goto error;1871 goto error;
1849 }1872 }
1850 1873
qjs.c+14−1
@@ -270,6 +270,7 @@ void help(void) · 269 unmodified lines
270 "-T --trace trace memory allocation\n"270 "-T --trace trace memory allocation\n"
271 "-d --dump dump the memory usage stats\n"271 "-d --dump dump the memory usage stats\n"
272 " --memory-limit n limit the memory usage to 'n' bytes\n"272 " --memory-limit n limit the memory usage to 'n' bytes\n"
273 " --stack-size n limit the stack size to 'n' bytes\n"
273 " --unhandled-rejection dump unhandled promise rejections\n"274 " --unhandled-rejection dump unhandled promise rejections\n"
274 "-q --quit just instantiate the interpreter and quit\n");275 "-q --quit just instantiate the interpreter and quit\n");
275 exit(1);276 exit(1);
@@ -295,7 +296,8 @@ int main(int argc, char **argv) · 19 unmodified lines
295#ifdef CONFIG_BIGNUM296#ifdef CONFIG_BIGNUM
296 int load_jscalc, bignum_ext = 0;297 int load_jscalc, bignum_ext = 0;
297#endif298#endif
298 299 size_t stack_size = 0;
300
299#ifdef CONFIG_BIGNUM301#ifdef CONFIG_BIGNUM
300 /* load jscalc runtime if invoked as 'qjscalc' */302 /* load jscalc runtime if invoked as 'qjscalc' */
301 {303 {
@@ -407,6 +409,14 @@ int main(int argc, char **argv) · 105 unmodified lines
407 memory_limit = (size_t)strtod(argv[optind++], NULL);409 memory_limit = (size_t)strtod(argv[optind++], NULL);
408 continue;410 continue;
409 }411 }
412 if (!strcmp(longopt, "stack-size")) {
413 if (optind >= argc) {
414 fprintf(stderr, "expecting stack size");
415 exit(1);
416 }
417 stack_size = (size_t)strtod(argv[optind++], NULL);
418 continue;
419 }
410 if (opt) {420 if (opt) {
411 fprintf(stderr, "qjs: unknown option '-%c'\n", opt);421 fprintf(stderr, "qjs: unknown option '-%c'\n", opt);
412 } else {422 } else {
@@ -428,6 +438,9 @@ int main(int argc, char **argv) · 15 unmodified lines
428 }438 }
429 if (memory_limit != 0)439 if (memory_limit != 0)
430 JS_SetMemoryLimit(rt, memory_limit);440 JS_SetMemoryLimit(rt, memory_limit);
441 if (stack_size != 0)
442 JS_SetMaxStackSize(rt, stack_size);
443 js_std_init_handlers(rt);
431 ctx = JS_NewContext(rt);444 ctx = JS_NewContext(rt);
432 if (!ctx) {445 if (!ctx) {
433 fprintf(stderr, "qjs: cannot allocate JS context\n");446 fprintf(stderr, "qjs: cannot allocate JS context\n");
qjsc.c+15−2
@@ -326,6 +326,7 @@ static const char main_c_template1[] = · 325 unmodified lines
326 " JSRuntime *rt;\n"326 " JSRuntime *rt;\n"
327 " JSContext *ctx;\n"327 " JSContext *ctx;\n"
328 " rt = JS_NewRuntime();\n"328 " rt = JS_NewRuntime();\n"
329 " js_std_init_handlers(rt);\n"
329 ;330 ;
330 331
331static const char main_c_template2[] =332static const char main_c_template2[] =
@@ -351,7 +352,8 @@ void help(void) · 19 unmodified lines
351 "-M module_name[,cname] add initialization code for an external C module\n"352 "-M module_name[,cname] add initialization code for an external C module\n"
352 "-x byte swapped output\n"353 "-x byte swapped output\n"
353 "-p prefix set the prefix of the generated C names\n"354 "-p prefix set the prefix of the generated C names\n"
354 );355 "-S n set the maximum stack size to 'n' bytes (default=%d)\n",
356 JS_DEFAULT_STACK_SIZE);
355#ifdef CONFIG_LTO357#ifdef CONFIG_LTO
356 {358 {
357 int i;359 int i;
@@ -447,6 +449,7 @@ static int output_executable(const char *out_filename, const char *cfilename, · 89 unmodified lines
447 *arg++ = libjsname;449 *arg++ = libjsname;
448 *arg++ = "-lm";450 *arg++ = "-lm";
449 *arg++ = "-ldl";451 *arg++ = "-ldl";
452 *arg++ = "-lpthread";
450 *arg = NULL;453 *arg = NULL;
451 454
452 if (verbose) {455 if (verbose) {
@@ -487,6 +490,7 @@ int main(int argc, char **argv) · 34 unmodified lines
487 BOOL use_lto;490 BOOL use_lto;
488 int module;491 int module;
489 OutputTypeEnum output_type;492 OutputTypeEnum output_type;
493 size_t stack_size;
490#ifdef CONFIG_BIGNUM494#ifdef CONFIG_BIGNUM
491 BOOL bignum_ext = FALSE;495 BOOL bignum_ext = FALSE;
492#endif496#endif
@@ -499,13 +503,14 @@ int main(int argc, char **argv) · 6 unmodified lines
499 byte_swap = FALSE;503 byte_swap = FALSE;
500 verbose = 0;504 verbose = 0;
501 use_lto = FALSE;505 use_lto = FALSE;
506 stack_size = 0;
502 507
503 /* add system modules */508 /* add system modules */
504 namelist_add(&cmodule_list, "std", "std", 0);509 namelist_add(&cmodule_list, "std", "std", 0);
505 namelist_add(&cmodule_list, "os", "os", 0);510 namelist_add(&cmodule_list, "os", "os", 0);
506 511
507 for(;;) {512 for(;;) {
508 c = getopt(argc, argv, "ho:cN:f:mxevM:p:");513 c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:");
509 if (c == -1)514 if (c == -1)
510 break;515 break;
511 switch(c) {516 switch(c) {
@@ -580,6 +585,9 @@ int main(int argc, char **argv) · 68 unmodified lines
580 case 'p':585 case 'p':
581 c_ident_prefix = optarg;586 c_ident_prefix = optarg;
582 break;587 break;
588 case 'S':
589 stack_size = (size_t)strtod(optarg, NULL);
590 break;
583 default:591 default:
584 break;592 break;
585 }593 }
@@ -652,6 +660,11 @@ int main(int argc, char **argv) · 66 unmodified lines
652 fputs(main_c_template1, fo);660 fputs(main_c_template1, fo);
653 fprintf(fo, " ctx = JS_NewContextRaw(rt);\n");661 fprintf(fo, " ctx = JS_NewContextRaw(rt);\n");
654 662
663 if (stack_size != 0) {
664 fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n",
665 (unsigned int)stack_size);
666 }
667
655 /* add the module loader if necessary */668 /* add the module loader if necessary */
656 if (feature_bitmap & (1 << FE_MODULE_LOADER)) {669 if (feature_bitmap & (1 << FE_MODULE_LOADER)) {
657 fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");670 fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
quickjs-atom.h+1−0
@@ -82,6 +82,7 @@ DEF(length, "length") · 81 unmodified lines
82DEF(fileName, "fileName")82DEF(fileName, "fileName")
83DEF(lineNumber, "lineNumber")83DEF(lineNumber, "lineNumber")
84DEF(message, "message")84DEF(message, "message")
85DEF(errors, "errors")
85DEF(stack, "stack")86DEF(stack, "stack")
86DEF(name, "name")87DEF(name, "name")
87DEF(toString, "toString")88DEF(toString, "toString")
quickjs-libc.c+1036−302
@@ -40,28 +40,38 @@ · 39 unmodified lines
40#if defined(_WIN32)40#if defined(_WIN32)
41#include <windows.h>41#include <windows.h>
42#include <conio.h>42#include <conio.h>
43#include <utime.h>
43#else44#else
44#include <dlfcn.h>45#include <dlfcn.h>
45#include <termios.h>46#include <termios.h>
46#include <sys/ioctl.h>47#include <sys/ioctl.h>
47#include <sys/wait.h>48#include <sys/wait.h>
49
48#if defined(__APPLE__)50#if defined(__APPLE__)
49typedef sig_t sighandler_t;51typedef sig_t sighandler_t;
52#if !defined(environ)
53#include <crt_externs.h>
54#define environ (*_NSGetEnviron())
55#endif
56#endif /* __APPLE__ */
57
58#endif
59
60#if !defined(_WIN32)
61/* enable the os.Worker API. IT relies on POSIX threads */
62#define USE_WORKER
50#endif63#endif
64
65#ifdef USE_WORKER
66#include <pthread.h>
67#include <stdatomic.h>
51#endif68#endif
52 69
53#include "cutils.h"70#include "cutils.h"
54#include "list.h"71#include "list.h"
55#include "quickjs-libc.h"72#include "quickjs-libc.h"
56 73
57static void js_std_dbuf_init(JSContext *ctx, DynBuf *s)
58{
59 dbuf_init2(s, JS_GetRuntime(ctx), (DynBufReallocFunc *)js_realloc_rt);
60}
61
62/* TODO:74/* TODO:
63 - add worker
64 - add minimal VT100 emulation for win32
65 - add socket calls75 - add socket calls
66*/76*/
67 77
@@ -84,14 +94,54 @@ typedef struct { · 16 unmodified lines
84 JSValue func;94 JSValue func;
85} JSOSTimer;95} JSOSTimer;
86 96
87/* initialize the lists so js_std_free_handlers() can always be called */97typedef struct {
88static struct list_head os_rw_handlers = LIST_HEAD_INIT(os_rw_handlers);98 struct list_head link;
89static struct list_head os_signal_handlers = LIST_HEAD_INIT(os_signal_handlers);99 uint8_t *data;
90static struct list_head os_timers = LIST_HEAD_INIT(os_timers);100 size_t data_len;
101 /* list of SharedArrayBuffers, necessary to free the message */
102 uint8_t **sab_tab;
103 size_t sab_tab_len;
104} JSWorkerMessage;
105
106typedef struct {
107 int ref_count;
108#ifdef USE_WORKER
109 pthread_mutex_t mutex;
110#endif
111 struct list_head msg_queue; /* list of JSWorkerMessage.link */
112 int read_fd;
113 int write_fd;
114} JSWorkerMessagePipe;
115
116typedef struct {
117 struct list_head link;
118 JSWorkerMessagePipe *recv_pipe;
119 JSValue on_message_func;
120} JSWorkerMessageHandler;
121
122typedef struct JSThreadState {
123 struct list_head os_rw_handlers; /* list of JSOSRWHandler.link */
124 struct list_head os_signal_handlers; /* list JSOSSignalHandler.link */
125 struct list_head os_timers; /* list of JSOSTimer.link */
126 struct list_head port_list; /* list of JSWorkerMessageHandler.link */
127 int eval_script_recurse; /* only used in the main thread */
128 /* not used in the main thread */
129 JSWorkerMessagePipe *recv_pipe, *send_pipe;
130} JSThreadState;
131
91static uint64_t os_pending_signals;132static uint64_t os_pending_signals;
92static int eval_script_recurse;
93static int (*os_poll_func)(JSContext *ctx);133static int (*os_poll_func)(JSContext *ctx);
94 134
135static void js_std_dbuf_init(JSContext *ctx, DynBuf *s)
136{
137 dbuf_init2(s, JS_GetRuntime(ctx), (DynBufReallocFunc *)js_realloc_rt);
138}
139
140static BOOL my_isdigit(int c)
141{
142 return (c >= '0' && c <= '9');
143}
144
95static JSValue js_printf_internal(JSContext *ctx,145static JSValue js_printf_internal(JSContext *ctx,
96 int argc, JSValueConst *argv, FILE *fp)146 int argc, JSValueConst *argv, FILE *fp)
97{147{
@@ -103,14 +153,12 @@ static JSValue js_printf_internal(JSContext *ctx, · 5 unmodified lines
103 const uint8_t *fmt, *fmt_end;153 const uint8_t *fmt, *fmt_end;
104 const uint8_t *p;154 const uint8_t *p;
105 char *q;155 char *q;
106 int i, c, len;156 int i, c, len, mod;
107 size_t fmt_len;157 size_t fmt_len;
108 int32_t int32_arg;158 int32_t int32_arg;
109 int64_t int64_arg;159 int64_t int64_arg;
110 double double_arg;160 double double_arg;
111 const char *string_arg;161 const char *string_arg;
112 enum { PART_FLAGS, PART_WIDTH, PART_DOT, PART_PREC, PART_MODIFIER } part;
113 int modsize;
114 /* Use indirect call to dbuf_printf to prevent gcc warning */162 /* Use indirect call to dbuf_printf to prevent gcc warning */
115 int (*dbuf_printf_fun)(DynBuf *s, const char *fmt, ...) = (void*)dbuf_printf;163 int (*dbuf_printf_fun)(DynBuf *s, const char *fmt, ...) = (void*)dbuf_printf;
116 164
@@ -132,150 +180,162 @@ static JSValue js_printf_internal(JSContext *ctx, · 15 unmodified lines
132 break;180 break;
133 q = fmtbuf;181 q = fmtbuf;
134 *q++ = *fmt++; /* copy '%' */182 *q++ = *fmt++; /* copy '%' */
135 part = PART_FLAGS;183
136 modsize = 0;184 /* flags */
137 for (;;) {185 for(;;) {
138 if (q >= fmtbuf + sizeof(fmtbuf) - 1)186 c = *fmt;
139 goto invalid;187 if (c == '0' || c == '#' || c == '+' || c == '-' || c == ' ' ||
140 188 c == '\'') {
141 c = *fmt++;189 if (q >= fmtbuf + sizeof(fmtbuf) - 1)
142 *q++ = c;
143 *q = '\0';
144
145 switch (c) {
146 case '1': case '2': case '3':
147 case '4': case '5': case '6':
148 case '7': case '8': case '9':
149 if (part != PART_PREC) {
150 if (part <= PART_WIDTH)
151 part = PART_WIDTH;
152 else
153 goto invalid;
154 }
155 continue;
156
157 case '0': case '#': case '+': case '-': case ' ': case '\'':
158 if (part > PART_FLAGS)
159 goto invalid;
160 continue;
161
162 case '.':
163 if (part > PART_DOT)
164 goto invalid;190 goto invalid;
165 part = PART_DOT;191 *q++ = c;
166 continue;192 fmt++;
167 193 } else {
168 case '*':194 break;
169 if (part < PART_WIDTH)195 }
170 part = PART_DOT;196 }
171 else if (part == PART_DOT)197 /* width */
172 part = PART_MODIFIER;198 if (*fmt == '*') {
173 else199 if (i >= argc)
200 goto missing;
201 if (JS_ToInt32(ctx, &int32_arg, argv[i++]))
202 goto fail;
203 q += snprintf(q, fmtbuf + sizeof(fmtbuf) - q, "%d", int32_arg);
204 fmt++;
205 } else {
206 while (my_isdigit(*fmt)) {
207 if (q >= fmtbuf + sizeof(fmtbuf) - 1)
174 goto invalid;208 goto invalid;
175 209 *q++ = *fmt++;
210 }
211 }
212 if (*fmt == '.') {
213 if (q >= fmtbuf + sizeof(fmtbuf) - 1)
214 goto invalid;
215 *q++ = *fmt++;
216 if (*fmt == '*') {
176 if (i >= argc)217 if (i >= argc)
177 goto missing;218 goto missing;
178
179 if (JS_ToInt32(ctx, &int32_arg, argv[i++]))219 if (JS_ToInt32(ctx, &int32_arg, argv[i++]))
180 goto fail;220 goto fail;
181 q += snprintf(q, fmtbuf + sizeof(fmtbuf) - q, "%d", int32_arg);221 q += snprintf(q, fmtbuf + sizeof(fmtbuf) - q, "%d", int32_arg);
182 continue;222 fmt++;
183 223 } else {
184 case 'h':224 while (my_isdigit(*fmt)) {
185 if (modsize != 0 && modsize != -1)225 if (q >= fmtbuf + sizeof(fmtbuf) - 1)
186 goto invalid;226 goto invalid;
187 modsize--;227 *q++ = *fmt++;
188 part = PART_MODIFIER;
189 continue;
190 case 'l':
191 q--;
192 if (modsize != 0 && modsize != 1)
193 goto invalid;
194 modsize++;
195 part = PART_MODIFIER;
196 continue;
197
198 case 'c':
199 if (i >= argc)
200 goto missing;
201 if (JS_IsString(argv[i])) {
202 string_arg = JS_ToCString(ctx, argv[i++]);
203 if (!string_arg)
204 goto fail;
205 int32_arg = unicode_from_utf8((uint8_t *)string_arg, UTF8_CHAR_LEN_MAX, &p);
206 JS_FreeCString(ctx, string_arg);
207 } else {
208 if (JS_ToInt32(ctx, &int32_arg, argv[i++]))
209 goto fail;
210 }
211 /* handle utf-8 encoding explicitly */
212 if ((unsigned)int32_arg > 0x10FFFF)
213 int32_arg = 0xFFFD;
214 /* ignore conversion flags, width and precision */
215 len = unicode_to_utf8(cbuf, int32_arg);
216 dbuf_put(&dbuf, cbuf, len);
217 break;
218
219 case 'd':
220 case 'i':
221 case 'o':
222 case 'u':
223 case 'x':
224 case 'X':
225 if (i >= argc)
226 goto missing;
227 if (JS_ToInt64Ext(ctx, &int64_arg, argv[i++]))
228 goto fail;
229 if (modsize > 0) {
230 q[1] = q[-1];
231 q[-1] = q[0] = 'l';
232 q[2] = '\0';
233 dbuf_printf_fun(&dbuf, fmtbuf, (long long)int64_arg);
234 } else {
235 dbuf_printf_fun(&dbuf, fmtbuf, (int)int64_arg);
236 }228 }
237 break;229 }
230 }
238 231
239 case 's':232 /* we only support the "l" modifier for 64 bit numbers */
240 if (i >= argc)233 mod = ' ';
241 goto missing;234 if (*fmt == 'l') {
242 /* XXX: handle strings containing null characters */235 mod = *fmt++;
236 }
237
238 /* type */
239 c = *fmt++;
240 if (q >= fmtbuf + sizeof(fmtbuf) - 1)
241 goto invalid;
242 *q++ = c;
243 *q = '\0';
244
245 switch (c) {
246 case 'c':
247 if (i >= argc)
248 goto missing;
249 if (JS_IsString(argv[i])) {
243 string_arg = JS_ToCString(ctx, argv[i++]);250 string_arg = JS_ToCString(ctx, argv[i++]);
244 if (!string_arg)251 if (!string_arg)
245 goto fail;252 goto fail;
246 dbuf_printf_fun(&dbuf, fmtbuf, string_arg);253 int32_arg = unicode_from_utf8((uint8_t *)string_arg, UTF8_CHAR_LEN_MAX, &p);
247 JS_FreeCString(ctx, string_arg);254 JS_FreeCString(ctx, string_arg);
248 break;255 } else {
249 256 if (JS_ToInt32(ctx, &int32_arg, argv[i++]))
250 case 'e':
251 case 'f':
252 case 'g':
253 case 'a':
254 case 'E':
255 case 'F':
256 case 'G':
257 case 'A':
258 if (i >= argc)
259 goto missing;
260 if (JS_ToFloat64(ctx, &double_arg, argv[i++]))
261 goto fail;257 goto fail;
262 dbuf_printf_fun(&dbuf, fmtbuf, double_arg);258 }
263 break;259 /* handle utf-8 encoding explicitly */
264 260 if ((unsigned)int32_arg > 0x10FFFF)
265 case '%':261 int32_arg = 0xFFFD;
266 dbuf_putc(&dbuf, '%');262 /* ignore conversion flags, width and precision */
267 break;263 len = unicode_to_utf8(cbuf, int32_arg);
264 dbuf_put(&dbuf, cbuf, len);
265 break;
266
267 case 'd':
268 case 'i':
269 case 'o':
270 case 'u':
271 case 'x':
272 case 'X':
273 if (i >= argc)
274 goto missing;
275 if (JS_ToInt64Ext(ctx, &int64_arg, argv[i++]))
276 goto fail;
277 if (mod == 'l') {
278 /* 64 bit number */
279#if defined(_WIN32)
280 if (q >= fmtbuf + sizeof(fmtbuf) - 3)
281 goto invalid;
282 q[2] = q[-1];
283 q[-1] = 'I';
284 q[0] = '6';
285 q[1] = '4';
286 q[3] = '\0';
287 dbuf_printf_fun(&dbuf, fmtbuf, (int64_t)int64_arg);
288#else
289 if (q >= fmtbuf + sizeof(fmtbuf) - 2)
290 goto invalid;
291 q[1] = q[-1];
292 q[-1] = q[0] = 'l';
293 q[2] = '\0';
294 dbuf_printf_fun(&dbuf, fmtbuf, (long long)int64_arg);
295#endif
296 } else {
297 dbuf_printf_fun(&dbuf, fmtbuf, (int)int64_arg);
298 }
299 break;
268 300
269 default:301 case 's':
270 /* XXX: should support an extension mechanism */302 if (i >= argc)
271 invalid:303 goto missing;
272 JS_ThrowTypeError(ctx, "invalid conversion specifier in format string");304 /* XXX: handle strings containing null characters */
305 string_arg = JS_ToCString(ctx, argv[i++]);
306 if (!string_arg)
273 goto fail;307 goto fail;
274 missing:308 dbuf_printf_fun(&dbuf, fmtbuf, string_arg);
275 JS_ThrowReferenceError(ctx, "missing argument for conversion specifier");309 JS_FreeCString(ctx, string_arg);
310 break;
311
312 case 'e':
313 case 'f':
314 case 'g':
315 case 'a':
316 case 'E':
317 case 'F':
318 case 'G':
319 case 'A':
320 if (i >= argc)
321 goto missing;
322 if (JS_ToFloat64(ctx, &double_arg, argv[i++]))
276 goto fail;323 goto fail;
277 }324 dbuf_printf_fun(&dbuf, fmtbuf, double_arg);
325 break;
326
327 case '%':
328 dbuf_putc(&dbuf, '%');
278 break;329 break;
330
331 default:
332 /* XXX: should support an extension mechanism */
333 invalid:
334 JS_ThrowTypeError(ctx, "invalid conversion specifier in format string");
335 goto fail;
336 missing:
337 JS_ThrowReferenceError(ctx, "missing argument for conversion specifier");
338 goto fail;
279 }339 }
280 }340 }
281 JS_FreeCString(ctx, fmt_str);341 JS_FreeCString(ctx, fmt_str);
@@ -593,6 +653,8 @@ static int get_bool_option(JSContext *ctx, BOOL *pbool, · 311 unmodified lines
593static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val,653static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val,
594 int argc, JSValueConst *argv)654 int argc, JSValueConst *argv)
595{655{
656 JSRuntime *rt = JS_GetRuntime(ctx);
657 JSThreadState *ts = JS_GetRuntimeOpaque(rt);
596 const char *str;658 const char *str;
597 size_t len;659 size_t len;
598 JSValue ret;660 JSValue ret;
@@ -610,7 +672,7 @@ static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val, · 11 unmodified lines
610 str = JS_ToCStringLen(ctx, &len, argv[0]);672 str = JS_ToCStringLen(ctx, &len, argv[0]);
611 if (!str)673 if (!str)
612 return JS_EXCEPTION;674 return JS_EXCEPTION;
613 if (++eval_script_recurse == 1) {675 if (!ts->recv_pipe && ++ts->eval_script_recurse == 1) {
614 /* install the interrupt handler */676 /* install the interrupt handler */
615 JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL);677 JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL);
616 }678 }
@@ -619,7 +681,7 @@ static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val, · 2 unmodified lines
619 flags |= JS_EVAL_FLAG_BACKTRACE_BARRIER;681 flags |= JS_EVAL_FLAG_BACKTRACE_BARRIER;
620 ret = JS_Eval(ctx, str, len, "<evalScript>", flags);682 ret = JS_Eval(ctx, str, len, "<evalScript>", flags);
621 JS_FreeCString(ctx, str);683 JS_FreeCString(ctx, str);
622 if (--eval_script_recurse == 0) {684 if (!ts->recv_pipe && --ts->eval_script_recurse == 0) {
623 /* remove the interrupt handler */685 /* remove the interrupt handler */
624 JS_SetInterruptHandler(JS_GetRuntime(ctx), NULL, NULL);686 JS_SetInterruptHandler(JS_GetRuntime(ctx), NULL, NULL);
625 os_pending_signals &= ~((uint64_t)1 << SIGINT);687 os_pending_signals &= ~((uint64_t)1 << SIGINT);
@@ -669,6 +731,21 @@ static JSValue js_std_strerror(JSContext *ctx, JSValueConst this_val, · 43 unmodified lines
669 return JS_NewString(ctx, strerror(err));731 return JS_NewString(ctx, strerror(err));
670}732}
671 733
734static JSValue js_std_parseExtJSON(JSContext *ctx, JSValueConst this_val,
735 int argc, JSValueConst *argv)
736{
737 JSValue obj;
738 const char *str;
739 size_t len;
740
741 str = JS_ToCStringLen(ctx, &len, argv[0]);
742 if (!str)
743 return JS_EXCEPTION;
744 obj = JS_ParseJSON2(ctx, str, len, "<input>", JS_PARSE_JSON_EXT);
745 JS_FreeCString(ctx, str);
746 return obj;
747}
748
672static JSValue js_new_std_file(JSContext *ctx, FILE *f,749static JSValue js_new_std_file(JSContext *ctx, FILE *f,
673 BOOL close_in_finalizer,750 BOOL close_in_finalizer,
674 BOOL is_popen)751 BOOL is_popen)
@@ -1321,6 +1398,7 @@ static const JSCFunctionListEntry js_std_funcs[] = { · 646 unmodified lines
1321 JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ),1398 JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ),
1322 JS_CFUNC_DEF("loadFile", 1, js_std_loadFile ),1399 JS_CFUNC_DEF("loadFile", 1, js_std_loadFile ),
1323 JS_CFUNC_DEF("strerror", 1, js_std_strerror ),1400 JS_CFUNC_DEF("strerror", 1, js_std_strerror ),
1401 JS_CFUNC_DEF("parseExtJSON", 1, js_std_parseExtJSON ),
1324 1402
1325 /* FILE I/O */1403 /* FILE I/O */
1326 JS_CFUNC_DEF("open", 2, js_std_open ),1404 JS_CFUNC_DEF("open", 2, js_std_open ),
@@ -1626,11 +1704,18 @@ static JSValue js_os_rename(JSContext *ctx, JSValueConst this_val, · 299 unmodified lines
1626 return JS_NewInt32(ctx, ret);1704 return JS_NewInt32(ctx, ret);
1627}1705}
1628 1706
1629static JSOSRWHandler *find_rh(int fd)1707static BOOL is_main_thread(JSRuntime *rt)
1708{
1709 JSThreadState *ts = JS_GetRuntimeOpaque(rt);
1710 return !ts->recv_pipe;
1711}
1712
1713static JSOSRWHandler *find_rh(JSThreadState *ts, int fd)
1630{1714{
1631 JSOSRWHandler *rh;1715 JSOSRWHandler *rh;
1632 struct list_head *el;1716 struct list_head *el;
1633 list_for_each(el, &os_rw_handlers) {1717
1718 list_for_each(el, &ts->os_rw_handlers) {
1634 rh = list_entry(el, JSOSRWHandler, link);1719 rh = list_entry(el, JSOSRWHandler, link);
1635 if (rh->fd == fd)1720 if (rh->fd == fd)
1636 return rh;1721 return rh;
@@ -1651,6 +1736,8 @@ static void free_rw_handler(JSRuntime *rt, JSOSRWHandler *rh) · 14 unmodified lines
1651static JSValue js_os_setReadHandler(JSContext *ctx, JSValueConst this_val,1736static JSValue js_os_setReadHandler(JSContext *ctx, JSValueConst this_val,
1652 int argc, JSValueConst *argv, int magic)1737 int argc, JSValueConst *argv, int magic)
1653{1738{
1739 JSRuntime *rt = JS_GetRuntime(ctx);
1740 JSThreadState *ts = JS_GetRuntimeOpaque(rt);
1654 JSOSRWHandler *rh;1741 JSOSRWHandler *rh;
1655 int fd;1742 int fd;
1656 JSValueConst func;1743 JSValueConst func;
@@ -1659,7 +1746,7 @@ static JSValue js_os_setReadHandler(JSContext *ctx, JSValueConst this_val, · 2 unmodified lines
1659 return JS_EXCEPTION;1746 return JS_EXCEPTION;
1660 func = argv[1];1747 func = argv[1];
1661 if (JS_IsNull(func)) {1748 if (JS_IsNull(func)) {
1662 rh = find_rh(fd);1749 rh = find_rh(ts, fd);
1663 if (rh) {1750 if (rh) {
1664 JS_FreeValue(ctx, rh->rw_func[magic]);1751 JS_FreeValue(ctx, rh->rw_func[magic]);
1665 rh->rw_func[magic] = JS_NULL;1752 rh->rw_func[magic] = JS_NULL;
@@ -1672,7 +1759,7 @@ static JSValue js_os_setReadHandler(JSContext *ctx, JSValueConst this_val, · 6 unmodified lines
1672 } else {1759 } else {
1673 if (!JS_IsFunction(ctx, func))1760 if (!JS_IsFunction(ctx, func))
1674 return JS_ThrowTypeError(ctx, "not a function");1761 return JS_ThrowTypeError(ctx, "not a function");
1675 rh = find_rh(fd);1762 rh = find_rh(ts, fd);
1676 if (!rh) {1763 if (!rh) {
1677 rh = js_mallocz(ctx, sizeof(*rh));1764 rh = js_mallocz(ctx, sizeof(*rh));
1678 if (!rh)1765 if (!rh)
@@ -1680,7 +1767,7 @@ static JSValue js_os_setReadHandler(JSContext *ctx, JSValueConst this_val, · 1 unmodified line
1680 rh->fd = fd;1767 rh->fd = fd;
1681 rh->rw_func[0] = JS_NULL;1768 rh->rw_func[0] = JS_NULL;
1682 rh->rw_func[1] = JS_NULL;1769 rh->rw_func[1] = JS_NULL;
1683 list_add_tail(&rh->link, &os_rw_handlers);1770 list_add_tail(&rh->link, &ts->os_rw_handlers);
1684 }1771 }
1685 JS_FreeValue(ctx, rh->rw_func[magic]);1772 JS_FreeValue(ctx, rh->rw_func[magic]);
1686 rh->rw_func[magic] = JS_DupValue(ctx, func);1773 rh->rw_func[magic] = JS_DupValue(ctx, func);
@@ -1688,11 +1775,11 @@ static JSValue js_os_setReadHandler(JSContext *ctx, JSValueConst this_val, · 1 unmodified line
1688 return JS_UNDEFINED;1775 return JS_UNDEFINED;
1689}1776}
1690 1777
1691static JSOSSignalHandler *find_sh(int sig_num)1778static JSOSSignalHandler *find_sh(JSThreadState *ts, int sig_num)
1692{1779{
1693 JSOSSignalHandler *sh;1780 JSOSSignalHandler *sh;
1694 struct list_head *el;1781 struct list_head *el;
1695 list_for_each(el, &os_signal_handlers) {1782 list_for_each(el, &ts->os_signal_handlers) {
1696 sh = list_entry(el, JSOSSignalHandler, link);1783 sh = list_entry(el, JSOSSignalHandler, link);
1697 if (sh->sig_num == sig_num)1784 if (sh->sig_num == sig_num)
1698 return sh;1785 return sh;
@@ -1719,10 +1806,15 @@ typedef void (*sighandler_t)(int sig_num); · 20 unmodified lines
1719static JSValue js_os_signal(JSContext *ctx, JSValueConst this_val,1806static JSValue js_os_signal(JSContext *ctx, JSValueConst this_val,
1720 int argc, JSValueConst *argv)1807 int argc, JSValueConst *argv)
1721{1808{
1809 JSRuntime *rt = JS_GetRuntime(ctx);
1810 JSThreadState *ts = JS_GetRuntimeOpaque(rt);
1722 JSOSSignalHandler *sh;1811 JSOSSignalHandler *sh;
1723 uint32_t sig_num;1812 uint32_t sig_num;
1724 JSValueConst func;1813 JSValueConst func;
1725 sighandler_t handler;1814 sighandler_t handler;
1815
1816 if (!is_main_thread(rt))
1817 return JS_ThrowTypeError(ctx, "signal handler can only be set in the main thread");
1726 1818
1727 if (JS_ToUint32(ctx, &sig_num, argv[0]))1819 if (JS_ToUint32(ctx, &sig_num, argv[0]))
1728 return JS_EXCEPTION;1820 return JS_EXCEPTION;
@@ -1731,7 +1823,7 @@ static JSValue js_os_signal(JSContext *ctx, JSValueConst this_val, · 2 unmodified lines
1731 func = argv[1];1823 func = argv[1];
1732 /* func = null: SIG_DFL, func = undefined, SIG_IGN */1824 /* func = null: SIG_DFL, func = undefined, SIG_IGN */
1733 if (JS_IsNull(func) || JS_IsUndefined(func)) {1825 if (JS_IsNull(func) || JS_IsUndefined(func)) {
1734 sh = find_sh(sig_num);1826 sh = find_sh(ts, sig_num);
1735 if (sh) {1827 if (sh) {
1736 free_sh(JS_GetRuntime(ctx), sh);1828 free_sh(JS_GetRuntime(ctx), sh);
1737 }1829 }
@@ -1743,13 +1835,13 @@ static JSValue js_os_signal(JSContext *ctx, JSValueConst this_val, · 5 unmodified lines
1743 } else {1835 } else {
1744 if (!JS_IsFunction(ctx, func))1836 if (!JS_IsFunction(ctx, func))
1745 return JS_ThrowTypeError(ctx, "not a function");1837 return JS_ThrowTypeError(ctx, "not a function");
1746 sh = find_sh(sig_num);1838 sh = find_sh(ts, sig_num);
1747 if (!sh) {1839 if (!sh) {
1748 sh = js_mallocz(ctx, sizeof(*sh));1840 sh = js_mallocz(ctx, sizeof(*sh));
1749 if (!sh)1841 if (!sh)
1750 return JS_EXCEPTION;1842 return JS_EXCEPTION;
1751 sh->sig_num = sig_num;1843 sh->sig_num = sig_num;
1752 list_add_tail(&sh->link, &os_signal_handlers);1844 list_add_tail(&sh->link, &ts->os_signal_handlers);
1753 }1845 }
1754 JS_FreeValue(ctx, sh->func);1846 JS_FreeValue(ctx, sh->func);
1755 sh->func = JS_DupValue(ctx, func);1847 sh->func = JS_DupValue(ctx, func);
@@ -1813,6 +1905,8 @@ static void js_os_timer_mark(JSRuntime *rt, JSValueConst val, · 57 unmodified lines
1813static JSValue js_os_setTimeout(JSContext *ctx, JSValueConst this_val,1905static JSValue js_os_setTimeout(JSContext *ctx, JSValueConst this_val,
1814 int argc, JSValueConst *argv)1906 int argc, JSValueConst *argv)
1815{1907{
1908 JSRuntime *rt = JS_GetRuntime(ctx);
1909 JSThreadState *ts = JS_GetRuntimeOpaque(rt);
1816 int64_t delay;1910 int64_t delay;
1817 JSValueConst func;1911 JSValueConst func;
1818 JSOSTimer *th;1912 JSOSTimer *th;
@@ -1834,7 +1928,7 @@ static JSValue js_os_setTimeout(JSContext *ctx, JSValueConst this_val, · 15 unmodified lines
1834 th->has_object = TRUE;1928 th->has_object = TRUE;
1835 th->timeout = get_time_ms() + delay;1929 th->timeout = get_time_ms() + delay;
1836 th->func = JS_DupValue(ctx, func);1930 th->func = JS_DupValue(ctx, func);
1837 list_add_tail(&th->link, &os_timers);1931 list_add_tail(&th->link, &ts->os_timers);
1838 JS_SetOpaque(obj, th);1932 JS_SetOpaque(obj, th);
1839 return obj;1933 return obj;
1840}1934}
@@ -1872,6 +1966,8 @@ static void call_handler(JSContext *ctx, JSValueConst func) · 31 unmodified lines
1872 1966
1873static int js_os_poll(JSContext *ctx)1967static int js_os_poll(JSContext *ctx)
1874{1968{
1969 JSRuntime *rt = JS_GetRuntime(ctx);
1970 JSThreadState *ts = JS_GetRuntimeOpaque(rt);
1875 int min_delay, console_fd;1971 int min_delay, console_fd;
1876 int64_t cur_time, delay;1972 int64_t cur_time, delay;
1877 JSOSRWHandler *rh;1973 JSOSRWHandler *rh;
@@ -1879,14 +1975,14 @@ static int js_os_poll(JSContext *ctx) · 1 unmodified line
1879 1975
1880 /* XXX: handle signals if useful */1976 /* XXX: handle signals if useful */
1881 1977
1882 if (list_empty(&os_rw_handlers) && list_empty(&os_timers))1978 if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers))
1883 return -1; /* no more events */1979 return -1; /* no more events */
1884 1980
1885 /* XXX: only timers and basic console input are supported */1981 /* XXX: only timers and basic console input are supported */
1886 if (!list_empty(&os_timers)) {1982 if (!list_empty(&ts->os_timers)) {
1887 cur_time = get_time_ms();1983 cur_time = get_time_ms();
1888 min_delay = 10000;1984 min_delay = 10000;
1889 list_for_each(el, &os_timers) {1985 list_for_each(el, &ts->os_timers) {
1890 JSOSTimer *th = list_entry(el, JSOSTimer, link);1986 JSOSTimer *th = list_entry(el, JSOSTimer, link);
1891 delay = th->timeout - cur_time;1987 delay = th->timeout - cur_time;
1892 if (delay <= 0) {1988 if (delay <= 0) {
@@ -1894,9 +1990,9 @@ static int js_os_poll(JSContext *ctx) · 1 unmodified line
1894 /* the timer expired */1990 /* the timer expired */
1895 func = th->func;1991 func = th->func;
1896 th->func = JS_UNDEFINED;1992 th->func = JS_UNDEFINED;
1897 unlink_timer(JS_GetRuntime(ctx), th);1993 unlink_timer(rt, th);
1898 if (!th->has_object)1994 if (!th->has_object)
1899 free_timer(JS_GetRuntime(ctx), th);1995 free_timer(rt, th);
1900 call_handler(ctx, func);1996 call_handler(ctx, func);
1901 JS_FreeValue(ctx, func);1997 JS_FreeValue(ctx, func);
1902 return 0;1998 return 0;
@@ -1909,7 +2005,7 @@ static int js_os_poll(JSContext *ctx) · 6 unmodified lines
1909 }2005 }
1910 2006
1911 console_fd = -1;2007 console_fd = -1;
1912 list_for_each(el, &os_rw_handlers) {2008 list_for_each(el, &ts->os_rw_handlers) {
1913 rh = list_entry(el, JSOSRWHandler, link);2009 rh = list_entry(el, JSOSRWHandler, link);
1914 if (rh->fd == 0 && !JS_IsNull(rh->rw_func[0])) {2010 if (rh->fd == 0 && !JS_IsNull(rh->rw_func[0])) {
1915 console_fd = rh->fd;2011 console_fd = rh->fd;
@@ -1927,7 +2023,7 @@ static int js_os_poll(JSContext *ctx) · 11 unmodified lines
1927 handle = (HANDLE)_get_osfhandle(console_fd);2023 handle = (HANDLE)_get_osfhandle(console_fd);
1928 ret = WaitForSingleObject(handle, ti);2024 ret = WaitForSingleObject(handle, ti);
1929 if (ret == WAIT_OBJECT_0) {2025 if (ret == WAIT_OBJECT_0) {
1930 list_for_each(el, &os_rw_handlers) {2026 list_for_each(el, &ts->os_rw_handlers) {
1931 rh = list_entry(el, JSOSRWHandler, link);2027 rh = list_entry(el, JSOSRWHandler, link);
1932 if (rh->fd == console_fd && !JS_IsNull(rh->rw_func[0])) {2028 if (rh->fd == console_fd && !JS_IsNull(rh->rw_func[0])) {
1933 call_handler(ctx, rh->rw_func[0]);2029 call_handler(ctx, rh->rw_func[0]);
@@ -1942,8 +2038,88 @@ static int js_os_poll(JSContext *ctx) · 8 unmodified lines
1942 return 0;2038 return 0;
1943}2039}
1944#else2040#else
2041
2042#ifdef USE_WORKER
2043
2044static void js_free_message(JSWorkerMessage *msg);
2045
2046/* return 1 if a message was handled, 0 if no message */
2047static int handle_posted_message(JSRuntime *rt, JSContext *ctx,
2048 JSWorkerMessageHandler *port)
2049{
2050 JSWorkerMessagePipe *ps = port->recv_pipe;
2051 int ret;
2052 struct list_head *el;
2053 JSWorkerMessage *msg;
2054 JSValue obj, data_obj, func, retval;
2055
2056 pthread_mutex_lock(&ps->mutex);
2057 if (!list_empty(&ps->msg_queue)) {
2058 el = ps->msg_queue.next;
2059 msg = list_entry(el, JSWorkerMessage, link);
2060
2061 /* remove the message from the queue */
2062 list_del(&msg->link);
2063
2064 if (list_empty(&ps->msg_queue)) {
2065 uint8_t buf[16];
2066 int ret;
2067 for(;;) {
2068 ret = read(ps->read_fd, buf, sizeof(buf));
2069 if (ret >= 0)
2070 break;
2071 if (errno != EAGAIN && errno != EINTR)
2072 break;
2073 }
2074 }
2075
2076 pthread_mutex_unlock(&ps->mutex);
2077
2078 data_obj = JS_ReadObject(ctx, msg->data, msg->data_len,
2079 JS_READ_OBJ_SAB | JS_READ_OBJ_REFERENCE);
2080
2081 js_free_message(msg);
2082
2083 if (JS_IsException(data_obj))
2084 goto fail;
2085 obj = JS_NewObject(ctx);
2086 if (JS_IsException(obj)) {
2087 JS_FreeValue(ctx, data_obj);
2088 goto fail;
2089 }
2090 JS_DefinePropertyValueStr(ctx, obj, "data", data_obj, JS_PROP_C_W_E);
2091
2092 /* 'func' might be destroyed when calling itself (if it frees the
2093 handler), so must take extra care */
2094 func = JS_DupValue(ctx, port->on_message_func);
2095 retval = JS_Call(ctx, func, JS_UNDEFINED, 1, (JSValueConst *)&obj);
2096 JS_FreeValue(ctx, obj);
2097 JS_FreeValue(ctx, func);
2098 if (JS_IsException(retval)) {
2099 fail:
2100 js_std_dump_error(ctx);
2101 } else {
2102 JS_FreeValue(ctx, retval);
2103 }
2104 ret = 1;
2105 } else {
2106 pthread_mutex_unlock(&ps->mutex);
2107 ret = 0;
2108 }
2109 return ret;
2110}
2111#else
2112static int handle_posted_message(JSRuntime *rt, JSContext *ctx,
2113 JSWorkerMessageHandler *port)
2114{
2115 return 0;
2116}
2117#endif
2118
1945static int js_os_poll(JSContext *ctx)2119static int js_os_poll(JSContext *ctx)
1946{2120{
2121 JSRuntime *rt = JS_GetRuntime(ctx);
2122 JSThreadState *ts = JS_GetRuntimeOpaque(rt);
1947 int ret, fd_max, min_delay;2123 int ret, fd_max, min_delay;
1948 int64_t cur_time, delay;2124 int64_t cur_time, delay;
1949 fd_set rfds, wfds;2125 fd_set rfds, wfds;
@@ -1951,11 +2127,13 @@ static int js_os_poll(JSContext *ctx) · 1 unmodified line
1951 struct list_head *el;2127 struct list_head *el;
1952 struct timeval tv, *tvp;2128 struct timeval tv, *tvp;
1953 2129
1954 if (unlikely(os_pending_signals != 0)) {2130 /* only check signals in the main thread */
2131 if (!ts->recv_pipe &&
2132 unlikely(os_pending_signals != 0)) {
1955 JSOSSignalHandler *sh;2133 JSOSSignalHandler *sh;
1956 uint64_t mask;2134 uint64_t mask;
1957 2135
1958 list_for_each(el, &os_signal_handlers) {2136 list_for_each(el, &ts->os_signal_handlers) {
1959 sh = list_entry(el, JSOSSignalHandler, link);2137 sh = list_entry(el, JSOSSignalHandler, link);
1960 mask = (uint64_t)1 << sh->sig_num;2138 mask = (uint64_t)1 << sh->sig_num;
1961 if (os_pending_signals & mask) {2139 if (os_pending_signals & mask) {
@@ -1965,14 +2143,15 @@ static int js_os_poll(JSContext *ctx) · 3 unmodified lines
1965 }2143 }
1966 }2144 }
1967 }2145 }
1968 2146
1969 if (list_empty(&os_rw_handlers) && list_empty(&os_timers))2147 if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers) &&
2148 list_empty(&ts->port_list))
1970 return -1; /* no more events */2149 return -1; /* no more events */
1971 2150
1972 if (!list_empty(&os_timers)) {2151 if (!list_empty(&ts->os_timers)) {
1973 cur_time = get_time_ms();2152 cur_time = get_time_ms();
1974 min_delay = 10000;2153 min_delay = 10000;
1975 list_for_each(el, &os_timers) {2154 list_for_each(el, &ts->os_timers) {
1976 JSOSTimer *th = list_entry(el, JSOSTimer, link);2155 JSOSTimer *th = list_entry(el, JSOSTimer, link);
1977 delay = th->timeout - cur_time;2156 delay = th->timeout - cur_time;
1978 if (delay <= 0) {2157 if (delay <= 0) {
@@ -1980,9 +2159,9 @@ static int js_os_poll(JSContext *ctx) · 1 unmodified line
1980 /* the timer expired */2159 /* the timer expired */
1981 func = th->func;2160 func = th->func;
1982 th->func = JS_UNDEFINED;2161 th->func = JS_UNDEFINED;
1983 unlink_timer(JS_GetRuntime(ctx), th);2162 unlink_timer(rt, th);
1984 if (!th->has_object)2163 if (!th->has_object)
1985 free_timer(JS_GetRuntime(ctx), th);2164 free_timer(rt, th);
1986 call_handler(ctx, func);2165 call_handler(ctx, func);
1987 JS_FreeValue(ctx, func);2166 JS_FreeValue(ctx, func);
1988 return 0;2167 return 0;
@@ -2000,7 +2179,7 @@ static int js_os_poll(JSContext *ctx) · 11 unmodified lines
2000 FD_ZERO(&rfds);2179 FD_ZERO(&rfds);
2001 FD_ZERO(&wfds);2180 FD_ZERO(&wfds);
2002 fd_max = -1;2181 fd_max = -1;
2003 list_for_each(el, &os_rw_handlers) {2182 list_for_each(el, &ts->os_rw_handlers) {
2004 rh = list_entry(el, JSOSRWHandler, link);2183 rh = list_entry(el, JSOSRWHandler, link);
2005 fd_max = max_int(fd_max, rh->fd);2184 fd_max = max_int(fd_max, rh->fd);
2006 if (!JS_IsNull(rh->rw_func[0]))2185 if (!JS_IsNull(rh->rw_func[0]))
@@ -2008,25 +2187,46 @@ static int js_os_poll(JSContext *ctx) · 1 unmodified line
2008 if (!JS_IsNull(rh->rw_func[1]))2187 if (!JS_IsNull(rh->rw_func[1]))
2009 FD_SET(rh->fd, &wfds);2188 FD_SET(rh->fd, &wfds);
2010 }2189 }
2011 2190
2191 list_for_each(el, &ts->port_list) {
2192 JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link);
2193 if (!JS_IsNull(port->on_message_func)) {
2194 JSWorkerMessagePipe *ps = port->recv_pipe;
2195 fd_max = max_int(fd_max, ps->read_fd);
2196 FD_SET(ps->read_fd, &rfds);
2197 }
2198 }
2199
2012 ret = select(fd_max + 1, &rfds, &wfds, NULL, tvp);2200 ret = select(fd_max + 1, &rfds, &wfds, NULL, tvp);
2013 if (ret > 0) {2201 if (ret > 0) {
2014 list_for_each(el, &os_rw_handlers) {2202 list_for_each(el, &ts->os_rw_handlers) {
2015 rh = list_entry(el, JSOSRWHandler, link);2203 rh = list_entry(el, JSOSRWHandler, link);
2016 if (!JS_IsNull(rh->rw_func[0]) &&2204 if (!JS_IsNull(rh->rw_func[0]) &&
2017 FD_ISSET(rh->fd, &rfds)) {2205 FD_ISSET(rh->fd, &rfds)) {
2018 call_handler(ctx, rh->rw_func[0]);2206 call_handler(ctx, rh->rw_func[0]);
2019 /* must stop because the list may have been modified */2207 /* must stop because the list may have been modified */
2020 break;2208 goto done;
2021 }2209 }
2022 if (!JS_IsNull(rh->rw_func[1])) {2210 if (!JS_IsNull(rh->rw_func[1]) &&
2023 FD_SET(rh->fd, &wfds);2211 FD_ISSET(rh->fd, &wfds)) {
2024 call_handler(ctx, rh->rw_func[1]);2212 call_handler(ctx, rh->rw_func[1]);
2025 /* must stop because the list may have been modified */2213 /* must stop because the list may have been modified */
2026 break;2214 goto done;
2215 }
2216 }
2217
2218 list_for_each(el, &ts->port_list) {
2219 JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link);
2220 if (!JS_IsNull(port->on_message_func)) {
2221 JSWorkerMessagePipe *ps = port->recv_pipe;
2222 if (FD_ISSET(ps->read_fd, &rfds)) {
2223 if (handle_posted_message(rt, ctx, port))
2224 goto done;
2225 }
2027 }2226 }
2028 }2227 }
2029 }2228 }
2229 done:
2030 return 0;2230 return 0;
2031}2231}
2032#endif /* !_WIN32 */2232#endif /* !_WIN32 */
@@ -2071,8 +2271,6 @@ static JSValue js_os_getcwd(JSContext *ctx, JSValueConst this_val, · 38 unmodified lines
2071 return make_string_error(ctx, buf, err);2271 return make_string_error(ctx, buf, err);
2072}2272}
2073 2273
2074#if !defined(_WIN32)
2075
2076static JSValue js_os_chdir(JSContext *ctx, JSValueConst this_val,2274static JSValue js_os_chdir(JSContext *ctx, JSValueConst this_val,
2077 int argc, JSValueConst *argv)2275 int argc, JSValueConst *argv)
2078{2276{
@@ -2087,28 +2285,6 @@ static JSValue js_os_chdir(JSContext *ctx, JSValueConst this_val, · 8 unmodified lines
2087 return JS_NewInt32(ctx, err);2285 return JS_NewInt32(ctx, err);
2088}2286}
2089 2287
2090/* return [path, errorcode] */
2091static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val,
2092 int argc, JSValueConst *argv)
2093{
2094 const char *path;
2095 char buf[PATH_MAX], *res;
2096 int err;
2097
2098 path = JS_ToCString(ctx, argv[0]);
2099 if (!path)
2100 return JS_EXCEPTION;
2101 res = realpath(path, buf);
2102 JS_FreeCString(ctx, path);
2103 if (!res) {
2104 buf[0] = '\0';
2105 err = errno;
2106 } else {
2107 err = 0;
2108 }
2109 return make_string_error(ctx, buf, err);
2110}
2111
2112static JSValue js_os_mkdir(JSContext *ctx, JSValueConst this_val,2288static JSValue js_os_mkdir(JSContext *ctx, JSValueConst this_val,
2113 int argc, JSValueConst *argv)2289 int argc, JSValueConst *argv)
2114{2290{
@@ -2124,15 +2300,66 @@ static JSValue js_os_mkdir(JSContext *ctx, JSValueConst this_val, · 9 unmodified lines
2124 path = JS_ToCString(ctx, argv[0]);2300 path = JS_ToCString(ctx, argv[0]);
2125 if (!path)2301 if (!path)
2126 return JS_EXCEPTION;2302 return JS_EXCEPTION;
2303#if defined(_WIN32)
2304 (void)mode;
2305 ret = js_get_errno(mkdir(path));
2306#else
2127 ret = js_get_errno(mkdir(path, mode));2307 ret = js_get_errno(mkdir(path, mode));
2308#endif
2128 JS_FreeCString(ctx, path);2309 JS_FreeCString(ctx, path);
2129 return JS_NewInt32(ctx, ret);2310 return JS_NewInt32(ctx, ret);
2130}2311}
2131 2312
2313/* return [array, errorcode] */
2314static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val,
2315 int argc, JSValueConst *argv)
2316{
2317 const char *path;
2318 DIR *f;
2319 struct dirent *d;
2320 JSValue obj;
2321 int err;
2322 uint32_t len;
2323
2324 path = JS_ToCString(ctx, argv[0]);
2325 if (!path)
2326 return JS_EXCEPTION;
2327 obj = JS_NewArray(ctx);
2328 if (JS_IsException(obj)) {
2329 JS_FreeCString(ctx, path);
2330 return JS_EXCEPTION;
2331 }
2332 f = opendir(path);
2333 if (!f)
2334 err = errno;
2335 else
2336 err = 0;
2337 JS_FreeCString(ctx, path);
2338 if (!f)
2339 goto done;
2340 len = 0;
2341 for(;;) {
2342 errno = 0;
2343 d = readdir(f);
2344 if (!d) {
2345 err = errno;
2346 break;
2347 }
2348 JS_DefinePropertyValueUint32(ctx, obj, len++,
2349 JS_NewString(ctx, d->d_name),
2350 JS_PROP_C_W_E);
2351 }
2352 closedir(f);
2353 done:
2354 return make_obj_error(ctx, obj, err);
2355}
2356
2357#if !defined(_WIN32)
2132static int64_t timespec_to_ms(const struct timespec *tv)2358static int64_t timespec_to_ms(const struct timespec *tv)
2133{2359{
2134 return (int64_t)tv->tv_sec * 1000 + (tv->tv_nsec / 1000000);2360 return (int64_t)tv->tv_sec * 1000 + (tv->tv_nsec / 1000000);
2135}2361}
2362#endif
2136 2363
2137/* return [obj, errcode] */2364/* return [obj, errcode] */
2138static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val,2365static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val,
@@ -2146,10 +2373,14 @@ static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val, · 7 unmodified lines
2146 path = JS_ToCString(ctx, argv[0]);2373 path = JS_ToCString(ctx, argv[0]);
2147 if (!path)2374 if (!path)
2148 return JS_EXCEPTION;2375 return JS_EXCEPTION;
2376#if defined(_WIN32)
2377 res = stat(path, &st);
2378#else
2149 if (is_lstat)2379 if (is_lstat)
2150 res = lstat(path, &st);2380 res = lstat(path, &st);
2151 else2381 else
2152 res = stat(path, &st);2382 res = stat(path, &st);
2383#endif
2153 JS_FreeCString(ctx, path);2384 JS_FreeCString(ctx, path);
2154 if (res < 0) {2385 if (res < 0) {
2155 err = errno;2386 err = errno;
@@ -2183,10 +2414,22 @@ static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val, · 27 unmodified lines
2183 JS_DefinePropertyValueStr(ctx, obj, "size",2414 JS_DefinePropertyValueStr(ctx, obj, "size",
2184 JS_NewInt64(ctx, st.st_size),2415 JS_NewInt64(ctx, st.st_size),
2185 JS_PROP_C_W_E);2416 JS_PROP_C_W_E);
2417#if !defined(_WIN32)
2186 JS_DefinePropertyValueStr(ctx, obj, "blocks",2418 JS_DefinePropertyValueStr(ctx, obj, "blocks",
2187 JS_NewInt64(ctx, st.st_blocks),2419 JS_NewInt64(ctx, st.st_blocks),
2188 JS_PROP_C_W_E);2420 JS_PROP_C_W_E);
2189#if defined(__APPLE__)2421#endif
2422#if defined(_WIN32)
2423 JS_DefinePropertyValueStr(ctx, obj, "atime",
2424 JS_NewInt64(ctx, (int64_t)st.st_atime * 1000),
2425 JS_PROP_C_W_E);
2426 JS_DefinePropertyValueStr(ctx, obj, "mtime",
2427 JS_NewInt64(ctx, (int64_t)st.st_mtime * 1000),
2428 JS_PROP_C_W_E);
2429 JS_DefinePropertyValueStr(ctx, obj, "ctime",
2430 JS_NewInt64(ctx, (int64_t)st.st_ctime * 1000),
2431 JS_PROP_C_W_E);
2432#elif defined(__APPLE__)
2190 JS_DefinePropertyValueStr(ctx, obj, "atime",2433 JS_DefinePropertyValueStr(ctx, obj, "atime",
2191 JS_NewInt64(ctx, timespec_to_ms(&st.st_atimespec)),2434 JS_NewInt64(ctx, timespec_to_ms(&st.st_atimespec)),
2192 JS_PROP_C_W_E);2435 JS_PROP_C_W_E);
@@ -2211,120 +2454,113 @@ static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val, · 18 unmodified lines
2211 return make_obj_error(ctx, obj, err);2454 return make_obj_error(ctx, obj, err);
2212}2455}
2213 2456
2214static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val,2457#if !defined(_WIN32)
2215 int argc, JSValueConst *argv)2458static void ms_to_timeval(struct timeval *tv, uint64_t v)
2216{2459{
2217 const char *target, *linkpath;2460 tv->tv_sec = v / 1000;
2218 int err;2461 tv->tv_usec = (v % 1000) * 1000;
2219
2220 target = JS_ToCString(ctx, argv[0]);
2221 if (!target)
2222 return JS_EXCEPTION;
2223 linkpath = JS_ToCString(ctx, argv[1]);
2224 if (!linkpath) {
2225 JS_FreeCString(ctx, target);
2226 return JS_EXCEPTION;
2227 }
2228 err = js_get_errno(symlink(target, linkpath));
2229 JS_FreeCString(ctx, target);
2230 JS_FreeCString(ctx, linkpath);
2231 return JS_NewInt32(ctx, err);
2232}2462}
2463#endif
2233 2464
2234/* return [path, errorcode] */2465static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val,
2235static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val,2466 int argc, JSValueConst *argv)
2236 int argc, JSValueConst *argv)
2237{2467{
2238 const char *path;2468 const char *path;
2239 char buf[PATH_MAX];2469 int64_t atime, mtime;
2240 int err;2470 int ret;
2241 ssize_t res;
2242 2471
2472 if (JS_ToInt64(ctx, &atime, argv[1]))
2473 return JS_EXCEPTION;
2474 if (JS_ToInt64(ctx, &mtime, argv[2]))
2475 return JS_EXCEPTION;
2243 path = JS_ToCString(ctx, argv[0]);2476 path = JS_ToCString(ctx, argv[0]);
2244 if (!path)2477 if (!path)
2245 return JS_EXCEPTION;2478 return JS_EXCEPTION;
2246 res = readlink(path, buf, sizeof(buf) - 1);2479#if defined(_WIN32)
2247 if (res < 0) {2480 {
2248 buf[0] = '\0';2481 struct _utimbuf times;
2249 err = errno;2482 times.actime = atime / 1000;
2250 } else {2483 times.modtime = mtime / 1000;
2251 buf[res] = '\0';2484 ret = js_get_errno(_utime(path, &times));
2252 err = 0;2485 }
2486#else
2487 {
2488 struct timeval times[2];
2489 ms_to_timeval(&times[0], atime);
2490 ms_to_timeval(&times[1], mtime);
2491 ret = js_get_errno(utimes(path, times));
2253 }2492 }
2493#endif
2254 JS_FreeCString(ctx, path);2494 JS_FreeCString(ctx, path);
2255 return make_string_error(ctx, buf, err);2495 return JS_NewInt32(ctx, ret);
2256}2496}
2257 2497
2258/* return [array, errorcode] */2498#if !defined(_WIN32)
2259static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val,2499
2260 int argc, JSValueConst *argv)2500/* return [path, errorcode] */
2501static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val,
2502 int argc, JSValueConst *argv)
2261{2503{
2262 const char *path;2504 const char *path;
2263 DIR *f;2505 char buf[PATH_MAX], *res;
2264 struct dirent *d;
2265 JSValue obj;
2266 int err;2506 int err;
2267 uint32_t len;2507
2268
2269 path = JS_ToCString(ctx, argv[0]);2508 path = JS_ToCString(ctx, argv[0]);
2270 if (!path)2509 if (!path)
2271 return JS_EXCEPTION;2510 return JS_EXCEPTION;
2272 obj = JS_NewArray(ctx);2511 res = realpath(path, buf);
2273 if (JS_IsException(obj)) {2512 JS_FreeCString(ctx, path);
2274 JS_FreeCString(ctx, path);2513 if (!res) {
2275 return JS_EXCEPTION;2514 buf[0] = '\0';
2276 }
2277 f = opendir(path);
2278 if (!f)
2279 err = errno;2515 err = errno;
2280 else2516 } else {
2281 err = 0;2517 err = 0;
2282 JS_FreeCString(ctx, path);
2283 if (!f)
2284 goto done;
2285 len = 0;
2286 for(;;) {
2287 errno = 0;
2288 d = readdir(f);
2289 if (!d) {
2290 err = errno;
2291 break;
2292 }
2293 JS_DefinePropertyValueUint32(ctx, obj, len++,
2294 JS_NewString(ctx, d->d_name),
2295 JS_PROP_C_W_E);
2296 }2518 }
2297 closedir(f);2519 return make_string_error(ctx, buf, err);
2298 done:
2299 return make_obj_error(ctx, obj, err);
2300}2520}
2301 2521
2302static void ms_to_timeval(struct timeval *tv, uint64_t v)2522static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val,
2523 int argc, JSValueConst *argv)
2303{2524{
2304 tv->tv_sec = v / 1000;2525 const char *target, *linkpath;
2305 tv->tv_usec = (v % 1000) * 1000;2526 int err;
2527
2528 target = JS_ToCString(ctx, argv[0]);
2529 if (!target)
2530 return JS_EXCEPTION;
2531 linkpath = JS_ToCString(ctx, argv[1]);
2532 if (!linkpath) {
2533 JS_FreeCString(ctx, target);
2534 return JS_EXCEPTION;
2535 }
2536 err = js_get_errno(symlink(target, linkpath));
2537 JS_FreeCString(ctx, target);
2538 JS_FreeCString(ctx, linkpath);
2539 return JS_NewInt32(ctx, err);
2306}2540}
2307 2541
2308static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val,2542/* return [path, errorcode] */
2309 int argc, JSValueConst *argv)2543static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val,
2544 int argc, JSValueConst *argv)
2310{2545{
2311 const char *path;2546 const char *path;
2312 int64_t atime, mtime;2547 char buf[PATH_MAX];
2313 int ret;2548 int err;
2314 struct timeval times[2];2549 ssize_t res;
2315 2550
2316 if (JS_ToInt64(ctx, &atime, argv[1]))
2317 return JS_EXCEPTION;
2318 if (JS_ToInt64(ctx, &mtime, argv[2]))
2319 return JS_EXCEPTION;
2320 path = JS_ToCString(ctx, argv[0]);2551 path = JS_ToCString(ctx, argv[0]);
2321 if (!path)2552 if (!path)
2322 return JS_EXCEPTION;2553 return JS_EXCEPTION;
2323 ms_to_timeval(&times[0], atime);2554 res = readlink(path, buf, sizeof(buf) - 1);
2324 ms_to_timeval(&times[1], mtime);2555 if (res < 0) {
2325 ret = js_get_errno(utimes(path, times));2556 buf[0] = '\0';
2557 err = errno;
2558 } else {
2559 buf[res] = '\0';
2560 err = 0;
2561 }
2326 JS_FreeCString(ctx, path);2562 JS_FreeCString(ctx, path);
2327 return JS_NewInt32(ctx, ret);2563 return make_string_error(ctx, buf, err);
2328}2564}
2329 2565
2330static char **build_envp(JSContext *ctx, JSValueConst obj)2566static char **build_envp(JSContext *ctx, JSValueConst obj)
@@ -2404,7 +2640,7 @@ static int my_execvpe(const char *filename, char **argv, char **envp) · 73 unmodified lines
2404 2640
2405 path = getenv("PATH");2641 path = getenv("PATH");
2406 if (!path)2642 if (!path)
2407 path = "/bin:/usr/bin";2643 path = (char *)"/bin:/usr/bin";
2408 eacces_error = FALSE;2644 eacces_error = FALSE;
2409 p = path;2645 p = path;
2410 for(p = path; p != NULL; p = p_next) {2646 for(p = path; p != NULL; p = p_next) {
@@ -2746,6 +2982,441 @@ static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val, · 335 unmodified lines
2746 2982
2747#endif /* !_WIN32 */2983#endif /* !_WIN32 */
2748 2984
2985#ifdef USE_WORKER
2986
2987/* Worker */
2988
2989typedef struct {
2990 JSWorkerMessagePipe *recv_pipe;
2991 JSWorkerMessagePipe *send_pipe;
2992 JSWorkerMessageHandler *msg_handler;
2993} JSWorkerData;
2994
2995typedef struct {
2996 /* source code of the worker */
2997 char *eval_buf;
2998 size_t eval_buf_len;
2999 JSWorkerMessagePipe *recv_pipe, *send_pipe;
3000} WorkerFuncArgs;
3001
3002typedef struct {
3003 int ref_count;
3004 uint64_t buf[0];
3005} JSSABHeader;
3006
3007static JSClassID js_worker_class_id;
3008
3009static int atomic_add_int(int *ptr, int v)
3010{
3011 return atomic_fetch_add((_Atomic(uint32_t) *)ptr, v) + v;
3012}
3013
3014/* shared array buffer allocator */
3015static void *js_sab_alloc(void *opaque, size_t size)
3016{
3017 JSSABHeader *sab;
3018 sab = malloc(sizeof(JSSABHeader) + size);
3019 if (!sab)
3020 return NULL;
3021 sab->ref_count = 1;
3022 return sab->buf;
3023}
3024
3025static void js_sab_free(void *opaque, void *ptr)
3026{
3027 JSSABHeader *sab;
3028 int ref_count;
3029 sab = (JSSABHeader *)((uint8_t *)ptr - sizeof(JSSABHeader));
3030 ref_count = atomic_add_int(&sab->ref_count, -1);
3031 assert(ref_count >= 0);
3032 if (ref_count == 0) {
3033 free(sab);
3034 }
3035}
3036
3037static void js_sab_dup(void *opaque, void *ptr)
3038{
3039 JSSABHeader *sab;
3040 sab = (JSSABHeader *)((uint8_t *)ptr - sizeof(JSSABHeader));
3041 atomic_add_int(&sab->ref_count, 1);
3042}
3043
3044static JSWorkerMessagePipe *js_new_message_pipe(void)
3045{
3046 JSWorkerMessagePipe *ps;
3047 int pipe_fds[2];
3048
3049 if (pipe(pipe_fds) < 0)
3050 return NULL;
3051
3052 ps = malloc(sizeof(*ps));
3053 if (!ps) {
3054 close(pipe_fds[0]);
3055 close(pipe_fds[1]);
3056 return NULL;
3057 }
3058 ps->ref_count = 1;
3059 init_list_head(&ps->msg_queue);
3060 pthread_mutex_init(&ps->mutex, NULL);
3061 ps->read_fd = pipe_fds[0];
3062 ps->write_fd = pipe_fds[1];
3063 return ps;
3064}
3065
3066static JSWorkerMessagePipe *js_dup_message_pipe(JSWorkerMessagePipe *ps)
3067{
3068 atomic_add_int(&ps->ref_count, 1);
3069 return ps;
3070}
3071
3072static void js_free_message(JSWorkerMessage *msg)
3073{
3074 size_t i;
3075 /* free the SAB */
3076 for(i = 0; i < msg->sab_tab_len; i++) {
3077 js_sab_free(NULL, msg->sab_tab[i]);
3078 }
3079 free(msg->sab_tab);
3080 free(msg->data);
3081 free(msg);
3082}
3083
3084static void js_free_message_pipe(JSWorkerMessagePipe *ps)
3085{
3086 struct list_head *el, *el1;
3087 JSWorkerMessage *msg;
3088 int ref_count;
3089
3090 if (!ps)
3091 return;
3092
3093 ref_count = atomic_add_int(&ps->ref_count, -1);
3094 assert(ref_count >= 0);
3095 if (ref_count == 0) {
3096 list_for_each_safe(el, el1, &ps->msg_queue) {
3097 msg = list_entry(el, JSWorkerMessage, link);
3098 js_free_message(msg);
3099 }
3100 pthread_mutex_destroy(&ps->mutex);
3101 close(ps->read_fd);
3102 close(ps->write_fd);
3103 free(ps);
3104 }
3105}
3106
3107static void js_free_port(JSRuntime *rt, JSWorkerMessageHandler *port)
3108{
3109 if (port) {
3110 js_free_message_pipe(port->recv_pipe);
3111 JS_FreeValueRT(rt, port->on_message_func);
3112 list_del(&port->link);
3113 js_free_rt(rt, port);
3114 }
3115}
3116
3117static void js_worker_finalizer(JSRuntime *rt, JSValue val)
3118{
3119 JSWorkerData *worker = JS_GetOpaque(val, js_worker_class_id);
3120 if (worker) {
3121 js_free_message_pipe(worker->recv_pipe);
3122 js_free_message_pipe(worker->send_pipe);
3123 js_free_port(rt, worker->msg_handler);
3124 js_free_rt(rt, worker);
3125 }
3126}
3127
3128static JSClassDef js_worker_class = {
3129 "Worker",
3130 .finalizer = js_worker_finalizer,
3131};
3132
3133static void *worker_func(void *opaque)
3134{
3135 WorkerFuncArgs *args = opaque;
3136 JSRuntime *rt;
3137 JSThreadState *ts;
3138 JSContext *ctx;
3139 JSValue retval;
3140
3141 rt = JS_NewRuntime();
3142 if (rt == NULL) {
3143 fprintf(stderr, "JS_NewRuntime failure");
3144 exit(1);
3145 }
3146 js_std_init_handlers(rt);
3147
3148 /* set the pipe to communicate with the parent */
3149 ts = JS_GetRuntimeOpaque(rt);
3150 ts->recv_pipe = args->recv_pipe;
3151 ts->send_pipe = args->send_pipe;
3152
3153 ctx = JS_NewContext(rt);
3154 if (ctx == NULL) {
3155 fprintf(stderr, "JS_NewContext failure");
3156 }
3157
3158 JS_SetCanBlock(rt, TRUE);
3159
3160 js_std_add_helpers(ctx, -1, NULL);
3161
3162 /* system modules */
3163 js_init_module_std(ctx, "std");
3164 js_init_module_os(ctx, "os");
3165
3166 retval = JS_Eval(ctx, args->eval_buf, args->eval_buf_len,
3167 "<worker>", JS_EVAL_TYPE_MODULE);
3168 free(args->eval_buf);
3169 free(args);
3170
3171 if (JS_IsException(retval))
3172 js_std_dump_error(ctx);
3173 JS_FreeValue(ctx, retval);
3174
3175 js_std_loop(ctx);
3176
3177 JS_FreeContext(ctx);
3178 js_std_free_handlers(rt);
3179 JS_FreeRuntime(rt);
3180 return NULL;
3181}
3182
3183static JSValue js_worker_ctor_internal(JSContext *ctx, JSValueConst new_target,
3184 JSWorkerMessagePipe *recv_pipe,
3185 JSWorkerMessagePipe *send_pipe)
3186{
3187 JSValue obj = JS_UNDEFINED, proto;
3188 JSWorkerData *s;
3189
3190 /* create the object */
3191 if (JS_IsUndefined(new_target)) {
3192 proto = JS_GetClassProto(ctx, js_worker_class_id);
3193 } else {
3194 proto = JS_GetPropertyStr(ctx, new_target, "prototype");
3195 if (JS_IsException(proto))
3196 goto fail;
3197 }
3198 obj = JS_NewObjectProtoClass(ctx, proto, js_worker_class_id);
3199 JS_FreeValue(ctx, proto);
3200 if (JS_IsException(obj))
3201 goto fail;
3202 s = js_mallocz(ctx, sizeof(*s));
3203 if (!s)
3204 goto fail;
3205 s->recv_pipe = js_dup_message_pipe(recv_pipe);
3206 s->send_pipe = js_dup_message_pipe(send_pipe);
3207
3208 JS_SetOpaque(obj, s);
3209 return obj;
3210 fail:
3211 JS_FreeValue(ctx, obj);
3212 return JS_EXCEPTION;
3213}
3214
3215static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target,
3216 int argc, JSValueConst *argv)
3217{
3218 JSRuntime *rt = JS_GetRuntime(ctx);
3219 WorkerFuncArgs *args;
3220 const char *str;
3221 size_t str_len;
3222 pthread_t tid;
3223 pthread_attr_t attr;
3224 JSValue obj = JS_UNDEFINED;
3225 int ret;
3226
3227 /* XXX: in order to avoid problems with resource liberation, we
3228 don't support creating workers inside workers */
3229 if (!is_main_thread(rt))
3230 return JS_ThrowTypeError(ctx, "cannot create a worker inside a worker");
3231
3232 /* script source */
3233
3234 str = JS_ToCStringLen(ctx, &str_len, argv[0]);
3235 if (!str)
3236 return JS_EXCEPTION;
3237
3238 args = malloc(sizeof(*args));
3239 if (!args) {
3240 JS_ThrowOutOfMemory(ctx);
3241 goto fail;
3242 }
3243 memset(args, 0, sizeof(*args));
3244 args->eval_buf = malloc(str_len + 1);
3245 if (!args->eval_buf) {
3246 JS_ThrowOutOfMemory(ctx);
3247 goto fail;
3248 }
3249 memcpy(args->eval_buf, str, str_len + 1);
3250 args->eval_buf_len = str_len;
3251 JS_FreeCString(ctx, str);
3252 str = NULL;
3253
3254 /* ports */
3255 args->recv_pipe = js_new_message_pipe();
3256 if (!args->recv_pipe)
3257 goto fail;
3258 args->send_pipe = js_new_message_pipe();
3259 if (!args->send_pipe)
3260 goto fail;
3261
3262 obj = js_worker_ctor_internal(ctx, new_target,
3263 args->send_pipe, args->recv_pipe);
3264 if (JS_IsUndefined(obj))
3265 goto fail;
3266
3267 pthread_attr_init(&attr);
3268 /* no join at the end */
3269 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3270 ret = pthread_create(&tid, &attr, worker_func, args);
3271 pthread_attr_destroy(&attr);
3272 if (ret != 0) {
3273 JS_ThrowTypeError(ctx, "could not create worker");
3274 goto fail;
3275 }
3276 return obj;
3277 fail:
3278 JS_FreeCString(ctx, str);
3279 if (args) {
3280 free(args->eval_buf);
3281 js_free_message_pipe(args->recv_pipe);
3282 js_free_message_pipe(args->send_pipe);
3283 free(args);
3284 }
3285 JS_FreeValue(ctx, obj);
3286 return JS_EXCEPTION;
3287}
3288
3289static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val,
3290 int argc, JSValueConst *argv)
3291{
3292 JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id);
3293 JSWorkerMessagePipe *ps;
3294 size_t data_len, sab_tab_len, i;
3295 uint8_t *data;
3296 JSWorkerMessage *msg;
3297 uint8_t **sab_tab;
3298
3299 if (!worker)
3300 return JS_EXCEPTION;
3301
3302 data = JS_WriteObject2(ctx, &data_len, argv[0],
3303 JS_WRITE_OBJ_SAB | JS_WRITE_OBJ_REFERENCE,
3304 &sab_tab, &sab_tab_len);
3305 if (!data)
3306 return JS_EXCEPTION;
3307
3308 msg = malloc(sizeof(*msg));
3309 if (!msg)
3310 goto fail;
3311 msg->data = NULL;
3312 msg->sab_tab = NULL;
3313
3314 /* must reallocate because the allocator may be different */
3315 msg->data = malloc(data_len);
3316 if (!msg->data)
3317 goto fail;
3318 memcpy(msg->data, data, data_len);
3319 msg->data_len = data_len;
3320
3321 msg->sab_tab = malloc(sizeof(msg->sab_tab[0]) * sab_tab_len);
3322 if (!msg->sab_tab)
3323 goto fail;
3324 memcpy(msg->sab_tab, sab_tab, sizeof(msg->sab_tab[0]) * sab_tab_len);
3325 msg->sab_tab_len = sab_tab_len;
3326
3327 js_free(ctx, data);
3328 js_free(ctx, sab_tab);
3329
3330 /* increment the SAB reference counts */
3331 for(i = 0; i < msg->sab_tab_len; i++) {
3332 js_sab_dup(NULL, msg->sab_tab[i]);
3333 }
3334
3335 ps = worker->send_pipe;
3336 pthread_mutex_lock(&ps->mutex);
3337 /* indicate that data is present */
3338 if (list_empty(&ps->msg_queue)) {
3339 uint8_t ch = '\0';
3340 int ret;
3341 for(;;) {
3342 ret = write(ps->write_fd, &ch, 1);
3343 if (ret == 1)
3344 break;
3345 if (ret < 0 && (errno != EAGAIN || errno != EINTR))
3346 break;
3347 }
3348 }
3349 list_add_tail(&msg->link, &ps->msg_queue);
3350 pthread_mutex_unlock(&ps->mutex);
3351 return JS_UNDEFINED;
3352 fail:
3353 if (msg) {
3354 free(msg->data);
3355 free(msg->sab_tab);
3356 free(msg);
3357 }
3358 js_free(ctx, data);
3359 js_free(ctx, sab_tab);
3360 return JS_EXCEPTION;
3361
3362}
3363
3364static JSValue js_worker_set_onmessage(JSContext *ctx, JSValueConst this_val,
3365 JSValueConst func)
3366{
3367 JSRuntime *rt = JS_GetRuntime(ctx);
3368 JSThreadState *ts = JS_GetRuntimeOpaque(rt);
3369 JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id);
3370 JSWorkerMessageHandler *port;
3371
3372 if (!worker)
3373 return JS_EXCEPTION;
3374
3375 port = worker->msg_handler;
3376 if (JS_IsNull(func)) {
3377 if (port) {
3378 js_free_port(rt, port);
3379 worker->msg_handler = NULL;
3380 }
3381 } else {
3382 if (!JS_IsFunction(ctx, func))
3383 return JS_ThrowTypeError(ctx, "not a function");
3384 if (!port) {
3385 port = js_mallocz(ctx, sizeof(*port));
3386 if (!port)
3387 return JS_EXCEPTION;
3388 port->recv_pipe = js_dup_message_pipe(worker->recv_pipe);
3389 port->on_message_func = JS_NULL;
3390 list_add_tail(&port->link, &ts->port_list);
3391 worker->msg_handler = port;
3392 }
3393 JS_FreeValue(ctx, port->on_message_func);
3394 port->on_message_func = JS_DupValue(ctx, func);
3395 }
3396 return JS_UNDEFINED;
3397}
3398
3399static JSValue js_worker_get_onmessage(JSContext *ctx, JSValueConst this_val)
3400{
3401 JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id);
3402 JSWorkerMessageHandler *port;
3403 if (!worker)
3404 return JS_EXCEPTION;
3405 port = worker->msg_handler;
3406 if (port) {
3407 return JS_DupValue(ctx, port->on_message_func);
3408 } else {
3409 return JS_NULL;
3410 }
3411}
3412
3413static const JSCFunctionListEntry js_worker_proto_funcs[] = {
3414 JS_CFUNC_DEF("postMessage", 1, js_worker_postMessage ),
3415 JS_CGETSET_DEF("onmessage", js_worker_get_onmessage, js_worker_set_onmessage ),
3416};
3417
3418#endif /* USE_WORKER */
3419
2749#if defined(_WIN32)3420#if defined(_WIN32)
2750#define OS_PLATFORM "win32"3421#define OS_PLATFORM "win32"
2751#elif defined(__APPLE__)3422#elif defined(__APPLE__)
@@ -2806,12 +3477,9 @@ static const JSCFunctionListEntry js_os_funcs[] = { · 54 unmodified lines
2806 JS_CFUNC_DEF("clearTimeout", 1, js_os_clearTimeout ),3477 JS_CFUNC_DEF("clearTimeout", 1, js_os_clearTimeout ),
2807 JS_PROP_STRING_DEF("platform", OS_PLATFORM, 0 ),3478 JS_PROP_STRING_DEF("platform", OS_PLATFORM, 0 ),
2808 JS_CFUNC_DEF("getcwd", 0, js_os_getcwd ),3479 JS_CFUNC_DEF("getcwd", 0, js_os_getcwd ),
2809#if !defined(_WIN32)
2810 JS_CFUNC_DEF("chdir", 0, js_os_chdir ),3480 JS_CFUNC_DEF("chdir", 0, js_os_chdir ),
2811 JS_CFUNC_DEF("realpath", 1, js_os_realpath ),
2812 JS_CFUNC_DEF("mkdir", 1, js_os_mkdir ),3481 JS_CFUNC_DEF("mkdir", 1, js_os_mkdir ),
2813 JS_CFUNC_MAGIC_DEF("stat", 1, js_os_stat, 0 ),3482 JS_CFUNC_DEF("readdir", 1, js_os_readdir ),
2814 JS_CFUNC_MAGIC_DEF("lstat", 1, js_os_stat, 1 ),
2815 /* st_mode constants */3483 /* st_mode constants */
2816 OS_FLAG(S_IFMT),3484 OS_FLAG(S_IFMT),
2817 OS_FLAG(S_IFIFO),3485 OS_FLAG(S_IFIFO),
@@ -2819,14 +3487,19 @@ static const JSCFunctionListEntry js_os_funcs[] = { · 1 unmodified line
2819 OS_FLAG(S_IFDIR),3487 OS_FLAG(S_IFDIR),
2820 OS_FLAG(S_IFBLK),3488 OS_FLAG(S_IFBLK),
2821 OS_FLAG(S_IFREG),3489 OS_FLAG(S_IFREG),
3490#if !defined(_WIN32)
2822 OS_FLAG(S_IFSOCK),3491 OS_FLAG(S_IFSOCK),
2823 OS_FLAG(S_IFLNK),3492 OS_FLAG(S_IFLNK),
2824 OS_FLAG(S_ISGID),3493 OS_FLAG(S_ISGID),
2825 OS_FLAG(S_ISUID),3494 OS_FLAG(S_ISUID),
3495#endif
3496 JS_CFUNC_MAGIC_DEF("stat", 1, js_os_stat, 0 ),
3497 JS_CFUNC_DEF("utimes", 3, js_os_utimes ),
3498#if !defined(_WIN32)
3499 JS_CFUNC_MAGIC_DEF("lstat", 1, js_os_stat, 1 ),
3500 JS_CFUNC_DEF("realpath", 1, js_os_realpath ),
2826 JS_CFUNC_DEF("symlink", 2, js_os_symlink ),3501 JS_CFUNC_DEF("symlink", 2, js_os_symlink ),
2827 JS_CFUNC_DEF("readlink", 1, js_os_readlink ),3502 JS_CFUNC_DEF("readlink", 1, js_os_readlink ),
2828 JS_CFUNC_DEF("readdir", 1, js_os_readdir ),
2829 JS_CFUNC_DEF("utimes", 3, js_os_utimes ),
2830 JS_CFUNC_DEF("exec", 1, js_os_exec ),3503 JS_CFUNC_DEF("exec", 1, js_os_exec ),
2831 JS_CFUNC_DEF("waitpid", 2, js_os_waitpid ),3504 JS_CFUNC_DEF("waitpid", 2, js_os_waitpid ),
2832 OS_FLAG(WNOHANG),3505 OS_FLAG(WNOHANG),
@@ -2845,7 +3518,35 @@ static int js_os_init(JSContext *ctx, JSModuleDef *m) · 12 unmodified lines
2845 /* OSTimer class */3518 /* OSTimer class */
2846 JS_NewClassID(&js_os_timer_class_id);3519 JS_NewClassID(&js_os_timer_class_id);
2847 JS_NewClass(JS_GetRuntime(ctx), js_os_timer_class_id, &js_os_timer_class);3520 JS_NewClass(JS_GetRuntime(ctx), js_os_timer_class_id, &js_os_timer_class);
2848 3521
3522#ifdef USE_WORKER
3523 {
3524 JSRuntime *rt = JS_GetRuntime(ctx);
3525 JSThreadState *ts = JS_GetRuntimeOpaque(rt);
3526 JSValue proto, obj;
3527 /* Worker class */
3528 JS_NewClassID(&js_worker_class_id);
3529 JS_NewClass(JS_GetRuntime(ctx), js_worker_class_id, &js_worker_class);
3530 proto = JS_NewObject(ctx);
3531 JS_SetPropertyFunctionList(ctx, proto, js_worker_proto_funcs, countof(js_worker_proto_funcs));
3532
3533 obj = JS_NewCFunction2(ctx, js_worker_ctor, "Worker", 1,
3534 JS_CFUNC_constructor, 0);
3535 JS_SetConstructor(ctx, obj, proto);
3536
3537 JS_SetClassProto(ctx, js_worker_class_id, proto);
3538
3539 /* set 'Worker.parent' if necessary */
3540 if (ts->recv_pipe && ts->send_pipe) {
3541 JS_DefinePropertyValueStr(ctx, obj, "parent",
3542 js_worker_ctor_internal(ctx, JS_UNDEFINED, ts->recv_pipe, ts->send_pipe),
3543 JS_PROP_C_W_E);
3544 }
3545
3546 JS_SetModuleExport(ctx, m, "Worker", obj);
3547 }
3548#endif /* USE_WORKER */
3549
2849 return JS_SetModuleExportList(ctx, m, js_os_funcs,3550 return JS_SetModuleExportList(ctx, m, js_os_funcs,
2850 countof(js_os_funcs));3551 countof(js_os_funcs));
2851}3552}
@@ -2857,6 +3558,9 @@ JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name) · 5 unmodified lines
2857 if (!m)3558 if (!m)
2858 return NULL;3559 return NULL;
2859 JS_AddModuleExportList(ctx, m, js_os_funcs, countof(js_os_funcs));3560 JS_AddModuleExportList(ctx, m, js_os_funcs, countof(js_os_funcs));
3561#ifdef USE_WORKER
3562 JS_AddModuleExport(ctx, m, "Worker");
3563#endif
2860 return m;3564 return m;
2861}3565}
2862 3566
@@ -2896,46 +3600,76 @@ void js_std_add_helpers(JSContext *ctx, int argc, char **argv) · 33 unmodified lines
2896 JS_SetPropertyStr(ctx, global_obj, "console", console);3600 JS_SetPropertyStr(ctx, global_obj, "console", console);
2897 3601
2898 /* same methods as the mozilla JS shell */3602 /* same methods as the mozilla JS shell */
2899 args = JS_NewArray(ctx);3603 if (argc >= 0) {
2900 for(i = 0; i < argc; i++) {3604 args = JS_NewArray(ctx);
2901 JS_SetPropertyUint32(ctx, args, i, JS_NewString(ctx, argv[i]));3605 for(i = 0; i < argc; i++) {
3606 JS_SetPropertyUint32(ctx, args, i, JS_NewString(ctx, argv[i]));
3607 }
3608 JS_SetPropertyStr(ctx, global_obj, "scriptArgs", args);
2902 }3609 }
2903 JS_SetPropertyStr(ctx, global_obj, "scriptArgs", args);3610
2904
2905 JS_SetPropertyStr(ctx, global_obj, "print",3611 JS_SetPropertyStr(ctx, global_obj, "print",
2906 JS_NewCFunction(ctx, js_print, "print", 1));3612 JS_NewCFunction(ctx, js_print, "print", 1));
2907 JS_SetPropertyStr(ctx, global_obj, "__loadScript",3613 JS_SetPropertyStr(ctx, global_obj, "__loadScript",
2908 JS_NewCFunction(ctx, js_loadScript, "__loadScript", 1));3614 JS_NewCFunction(ctx, js_loadScript, "__loadScript", 1));
2909 3615
2910 JS_FreeValue(ctx, global_obj);3616 JS_FreeValue(ctx, global_obj);
3617}
3618
3619void js_std_init_handlers(JSRuntime *rt)
3620{
3621 JSThreadState *ts;
3622
3623 ts = malloc(sizeof(*ts));
3624 if (!ts) {
3625 fprintf(stderr, "Could not allocate memory for the worker");
3626 exit(1);
3627 }
3628 memset(ts, 0, sizeof(*ts));
3629 init_list_head(&ts->os_rw_handlers);
3630 init_list_head(&ts->os_signal_handlers);
3631 init_list_head(&ts->os_timers);
3632 init_list_head(&ts->port_list);
3633
3634 JS_SetRuntimeOpaque(rt, ts);
2911 3635
2912 /* XXX: not multi-context */3636#ifdef USE_WORKER
2913 init_list_head(&os_rw_handlers);3637 /* set the SharedArrayBuffer memory handlers */
2914 init_list_head(&os_signal_handlers);3638 {
2915 init_list_head(&os_timers);3639 JSSharedArrayBufferFunctions sf;
2916 os_pending_signals = 0;3640 memset(&sf, 0, sizeof(sf));
3641 sf.sab_alloc = js_sab_alloc;
3642 sf.sab_free = js_sab_free;
3643 sf.sab_dup = js_sab_dup;
3644 JS_SetSharedArrayBufferFunctions(rt, &sf);
3645 }
3646#endif
2917}3647}
2918 3648
2919void js_std_free_handlers(JSRuntime *rt)3649void js_std_free_handlers(JSRuntime *rt)
2920{3650{
3651 JSThreadState *ts = JS_GetRuntimeOpaque(rt);
2921 struct list_head *el, *el1;3652 struct list_head *el, *el1;
2922 3653
2923 list_for_each_safe(el, el1, &os_rw_handlers) {3654 list_for_each_safe(el, el1, &ts->os_rw_handlers) {
2924 JSOSRWHandler *rh = list_entry(el, JSOSRWHandler, link);3655 JSOSRWHandler *rh = list_entry(el, JSOSRWHandler, link);
2925 free_rw_handler(rt, rh);3656 free_rw_handler(rt, rh);
2926 }3657 }
2927 3658
2928 list_for_each_safe(el, el1, &os_signal_handlers) {3659 list_for_each_safe(el, el1, &ts->os_signal_handlers) {
2929 JSOSSignalHandler *sh = list_entry(el, JSOSSignalHandler, link);3660 JSOSSignalHandler *sh = list_entry(el, JSOSSignalHandler, link);
2930 free_sh(rt, sh);3661 free_sh(rt, sh);
2931 }3662 }
2932 3663
2933 list_for_each_safe(el, el1, &os_timers) {3664 list_for_each_safe(el, el1, &ts->os_timers) {
2934 JSOSTimer *th = list_entry(el, JSOSTimer, link);3665 JSOSTimer *th = list_entry(el, JSOSTimer, link);
2935 unlink_timer(rt, th);3666 unlink_timer(rt, th);
2936 if (!th->has_object)3667 if (!th->has_object)
2937 free_timer(rt, th);3668 free_timer(rt, th);
2938 }3669 }
3670
3671 free(ts);
3672 JS_SetRuntimeOpaque(rt, NULL); /* fail safe */
2939}3673}
2940 3674
2941static void js_dump_obj(JSContext *ctx, FILE *f, JSValueConst val)3675static void js_dump_obj(JSContext *ctx, FILE *f, JSValueConst val)
quickjs-libc.h+9−0
@@ -29,10 +29,15 @@ · 28 unmodified lines
29 29
30#include "quickjs.h"30#include "quickjs.h"
31 31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
32JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name);36JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name);
33JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name);37JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name);
34void js_std_add_helpers(JSContext *ctx, int argc, char **argv);38void js_std_add_helpers(JSContext *ctx, int argc, char **argv);
35void js_std_loop(JSContext *ctx);39void js_std_loop(JSContext *ctx);
40void js_std_init_handlers(JSRuntime *rt);
36void js_std_free_handlers(JSRuntime *rt);41void js_std_free_handlers(JSRuntime *rt);
37void js_std_dump_error(JSContext *ctx);42void js_std_dump_error(JSContext *ctx);
38uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename);43uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename);
@@ -46,4 +51,8 @@ void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, · 7 unmodified lines
46 JSValueConst reason,51 JSValueConst reason,
47 JS_BOOL is_handled, void *opaque);52 JS_BOOL is_handled, void *opaque);
48 53
54#ifdef __cplusplus
55} /* extern "C" { */
56#endif
57
49#endif /* QUICKJS_LIBC_H */58#endif /* QUICKJS_LIBC_H */
quickjs.c+2058−1253
@@ -71,6 +71,12 @@ · 70 unmodified lines
71#define CONFIG_ATOMICS71#define CONFIG_ATOMICS
72#endif72#endif
73 73
74#if !defined(EMSCRIPTEN)
75/* enable stack limitation */
76#define CONFIG_STACK_CHECK
77#endif
78
79
74/* dump object free */80/* dump object free */
75//#define DUMP_FREE81//#define DUMP_FREE
76//#define DUMP_CLOSURE82//#define DUMP_CLOSURE
@@ -281,7 +287,9 @@ struct JSRuntime { · 204 unmodified lines
281 void *module_loader_opaque;287 void *module_loader_opaque;
282 288
283 BOOL can_block : 8; /* TRUE if Atomics.wait can block */289 BOOL can_block : 8; /* TRUE if Atomics.wait can block */
284 290 /* used to allocate, free and clone SharedArrayBuffers */
291 JSSharedArrayBufferFunctions sab_funcs;
292
285 /* Shape hash table */293 /* Shape hash table */
286 int shape_hash_bits;294 int shape_hash_bits;
287 int shape_hash_size;295 int shape_hash_size;
@@ -392,7 +400,7 @@ typedef struct JSBigDecimal { · 104 unmodified lines
392typedef enum {400typedef enum {
393 JS_AUTOINIT_ID_PROTOTYPE,401 JS_AUTOINIT_ID_PROTOTYPE,
394 JS_AUTOINIT_ID_MODULE_NS,402 JS_AUTOINIT_ID_MODULE_NS,
395 JS_AUTOINIT_ID_PROP, /* must be last */403 JS_AUTOINIT_ID_PROP,
396} JSAutoInitIDEnum;404} JSAutoInitIDEnum;
397 405
398/* must be large enough to have a negligible runtime cost and small406/* must be large enough to have a negligible runtime cost and small
@@ -625,7 +633,6 @@ typedef struct JSRegExp { · 226 unmodified lines
625typedef struct JSProxyData {633typedef struct JSProxyData {
626 JSValue target;634 JSValue target;
627 JSValue handler;635 JSValue handler;
628 JSValue proto;
629 uint8_t is_func;636 uint8_t is_func;
630 uint8_t is_revoked;637 uint8_t is_revoked;
631} JSProxyData;638} JSProxyData;
@@ -770,6 +777,7 @@ struct JSModuleDef { · 138 unmodified lines
770 JSValue func_obj; /* only used for JS modules */777 JSValue func_obj; /* only used for JS modules */
771 JSModuleInitFunc *init_func; /* only used for C modules */778 JSModuleInitFunc *init_func; /* only used for C modules */
772 BOOL resolved : 8;779 BOOL resolved : 8;
780 BOOL func_created : 8;
773 BOOL instantiated : 8;781 BOOL instantiated : 8;
774 BOOL evaluated : 8;782 BOOL evaluated : 8;
775 BOOL eval_mark : 8; /* temporary use during js_evaluate_module() */783 BOOL eval_mark : 8; /* temporary use during js_evaluate_module() */
@@ -799,10 +807,8 @@ typedef struct JSProperty { · 23 unmodified lines
799 struct { /* JS_PROP_AUTOINIT */807 struct { /* JS_PROP_AUTOINIT */
800 /* in order to use only 2 pointers, we compress the realm808 /* in order to use only 2 pointers, we compress the realm
801 and the init function pointer */809 and the init function pointer */
802 union {810 uintptr_t realm_and_id; /* realm and init_id (JS_AUTOINIT_ID_x)
803 JSContext *realm; /* for JS_AUTOINIT_ID_PROP */811 in the 2 low bits */
804 uintptr_t init_id; /* JS_AUTOINIT_ID_x */
805 } u;
806 void *opaque;812 void *opaque;
807 } init;813 } init;
808 } u;814 } u;
@@ -832,11 +838,13 @@ struct JSShape { · 23 unmodified lines
832 uint32_t hash; /* current hash value */838 uint32_t hash; /* current hash value */
833 uint32_t prop_hash_mask;839 uint32_t prop_hash_mask;
834 int prop_size; /* allocated properties */840 int prop_size; /* allocated properties */
835 int prop_count;841 int prop_count; /* include deleted properties */
842 int deleted_prop_count;
836 JSShape *shape_hash_next; /* in JSRuntime.shape_hash[h] list */843 JSShape *shape_hash_next; /* in JSRuntime.shape_hash[h] list */
837 JSObject *proto;844 JSObject *proto;
838 JSShapeProperty prop[0]; /* prop_size elements */845 JSShapeProperty prop[0]; /* prop_size elements */
839};846};
847
840struct JSObject {848struct JSObject {
841 union {849 union {
842 JSGCObjectHeader header;850 JSGCObjectHeader header;
@@ -850,7 +858,6 @@ struct JSObject { · 7 unmodified lines
850 uint8_t fast_array : 1; /* TRUE if u.array is used for get/put */858 uint8_t fast_array : 1; /* TRUE if u.array is used for get/put */
851 uint8_t is_constructor : 1; /* TRUE if object is a constructor function */859 uint8_t is_constructor : 1; /* TRUE if object is a constructor function */
852 uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */860 uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */
853 uint8_t is_class : 1; /* TRUE if object is a class constructor */
854 uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */861 uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */
855 uint16_t class_id; /* see JS_CLASS_x */862 uint16_t class_id; /* see JS_CLASS_x */
856 };863 };
@@ -1124,7 +1131,7 @@ static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val); · 267 unmodified lines
1124#endif1131#endif
1125JSValue JS_ThrowOutOfMemory(JSContext *ctx);1132JSValue JS_ThrowOutOfMemory(JSContext *ctx);
1126static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx);1133static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx);
1127static JSValueConst js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj);1134static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj);
1128static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,1135static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
1129 JSValueConst proto_val, BOOL throw_flag);1136 JSValueConst proto_val, BOOL throw_flag);
1130static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj);1137static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj);
@@ -1136,6 +1143,17 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p, · 5 unmodified lines
1136 int flags);1143 int flags);
1137static int js_string_memcmp(const JSString *p1, const JSString *p2, int len);1144static int js_string_memcmp(const JSString *p1, const JSString *p2, int len);
1138static void reset_weak_ref(JSRuntime *rt, JSObject *p);1145static void reset_weak_ref(JSRuntime *rt, JSObject *p);
1146static JSValue js_array_buffer_constructor3(JSContext *ctx,
1147 JSValueConst new_target,
1148 uint64_t len, JSClassID class_id,
1149 uint8_t *buf,
1150 JSFreeArrayBufferDataFunc *free_func,
1151 void *opaque, BOOL alloc_flag);
1152static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj);
1153static JSValue js_typed_array_constructor(JSContext *ctx,
1154 JSValueConst this_val,
1155 int argc, JSValueConst *argv,
1156 int classid);
1139static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p);1157static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p);
1140static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p);1158static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p);
1141static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx);1159static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx);
@@ -1212,6 +1230,7 @@ static int js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, · 70 unmodified lines
1212 void *opaque);1230 void *opaque);
1213static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,1231static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,
1214 JSAtom atom, void *opaque);1232 JSAtom atom, void *opaque);
1233void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag);
1215 1234
1216static const JSClassExoticMethods js_arguments_exotic_methods;1235static const JSClassExoticMethods js_arguments_exotic_methods;
1217static const JSClassExoticMethods js_string_exotic_methods;1236static const JSClassExoticMethods js_string_exotic_methods;
@@ -1361,6 +1380,33 @@ char *js_strdup(JSContext *ctx, const char *str) · 143 unmodified lines
1361 return js_strndup(ctx, str, strlen(str));1380 return js_strndup(ctx, str, strlen(str));
1362}1381}
1363 1382
1383static no_inline int js_realloc_array(JSContext *ctx, void **parray,
1384 int elem_size, int *psize, int req_size)
1385{
1386 int new_size;
1387 size_t slack;
1388 void *new_array;
1389 /* XXX: potential arithmetic overflow */
1390 new_size = max_int(req_size, *psize * 3 / 2);
1391 new_array = js_realloc2(ctx, *parray, new_size * elem_size, &slack);
1392 if (!new_array)
1393 return -1;
1394 new_size += slack / elem_size;
1395 *psize = new_size;
1396 *parray = new_array;
1397 return 0;
1398}
1399
1400/* resize the array and update its size if req_size > *psize */
1401static inline int js_resize_array(JSContext *ctx, void **parray, int elem_size,
1402 int *psize, int req_size)
1403{
1404 if (unlikely(req_size > *psize))
1405 return js_realloc_array(ctx, parray, elem_size, psize, req_size);
1406 else
1407 return 0;
1408}
1409
1364static inline void js_dbuf_init(JSContext *ctx, DynBuf *s)1410static inline void js_dbuf_init(JSContext *ctx, DynBuf *s)
1365{1411{
1366 dbuf_init2(s, ctx->rt, (DynBufReallocFunc *)js_realloc_rt);1412 dbuf_init2(s, ctx->rt, (DynBufReallocFunc *)js_realloc_rt);
@@ -1379,7 +1425,7 @@ typedef struct JSClassShortDef { · 12 unmodified lines
1379static JSClassShortDef const js_std_class_def[] = {1425static JSClassShortDef const js_std_class_def[] = {
1380 { JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_OBJECT */1426 { JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_OBJECT */
1381 { JS_ATOM_Array, js_array_finalizer, js_array_mark }, /* JS_CLASS_ARRAY */1427 { JS_ATOM_Array, js_array_finalizer, js_array_mark }, /* JS_CLASS_ARRAY */
1382 { JS_ATOM_Error, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_ERROR */1428 { JS_ATOM_Error, NULL, NULL }, /* JS_CLASS_ERROR */
1383 { JS_ATOM_Number, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_NUMBER */1429 { JS_ATOM_Number, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_NUMBER */
1384 { JS_ATOM_String, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_STRING */1430 { JS_ATOM_String, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_STRING */
1385 { JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */1431 { JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */
@@ -1426,7 +1472,7 @@ static JSClassShortDef const js_std_class_def[] = { · 40 unmodified lines
1426 { JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */1472 { JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */
1427 { JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */1473 { JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */
1428 { JS_ATOM_String_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */1474 { JS_ATOM_String_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */
1429 { JS_ATOM_RegExp_String_Iterator, js_regexp_string_iterator_finalizer, js_regexp_string_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */1475 { JS_ATOM_RegExp_String_Iterator, js_regexp_string_iterator_finalizer, js_regexp_string_iterator_mark }, /* JS_CLASS_REGEXP_STRING_ITERATOR */
1430 { JS_ATOM_Generator, js_generator_finalizer, js_generator_mark }, /* JS_CLASS_GENERATOR */1476 { JS_ATOM_Generator, js_generator_finalizer, js_generator_mark }, /* JS_CLASS_GENERATOR */
1431};1477};
1432 1478
@@ -1505,8 +1551,8 @@ static void set_dummy_numeric_ops(JSNumericOperations *ops) · 72 unmodified lines
1505 1551
1506#endif /* CONFIG_BIGNUM */1552#endif /* CONFIG_BIGNUM */
1507 1553
1508#if defined(EMSCRIPTEN)1554#if !defined(CONFIG_STACK_CHECK)
1509/* currently no stack limitation */1555/* no stack limitation */
1510static inline uint8_t *js_get_stack_pointer(void)1556static inline uint8_t *js_get_stack_pointer(void)
1511{1557{
1512 return NULL;1558 return NULL;
@@ -1729,6 +1775,12 @@ void JS_SetCanBlock(JSRuntime *rt, BOOL can_block) · 216 unmodified lines
1729 rt->can_block = can_block;1775 rt->can_block = can_block;
1730}1776}
1731 1777
1778void JS_SetSharedArrayBufferFunctions(JSRuntime *rt,
1779 const JSSharedArrayBufferFunctions *sf)
1780{
1781 rt->sab_funcs = *sf;
1782}
1783
1732/* return 0 if OK, < 0 if exception */1784/* return 0 if OK, < 0 if exception */
1733int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func,1785int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func,
1734 int argc, JSValueConst *argv)1786 int argc, JSValueConst *argv)
@@ -4262,9 +4314,10 @@ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, · 2527 unmodified lines
4262 memset(sh->prop_hash_end - hash_size, 0, sizeof(sh->prop_hash_end[0]) *4314 memset(sh->prop_hash_end - hash_size, 0, sizeof(sh->prop_hash_end[0]) *
4263 hash_size);4315 hash_size);
4264 sh->prop_hash_mask = hash_size - 1;4316 sh->prop_hash_mask = hash_size - 1;
4265 sh->prop_count = 0;
4266 sh->prop_size = prop_size;4317 sh->prop_size = prop_size;
4267 4318 sh->prop_count = 0;
4319 sh->deleted_prop_count = 0;
4320
4268 /* insert in the hash table */4321 /* insert in the hash table */
4269 sh->hash = shape_initial_hash(proto);4322 sh->hash = shape_initial_hash(proto);
4270 sh->is_hashed = TRUE;4323 sh->is_hashed = TRUE;
@@ -4415,6 +4468,74 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh, · 144 unmodified lines
4415 return 0;4468 return 0;
4416}4469}
4417 4470
4471/* remove the deleted properties. */
4472static int compact_properties(JSContext *ctx, JSObject *p)
4473{
4474 JSShape *sh, *old_sh;
4475 void *sh_alloc;
4476 intptr_t h;
4477 uint32_t new_hash_size, i, j, new_hash_mask, new_size;
4478 JSShapeProperty *old_pr, *pr;
4479 JSProperty *prop, *new_prop;
4480
4481 sh = p->shape;
4482 assert(!sh->is_hashed);
4483
4484 new_size = max_int(JS_PROP_INITIAL_SIZE,
4485 sh->prop_count - sh->deleted_prop_count);
4486 assert(new_size <= sh->prop_size);
4487
4488 new_hash_size = sh->prop_hash_mask + 1;
4489 while ((new_hash_size / 2) >= new_size)
4490 new_hash_size = new_hash_size / 2;
4491 new_hash_mask = new_hash_size - 1;
4492
4493 /* resize the hash table and the properties */
4494 old_sh = sh;
4495 sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));
4496 if (!sh_alloc)
4497 return -1;
4498 sh = get_shape_from_alloc(sh_alloc, new_hash_size);
4499 list_del(&old_sh->header.link);
4500 memcpy(sh, old_sh, sizeof(JSShape));
4501 list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
4502
4503 memset(sh->prop_hash_end - new_hash_size, 0,
4504 sizeof(sh->prop_hash_end[0]) * new_hash_size);
4505
4506 j = 0;
4507 old_pr = old_sh->prop;
4508 pr = sh->prop;
4509 prop = p->prop;
4510 for(i = 0; i < sh->prop_count; i++) {
4511 if (old_pr->atom != JS_ATOM_NULL) {
4512 pr->atom = old_pr->atom;
4513 pr->flags = old_pr->flags;
4514 h = ((uintptr_t)old_pr->atom & new_hash_mask);
4515 pr->hash_next = sh->prop_hash_end[-h - 1];
4516 sh->prop_hash_end[-h - 1] = j + 1;
4517 prop[j] = prop[i];
4518 j++;
4519 pr++;
4520 }
4521 old_pr++;
4522 }
4523 assert(j == (sh->prop_count - sh->deleted_prop_count));
4524 sh->prop_hash_mask = new_hash_mask;
4525 sh->prop_size = new_size;
4526 sh->deleted_prop_count = 0;
4527 sh->prop_count = j;
4528
4529 p->shape = sh;
4530 js_free(ctx, get_alloc_from_shape(old_sh));
4531
4532 /* reduce the size of the object properties */
4533 new_prop = js_realloc(ctx, p->prop, sizeof(new_prop[0]) * new_size);
4534 if (new_prop)
4535 p->prop = new_prop;
4536 return 0;
4537}
4538
4418static int add_shape_property(JSContext *ctx, JSShape **psh,4539static int add_shape_property(JSContext *ctx, JSShape **psh,
4419 JSObject *p, JSAtom atom, int prop_flags)4540 JSObject *p, JSAtom atom, int prop_flags)
4420{4541{
@@ -4571,7 +4692,6 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas · 150 unmodified lines
4571 p->fast_array = 0;4692 p->fast_array = 0;
4572 p->is_constructor = 0;4693 p->is_constructor = 0;
4573 p->is_uncatchable_error = 0;4694 p->is_uncatchable_error = 0;
4574 p->is_class = 0;
4575 p->tmp_mark = 0;4695 p->tmp_mark = 0;
4576 p->first_weak_ref = NULL;4696 p->first_weak_ref = NULL;
4577 p->u.opaque = NULL;4697 p->u.opaque = NULL;
@@ -4621,7 +4741,6 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas · 43 unmodified lines
4621 p->u.array.u.ptr = NULL;4741 p->u.array.u.ptr = NULL;
4622 p->u.array.count = 0;4742 p->u.array.count = 0;
4623 break;4743 break;
4624 case JS_CLASS_ERROR:
4625 case JS_CLASS_NUMBER:4744 case JS_CLASS_NUMBER:
4626 case JS_CLASS_STRING:4745 case JS_CLASS_STRING:
4627 case JS_CLASS_BOOLEAN:4746 case JS_CLASS_BOOLEAN:
@@ -4967,19 +5086,25 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, · 339 unmodified lines
4967 return func_obj;5086 return func_obj;
4968}5087}
4969 5088
5089static JSContext *js_autoinit_get_realm(JSProperty *pr)
5090{
5091 return (JSContext *)(pr->u.init.realm_and_id & ~3);
5092}
5093
5094static JSAutoInitIDEnum js_autoinit_get_id(JSProperty *pr)
5095{
5096 return pr->u.init.realm_and_id & 3;
5097}
5098
4970static void js_autoinit_free(JSRuntime *rt, JSProperty *pr)5099static void js_autoinit_free(JSRuntime *rt, JSProperty *pr)
4971{5100{
4972 if (pr->u.init.u.init_id >= JS_AUTOINIT_ID_PROP) {5101 JS_FreeContext(js_autoinit_get_realm(pr));
4973 JS_FreeContext(pr->u.init.u.realm);
4974 }
4975}5102}
4976 5103
4977static void js_autoinit_mark(JSRuntime *rt, JSProperty *pr,5104static void js_autoinit_mark(JSRuntime *rt, JSProperty *pr,
4978 JS_MarkFunc *mark_func)5105 JS_MarkFunc *mark_func)
4979{5106{
4980 if (pr->u.init.u.init_id >= JS_AUTOINIT_ID_PROP) {5107 mark_func(rt, &js_autoinit_get_realm(pr)->header);
4981 mark_func(rt, &pr->u.init.u.realm->header);
4982 }
4983}5108}
4984 5109
4985static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags)5110static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags)
@@ -6331,7 +6456,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj, · 1345 unmodified lines
6331 backtrace_barrier = FALSE;6456 backtrace_barrier = FALSE;
6332 if (js_class_has_bytecode(p->class_id)) {6457 if (js_class_has_bytecode(p->class_id)) {
6333 JSFunctionBytecode *b;6458 JSFunctionBytecode *b;
6334 char atom_buf[ATOM_GET_STR_BUF_SIZE];6459 const char *atom_str;
6335 int line_num1;6460 int line_num1;
6336 6461
6337 b = p->u.func.function_bytecode;6462 b = p->u.func.function_bytecode;
@@ -6339,9 +6464,10 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj, · 1 unmodified line
6339 if (b->has_debug) {6464 if (b->has_debug) {
6340 line_num1 = find_line_num(ctx, b,6465 line_num1 = find_line_num(ctx, b,
6341 sf->cur_pc - b->byte_code_buf - 1);6466 sf->cur_pc - b->byte_code_buf - 1);
6467 atom_str = JS_AtomToCString(ctx, b->debug.filename);
6342 dbuf_printf(&dbuf, " (%s",6468 dbuf_printf(&dbuf, " (%s",
6343 JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf),6469 atom_str ? atom_str : "<null>");
6344 b->debug.filename));6470 JS_FreeCString(ctx, atom_str);
6345 if (line_num1 != -1)6471 if (line_num1 != -1)
6346 dbuf_printf(&dbuf, ":%d", line_num1);6472 dbuf_printf(&dbuf, ":%d", line_num1);
6347 dbuf_putc(&dbuf, ')');6473 dbuf_putc(&dbuf, ')');
@@ -6459,13 +6585,32 @@ static int __attribute__((format(printf, 3, 4))) JS_ThrowTypeErrorOrFalse(JSCont · 111 unmodified lines
6459 }6585 }
6460}6586}
6461 6587
6588/* never use it directly */
6589static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowTypeErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
6590{
6591 char buf[ATOM_GET_STR_BUF_SIZE];
6592 return JS_ThrowTypeError(ctx, fmt,
6593 JS_AtomGetStr(ctx, buf, sizeof(buf), atom));
6594}
6595
6596/* never use it directly */
6597static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowSyntaxErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
6598{
6599 char buf[ATOM_GET_STR_BUF_SIZE];
6600 return JS_ThrowSyntaxError(ctx, fmt,
6601 JS_AtomGetStr(ctx, buf, sizeof(buf), atom));
6602}
6603
6604/* %s is replaced by 'atom'. The macro is used so that gcc can check
6605 the format string. */
6606#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "")
6607#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "")
6608
6462static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)6609static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)
6463{6610{
6464 if ((flags & JS_PROP_THROW) ||6611 if ((flags & JS_PROP_THROW) ||
6465 ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {6612 ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {
6466 char buf[ATOM_GET_STR_BUF_SIZE];6613 JS_ThrowTypeErrorAtom(ctx, "'%s' is read-only", atom);
6467 JS_ThrowTypeError(ctx, "%s is read-only",
6468 JS_AtomGetStr(ctx, buf, sizeof(buf), atom));
6469 return -1;6614 return -1;
6470 } else {6615 } else {
6471 return FALSE;6616 return FALSE;
@@ -6534,7 +6679,7 @@ static JSValue JS_ThrowTypeErrorNotASymbol(JSContext *ctx) · 62 unmodified lines
6534static JSValue JS_ThrowReferenceErrorNotDefined(JSContext *ctx, JSAtom name)6679static JSValue JS_ThrowReferenceErrorNotDefined(JSContext *ctx, JSAtom name)
6535{6680{
6536 char buf[ATOM_GET_STR_BUF_SIZE];6681 char buf[ATOM_GET_STR_BUF_SIZE];
6537 return JS_ThrowReferenceError(ctx, "%s is not defined",6682 return JS_ThrowReferenceError(ctx, "'%s' is not defined",
6538 JS_AtomGetStr(ctx, buf, sizeof(buf), name));6683 JS_AtomGetStr(ctx, buf, sizeof(buf), name));
6539}6684}
6540 6685
@@ -6549,11 +6694,33 @@ static JSValue JS_ThrowReferenceErrorUninitialized(JSContext *ctx, JSAtom name) · 8 unmodified lines
6549static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id)6694static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id)
6550{6695{
6551 JSRuntime *rt = ctx->rt;6696 JSRuntime *rt = ctx->rt;
6552 char buf[ATOM_GET_STR_BUF_SIZE];
6553 JSAtom name;6697 JSAtom name;
6554 name = rt->class_array[class_id].class_name;6698 name = rt->class_array[class_id].class_name;
6555 return JS_ThrowTypeError(ctx, "%s object expected",6699 return JS_ThrowTypeErrorAtom(ctx, "%s object expected", name);
6556 JS_AtomGetStr(ctx, buf, sizeof(buf), name));6700}
6701
6702static no_inline __exception int __js_poll_interrupts(JSContext *ctx)
6703{
6704 JSRuntime *rt = ctx->rt;
6705 ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT;
6706 if (rt->interrupt_handler) {
6707 if (rt->interrupt_handler(rt, rt->interrupt_opaque)) {
6708 /* XXX: should set a specific flag to avoid catching */
6709 JS_ThrowInternalError(ctx, "interrupted");
6710 JS_SetUncatchableError(ctx, ctx->rt->current_exception, TRUE);
6711 return -1;
6712 }
6713 }
6714 return 0;
6715}
6716
6717static inline __exception int js_poll_interrupts(JSContext *ctx)
6718{
6719 if (unlikely(--ctx->interrupt_counter <= 0)) {
6720 return __js_poll_interrupts(ctx);
6721 } else {
6722 return 0;
6723 }
6557}6724}
6558 6725
6559/* return -1 (exception) or TRUE/FALSE */6726/* return -1 (exception) or TRUE/FALSE */
@@ -6633,11 +6800,9 @@ int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val) · 73 unmodified lines
6633 return JS_SetPrototypeInternal(ctx, obj, proto_val, TRUE);6800 return JS_SetPrototypeInternal(ctx, obj, proto_val, TRUE);
6634}6801}
6635 6802
6636/* Return an Object, JS_NULL or JS_EXCEPTION in case of Proxy object. */6803/* Only works for primitive types, otherwise return JS_NULL. */
6637JSValueConst JS_GetPrototype(JSContext *ctx, JSValueConst val)6804static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val)
6638{6805{
6639 JSObject *p;
6640
6641 switch(JS_VALUE_GET_NORM_TAG(val)) {6806 switch(JS_VALUE_GET_NORM_TAG(val)) {
6642#ifdef CONFIG_BIGNUM6807#ifdef CONFIG_BIGNUM
6643 case JS_TAG_BIG_INT:6808 case JS_TAG_BIG_INT:
@@ -6664,26 +6829,45 @@ JSValueConst JS_GetPrototype(JSContext *ctx, JSValueConst val) · 20 unmodified lines
6664 val = ctx->class_proto[JS_CLASS_SYMBOL];6829 val = ctx->class_proto[JS_CLASS_SYMBOL];
6665 break;6830 break;
6666 case JS_TAG_OBJECT:6831 case JS_TAG_OBJECT:
6667 p = JS_VALUE_GET_OBJ(val);6832 case JS_TAG_NULL:
6833 case JS_TAG_UNDEFINED:
6834 default:
6835 val = JS_NULL;
6836 break;
6837 }
6838 return val;
6839}
6840
6841/* Return an Object, JS_NULL or JS_EXCEPTION in case of Proxy object. */
6842JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj)
6843{
6844 JSValue val;
6845 if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
6846 JSObject *p;
6847 p = JS_VALUE_GET_OBJ(obj);
6668 if (unlikely(p->class_id == JS_CLASS_PROXY)) {6848 if (unlikely(p->class_id == JS_CLASS_PROXY)) {
6669 val = js_proxy_getPrototypeOf(ctx, val);6849 val = js_proxy_getPrototypeOf(ctx, obj);
6670 } else {6850 } else {
6671 p = p->shape->proto;6851 p = p->shape->proto;
6672 if (!p)6852 if (!p)
6673 val = JS_NULL;6853 val = JS_NULL;
6674 else6854 else
6675 val = JS_MKPTR(JS_TAG_OBJECT, p);6855 val = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
6676 }6856 }
6677 break;6857 } else {
6678 case JS_TAG_NULL:6858 val = JS_DupValue(ctx, JS_GetPrototypePrimitive(ctx, obj));
6679 case JS_TAG_UNDEFINED:
6680 default:
6681 val = JS_NULL;
6682 break;
6683 }6859 }
6684 return val;6860 return val;
6685}6861}
6686 6862
6863static JSValue JS_GetPrototypeFree(JSContext *ctx, JSValue obj)
6864{
6865 JSValue obj1;
6866 obj1 = JS_GetPrototype(ctx, obj);
6867 JS_FreeValue(ctx, obj);
6868 return obj1;
6869}
6870
6687/* return TRUE, FALSE or (-1) in case of exception */6871/* return TRUE, FALSE or (-1) in case of exception */
6688static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val,6872static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val,
6689 JSValueConst obj)6873 JSValueConst obj)
@@ -6704,7 +6888,6 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, · 14 unmodified lines
6704 /* Only explicitly boxed values are instances of constructors */6888 /* Only explicitly boxed values are instances of constructors */
6705 if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)6889 if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
6706 return FALSE;6890 return FALSE;
6707 ret = FALSE;
6708 obj_proto = JS_GetProperty(ctx, obj, JS_ATOM_prototype);6891 obj_proto = JS_GetProperty(ctx, obj, JS_ATOM_prototype);
6709 if (JS_VALUE_GET_TAG(obj_proto) != JS_TAG_OBJECT) {6892 if (JS_VALUE_GET_TAG(obj_proto) != JS_TAG_OBJECT) {
6710 if (!JS_IsException(obj_proto))6893 if (!JS_IsException(obj_proto))
@@ -6717,19 +6900,36 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, · 6 unmodified lines
6717 for(;;) {6900 for(;;) {
6718 proto1 = p->shape->proto;6901 proto1 = p->shape->proto;
6719 if (!proto1) {6902 if (!proto1) {
6720 if (p->class_id == JS_CLASS_PROXY) {6903 /* slow case if proxy in the prototype chain */
6721 JSValueConst proto_val;6904 if (unlikely(p->class_id == JS_CLASS_PROXY)) {
6722 proto_val = JS_GetPrototype(ctx, JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p));6905 JSValue obj1;
6723 if (JS_IsException(proto_val)) {6906 obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p));
6724 ret = -1;6907 for(;;) {
6725 goto done;6908 obj1 = JS_GetPrototypeFree(ctx, obj1);
6909 if (JS_IsException(obj1)) {
6910 ret = -1;
6911 break;
6912 }
6913 if (JS_IsNull(obj1)) {
6914 ret = FALSE;
6915 break;
6916 }
6917 if (proto == JS_VALUE_GET_OBJ(obj1)) {
6918 JS_FreeValue(ctx, obj1);
6919 ret = TRUE;
6920 break;
6921 }
6922 /* must check for timeout to avoid infinite loop */
6923 if (js_poll_interrupts(ctx)) {
6924 JS_FreeValue(ctx, obj1);
6925 ret = -1;
6926 break;
6927 }
6726 }6928 }
6727 proto1 = JS_VALUE_GET_OBJ(proto_val);
6728 if (!proto1)
6729 break;
6730 } else {6929 } else {
6731 break;6930 ret = FALSE;
6732 }6931 }
6932 break;
6733 }6933 }
6734 p = proto1;6934 p = proto1;
6735 if (proto == p) {6935 if (proto == p) {
@@ -6767,28 +6967,24 @@ int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj) · 31 unmodified lines
6767 return JS_OrdinaryIsInstanceOf(ctx, val, obj);6967 return JS_OrdinaryIsInstanceOf(ctx, val, obj);
6768}6968}
6769 6969
6770static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop, JSProperty *pr)6970typedef int JSAutoInitFunc(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);
6971
6972static JSAutoInitFunc *js_autoinit_func_table[] = {
6973 js_instantiate_prototype, /* JS_AUTOINIT_ID_PROTOTYPE */
6974 js_module_ns_autoinit, /* JS_AUTOINIT_ID_MODULE_NS */
6975 JS_InstantiateFunctionListItem, /* JS_AUTOINIT_ID_PROP */
6976};
6977
6978static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop,
6979 JSProperty *pr)
6771{6980{
6772 int ret;6981 int ret;
6773 JSContext *realm;6982 JSContext *realm;
6774 6983 JSAutoInitFunc *func;
6775 if (pr->u.init.u.init_id >= JS_AUTOINIT_ID_PROP) {6984
6776 realm = pr->u.init.u.realm;6985 realm = js_autoinit_get_realm(pr);
6777 ret = JS_InstantiateFunctionListItem(realm, p, prop, pr->u.init.opaque);6986 func = js_autoinit_func_table[js_autoinit_get_id(pr)];
6778 if (ret)6987 ret = func(realm, p, prop, pr->u.init.opaque);
6779 return ret;
6780 } else {
6781 switch(pr->u.init.u.init_id) {
6782 case JS_AUTOINIT_ID_PROTOTYPE:
6783 ret = js_instantiate_prototype(ctx, p, prop, pr->u.init.opaque);
6784 break;
6785 case JS_AUTOINIT_ID_MODULE_NS:
6786 ret = js_module_ns_autoinit(ctx, p, prop, pr->u.init.opaque);
6787 break;
6788 default:
6789 abort();
6790 }
6791 }
6792 return ret;6988 return ret;
6793}6989}
6794 6990
@@ -6805,8 +7001,9 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, · 10 unmodified lines
6805 if (unlikely(tag != JS_TAG_OBJECT)) {7001 if (unlikely(tag != JS_TAG_OBJECT)) {
6806 switch(tag) {7002 switch(tag) {
6807 case JS_TAG_NULL:7003 case JS_TAG_NULL:
7004 return JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of null", prop);
6808 case JS_TAG_UNDEFINED:7005 case JS_TAG_UNDEFINED:
6809 return JS_ThrowTypeError(ctx, "value has no property");7006 return JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of undefined", prop);
6810 case JS_TAG_EXCEPTION:7007 case JS_TAG_EXCEPTION:
6811 return JS_EXCEPTION;7008 return JS_EXCEPTION;
6812 case JS_TAG_STRING:7009 case JS_TAG_STRING:
@@ -6831,7 +7028,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, · 18 unmodified lines
6831 break;7028 break;
6832 }7029 }
6833 /* cannot raise an exception */7030 /* cannot raise an exception */
6834 p = JS_VALUE_GET_OBJ(JS_GetPrototype(ctx, obj));7031 p = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, obj));
6835 if (!p)7032 if (!p)
6836 return JS_UNDEFINED;7033 return JS_UNDEFINED;
6837 } else {7034 } else {
@@ -6896,15 +7093,25 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, · 58 unmodified lines
6896 const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;7093 const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
6897 if (em) {7094 if (em) {
6898 if (em->get_property) {7095 if (em->get_property) {
7096 JSValue obj1, retval;
6899 /* XXX: should pass throw_ref_error */7097 /* XXX: should pass throw_ref_error */
6900 return em->get_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p),7098 /* Note: if 'p' is a prototype, it can be
6901 prop, this_obj);7099 freed in the called function */
7100 obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
7101 retval = em->get_property(ctx, obj1, prop, this_obj);
7102 JS_FreeValue(ctx, obj1);
7103 return retval;
6902 }7104 }
6903 if (em->get_own_property) {7105 if (em->get_own_property) {
6904 JSPropertyDescriptor desc;7106 JSPropertyDescriptor desc;
6905 int ret;7107 int ret;
7108 JSValue obj1;
6906 7109
6907 ret = em->get_own_property(ctx, &desc, JS_MKPTR(JS_TAG_OBJECT, p), prop);7110 /* Note: if 'p' is a prototype, it can be
7111 freed in the called function */
7112 obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
7113 ret = em->get_own_property(ctx, &desc, obj1, prop);
7114 JS_FreeValue(ctx, obj1);
6908 if (ret < 0)7115 if (ret < 0)
6909 return JS_EXCEPTION;7116 return JS_EXCEPTION;
6910 if (ret) {7117 if (ret) {
@@ -6932,9 +7139,8 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, · 21 unmodified lines
6932 7139
6933static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom)7140static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom)
6934{7141{
6935 char buf[ATOM_GET_STR_BUF_SIZE];7142 return JS_ThrowTypeErrorAtom(ctx, "private class field '%s' does not exist",
6936 return JS_ThrowTypeError(ctx, "private class field %s does not exist",7143 atom);
6937 JS_AtomGetStr(ctx, buf, sizeof(buf), atom));
6938}7144}
6939 7145
6940/* Private fields can be added even on non extensible objects or7146/* Private fields can be added even on non extensible objects or
@@ -6960,9 +7166,8 @@ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj, · 19 unmodified lines
6960 p = JS_VALUE_GET_OBJ(obj);7166 p = JS_VALUE_GET_OBJ(obj);
6961 prs = find_own_property(&pr, p, prop);7167 prs = find_own_property(&pr, p, prop);
6962 if (prs) {7168 if (prs) {
6963 char buf[ATOM_GET_STR_BUF_SIZE];7169 JS_ThrowTypeErrorAtom(ctx, "private class field '%s' already exists",
6964 JS_ThrowTypeError(ctx, "private class field %s already exists",7170 prop);
6965 JS_AtomGetStr(ctx, buf, sizeof(buf), prop));
6966 goto fail;7171 goto fail;
6967 }7172 }
6968 pr = add_property(ctx, p, prop, JS_PROP_C_W_E);7173 pr = add_property(ctx, p, prop, JS_PROP_C_W_E);
@@ -7211,7 +7416,9 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, · 242 unmodified lines
7211 JS_ThrowTypeErrorDetachedArrayBuffer(ctx);7416 JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
7212 return -1;7417 return -1;
7213 }7418 }
7214 num_keys_count += p->u.array.count;7419 if (flags & JS_GPN_STRING_MASK) {
7420 num_keys_count += p->u.array.count;
7421 }
7215 } else {7422 } else {
7216 const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;7423 const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
7217 if (em && em->get_own_property_names) {7424 if (em && em->get_own_property_names) {
@@ -7293,15 +7500,17 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, · 75 unmodified lines
7293 7500
7294 if (p->is_exotic) {7501 if (p->is_exotic) {
7295 if (p->fast_array) {7502 if (p->fast_array) {
7296 for(i = 0; i < p->u.array.count; i++) {7503 if (flags & JS_GPN_STRING_MASK) {
7297 tab_atom[num_index].atom = __JS_AtomFromUInt32(i);7504 for(i = 0; i < p->u.array.count; i++) {
7298 if (tab_atom[num_index].atom == JS_ATOM_NULL) {7505 tab_atom[num_index].atom = __JS_AtomFromUInt32(i);
7299 js_free_prop_enum(ctx, tab_exotic, exotic_count);7506 if (tab_atom[num_index].atom == JS_ATOM_NULL) {
7300 js_free_prop_enum(ctx, tab_atom, num_index);7507 js_free_prop_enum(ctx, tab_exotic, exotic_count);
7301 return -1;7508 js_free_prop_enum(ctx, tab_atom, num_index);
7509 return -1;
7510 }
7511 tab_atom[num_index].is_enumerable = TRUE;
7512 num_index++;
7302 }7513 }
7303 tab_atom[num_index].is_enumerable = TRUE;
7304 num_index++;
7305 }7514 }
7306 }7515 }
7307 if (exotic_count > 0) {7516 if (exotic_count > 0) {
@@ -7492,6 +7701,7 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) · 184 unmodified lines
7492{7701{
7493 JSObject *p;7702 JSObject *p;
7494 int ret;7703 int ret;
7704 JSValue obj1;
7495 7705
7496 if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))7706 if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))
7497 return FALSE;7707 return FALSE;
@@ -7499,10 +7709,18 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) · 1 unmodified line
7499 for(;;) {7709 for(;;) {
7500 if (p->is_exotic) {7710 if (p->is_exotic) {
7501 const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;7711 const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
7502 if (em && em->has_property)7712 if (em && em->has_property) {
7503 return em->has_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p), prop);7713 /* has_property can free the prototype */
7714 obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
7715 ret = em->has_property(ctx, obj1, prop);
7716 JS_FreeValue(ctx, obj1);
7717 return ret;
7718 }
7504 }7719 }
7720 /* JS_GetOwnPropertyInternal can free the prototype */
7721 JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
7505 ret = JS_GetOwnPropertyInternal(ctx, NULL, p, prop);7722 ret = JS_GetOwnPropertyInternal(ctx, NULL, p, prop);
7723 JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
7506 if (ret != 0)7724 if (ret != 0)
7507 return ret;7725 return ret;
7508 if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&7726 if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
@@ -7799,6 +8017,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) · 290 unmodified lines
7799 } else {8017 } else {
7800 sh->prop_hash_end[-h1 - 1] = pr->hash_next;8018 sh->prop_hash_end[-h1 - 1] = pr->hash_next;
7801 }8019 }
8020 sh->deleted_prop_count++;
7802 /* free the entry */8021 /* free the entry */
7803 pr1 = &p->prop[h - 1];8022 pr1 = &p->prop[h - 1];
7804 free_property(ctx->rt, pr1, pr->flags);8023 free_property(ctx->rt, pr1, pr->flags);
@@ -7807,6 +8026,12 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) · 2 unmodified lines
7807 pr->flags = 0;8026 pr->flags = 0;
7808 pr->atom = JS_ATOM_NULL;8027 pr->atom = JS_ATOM_NULL;
7809 pr1->u.value = JS_UNDEFINED;8028 pr1->u.value = JS_UNDEFINED;
8029
8030 /* compact the properties if too many deleted properties */
8031 if (sh->deleted_prop_count >= 8 &&
8032 sh->deleted_prop_count >= ((unsigned)sh->prop_count / 2)) {
8033 compact_properties(ctx, p);
8034 }
7810 return TRUE;8035 return TRUE;
7811 }8036 }
7812 lpr = pr;8037 lpr = pr;
@@ -8016,8 +8241,12 @@ static int JS_SetPropertyGeneric(JSContext *ctx, · 203 unmodified lines
8016 if (p->is_exotic) {8241 if (p->is_exotic) {
8017 const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;8242 const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
8018 if (em && em->set_property) {8243 if (em && em->set_property) {
8019 ret = em->set_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p), prop,8244 JSValue obj1;
8245 /* set_property can free the prototype */
8246 obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
8247 ret = em->set_property(ctx, obj1, prop,
8020 val, this_obj, flags);8248 val, this_obj, flags);
8249 JS_FreeValue(ctx, obj1);
8021 JS_FreeValue(ctx, val);8250 JS_FreeValue(ctx, val);
8022 return ret;8251 return ret;
8023 }8252 }
@@ -8110,14 +8339,17 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, · 86 unmodified lines
8110 if (unlikely(tag != JS_TAG_OBJECT)) {8339 if (unlikely(tag != JS_TAG_OBJECT)) {
8111 switch(tag) {8340 switch(tag) {
8112 case JS_TAG_NULL:8341 case JS_TAG_NULL:
8342 JS_FreeValue(ctx, val);
8343 JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop);
8344 return -1;
8113 case JS_TAG_UNDEFINED:8345 case JS_TAG_UNDEFINED:
8114 JS_FreeValue(ctx, val);8346 JS_FreeValue(ctx, val);
8115 JS_ThrowTypeError(ctx, "value has no property");8347 JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop);
8116 return -1;8348 return -1;
8117 default:8349 default:
8118 /* even on a primitive type we can have setters on the prototype */8350 /* even on a primitive type we can have setters on the prototype */
8119 p = NULL;8351 p = NULL;
8120 p1 = JS_VALUE_GET_OBJ(JS_GetPrototype(ctx, this_obj));8352 p1 = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, this_obj));
8121 goto prototype_lookup;8353 goto prototype_lookup;
8122 }8354 }
8123 }8355 }
@@ -8195,15 +8427,22 @@ retry: · 71 unmodified lines
8195 } else {8427 } else {
8196 const JSClassExoticMethods *em = ctx->rt->class_array[p1->class_id].exotic;8428 const JSClassExoticMethods *em = ctx->rt->class_array[p1->class_id].exotic;
8197 if (em) {8429 if (em) {
8430 JSValue obj1;
8198 if (em->set_property) {8431 if (em->set_property) {
8199 ret = em->set_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p1), prop,8432 /* set_property can free the prototype */
8433 obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));
8434 ret = em->set_property(ctx, obj1, prop,
8200 val, this_obj, flags);8435 val, this_obj, flags);
8436 JS_FreeValue(ctx, obj1);
8201 JS_FreeValue(ctx, val);8437 JS_FreeValue(ctx, val);
8202 return ret;8438 return ret;
8203 }8439 }
8204 if (em->get_own_property) {8440 if (em->get_own_property) {
8441 /* get_own_property can free the prototype */
8442 obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));
8205 ret = em->get_own_property(ctx, &desc,8443 ret = em->get_own_property(ctx, &desc,
8206 JS_MKPTR(JS_TAG_OBJECT, p1), prop);8444 obj1, prop);
8445 JS_FreeValue(ctx, obj1);
8207 if (ret < 0) {8446 if (ret < 0) {
8208 JS_FreeValue(ctx, val);8447 JS_FreeValue(ctx, val);
8209 return ret;8448 return ret;
@@ -8973,11 +9212,10 @@ static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj, · 763 unmodified lines
8973 pr = add_property(ctx, p, prop, (flags & JS_PROP_C_W_E) | JS_PROP_AUTOINIT);9212 pr = add_property(ctx, p, prop, (flags & JS_PROP_C_W_E) | JS_PROP_AUTOINIT);
8974 if (unlikely(!pr))9213 if (unlikely(!pr))
8975 return -1;9214 return -1;
8976 if (id == JS_AUTOINIT_ID_PROP) {9215 pr->u.init.realm_and_id = (uintptr_t)JS_DupContext(ctx);
8977 pr->u.init.u.realm = JS_DupContext(ctx);9216 assert((pr->u.init.realm_and_id & 3) == 0);
8978 } else {9217 assert(id <= 3);
8979 pr->u.init.u.init_id = id;9218 pr->u.init.realm_and_id |= id;
8980 }
8981 pr->u.init.opaque = opaque;9219 pr->u.init.opaque = opaque;
8982 return TRUE;9220 return TRUE;
8983}9221}
@@ -9114,9 +9352,7 @@ static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj, · 130 unmodified lines
9114 9352
9115static JSValue JS_ThrowSyntaxErrorVarRedeclaration(JSContext *ctx, JSAtom prop)9353static JSValue JS_ThrowSyntaxErrorVarRedeclaration(JSContext *ctx, JSAtom prop)
9116{9354{
9117 char buf[ATOM_GET_STR_BUF_SIZE];9355 return JS_ThrowSyntaxErrorAtom(ctx, "redeclaration of '%s'", prop);
9118 return JS_ThrowSyntaxError(ctx, "redeclaration of %s",
9119 JS_AtomGetStr(ctx, buf, sizeof(buf), prop));
9120}9356}
9121 9357
9122/* flags is 0, DEFINE_GLOBAL_LEX_VAR or DEFINE_GLOBAL_FUNC_VAR */9358/* flags is 0, DEFINE_GLOBAL_LEX_VAR or DEFINE_GLOBAL_FUNC_VAR */
@@ -9125,7 +9361,6 @@ static int JS_CheckDefineGlobalVar(JSContext *ctx, JSAtom prop, int flags) · 2 unmodified lines
9125{9361{
9126 JSObject *p;9362 JSObject *p;
9127 JSShapeProperty *prs;9363 JSShapeProperty *prs;
9128 char buf[ATOM_GET_STR_BUF_SIZE];
9129 9364
9130 p = JS_VALUE_GET_OBJ(ctx->global_obj);9365 p = JS_VALUE_GET_OBJ(ctx->global_obj);
9131 prs = find_own_property1(p, prop);9366 prs = find_own_property1(p, prop);
@@ -9143,8 +9378,8 @@ static int JS_CheckDefineGlobalVar(JSContext *ctx, JSAtom prop, int flags) · 11 unmodified lines
9143 ((prs->flags & (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)) !=9378 ((prs->flags & (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)) !=
9144 (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)))) {9379 (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)))) {
9145 define_error:9380 define_error:
9146 JS_ThrowTypeError(ctx, "cannot define variable %s",9381 JS_ThrowTypeErrorAtom(ctx, "cannot define variable '%s'",
9147 JS_AtomGetStr(ctx, buf, sizeof(buf), prop));9382 prop);
9148 return -1;9383 return -1;
9149 }9384 }
9150 }9385 }
@@ -11395,7 +11630,9 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) · 2244 unmodified lines
11395 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {11630 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
11396 printf("[varref %p]", (void *)pr->u.var_ref);11631 printf("[varref %p]", (void *)pr->u.var_ref);
11397 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {11632 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
11398 printf("[autoinit %p %p]", (void *)pr->u.init.u.realm,11633 printf("[autoinit %p %d %p]",
11634 (void *)js_autoinit_get_realm(pr),
11635 js_autoinit_get_id(pr),
11399 (void *)pr->u.init.opaque);11636 (void *)pr->u.init.opaque);
11400 } else {11637 } else {
11401 JS_DumpValueShort(rt, pr->u.value);11638 JS_DumpValueShort(rt, pr->u.value);
@@ -15726,30 +15963,6 @@ static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj, · 4324 unmodified lines
15726 }15963 }
15727}15964}
15728 15965
15729static no_inline __exception int __js_poll_interrupts(JSContext *ctx)
15730{
15731 JSRuntime *rt = ctx->rt;
15732 ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT;
15733 if (rt->interrupt_handler) {
15734 if (rt->interrupt_handler(rt, rt->interrupt_opaque)) {
15735 /* XXX: should set a specific flag to avoid catching */
15736 JS_ThrowInternalError(ctx, "interrupted");
15737 JS_SetUncatchableError(ctx, ctx->rt->current_exception, TRUE);
15738 return -1;
15739 }
15740 }
15741 return 0;
15742}
15743
15744static inline __exception int js_poll_interrupts(JSContext *ctx)
15745{
15746 if (unlikely(--ctx->interrupt_counter <= 0)) {
15747 return __js_poll_interrupts(ctx);
15748 } else {
15749 return 0;
15750 }
15751}
15752
15753/* argument of OP_special_object */15966/* argument of OP_special_object */
15754typedef enum {15967typedef enum {
15755 OP_SPECIAL_OBJECT_ARGUMENTS,15968 OP_SPECIAL_OBJECT_ARGUMENTS,
@@ -16440,7 +16653,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, · 684 unmodified lines
16440 CASE(OP_get_super):16653 CASE(OP_get_super):
16441 {16654 {
16442 JSValue proto;16655 JSValue proto;
16443 proto = JS_DupValue(ctx, JS_GetPrototype(ctx, sp[-1]));16656 proto = JS_GetPrototype(ctx, sp[-1]);
16444 if (JS_IsException(proto))16657 if (JS_IsException(proto))
16445 goto exception;16658 goto exception;
16446 JS_FreeValue(ctx, sp[-1]);16659 JS_FreeValue(ctx, sp[-1]);
@@ -18543,6 +18756,9 @@ static JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s) · 2096 unmodified lines
18543{18756{
18544 JSValue func_obj;18757 JSValue func_obj;
18545 18758
18759 if (js_check_stack_overflow(ctx->rt, 0))
18760 return JS_ThrowStackOverflow(ctx);
18761
18546 /* the tag does not matter provided it is not an object */18762 /* the tag does not matter provided it is not an object */
18547 func_obj = JS_MKPTR(JS_TAG_INT, s);18763 func_obj = JS_MKPTR(JS_TAG_INT, s);
18548 return JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED,18764 return JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED,
@@ -19670,8 +19886,8 @@ typedef struct JSFunctionDef { · 1121 unmodified lines
19670 19886
19671 /* constant pool (strings, functions, numbers) */19887 /* constant pool (strings, functions, numbers) */
19672 JSValue *cpool;19888 JSValue *cpool;
19673 uint32_t cpool_count;19889 int cpool_count;
19674 uint32_t cpool_size;19890 int cpool_size;
19675 19891
19676 /* list of variables in the closure */19892 /* list of variables in the closure */
19677 int closure_var_count;19893 int closure_var_count;
@@ -19741,6 +19957,7 @@ typedef struct JSParseState { · 63 unmodified lines
19741 JSFunctionDef *cur_func;19957 JSFunctionDef *cur_func;
19742 BOOL is_module; /* parsing a module */19958 BOOL is_module; /* parsing a module */
19743 BOOL allow_html_comments;19959 BOOL allow_html_comments;
19960 BOOL ext_json; /* true if accepting JSON superset */
19744} JSParseState;19961} JSParseState;
19745 19962
19746typedef struct JSOpCode {19963typedef struct JSOpCode {
@@ -20308,23 +20525,18 @@ static __exception int next_token(JSParseState *s) · 561 unmodified lines
20308 c = *p;20525 c = *p;
20309 switch(c) {20526 switch(c) {
20310 case 0:20527 case 0:
20311 s->token.val = TOK_EOF;20528 if (p >= s->buf_end) {
20312 break;20529 s->token.val = TOK_EOF;
20313 case '`':20530 } else {
20314 if (!s->cur_func) {
20315 /* JSON does not accept templates */
20316 goto def_token;20531 goto def_token;
20317 }20532 }
20533 break;
20534 case '`':
20318 if (js_parse_template_part(s, p + 1))20535 if (js_parse_template_part(s, p + 1))
20319 goto fail;20536 goto fail;
20320 p = s->buf_ptr;20537 p = s->buf_ptr;
20321 break;20538 break;
20322 case '\'':20539 case '\'':
20323 if (!s->cur_func) {
20324 /* JSON does not accept single quoted strings */
20325 goto def_token;
20326 }
20327 /* fall through */
20328 case '\"':20540 case '\"':
20329 if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p))20541 if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p))
20330 goto fail;20542 goto fail;
@@ -20342,11 +20554,6 @@ static __exception int next_token(JSParseState *s) · 11 unmodified lines
20342 goto redo;20554 goto redo;
20343 case '\f':20555 case '\f':
20344 case '\v':20556 case '\v':
20345 if (!s->cur_func) {
20346 /* JSONWhitespace does not match <VT>, nor <FF> */
20347 goto def_token;
20348 }
20349 /* fall through */
20350 case ' ':20557 case ' ':
20351 case '\t':20558 case '\t':
20352 p++;20559 p++;
@@ -20443,16 +20650,15 @@ static __exception int next_token(JSParseState *s) · 90 unmodified lines
20443 s->token.u.ident.is_reserved = FALSE;20650 s->token.u.ident.is_reserved = FALSE;
20444 if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||20651 if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||
20445 (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&20652 (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&
20446 s->cur_func && (s->cur_func->js_mode & JS_MODE_STRICT)) ||20653 (s->cur_func->js_mode & JS_MODE_STRICT)) ||
20447 (s->token.u.ident.atom == JS_ATOM_yield && s->cur_func &&20654 (s->token.u.ident.atom == JS_ATOM_yield &&
20448 ((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||20655 ((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||
20449 (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&20656 (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
20450 !s->cur_func->in_function_body && s->cur_func->parent &&20657 !s->cur_func->in_function_body && s->cur_func->parent &&
20451 (s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||20658 (s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||
20452 (s->token.u.ident.atom == JS_ATOM_await &&20659 (s->token.u.ident.atom == JS_ATOM_await &&
20453 (s->is_module ||20660 (s->is_module ||
20454 (s->cur_func &&20661 (((s->cur_func->func_kind & JS_FUNC_ASYNC) ||
20455 ((s->cur_func->func_kind & JS_FUNC_ASYNC) ||
20456 (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&20662 (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
20457 !s->cur_func->in_function_body && s->cur_func->parent &&20663 !s->cur_func->in_function_body && s->cur_func->parent &&
20458 (s->cur_func->parent->func_kind & JS_FUNC_ASYNC))))))) {20664 (s->cur_func->parent->func_kind & JS_FUNC_ASYNC))))))) {
@@ -20505,9 +20711,8 @@ static __exception int next_token(JSParseState *s) · 46 unmodified lines
20505 }20711 }
20506 break;20712 break;
20507 case '0':20713 case '0':
20508 /* in strict or JSON parsing mode, octal literals are not accepted */20714 /* in strict mode, octal literals are not accepted */
20509 if (is_digit(p[1]) && (!s->cur_func ||20715 if (is_digit(p[1]) && (s->cur_func->js_mode & JS_MODE_STRICT)) {
20510 (s->cur_func->js_mode & JS_MODE_STRICT))) {
20511 js_parse_error(s, "octal literals are deprecated in strict mode");20716 js_parse_error(s, "octal literals are deprecated in strict mode");
20512 goto fail;20717 goto fail;
20513 }20718 }
@@ -20519,22 +20724,17 @@ static __exception int next_token(JSParseState *s) · 5 unmodified lines
20519 JSValue ret;20724 JSValue ret;
20520 const uint8_t *p1;20725 const uint8_t *p1;
20521 int flags, radix;20726 int flags, radix;
20522 if (!s->cur_func) {20727 flags = ATOD_ACCEPT_BIN_OCT | ATOD_ACCEPT_LEGACY_OCTAL |
20523 flags = 0;20728 ATOD_ACCEPT_UNDERSCORES;
20524 radix = 10;
20525 } else {
20526 flags = ATOD_ACCEPT_BIN_OCT | ATOD_ACCEPT_LEGACY_OCTAL |
20527 ATOD_ACCEPT_UNDERSCORES;
20528#ifdef CONFIG_BIGNUM20729#ifdef CONFIG_BIGNUM
20529 flags |= ATOD_ACCEPT_SUFFIX;20730 flags |= ATOD_ACCEPT_SUFFIX;
20530 if (s->cur_func->js_mode & JS_MODE_MATH) {20731 if (s->cur_func->js_mode & JS_MODE_MATH) {
20531 flags |= ATOD_MODE_BIGINT;20732 flags |= ATOD_MODE_BIGINT;
20532 if (s->cur_func->js_mode & JS_MODE_MATH)20733 if (s->cur_func->js_mode & JS_MODE_MATH)
20533 flags |= ATOD_TYPE_BIG_FLOAT;20734 flags |= ATOD_TYPE_BIG_FLOAT;
20534 }
20535#endif
20536 radix = 0;
20537 }20735 }
20736#endif
20737 radix = 0;
20538#ifdef CONFIG_BIGNUM20738#ifdef CONFIG_BIGNUM
20539 s->token.u.num.exponent = 0;20739 s->token.u.num.exponent = 0;
20540 ret = js_atof2(s->ctx, (const char *)p, (const char **)&p, radix,20740 ret = js_atof2(s->ctx, (const char *)p, (const char **)&p, radix,
@@ -20699,7 +20899,7 @@ static __exception int next_token(JSParseState *s) · 158 unmodified lines
20699 case '^':20899 case '^':
20700 if (p[1] == '=') {20900 if (p[1] == '=') {
20701 p += 2;20901 p += 2;
20702 if (s->cur_func && (s->cur_func->js_mode & JS_MODE_MATH))20902 if (s->cur_func->js_mode & JS_MODE_MATH)
20703 s->token.val = TOK_MATH_POW_ASSIGN;20903 s->token.val = TOK_MATH_POW_ASSIGN;
20704 else20904 else
20705 s->token.val = TOK_XOR_ASSIGN;20905 s->token.val = TOK_XOR_ASSIGN;
@@ -20713,7 +20913,7 @@ static __exception int next_token(JSParseState *s) · 7 unmodified lines
20713 }20913 }
20714 } else {20914 } else {
20715 p++;20915 p++;
20716 if (s->cur_func && (s->cur_func->js_mode & JS_MODE_MATH))20916 if (s->cur_func->js_mode & JS_MODE_MATH)
20717 s->token.val = TOK_MATH_POW;20917 s->token.val = TOK_MATH_POW;
20718 else20918 else
20719 s->token.val = '^';20919 s->token.val = '^';
@@ -20758,22 +20958,12 @@ static __exception int next_token(JSParseState *s) · 38 unmodified lines
20758 switch(c) {20958 switch(c) {
20759 case CP_PS:20959 case CP_PS:
20760 case CP_LS:20960 case CP_LS:
20761 if (!s->cur_func) {20961 /* XXX: should avoid incrementing line_number, but
20762 /* <PS> and <LS> are not JSONWhitespace */20962 needed to handle HTML comments */
20763 goto def_token;20963 goto line_terminator;
20764 } else {
20765 /* XXX: should avoid incrementing line_number, but
20766 needed to handle HTML comments */
20767 goto line_terminator;
20768 }
20769 default:20964 default:
20770 if (lre_is_space(c)) {20965 if (lre_is_space(c)) {
20771 if (!s->cur_func) {20966 goto redo;
20772 /* category z spaces are not JSONWhitespace */
20773 goto def_token;
20774 } else {
20775 goto redo;
20776 }
20777 } else if (lre_js_is_ident_first(c)) {20967 } else if (lre_js_is_ident_first(c)) {
20778 ident_has_escape = FALSE;20968 ident_has_escape = FALSE;
20779 goto has_ident;20969 goto has_ident;
@@ -20798,6 +20988,220 @@ static __exception int next_token(JSParseState *s) · 18 unmodified lines
20798 return -1;20988 return -1;
20799}20989}
20800 20990
20991/* 'c' is the first character. Return JS_ATOM_NULL in case of error */
20992static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
20993{
20994 const uint8_t *p;
20995 char ident_buf[128], *buf;
20996 size_t ident_size, ident_pos;
20997 JSAtom atom;
20998
20999 p = *pp;
21000 buf = ident_buf;
21001 ident_size = sizeof(ident_buf);
21002 ident_pos = 0;
21003 for(;;) {
21004 buf[ident_pos++] = c;
21005 c = *p;
21006 if (c >= 128 ||
21007 !((lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1))
21008 break;
21009 p++;
21010 if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) {
21011 if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) {
21012 atom = JS_ATOM_NULL;
21013 goto done;
21014 }
21015 }
21016 }
21017 atom = JS_NewAtomLen(s->ctx, buf, ident_pos);
21018 done:
21019 if (unlikely(buf != ident_buf))
21020 js_free(s->ctx, buf);
21021 *pp = p;
21022 return atom;
21023}
21024
21025static __exception int json_next_token(JSParseState *s)
21026{
21027 const uint8_t *p;
21028 int c;
21029 JSAtom atom;
21030
21031 if (js_check_stack_overflow(s->ctx->rt, 0)) {
21032 return js_parse_error(s, "stack overflow");
21033 }
21034
21035 free_token(s, &s->token);
21036
21037 p = s->last_ptr = s->buf_ptr;
21038 s->last_line_num = s->token.line_num;
21039 redo:
21040 s->token.line_num = s->line_num;
21041 s->token.ptr = p;
21042 c = *p;
21043 switch(c) {
21044 case 0:
21045 if (p >= s->buf_end) {
21046 s->token.val = TOK_EOF;
21047 } else {
21048 goto def_token;
21049 }
21050 break;
21051 case '\'':
21052 if (!s->ext_json) {
21053 /* JSON does not accept single quoted strings */
21054 goto def_token;
21055 }
21056 /* fall through */
21057 case '\"':
21058 if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p))
21059 goto fail;
21060 break;
21061 case '\r': /* accept DOS and MAC newline sequences */
21062 if (p[1] == '\n') {
21063 p++;
21064 }
21065 /* fall thru */
21066 case '\n':
21067 p++;
21068 s->line_num++;
21069 goto redo;
21070 case '\f':
21071 case '\v':
21072 if (!s->ext_json) {
21073 /* JSONWhitespace does not match <VT>, nor <FF> */
21074 goto def_token;
21075 }
21076 /* fall through */
21077 case ' ':
21078 case '\t':
21079 p++;
21080 goto redo;
21081 case '/':
21082 if (!s->ext_json) {
21083 /* JSON does not accept comments */
21084 goto def_token;
21085 }
21086 if (p[1] == '*') {
21087 /* comment */
21088 p += 2;
21089 for(;;) {
21090 if (*p == '\0' && p >= s->buf_end) {
21091 js_parse_error(s, "unexpected end of comment");
21092 goto fail;
21093 }
21094 if (p[0] == '*' && p[1] == '/') {
21095 p += 2;
21096 break;
21097 }
21098 if (*p == '\n') {
21099 s->line_num++;
21100 p++;
21101 } else if (*p == '\r') {
21102 p++;
21103 } else if (*p >= 0x80) {
21104 c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
21105 if (c == -1) {
21106 p++; /* skip invalid UTF-8 */
21107 }
21108 } else {
21109 p++;
21110 }
21111 }
21112 goto redo;
21113 } else if (p[1] == '/') {
21114 /* line comment */
21115 p += 2;
21116 for(;;) {
21117 if (*p == '\0' && p >= s->buf_end)
21118 break;
21119 if (*p == '\r' || *p == '\n')
21120 break;
21121 if (*p >= 0x80) {
21122 c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
21123 /* LS or PS are considered as line terminator */
21124 if (c == CP_LS || c == CP_PS) {
21125 break;
21126 } else if (c == -1) {
21127 p++; /* skip invalid UTF-8 */
21128 }
21129 } else {
21130 p++;
21131 }
21132 }
21133 goto redo;
21134 } else {
21135 goto def_token;
21136 }
21137 break;
21138 case 'a' ... 'z':
21139 case 'A' ... 'Z':
21140 case '_':
21141 case '$':
21142 /* identifier : only pure ascii characters are accepted */
21143 p++;
21144 atom = json_parse_ident(s, &p, c);
21145 if (atom == JS_ATOM_NULL)
21146 goto fail;
21147 s->token.u.ident.atom = atom;
21148 s->token.u.ident.has_escape = FALSE;
21149 s->token.u.ident.is_reserved = FALSE;
21150 s->token.val = TOK_IDENT;
21151 break;
21152 case '+':
21153 if (!s->ext_json || !is_digit(p[1]))
21154 goto def_token;
21155 goto parse_number;
21156 case '0':
21157 if (is_digit(p[1]))
21158 goto def_token;
21159 goto parse_number;
21160 case '-':
21161 if (!is_digit(p[1]))
21162 goto def_token;
21163 goto parse_number;
21164 case '1' ... '9':
21165 /* number */
21166 parse_number:
21167 {
21168 JSValue ret;
21169 int flags, radix;
21170 if (!s->ext_json) {
21171 flags = 0;
21172 radix = 10;
21173 } else {
21174 flags = ATOD_ACCEPT_BIN_OCT;
21175 radix = 0;
21176 }
21177 ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix,
21178 flags);
21179 if (JS_IsException(ret))
21180 goto fail;
21181 s->token.val = TOK_NUMBER;
21182 s->token.u.num.val = ret;
21183 }
21184 break;
21185 default:
21186 if (c >= 128) {
21187 js_parse_error(s, "unexpected character");
21188 goto fail;
21189 }
21190 def_token:
21191 s->token.val = c;
21192 p++;
21193 break;
21194 }
21195 s->buf_ptr = p;
21196
21197 // dump_token(s, &s->token);
21198 return 0;
21199
21200 fail:
21201 s->token.val = TOK_ERROR;
21202 return -1;
21203}
21204
20801/* only used for ':' and '=>', 'let' or 'function' look-ahead. *pp is21205/* only used for ':' and '=>', 'let' or 'function' look-ahead. *pp is
20802 only set if TOK_IMPORT is returned */21206 only set if TOK_IMPORT is returned */
20803/* XXX: handle all unicode cases */21207/* XXX: handle all unicode cases */
@@ -20858,6 +21262,12 @@ static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator) · 54 unmodified lines
20858 }21262 }
20859 } else if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) {21263 } else if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) {
20860 return TOK_OF;21264 return TOK_OF;
21265 } else if (c == 'e' &&
21266 p[0] == 'x' && p[1] == 'p' && p[2] == 'o' &&
21267 p[3] == 'r' && p[4] == 't' &&
21268 !lre_js_is_ident_next(p[5])) {
21269 *pp = p + 5;
21270 return TOK_EXPORT;
20861 } else if (c == 'f' && p[0] == 'u' && p[1] == 'n' &&21271 } else if (c == 'f' && p[0] == 'u' && p[1] == 'n' &&
20862 p[2] == 'c' && p[3] == 't' && p[4] == 'i' &&21272 p[2] == 'c' && p[3] == 't' && p[4] == 'i' &&
20863 p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) {21273 p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) {
@@ -20881,16 +21291,21 @@ static int peek_token(JSParseState *s, BOOL no_line_terminator) · 17 unmodified lines
20881 (heuristic). 'input' must be a zero terminated.21291 (heuristic). 'input' must be a zero terminated.
20882 21292
20883 Heuristic: skip comments and expect 'import' keyword not followed21293 Heuristic: skip comments and expect 'import' keyword not followed
20884 by '(' or '.'21294 by '(' or '.' or export keyword.
20885*/21295*/
20886BOOL JS_DetectModule(const char *input, size_t input_len)21296BOOL JS_DetectModule(const char *input, size_t input_len)
20887{21297{
20888 const uint8_t *p = (const uint8_t *)input;21298 const uint8_t *p = (const uint8_t *)input;
20889 int tok;21299 int tok;
20890 if (simple_next_token(&p, FALSE) != TOK_IMPORT)21300 switch(simple_next_token(&p, FALSE)) {
21301 case TOK_IMPORT:
21302 tok = simple_next_token(&p, FALSE);
21303 return (tok != '.' && tok != '(');
21304 case TOK_EXPORT:
21305 return TRUE;
21306 default:
20891 return FALSE;21307 return FALSE;
20892 tok = simple_next_token(&p, FALSE);21308 }
20893 return (tok != '.' && tok != '(');
20894}21309}
20895 21310
20896static inline int get_prev_opcode(JSFunctionDef *fd) {21311static inline int get_prev_opcode(JSFunctionDef *fd) {
@@ -20974,20 +21389,10 @@ static int new_label_fd(JSFunctionDef *fd, int label) · 77 unmodified lines
20974 LabelSlot *ls;21389 LabelSlot *ls;
20975 21390
20976 if (label < 0) {21391 if (label < 0) {
20977 if (fd->label_count >= fd->label_size) {21392 if (js_resize_array(fd->ctx, (void *)&fd->label_slots,
20978 int new_size;21393 sizeof(fd->label_slots[0]),
20979 size_t slack;21394 &fd->label_size, fd->label_count + 1))
20980 LabelSlot *new_tab;21395 return -1;
20981
20982 /* XXX: potential arithmetic overflow */
20983 new_size = fd->label_size * 3 / 2 + 4;
20984 new_tab = js_realloc2(fd->ctx, fd->label_slots, new_size * sizeof(*new_tab), &slack);
20985 if (!new_tab)
20986 return -1;
20987 new_size += slack / sizeof(*new_tab);
20988 fd->label_slots = new_tab;
20989 fd->label_size = new_size;
20990 }
20991 label = fd->label_count++;21396 label = fd->label_count++;
20992 ls = &fd->label_slots[label];21397 ls = &fd->label_slots[label];
20993 ls->ref_count = 0;21398 ls->ref_count = 0;
@@ -21035,19 +21440,10 @@ static int emit_goto(JSParseState *s, int opcode, int label) · 41 unmodified lines
21035static int cpool_add(JSParseState *s, JSValue val)21440static int cpool_add(JSParseState *s, JSValue val)
21036{21441{
21037 JSFunctionDef *fd = s->cur_func;21442 JSFunctionDef *fd = s->cur_func;
21038 if (fd->cpool_count >= fd->cpool_size) {21443
21039 int new_size;21444 if (js_resize_array(s->ctx, (void *)&fd->cpool, sizeof(fd->cpool[0]),
21040 size_t slack;21445 &fd->cpool_size, fd->cpool_count + 1))
21041 JSValue *new_tab;21446 return -1;
21042 /* XXX: potential arithmetic overflow */
21043 new_size = max_int(fd->cpool_count + 1, fd->cpool_size * 3 / 2);
21044 new_tab = js_realloc2(s->ctx, fd->cpool, new_size * sizeof(JSValue), &slack);
21045 if (!new_tab)
21046 return -1;
21047 new_size += slack / sizeof(*new_tab);
21048 fd->cpool = new_tab;
21049 fd->cpool_size = new_size;
21050 }
21051 fd->cpool[fd->cpool_count++] = val;21447 fd->cpool[fd->cpool_count++] = val;
21052 return fd->cpool_count - 1;21448 return fd->cpool_count - 1;
21053}21449}
@@ -21246,18 +21642,9 @@ static int add_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name) · 192 unmodified lines
21246 JS_ThrowInternalError(ctx, "too many local variables");21642 JS_ThrowInternalError(ctx, "too many local variables");
21247 return -1;21643 return -1;
21248 }21644 }
21249 if ((fd->var_count + 1) > fd->var_size) {21645 if (js_resize_array(ctx, (void **)&fd->vars, sizeof(fd->vars[0]),
21250 int new_size;21646 &fd->var_size, fd->var_count + 1))
21251 size_t slack;21647 return -1;
21252 JSVarDef *new_buf;
21253 new_size = max_int(fd->var_count + 1, fd->var_size * 3 / 2);
21254 new_buf = js_realloc2(ctx, fd->vars, new_size * sizeof(*fd->vars), &slack);
21255 if (!new_buf)
21256 return -1;
21257 new_size += slack / sizeof(*new_buf);
21258 fd->vars = new_buf;
21259 fd->var_size = new_size;
21260 }
21261 vd = &fd->vars[fd->var_count++];21648 vd = &fd->vars[fd->var_count++];
21262 memset(vd, 0, sizeof(*vd));21649 memset(vd, 0, sizeof(*vd));
21263 vd->var_name = JS_DupAtom(ctx, name);21650 vd->var_name = JS_DupAtom(ctx, name);
@@ -21309,18 +21696,9 @@ static int add_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name) · 45 unmodified lines
21309 JS_ThrowInternalError(ctx, "too many arguments");21696 JS_ThrowInternalError(ctx, "too many arguments");
21310 return -1;21697 return -1;
21311 }21698 }
21312 if ((fd->arg_count + 1) > fd->arg_size) {21699 if (js_resize_array(ctx, (void **)&fd->args, sizeof(fd->args[0]),
21313 int new_size;21700 &fd->arg_size, fd->arg_count + 1))
21314 size_t slack;21701 return -1;
21315 JSVarDef *new_buf;
21316 new_size = max_int(fd->arg_count + 1, fd->arg_size * 3 / 2);
21317 new_buf = js_realloc2(ctx, fd->args, new_size * sizeof(*fd->args), &slack);
21318 if (!new_buf)
21319 return -1;
21320 new_size += slack / sizeof(*new_buf);
21321 fd->args = new_buf;
21322 fd->arg_size = new_size;
21323 }
21324 vd = &fd->args[fd->arg_count++];21702 vd = &fd->args[fd->arg_count++];
21325 memset(vd, 0, sizeof(*vd));21703 memset(vd, 0, sizeof(*vd));
21326 vd->var_name = JS_DupAtom(ctx, name);21704 vd->var_name = JS_DupAtom(ctx, name);
@@ -21335,19 +21713,10 @@ static JSHoistedDef *add_hoisted_def(JSContext *ctx, · 8 unmodified lines
21335{21713{
21336 JSHoistedDef *hf;21714 JSHoistedDef *hf;
21337 21715
21338 if (s->hoisted_def_count >= s->hoisted_def_size) {21716 if (js_resize_array(ctx, (void **)&s->hoisted_def,
21339 int new_size;21717 sizeof(s->hoisted_def[0]),
21340 size_t slack;21718 &s->hoisted_def_size, s->hoisted_def_count + 1))
21341 JSHoistedDef *new_tab;21719 return NULL;
21342 new_size = max_int(s->hoisted_def_count + 1,
21343 s->hoisted_def_size * 3 / 2);
21344 new_tab = js_realloc2(ctx, s->hoisted_def, new_size * sizeof(s->hoisted_def[0]), &slack);
21345 if (!new_tab)
21346 return NULL;
21347 new_size += slack / sizeof(*new_tab);
21348 s->hoisted_def = new_tab;
21349 s->hoisted_def_size = new_size;
21350 }
21351 hf = &s->hoisted_def[s->hoisted_def_count++];21720 hf = &s->hoisted_def[s->hoisted_def_count++];
21352 hf->cpool_idx = cpool_idx;21721 hf->cpool_idx = cpool_idx;
21353 hf->force_init = 0;21722 hf->force_init = 0;
@@ -21639,7 +22008,7 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) · 285 unmodified lines
21639 goto done;22008 goto done;
21640 if (next_token(s))22009 if (next_token(s))
21641 return -1;22010 return -1;
21642 if (js_parse_assign_expr(s, TRUE))22011 if (js_parse_expr(s))
21643 return -1;22012 return -1;
21644 depth++;22013 depth++;
21645 if (s->token.val != '}') {22014 if (s->token.val != '}') {
@@ -21647,7 +22016,8 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) · 1 unmodified line
21647 }22016 }
21648 /* XXX: should convert to string at this stage? */22017 /* XXX: should convert to string at this stage? */
21649 free_token(s, &s->token);22018 free_token(s, &s->token);
21650 /* Resume TOK_TEMPLATE parsing (s->token.line_num and s->token.ptr are OK) */22019 /* Resume TOK_TEMPLATE parsing (s->token.line_num and
22020 * s->token.ptr are OK) */
21651 s->got_lf = FALSE;22021 s->got_lf = FALSE;
21652 s->last_line_num = s->token.line_num;22022 s->last_line_num = s->token.line_num;
21653 if (js_parse_template_part(s, s->buf_ptr))22023 if (js_parse_template_part(s, s->buf_ptr))
@@ -21875,7 +22245,7 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ · 221 unmodified lines
21875 size_t level = 0;22245 size_t level = 0;
21876 JSParsePos pos;22246 JSParsePos pos;
21877 int last_tok, tok = TOK_EOF;22247 int last_tok, tok = TOK_EOF;
21878 int tok_len, bits = 0;22248 int c, tok_len, bits = 0;
21879 22249
21880 /* protect from underflow */22250 /* protect from underflow */
21881 state[level++] = 0;22251 state[level++] = 0;
@@ -21900,8 +22270,30 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ · 18 unmodified lines
21900 goto done;22270 goto done;
21901 break;22271 break;
21902 case '}':22272 case '}':
21903 if (state[--level] != '{')22273 c = state[--level];
22274 if (c == '`') {
22275 /* continue the parsing of the template */
22276 free_token(s, &s->token);
22277 /* Resume TOK_TEMPLATE parsing (s->token.line_num and
22278 * s->token.ptr are OK) */
22279 s->got_lf = FALSE;
22280 s->last_line_num = s->token.line_num;
22281 if (js_parse_template_part(s, s->buf_ptr))
22282 goto done;
22283 goto handle_template;
22284 } else if (c != '{') {
21904 goto done;22285 goto done;
22286 }
22287 break;
22288 case TOK_TEMPLATE:
22289 handle_template:
22290 if (s->token.u.str.sep != '`') {
22291 /* '${' inside the template : closing '}' and continue
22292 parsing the template */
22293 if (level >= sizeof(state))
22294 goto done;
22295 state[level++] = '`';
22296 }
21905 break;22297 break;
21906 case TOK_EOF:22298 case TOK_EOF:
21907 goto done;22299 goto done;
@@ -24005,7 +24397,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen · 2097 unmodified lines
24005 int scope;24397 int scope;
24006 name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);24398 name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);
24007 scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5);24399 scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5);
24008 if (name == JS_ATOM_eval && call_type == FUNC_CALL_NORMAL) {24400 if (name == JS_ATOM_eval && call_type == FUNC_CALL_NORMAL && !has_optional_chain) {
24009 /* direct 'eval' */24401 /* direct 'eval' */
24010 opcode = OP_eval;24402 opcode = OP_eval;
24011 } else {24403 } else {
@@ -26318,26 +26710,6 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m) · 2306 unmodified lines
26318 js_free(ctx, m);26710 js_free(ctx, m);
26319}26711}
26320 26712
26321static int js_resize_array(JSContext *ctx, void **parray, int elem_size,
26322 int *psize, int *pcount, int new_count)
26323{
26324 if (unlikely(new_count > *psize)) {
26325 int new_size;
26326 size_t slack;
26327 void *new_array;
26328 /* XXX: potential arithmetic overflow */
26329 new_size = max_int(new_count, *psize * 3 / 2);
26330 new_array = js_realloc2(ctx, *parray, new_size * elem_size, &slack);
26331 if (!new_array)
26332 return -1;
26333 new_size += slack / elem_size;
26334 *psize = new_size;
26335 *parray = new_array;
26336 }
26337 *pcount = new_count;
26338 return 0;
26339}
26340
26341static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,26713static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,
26342 JSAtom module_name)26714 JSAtom module_name)
26343{26715{
@@ -26353,11 +26725,10 @@ static int add_req_module_entry(JSContext *ctx, JSModuleDef *m, · 9 unmodified lines
26353 26725
26354 if (js_resize_array(ctx, (void **)&m->req_module_entries,26726 if (js_resize_array(ctx, (void **)&m->req_module_entries,
26355 sizeof(JSReqModuleEntry),26727 sizeof(JSReqModuleEntry),
26356 &m->req_module_entries_size, &m->req_module_entries_count,26728 &m->req_module_entries_size,
26357 m->req_module_entries_count + 1))26729 m->req_module_entries_count + 1))
26358 return -1;26730 return -1;
26359 i = m->req_module_entries_count - 1;26731 rme = &m->req_module_entries[m->req_module_entries_count++];
26360 rme = &m->req_module_entries[i];
26361 rme->module_name = JS_DupAtom(ctx, module_name);26732 rme->module_name = JS_DupAtom(ctx, module_name);
26362 rme->module = NULL;26733 rme->module = NULL;
26363 return i;26734 return i;
@@ -26389,18 +26760,17 @@ static JSExportEntry *add_export_entry2(JSContext *ctx, · 25 unmodified lines
26389 js_parse_error(s, "duplicate exported name '%s'",26760 js_parse_error(s, "duplicate exported name '%s'",
26390 JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name));26761 JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name));
26391 } else {26762 } else {
26392 JS_ThrowSyntaxError(ctx, "duplicate exported name '%s'",26763 JS_ThrowSyntaxErrorAtom(ctx, "duplicate exported name '%s'", export_name);
26393 JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name));
26394 }26764 }
26395 return NULL;26765 return NULL;
26396 }26766 }
26397 26767
26398 if (js_resize_array(ctx, (void **)&m->export_entries,26768 if (js_resize_array(ctx, (void **)&m->export_entries,
26399 sizeof(JSExportEntry),26769 sizeof(JSExportEntry),
26400 &m->export_entries_size, &m->export_entries_count,26770 &m->export_entries_size,
26401 m->export_entries_count + 1))26771 m->export_entries_count + 1))
26402 return NULL;26772 return NULL;
26403 me = &m->export_entries[m->export_entries_count - 1];26773 me = &m->export_entries[m->export_entries_count++];
26404 memset(me, 0, sizeof(*me));26774 memset(me, 0, sizeof(*me));
26405 me->local_name = JS_DupAtom(ctx, local_name);26775 me->local_name = JS_DupAtom(ctx, local_name);
26406 me->export_name = JS_DupAtom(ctx, export_name);26776 me->export_name = JS_DupAtom(ctx, export_name);
@@ -26423,10 +26793,10 @@ static int add_star_export_entry(JSContext *ctx, JSModuleDef *m, · 16 unmodified lines
26423 26793
26424 if (js_resize_array(ctx, (void **)&m->star_export_entries,26794 if (js_resize_array(ctx, (void **)&m->star_export_entries,
26425 sizeof(JSStarExportEntry),26795 sizeof(JSStarExportEntry),
26426 &m->star_export_entries_size, &m->star_export_entries_count,26796 &m->star_export_entries_size,
26427 m->star_export_entries_count + 1))26797 m->star_export_entries_count + 1))
26428 return -1;26798 return -1;
26429 se = &m->star_export_entries[m->star_export_entries_count - 1];26799 se = &m->star_export_entries[m->star_export_entries_count++];
26430 se->req_module_idx = req_module_idx;26800 se->req_module_idx = req_module_idx;
26431 return 0;26801 return 0;
26432}26802}
@@ -26652,10 +27022,9 @@ static int add_resolve_entry(JSContext *ctx, JSResolveState *s, · 219 unmodified lines
26652 27022
26653 if (js_resize_array(ctx, (void **)&s->array,27023 if (js_resize_array(ctx, (void **)&s->array,
26654 sizeof(JSResolveEntry),27024 sizeof(JSResolveEntry),
26655 &s->size, &s->count,27025 &s->size, s->count + 1))
26656 s->count + 1))
26657 return -1;27026 return -1;
26658 re = &s->array[s->count - 1];27027 re = &s->array[s->count++];
26659 re->module = m;27028 re->module = m;
26660 re->name = JS_DupAtom(ctx, name);27029 re->name = JS_DupAtom(ctx, name);
26661 return 0;27030 return 0;
@@ -26780,17 +27149,17 @@ static void js_resolve_export_throw_error(JSContext *ctx, · 118 unmodified lines
26780 break;27149 break;
26781 default:27150 default:
26782 case JS_RESOLVE_RES_NOT_FOUND:27151 case JS_RESOLVE_RES_NOT_FOUND:
26783 JS_ThrowSyntaxError(ctx, "export '%s' in module '%s' is ambiguous",27152 JS_ThrowSyntaxError(ctx, "Could not find export '%s' in module '%s'",
26784 JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),27153 JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),
26785 JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));27154 JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));
26786 break;27155 break;
26787 case JS_RESOLVE_RES_CIRCULAR:27156 case JS_RESOLVE_RES_CIRCULAR:
26788 JS_ThrowSyntaxError(ctx, "Could not find export '%s' in module '%s'",27157 JS_ThrowSyntaxError(ctx, "circular reference when looking for export '%s' in module '%s'",
26789 JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),27158 JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),
26790 JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));27159 JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));
26791 break;27160 break;
26792 case JS_RESOLVE_RES_AMBIGUOUS:27161 case JS_RESOLVE_RES_AMBIGUOUS:
26793 JS_ThrowSyntaxError(ctx, "circular reference when looking for export '%s' in module '%s'",27162 JS_ThrowSyntaxError(ctx, "export '%s' in module '%s' is ambiguous",
26794 JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),27163 JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),
26795 JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));27164 JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));
26796 break;27165 break;
@@ -26847,9 +27216,9 @@ static __exception int get_exported_names(JSContext *ctx, · 50 unmodified lines
26847 return 0;27216 return 0;
26848 }27217 }
26849 if (js_resize_array(ctx, (void **)&s->modules, sizeof(s->modules[0]),27218 if (js_resize_array(ctx, (void **)&s->modules, sizeof(s->modules[0]),
26850 &s->modules_size, &s->modules_count, s->modules_count + 1))27219 &s->modules_size, s->modules_count + 1))
26851 return -1;27220 return -1;
26852 s->modules[s->modules_count - 1] = m;27221 s->modules[s->modules_count++] = m;
26853 27222
26854 for(i = 0; i < m->export_entries_count; i++) {27223 for(i = 0; i < m->export_entries_count; i++) {
26855 JSExportEntry *me = &m->export_entries[i];27224 JSExportEntry *me = &m->export_entries[i];
@@ -26858,9 +27227,10 @@ static __exception int get_exported_names(JSContext *ctx, · 2 unmodified lines
26858 j = find_exported_name(s, me->export_name);27227 j = find_exported_name(s, me->export_name);
26859 if (j < 0) {27228 if (j < 0) {
26860 if (js_resize_array(ctx, (void **)&s->exported_names, sizeof(s->exported_names[0]),27229 if (js_resize_array(ctx, (void **)&s->exported_names, sizeof(s->exported_names[0]),
26861 &s->exported_names_size, &s->exported_names_count, s->exported_names_count + 1))27230 &s->exported_names_size,
27231 s->exported_names_count + 1))
26862 return -1;27232 return -1;
26863 en = &s->exported_names[s->exported_names_count - 1];27233 en = &s->exported_names[s->exported_names_count++];
26864 en->export_name = me->export_name;27234 en->export_name = me->export_name;
26865 /* avoid a second lookup for simple module exports */27235 /* avoid a second lookup for simple module exports */
26866 if (from_star || me->export_type != JS_EXPORT_TYPE_LOCAL)27236 if (from_star || me->export_type != JS_EXPORT_TYPE_LOCAL)
@@ -27096,7 +27466,7 @@ static JSVarRef *js_create_module_var(JSContext *ctx, BOOL is_lexical) · 229 unmodified lines
27096}27466}
27097 27467
27098/* Create the <eval> function associated with the module */27468/* Create the <eval> function associated with the module */
27099static int js_create_module_function(JSContext *ctx, JSModuleDef *m)27469static int js_create_module_bytecode_function(JSContext *ctx, JSModuleDef *m)
27100{27470{
27101 JSFunctionBytecode *b;27471 JSFunctionBytecode *b;
27102 int i;27472 int i;
@@ -27147,20 +27517,15 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m) · 44 unmodified lines
27147 return -1;27517 return -1;
27148}27518}
27149 27519
27150/* Prepare a module to be executed by resolving all the imported27520/* must be done before js_instantiate_module() because of cyclic references */
27151 variables. */27521static int js_create_module_function(JSContext *ctx, JSModuleDef *m)
27152static int js_instantiate_module(JSContext *ctx, JSModuleDef *m)
27153{27522{
27154 int i;
27155 JSImportEntry *mi;
27156 JSModuleDef *m1;
27157 JSVarRef **var_refs, *var_ref;
27158 JSObject *p;
27159 BOOL is_c_module;27523 BOOL is_c_module;
27160 27524 int i;
27161 if (m->instantiated)27525 JSVarRef *var_ref;
27526
27527 if (m->func_created)
27162 return 0;27528 return 0;
27163 m->instantiated = TRUE;
27164 27529
27165 is_c_module = (m->init_func != NULL);27530 is_c_module = (m->init_func != NULL);
27166 27531
@@ -27171,14 +27536,49 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) · 4 unmodified lines
27171 if (me->export_type == JS_EXPORT_TYPE_LOCAL) {27536 if (me->export_type == JS_EXPORT_TYPE_LOCAL) {
27172 var_ref = js_create_module_var(ctx, FALSE);27537 var_ref = js_create_module_var(ctx, FALSE);
27173 if (!var_ref)27538 if (!var_ref)
27174 goto fail;27539 return -1;
27175 me->u.local.var_ref = var_ref;27540 me->u.local.var_ref = var_ref;
27176 }27541 }
27177 }27542 }
27178 } else {27543 } else {
27179 if (js_create_module_function(ctx, m) < 0)27544 if (js_create_module_bytecode_function(ctx, m))
27180 goto fail;27545 return -1;
27181 }27546 }
27547 m->func_created = TRUE;
27548
27549 /* do it on the dependencies */
27550
27551 for(i = 0; i < m->req_module_entries_count; i++) {
27552 JSReqModuleEntry *rme = &m->req_module_entries[i];
27553 if (js_create_module_function(ctx, rme->module) < 0)
27554 return -1;
27555 }
27556
27557 return 0;
27558}
27559
27560
27561/* Prepare a module to be executed by resolving all the imported
27562 variables. */
27563static int js_instantiate_module(JSContext *ctx, JSModuleDef *m)
27564{
27565 int i;
27566 JSImportEntry *mi;
27567 JSModuleDef *m1;
27568 JSVarRef **var_refs, *var_ref;
27569 JSObject *p;
27570 BOOL is_c_module;
27571
27572 if (m->instantiated)
27573 return 0;
27574 m->instantiated = TRUE;
27575
27576#ifdef DUMP_MODULE_RESOLVE
27577 {
27578 char buf1[ATOM_GET_STR_BUF_SIZE];
27579 printf("start instantiating module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
27580 }
27581#endif
27182 27582
27183 for(i = 0; i < m->req_module_entries_count; i++) {27583 for(i = 0; i < m->req_module_entries_count; i++) {
27184 JSReqModuleEntry *rme = &m->req_module_entries[i];27584 JSReqModuleEntry *rme = &m->req_module_entries[i];
@@ -27221,6 +27621,8 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) · 36 unmodified lines
27221 }27621 }
27222#endif27622#endif
27223 27623
27624 is_c_module = (m->init_func != NULL);
27625
27224 if (!is_c_module) {27626 if (!is_c_module) {
27225 p = JS_VALUE_GET_OBJ(m->func_obj);27627 p = JS_VALUE_GET_OBJ(m->func_obj);
27226 var_refs = p->u.func.var_refs;27628 var_refs = p->u.func.var_refs;
@@ -27740,10 +28142,10 @@ static int add_import(JSParseState *s, JSModuleDef *m, · 513 unmodified lines
27740 return -1;28142 return -1;
27741 if (js_resize_array(ctx, (void **)&m->import_entries,28143 if (js_resize_array(ctx, (void **)&m->import_entries,
27742 sizeof(JSImportEntry),28144 sizeof(JSImportEntry),
27743 &m->import_entries_size, &m->import_entries_count,28145 &m->import_entries_size,
27744 m->import_entries_count + 1))28146 m->import_entries_count + 1))
27745 return -1;28147 return -1;
27746 mi = &m->import_entries[m->import_entries_count - 1];28148 mi = &m->import_entries[m->import_entries_count++];
27747 mi->import_name = JS_DupAtom(ctx, import_name);28149 mi->import_name = JS_DupAtom(ctx, import_name);
27748 mi->var_idx = var_idx;28150 mi->var_idx = var_idx;
27749 return 0;28151 return 0;
@@ -28474,20 +28876,10 @@ static int add_closure_var(JSContext *ctx, JSFunctionDef *s, · 724 unmodified lines
28474 return -1;28876 return -1;
28475 }28877 }
28476 28878
28477 if (s->closure_var_count >= s->closure_var_size) {28879 if (js_resize_array(ctx, (void **)&s->closure_var,
28478 JSClosureVar *new_tab;28880 sizeof(s->closure_var[0]),
28479 int new_size;28881 &s->closure_var_size, s->closure_var_count + 1))
28480 size_t slack;28882 return -1;
28481 new_size = max_int(s->closure_var_count + 1,
28482 s->closure_var_size * 3 / 2);
28483 new_tab = js_realloc2(ctx, s->closure_var,
28484 new_size * sizeof(JSClosureVar), &slack);
28485 if (!new_tab)
28486 return -1;
28487 new_size += slack / sizeof(*new_tab);
28488 s->closure_var = new_tab;
28489 s->closure_var_size = new_size;
28490 }
28491 cv = &s->closure_var[s->closure_var_count++];28883 cv = &s->closure_var[s->closure_var_count++];
28492 cv->is_local = is_local;28884 cv->is_local = is_local;
28493 cv->is_arg = is_arg;28885 cv->is_arg = is_arg;
@@ -29243,8 +29635,6 @@ static int resolve_scope_private_field1(JSContext *ctx, · 749 unmodified lines
29243 }29635 }
29244 scope_level = fd->parent_scope_level;29636 scope_level = fd->parent_scope_level;
29245 if (!fd->parent) {29637 if (!fd->parent) {
29246 char buf[ATOM_GET_STR_BUF_SIZE];
29247
29248 if (fd->is_eval) {29638 if (fd->is_eval) {
29249 /* closure of the eval function (top level) */29639 /* closure of the eval function (top level) */
29250 for (idx = 0; idx < fd->closure_var_count; idx++) {29640 for (idx = 0; idx < fd->closure_var_count; idx++) {
@@ -29267,8 +29657,8 @@ static int resolve_scope_private_field1(JSContext *ctx, · 16 unmodified lines
29267 }29657 }
29268 }29658 }
29269 /* XXX: no line number info */29659 /* XXX: no line number info */
29270 JS_ThrowSyntaxError(ctx, "undefined private field %s",29660 JS_ThrowSyntaxErrorAtom(ctx, "undefined private field '%s'",
29271 JS_AtomGetStr(ctx, buf, sizeof(buf), var_name));29661 var_name);
29272 return -1;29662 return -1;
29273 } else {29663 } else {
29274 fd = fd->parent;29664 fd = fd->parent;
@@ -31535,9 +31925,8 @@ static int add_module_variables(JSContext *ctx, JSFunctionDef *fd) · 2260 unmodified lines
31535 if (me->export_type == JS_EXPORT_TYPE_LOCAL) {31925 if (me->export_type == JS_EXPORT_TYPE_LOCAL) {
31536 idx = find_closure_var(ctx, fd, me->local_name);31926 idx = find_closure_var(ctx, fd, me->local_name);
31537 if (idx < 0) {31927 if (idx < 0) {
31538 char buf1[ATOM_GET_STR_BUF_SIZE];31928 JS_ThrowSyntaxErrorAtom(ctx, "exported variable '%s' does not exist",
31539 JS_ThrowSyntaxError(ctx, "exported variable '%s' does not exist",31929 me->local_name);
31540 JS_AtomGetStr(ctx, buf1, sizeof(buf1), me->local_name));
31541 return -1;31930 return -1;
31542 }31931 }
31543 me->u.local.var_idx = idx;31932 me->u.local.var_idx = idx;
@@ -32559,6 +32948,8 @@ static JSValue JS_EvalFunctionInternal(JSContext *ctx, JSValue fun_obj, · 1015 unmodified lines
32559 m = JS_VALUE_GET_PTR(fun_obj);32948 m = JS_VALUE_GET_PTR(fun_obj);
32560 /* the module refcount should be >= 2 */32949 /* the module refcount should be >= 2 */
32561 JS_FreeValue(ctx, fun_obj);32950 JS_FreeValue(ctx, fun_obj);
32951 if (js_create_module_function(ctx, m) < 0)
32952 goto fail;
32562 if (js_instantiate_module(ctx, m) < 0)32953 if (js_instantiate_module(ctx, m) < 0)
32563 goto fail;32954 goto fail;
32564 ret_val = js_evaluate_module(ctx, m);32955 ret_val = js_evaluate_module(ctx, m);
@@ -32769,6 +33160,110 @@ int JS_ResolveModule(JSContext *ctx, JSValueConst obj) · 204 unmodified lines
32769 return 0;33160 return 0;
32770}33161}
32771 33162
33163/*******************************************************************/
33164/* object list */
33165
33166typedef struct {
33167 JSObject *obj;
33168 uint32_t hash_next; /* -1 if no next entry */
33169} JSObjectListEntry;
33170
33171/* XXX: reuse it to optimize weak references */
33172typedef struct {
33173 JSObjectListEntry *object_tab;
33174 int object_count;
33175 int object_size;
33176 uint32_t *hash_table;
33177 uint32_t hash_size;
33178} JSObjectList;
33179
33180static void js_object_list_init(JSObjectList *s)
33181{
33182 memset(s, 0, sizeof(*s));
33183}
33184
33185static uint32_t js_object_list_get_hash(JSObject *p, uint32_t hash_size)
33186{
33187 return ((uintptr_t)p * 3163) & (hash_size - 1);
33188}
33189
33190static int js_object_list_resize_hash(JSContext *ctx, JSObjectList *s,
33191 uint32_t new_hash_size)
33192{
33193 JSObjectListEntry *e;
33194 uint32_t i, h, *new_hash_table;
33195
33196 new_hash_table = js_malloc(ctx, sizeof(new_hash_table[0]) * new_hash_size);
33197 if (!new_hash_table)
33198 return -1;
33199 js_free(ctx, s->hash_table);
33200 s->hash_table = new_hash_table;
33201 s->hash_size = new_hash_size;
33202
33203 for(i = 0; i < s->hash_size; i++) {
33204 s->hash_table[i] = -1;
33205 }
33206 for(i = 0; i < s->object_count; i++) {
33207 e = &s->object_tab[i];
33208 h = js_object_list_get_hash(e->obj, s->hash_size);
33209 e->hash_next = s->hash_table[h];
33210 s->hash_table[h] = i;
33211 }
33212 return 0;
33213}
33214
33215/* the reference count of 'obj' is not modified. Return 0 if OK, -1 if
33216 memory error */
33217static int js_object_list_add(JSContext *ctx, JSObjectList *s, JSObject *obj)
33218{
33219 JSObjectListEntry *e;
33220 uint32_t h, new_hash_size;
33221
33222 if (js_resize_array(ctx, (void *)&s->object_tab,
33223 sizeof(s->object_tab[0]),
33224 &s->object_size, s->object_count + 1))
33225 return -1;
33226 if (unlikely((s->object_count + 1) >= s->hash_size)) {
33227 new_hash_size = max_uint32(s->hash_size, 4);
33228 while (new_hash_size <= s->object_count)
33229 new_hash_size *= 2;
33230 if (js_object_list_resize_hash(ctx, s, new_hash_size))
33231 return -1;
33232 }
33233 e = &s->object_tab[s->object_count++];
33234 h = js_object_list_get_hash(obj, s->hash_size);
33235 e->obj = obj;
33236 e->hash_next = s->hash_table[h];
33237 s->hash_table[h] = s->object_count - 1;
33238 return 0;
33239}
33240
33241/* return -1 if not present or the object index */
33242static int js_object_list_find(JSContext *ctx, JSObjectList *s, JSObject *obj)
33243{
33244 JSObjectListEntry *e;
33245 uint32_t h, p;
33246
33247 /* must test empty size because there is no hash table */
33248 if (s->object_count == 0)
33249 return -1;
33250 h = js_object_list_get_hash(obj, s->hash_size);
33251 p = s->hash_table[h];
33252 while (p != -1) {
33253 e = &s->object_tab[p];
33254 if (e->obj == obj)
33255 return p;
33256 p = e->hash_next;
33257 }
33258 return -1;
33259}
33260
33261static void js_object_list_end(JSContext *ctx, JSObjectList *s)
33262{
33263 js_free(ctx, s->object_tab);
33264 js_free(ctx, s->hash_table);
33265}
33266
32772/*******************************************************************/33267/*******************************************************************/
32773/* binary object writer & reader */33268/* binary object writer & reader */
32774 33269
@@ -32788,6 +33283,12 @@ typedef enum BCTagEnum { · 13 unmodified lines
32788 BC_TAG_TEMPLATE_OBJECT,33283 BC_TAG_TEMPLATE_OBJECT,
32789 BC_TAG_FUNCTION_BYTECODE,33284 BC_TAG_FUNCTION_BYTECODE,
32790 BC_TAG_MODULE,33285 BC_TAG_MODULE,
33286 BC_TAG_TYPED_ARRAY,
33287 BC_TAG_ARRAY_BUFFER,
33288 BC_TAG_SHARED_ARRAY_BUFFER,
33289 BC_TAG_DATE,
33290 BC_TAG_OBJECT_VALUE,
33291 BC_TAG_OBJECT_REFERENCE,
32791} BCTagEnum;33292} BCTagEnum;
32792 33293
32793#ifdef CONFIG_BIGNUM33294#ifdef CONFIG_BIGNUM
@@ -32805,14 +33306,21 @@ typedef enum BCTagEnum { · 11 unmodified lines
32805typedef struct BCWriterState {33306typedef struct BCWriterState {
32806 JSContext *ctx;33307 JSContext *ctx;
32807 DynBuf dbuf;33308 DynBuf dbuf;
32808 BOOL byte_swap;33309 BOOL byte_swap : 8;
32809 BOOL allow_bytecode;33310 BOOL allow_bytecode : 8;
33311 BOOL allow_sab : 8;
33312 BOOL allow_reference : 8;
32810 uint32_t first_atom;33313 uint32_t first_atom;
32811 uint32_t *atom_to_idx;33314 uint32_t *atom_to_idx;
32812 int atom_to_idx_size;33315 int atom_to_idx_size;
32813 JSAtom *idx_to_atom;33316 JSAtom *idx_to_atom;
32814 int idx_to_atom_count;33317 int idx_to_atom_count;
32815 int idx_to_atom_size;33318 int idx_to_atom_size;
33319 uint8_t **sab_tab;
33320 int sab_tab_len;
33321 int sab_tab_size;
33322 /* list of referenced objects (used if allow_reference = TRUE) */
33323 JSObjectList object_list;
32816} BCWriterState;33324} BCWriterState;
32817 33325
32818#ifdef DUMP_READ_OBJECT33326#ifdef DUMP_READ_OBJECT
@@ -32833,6 +33341,12 @@ static const char * const bc_tag_str[] = { · 14 unmodified lines
32833 "template",33341 "template",
32834 "function",33342 "function",
32835 "module",33343 "module",
33344 "TypedArray",
33345 "ArrayBuffer",
33346 "SharedArrayBuffer",
33347 "Date",
33348 "ObjectValue",
33349 "ObjectReference",
32836};33350};
32837#endif33351#endif
32838 33352
@@ -32892,36 +33406,20 @@ static int bc_atom_to_idx(BCWriterState *s, uint32_t *pres, JSAtom atom) · 53 unmodified lines
32892 return 0;33406 return 0;
32893 }33407 }
32894 if (atom >= s->atom_to_idx_size) {33408 if (atom >= s->atom_to_idx_size) {
32895 size_t new_size, i, slack;33409 int old_size, i;
32896 uint32_t *new_tab;33410 old_size = s->atom_to_idx_size;
32897 /* XXX: potential arithmetic overflow */33411 if (js_resize_array(s->ctx, (void **)&s->atom_to_idx,
32898 new_size = s->atom_to_idx_size * 3 / 2;33412 sizeof(s->atom_to_idx[0]), &s->atom_to_idx_size,
32899 if ((atom + 1) > new_size)33413 atom + 1))
32900 new_size = atom + 1;33414 return -1;
32901 new_tab = js_realloc2(s->ctx, s->atom_to_idx,33415 /* XXX: could add a specific js_resize_array() function to do it */
32902 new_size * sizeof(s->atom_to_idx[0]), &slack);33416 for(i = old_size; i < s->atom_to_idx_size; i++)
32903 if (!new_tab)33417 s->atom_to_idx[i] = 0;
32904 goto fail;
32905 new_size += slack / sizeof(*new_tab);
32906 for(i = s->atom_to_idx_size; i < new_size; i++)
32907 new_tab[i] = 0;
32908 s->atom_to_idx = new_tab;
32909 s->atom_to_idx_size = new_size;
32910 }
32911 if ((s->idx_to_atom_count + 1) > s->idx_to_atom_size) {
32912 size_t new_size, slack;
32913 JSAtom *new_tab;
32914 new_size = s->idx_to_atom_size * 3 / 2;
32915 if ((s->idx_to_atom_count + 1) > new_size)
32916 new_size = s->idx_to_atom_count + 1;
32917 new_tab = js_realloc2(s->ctx, s->idx_to_atom,
32918 new_size * sizeof(s->idx_to_atom[0]), &slack);
32919 if (!new_tab)
32920 goto fail;
32921 new_size += slack / sizeof(*new_tab);
32922 s->idx_to_atom = new_tab;
32923 s->idx_to_atom_size = new_size;
32924 }33418 }
33419 if (js_resize_array(s->ctx, (void **)&s->idx_to_atom,
33420 sizeof(s->idx_to_atom[0]),
33421 &s->idx_to_atom_size, s->idx_to_atom_count + 1))
33422 goto fail;
32925 33423
32926 v = s->idx_to_atom_count++;33424 v = s->idx_to_atom_count++;
32927 s->idx_to_atom[v] = atom + s->first_atom;33425 s->idx_to_atom[v] = atom + s->first_atom;
@@ -33204,10 +33702,276 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj) · 276 unmodified lines
33204}33702}
33205#endif /* CONFIG_BIGNUM */33703#endif /* CONFIG_BIGNUM */
33206 33704
33705static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj);
33706
33707static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
33708{
33709 JSFunctionBytecode *b = JS_VALUE_GET_PTR(obj);
33710 uint32_t flags;
33711 int idx, i;
33712
33713 bc_put_u8(s, BC_TAG_FUNCTION_BYTECODE);
33714 flags = idx = 0;
33715 bc_set_flags(&flags, &idx, b->has_prototype, 1);
33716 bc_set_flags(&flags, &idx, b->has_simple_parameter_list, 1);
33717 bc_set_flags(&flags, &idx, b->is_derived_class_constructor, 1);
33718 bc_set_flags(&flags, &idx, b->need_home_object, 1);
33719 bc_set_flags(&flags, &idx, b->func_kind, 2);
33720 bc_set_flags(&flags, &idx, b->new_target_allowed, 1);
33721 bc_set_flags(&flags, &idx, b->super_call_allowed, 1);
33722 bc_set_flags(&flags, &idx, b->super_allowed, 1);
33723 bc_set_flags(&flags, &idx, b->arguments_allowed, 1);
33724 bc_set_flags(&flags, &idx, b->has_debug, 1);
33725 bc_set_flags(&flags, &idx, b->backtrace_barrier, 1);
33726 assert(idx <= 16);
33727 bc_put_u16(s, flags);
33728 bc_put_u8(s, b->js_mode);
33729 bc_put_atom(s, b->func_name);
33730
33731 bc_put_leb128(s, b->arg_count);
33732 bc_put_leb128(s, b->var_count);
33733 bc_put_leb128(s, b->defined_arg_count);
33734 bc_put_leb128(s, b->stack_size);
33735 bc_put_leb128(s, b->closure_var_count);
33736 bc_put_leb128(s, b->cpool_count);
33737 bc_put_leb128(s, b->byte_code_len);
33738 if (b->vardefs) {
33739 bc_put_leb128(s, b->arg_count + b->var_count);
33740 for(i = 0; i < b->arg_count + b->var_count; i++) {
33741 JSVarDef *vd = &b->vardefs[i];
33742 bc_put_atom(s, vd->var_name);
33743 bc_put_leb128(s, vd->scope_level);
33744 bc_put_leb128(s, vd->scope_next + 1);
33745 flags = idx = 0;
33746 bc_set_flags(&flags, &idx, vd->var_kind, 4);
33747 bc_set_flags(&flags, &idx, vd->is_func_var, 1);
33748 bc_set_flags(&flags, &idx, vd->is_const, 1);
33749 bc_set_flags(&flags, &idx, vd->is_lexical, 1);
33750 bc_set_flags(&flags, &idx, vd->is_captured, 1);
33751 assert(idx <= 8);
33752 bc_put_u8(s, flags);
33753 }
33754 } else {
33755 bc_put_leb128(s, 0);
33756 }
33757
33758 for(i = 0; i < b->closure_var_count; i++) {
33759 JSClosureVar *cv = &b->closure_var[i];
33760 bc_put_atom(s, cv->var_name);
33761 bc_put_leb128(s, cv->var_idx);
33762 flags = idx = 0;
33763 bc_set_flags(&flags, &idx, cv->is_local, 1);
33764 bc_set_flags(&flags, &idx, cv->is_arg, 1);
33765 bc_set_flags(&flags, &idx, cv->is_const, 1);
33766 bc_set_flags(&flags, &idx, cv->is_lexical, 1);
33767 bc_set_flags(&flags, &idx, cv->var_kind, 4);
33768 assert(idx <= 8);
33769 bc_put_u8(s, flags);
33770 }
33771
33772 if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len))
33773 goto fail;
33774
33775 if (b->has_debug) {
33776 bc_put_atom(s, b->debug.filename);
33777 bc_put_leb128(s, b->debug.line_num);
33778 bc_put_leb128(s, b->debug.pc2line_len);
33779 dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len);
33780 }
33781
33782 for(i = 0; i < b->cpool_count; i++) {
33783 if (JS_WriteObjectRec(s, b->cpool[i]))
33784 goto fail;
33785 }
33786 return 0;
33787 fail:
33788 return -1;
33789}
33790
33791static int JS_WriteModule(BCWriterState *s, JSValueConst obj)
33792{
33793 JSModuleDef *m = JS_VALUE_GET_PTR(obj);
33794 int i;
33795
33796 bc_put_u8(s, BC_TAG_MODULE);
33797 bc_put_atom(s, m->module_name);
33798
33799 bc_put_leb128(s, m->req_module_entries_count);
33800 for(i = 0; i < m->req_module_entries_count; i++) {
33801 JSReqModuleEntry *rme = &m->req_module_entries[i];
33802 bc_put_atom(s, rme->module_name);
33803 }
33804
33805 bc_put_leb128(s, m->export_entries_count);
33806 for(i = 0; i < m->export_entries_count; i++) {
33807 JSExportEntry *me = &m->export_entries[i];
33808 bc_put_u8(s, me->export_type);
33809 if (me->export_type == JS_EXPORT_TYPE_LOCAL) {
33810 bc_put_leb128(s, me->u.local.var_idx);
33811 } else {
33812 bc_put_leb128(s, me->u.req_module_idx);
33813 bc_put_atom(s, me->local_name);
33814 }
33815 bc_put_atom(s, me->export_name);
33816 }
33817
33818 bc_put_leb128(s, m->star_export_entries_count);
33819 for(i = 0; i < m->star_export_entries_count; i++) {
33820 JSStarExportEntry *se = &m->star_export_entries[i];
33821 bc_put_leb128(s, se->req_module_idx);
33822 }
33823
33824 bc_put_leb128(s, m->import_entries_count);
33825 for(i = 0; i < m->import_entries_count; i++) {
33826 JSImportEntry *mi = &m->import_entries[i];
33827 bc_put_leb128(s, mi->var_idx);
33828 bc_put_atom(s, mi->import_name);
33829 bc_put_leb128(s, mi->req_module_idx);
33830 }
33831
33832 if (JS_WriteObjectRec(s, m->func_obj))
33833 goto fail;
33834 return 0;
33835 fail:
33836 return -1;
33837}
33838
33839static int JS_WriteArray(BCWriterState *s, JSValueConst obj)
33840{
33841 JSObject *p = JS_VALUE_GET_OBJ(obj);
33842 uint32_t i, len;
33843 JSValue val;
33844 int ret;
33845 BOOL is_template;
33846
33847 if (s->allow_bytecode && !p->extensible) {
33848 /* not extensible array: we consider it is a
33849 template when we are saving bytecode */
33850 bc_put_u8(s, BC_TAG_TEMPLATE_OBJECT);
33851 is_template = TRUE;
33852 } else {
33853 bc_put_u8(s, BC_TAG_ARRAY);
33854 is_template = FALSE;
33855 }
33856 if (js_get_length32(s->ctx, &len, obj))
33857 goto fail1;
33858 bc_put_leb128(s, len);
33859 for(i = 0; i < len; i++) {
33860 val = JS_GetPropertyUint32(s->ctx, obj, i);
33861 if (JS_IsException(val))
33862 goto fail1;
33863 ret = JS_WriteObjectRec(s, val);
33864 JS_FreeValue(s->ctx, val);
33865 if (ret)
33866 goto fail1;
33867 }
33868 if (is_template) {
33869 val = JS_GetProperty(s->ctx, obj, JS_ATOM_raw);
33870 if (JS_IsException(val))
33871 goto fail1;
33872 ret = JS_WriteObjectRec(s, val);
33873 JS_FreeValue(s->ctx, val);
33874 if (ret)
33875 goto fail1;
33876 }
33877 return 0;
33878 fail1:
33879 return -1;
33880}
33881
33882static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj)
33883{
33884 JSObject *p = JS_VALUE_GET_OBJ(obj);
33885 uint32_t i, prop_count;
33886 JSShape *sh;
33887 JSShapeProperty *pr;
33888 int pass;
33889 JSAtom atom;
33890
33891 bc_put_u8(s, BC_TAG_OBJECT);
33892 prop_count = 0;
33893 sh = p->shape;
33894 for(pass = 0; pass < 2; pass++) {
33895 if (pass == 1)
33896 bc_put_leb128(s, prop_count);
33897 for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) {
33898 atom = pr->atom;
33899 if (atom != JS_ATOM_NULL &&
33900 JS_AtomIsString(s->ctx, atom) &&
33901 (pr->flags & JS_PROP_ENUMERABLE)) {
33902 if (pr->flags & JS_PROP_TMASK) {
33903 JS_ThrowTypeError(s->ctx, "only value properties are supported");
33904 goto fail;
33905 }
33906 if (pass == 0) {
33907 prop_count++;
33908 } else {
33909 bc_put_atom(s, atom);
33910 if (JS_WriteObjectRec(s, p->prop[i].u.value))
33911 goto fail;
33912 }
33913 }
33914 }
33915 }
33916 return 0;
33917 fail:
33918 return -1;
33919}
33920
33921static int JS_WriteTypedArray(BCWriterState *s, JSValueConst obj)
33922{
33923 JSObject *p = JS_VALUE_GET_OBJ(obj);
33924 JSTypedArray *ta = p->u.typed_array;
33925
33926 bc_put_u8(s, BC_TAG_TYPED_ARRAY);
33927 bc_put_u8(s, p->class_id - JS_CLASS_UINT8C_ARRAY);
33928 bc_put_leb128(s, p->u.array.count);
33929 bc_put_leb128(s, ta->offset);
33930 if (JS_WriteObjectRec(s, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)))
33931 return -1;
33932 return 0;
33933}
33934
33935static int JS_WriteArrayBuffer(BCWriterState *s, JSValueConst obj)
33936{
33937 JSObject *p = JS_VALUE_GET_OBJ(obj);
33938 JSArrayBuffer *abuf = p->u.array_buffer;
33939 if (abuf->detached) {
33940 JS_ThrowTypeErrorDetachedArrayBuffer(s->ctx);
33941 return -1;
33942 }
33943 bc_put_u8(s, BC_TAG_ARRAY_BUFFER);
33944 bc_put_leb128(s, abuf->byte_length);
33945 dbuf_put(&s->dbuf, abuf->data, abuf->byte_length);
33946 return 0;
33947}
33948
33949static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValueConst obj)
33950{
33951 JSObject *p = JS_VALUE_GET_OBJ(obj);
33952 JSArrayBuffer *abuf = p->u.array_buffer;
33953 assert(!abuf->detached); /* SharedArrayBuffer are never detached */
33954 bc_put_u8(s, BC_TAG_SHARED_ARRAY_BUFFER);
33955 bc_put_leb128(s, abuf->byte_length);
33956 bc_put_u64(s, (uintptr_t)abuf->data);
33957 if (js_resize_array(s->ctx, (void **)&s->sab_tab, sizeof(s->sab_tab[0]),
33958 &s->sab_tab_size, s->sab_tab_len + 1))
33959 return -1;
33960 /* keep the SAB pointer so that the user can clone it or free it */
33961 s->sab_tab[s->sab_tab_len++] = abuf->data;
33962 return 0;
33963}
33964
33207static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)33965static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)
33208{33966{
33209 uint32_t tag = JS_VALUE_GET_NORM_TAG(obj);33967 uint32_t tag;
33968
33969 if (js_check_stack_overflow(s->ctx->rt, 0)) {
33970 JS_ThrowStackOverflow(s->ctx);
33971 return -1;
33972 }
33210 33973
33974 tag = JS_VALUE_GET_NORM_TAG(obj);
33211 switch(tag) {33975 switch(tag) {
33212 case JS_TAG_NULL:33976 case JS_TAG_NULL:
33213 bc_put_u8(s, BC_TAG_NULL);33977 bc_put_u8(s, BC_TAG_NULL);
@@ -33238,218 +34002,82 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) · 24 unmodified lines
33238 }34002 }
33239 break;34003 break;
33240 case JS_TAG_FUNCTION_BYTECODE:34004 case JS_TAG_FUNCTION_BYTECODE:
33241 {34005 if (!s->allow_bytecode)
33242 JSFunctionBytecode *b = JS_VALUE_GET_PTR(obj);34006 goto invalid_tag;
33243 uint32_t flags;34007 if (JS_WriteFunctionTag(s, obj))
33244 int idx, i;34008 goto fail;
33245
33246 if (!s->allow_bytecode)
33247 goto invalid_tag;
33248 bc_put_u8(s, BC_TAG_FUNCTION_BYTECODE);
33249 flags = idx = 0;
33250 bc_set_flags(&flags, &idx, b->has_prototype, 1);
33251 bc_set_flags(&flags, &idx, b->has_simple_parameter_list, 1);
33252 bc_set_flags(&flags, &idx, b->is_derived_class_constructor, 1);
33253 bc_set_flags(&flags, &idx, b->need_home_object, 1);
33254 bc_set_flags(&flags, &idx, b->func_kind, 2);
33255 bc_set_flags(&flags, &idx, b->new_target_allowed, 1);
33256 bc_set_flags(&flags, &idx, b->super_call_allowed, 1);
33257 bc_set_flags(&flags, &idx, b->super_allowed, 1);
33258 bc_set_flags(&flags, &idx, b->arguments_allowed, 1);
33259 bc_set_flags(&flags, &idx, b->has_debug, 1);
33260 bc_set_flags(&flags, &idx, b->backtrace_barrier, 1);
33261 assert(idx <= 16);
33262 bc_put_u16(s, flags);
33263 bc_put_u8(s, b->js_mode);
33264 bc_put_atom(s, b->func_name);
33265
33266 bc_put_leb128(s, b->arg_count);
33267 bc_put_leb128(s, b->var_count);
33268 bc_put_leb128(s, b->defined_arg_count);
33269 bc_put_leb128(s, b->stack_size);
33270 bc_put_leb128(s, b->closure_var_count);
33271 bc_put_leb128(s, b->cpool_count);
33272 bc_put_leb128(s, b->byte_code_len);
33273 if (b->vardefs) {
33274 bc_put_leb128(s, b->arg_count + b->var_count);
33275 for(i = 0; i < b->arg_count + b->var_count; i++) {
33276 JSVarDef *vd = &b->vardefs[i];
33277 bc_put_atom(s, vd->var_name);
33278 bc_put_leb128(s, vd->scope_level);
33279 bc_put_leb128(s, vd->scope_next + 1);
33280 flags = idx = 0;
33281 bc_set_flags(&flags, &idx, vd->var_kind, 4);
33282 bc_set_flags(&flags, &idx, vd->is_func_var, 1);
33283 bc_set_flags(&flags, &idx, vd->is_const, 1);
33284 bc_set_flags(&flags, &idx, vd->is_lexical, 1);
33285 bc_set_flags(&flags, &idx, vd->is_captured, 1);
33286 assert(idx <= 8);
33287 bc_put_u8(s, flags);
33288 }
33289 } else {
33290 bc_put_leb128(s, 0);
33291 }
33292
33293 for(i = 0; i < b->closure_var_count; i++) {
33294 JSClosureVar *cv = &b->closure_var[i];
33295 bc_put_atom(s, cv->var_name);
33296 bc_put_leb128(s, cv->var_idx);
33297 flags = idx = 0;
33298 bc_set_flags(&flags, &idx, cv->is_local, 1);
33299 bc_set_flags(&flags, &idx, cv->is_arg, 1);
33300 bc_set_flags(&flags, &idx, cv->is_const, 1);
33301 bc_set_flags(&flags, &idx, cv->is_lexical, 1);
33302 bc_set_flags(&flags, &idx, cv->var_kind, 4);
33303 assert(idx <= 8);
33304 bc_put_u8(s, flags);
33305 }
33306
33307 if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len))
33308 goto fail;
33309
33310 if (b->has_debug) {
33311 bc_put_atom(s, b->debug.filename);
33312 bc_put_leb128(s, b->debug.line_num);
33313 bc_put_leb128(s, b->debug.pc2line_len);
33314 dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len);
33315 }
33316
33317 for(i = 0; i < b->cpool_count; i++) {
33318 if (JS_WriteObjectRec(s, b->cpool[i]))
33319 goto fail;
33320 }
33321 }
33322 break;34009 break;
33323 case JS_TAG_MODULE:34010 case JS_TAG_MODULE:
33324 {34011 if (!s->allow_bytecode)
33325 JSModuleDef *m = JS_VALUE_GET_PTR(obj);34012 goto invalid_tag;
33326 int i;34013 if (JS_WriteModule(s, obj))
33327 34014 goto fail;
33328 if (!s->allow_bytecode)
33329 goto invalid_tag;
33330 bc_put_u8(s, BC_TAG_MODULE);
33331 bc_put_atom(s, m->module_name);
33332
33333 bc_put_leb128(s, m->req_module_entries_count);
33334 for(i = 0; i < m->req_module_entries_count; i++) {
33335 JSReqModuleEntry *rme = &m->req_module_entries[i];
33336 bc_put_atom(s, rme->module_name);
33337 }
33338
33339 bc_put_leb128(s, m->export_entries_count);
33340 for(i = 0; i < m->export_entries_count; i++) {
33341 JSExportEntry *me = &m->export_entries[i];
33342 bc_put_u8(s, me->export_type);
33343 if (me->export_type == JS_EXPORT_TYPE_LOCAL) {
33344 bc_put_leb128(s, me->u.local.var_idx);
33345 } else {
33346 bc_put_leb128(s, me->u.req_module_idx);
33347 bc_put_atom(s, me->local_name);
33348 }
33349 bc_put_atom(s, me->export_name);
33350 }
33351
33352 bc_put_leb128(s, m->star_export_entries_count);
33353 for(i = 0; i < m->star_export_entries_count; i++) {
33354 JSStarExportEntry *se = &m->star_export_entries[i];
33355 bc_put_leb128(s, se->req_module_idx);
33356 }
33357
33358 bc_put_leb128(s, m->import_entries_count);
33359 for(i = 0; i < m->import_entries_count; i++) {
33360 JSImportEntry *mi = &m->import_entries[i];
33361 bc_put_leb128(s, mi->var_idx);
33362 bc_put_atom(s, mi->import_name);
33363 bc_put_leb128(s, mi->req_module_idx);
33364 }
33365
33366 if (JS_WriteObjectRec(s, m->func_obj))
33367 goto fail;
33368 }
33369 break;34015 break;
33370 case JS_TAG_OBJECT:34016 case JS_TAG_OBJECT:
33371 {34017 {
33372 JSObject *p = JS_VALUE_GET_OBJ(obj);34018 JSObject *p = JS_VALUE_GET_OBJ(obj);
33373 uint32_t i, prop_count, len;34019 int ret, idx;
33374 JSShape *sh;34020
33375 JSShapeProperty *pr;34021 if (s->allow_reference) {
33376 JSValue val;34022 idx = js_object_list_find(s->ctx, &s->object_list, p);
33377 int ret, pass;34023 if (idx >= 0) {
33378 BOOL is_template;34024 bc_put_u8(s, BC_TAG_OBJECT_REFERENCE);
33379 JSAtom atom;34025 bc_put_leb128(s, idx);
33380 34026 break;
33381 if (p->class_id != JS_CLASS_ARRAY &&
33382 p->class_id != JS_CLASS_OBJECT) {
33383 JS_ThrowTypeError(s->ctx, "unsupported object class");
33384 goto fail;
33385 }
33386 if (p->tmp_mark) {
33387 JS_ThrowTypeError(s->ctx, "circular reference");
33388 goto fail;
33389 }
33390 p->tmp_mark = 1;
33391 if (p->class_id == JS_CLASS_ARRAY) {
33392 if (s->allow_bytecode && !p->extensible) {
33393 /* not extensible array: we consider it is a
33394 template when we are saving bytecode */
33395 bc_put_u8(s, BC_TAG_TEMPLATE_OBJECT);
33396 is_template = TRUE;
33397 } else {34027 } else {
33398 bc_put_u8(s, BC_TAG_ARRAY);34028 if (js_object_list_add(s->ctx, &s->object_list, p))
33399 is_template = FALSE;34029 goto fail;
33400 }
33401 if (js_get_length32(s->ctx, &len, obj))
33402 goto fail1;
33403 bc_put_leb128(s, len);
33404 for(i = 0; i < len; i++) {
33405 val = JS_GetPropertyUint32(s->ctx, obj, i);
33406 if (JS_IsException(val))
33407 goto fail1;
33408 ret = JS_WriteObjectRec(s, val);
33409 JS_FreeValue(s->ctx, val);
33410 if (ret)
33411 goto fail1;
33412 }
33413 if (is_template) {
33414 val = JS_GetProperty(s->ctx, obj, JS_ATOM_raw);
33415 if (JS_IsException(val))
33416 goto fail1;
33417 ret = JS_WriteObjectRec(s, val);
33418 JS_FreeValue(s->ctx, val);
33419 if (ret)
33420 goto fail1;
33421 }34030 }
33422 } else {34031 } else {
33423 bc_put_u8(s, BC_TAG_OBJECT);34032 if (p->tmp_mark) {
33424 prop_count = 0;34033 JS_ThrowTypeError(s->ctx, "circular reference");
33425 sh = p->shape;34034 goto fail;
33426 for(pass = 0; pass < 2; pass++) {34035 }
33427 if (pass == 1)34036 p->tmp_mark = 1;
33428 bc_put_leb128(s, prop_count);34037 }
33429 for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) {34038 switch(p->class_id) {
33430 atom = pr->atom;34039 case JS_CLASS_ARRAY:
33431 if (atom != JS_ATOM_NULL &&34040 ret = JS_WriteArray(s, obj);
33432 JS_AtomIsString(s->ctx, atom) &&34041 break;
33433 (pr->flags & JS_PROP_ENUMERABLE)) {34042 case JS_CLASS_OBJECT:
33434 if (pr->flags & JS_PROP_TMASK) {34043 ret = JS_WriteObjectTag(s, obj);
33435 JS_ThrowTypeError(s->ctx, "only value properties are supported");34044 break;
33436 goto fail;34045 case JS_CLASS_ARRAY_BUFFER:
33437 }34046 ret = JS_WriteArrayBuffer(s, obj);
33438 if (pass == 0) {34047 break;
33439 prop_count++;34048 case JS_CLASS_SHARED_ARRAY_BUFFER:
33440 } else {34049 if (!s->allow_sab)
33441 bc_put_atom(s, atom);34050 goto invalid_tag;
33442 if (JS_WriteObjectRec(s, p->prop[i].u.value)) {34051 ret = JS_WriteSharedArrayBuffer(s, obj);
33443 fail1:34052 break;
33444 p->tmp_mark = 0;34053 case JS_CLASS_DATE:
33445 goto fail;34054 bc_put_u8(s, BC_TAG_DATE);
33446 }34055 ret = JS_WriteObjectRec(s, p->u.object_data);
33447 }34056 break;
33448 }34057 case JS_CLASS_NUMBER:
33449 }34058 case JS_CLASS_STRING:
34059 case JS_CLASS_BOOLEAN:
34060#ifdef CONFIG_BIGNUM
34061 case JS_CLASS_BIG_INT:
34062 case JS_CLASS_BIG_FLOAT:
34063 case JS_CLASS_BIG_DECIMAL:
34064#endif
34065 bc_put_u8(s, BC_TAG_OBJECT_VALUE);
34066 ret = JS_WriteObjectRec(s, p->u.object_data);
34067 break;
34068 default:
34069 if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
34070 p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
34071 ret = JS_WriteTypedArray(s, obj);
34072 } else {
34073 JS_ThrowTypeError(s->ctx, "unsupported object class");
34074 ret = -1;
33450 }34075 }
34076 break;
33451 }34077 }
33452 p->tmp_mark = 0;34078 p->tmp_mark = 0;
34079 if (ret)
34080 goto fail;
33453 }34081 }
33454 break;34082 break;
33455#ifdef CONFIG_BIGNUM34083#ifdef CONFIG_BIGNUM
@@ -33511,8 +34139,8 @@ static int JS_WriteObjectAtoms(BCWriterState *s) · 55 unmodified lines
33511 return -1;34139 return -1;
33512}34140}
33513 34141
33514uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,34142uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
33515 int flags)34143 int flags, uint8_t ***psab_tab, size_t *psab_tab_len)
33516{34144{
33517 BCWriterState ss, *s = &ss;34145 BCWriterState ss, *s = &ss;
33518 34146
@@ -33521,29 +34149,48 @@ uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj, · 2 unmodified lines
33521 /* XXX: byte swapped output is untested */34149 /* XXX: byte swapped output is untested */
33522 s->byte_swap = ((flags & JS_WRITE_OBJ_BSWAP) != 0);34150 s->byte_swap = ((flags & JS_WRITE_OBJ_BSWAP) != 0);
33523 s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0);34151 s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0);
34152 s->allow_sab = ((flags & JS_WRITE_OBJ_SAB) != 0);
34153 s->allow_reference = ((flags & JS_WRITE_OBJ_REFERENCE) != 0);
33524 /* XXX: could use a different version when bytecode is included */34154 /* XXX: could use a different version when bytecode is included */
33525 if (s->allow_bytecode)34155 if (s->allow_bytecode)
33526 s->first_atom = JS_ATOM_END;34156 s->first_atom = JS_ATOM_END;
33527 else34157 else
33528 s->first_atom = 1;34158 s->first_atom = 1;
33529 js_dbuf_init(ctx, &s->dbuf);34159 js_dbuf_init(ctx, &s->dbuf);
33530 34160 js_object_list_init(&s->object_list);
34161
33531 if (JS_WriteObjectRec(s, obj))34162 if (JS_WriteObjectRec(s, obj))
33532 goto fail;34163 goto fail;
33533 if (JS_WriteObjectAtoms(s))34164 if (JS_WriteObjectAtoms(s))
33534 goto fail;34165 goto fail;
34166 js_object_list_end(ctx, &s->object_list);
33535 js_free(ctx, s->atom_to_idx);34167 js_free(ctx, s->atom_to_idx);
33536 js_free(ctx, s->idx_to_atom);34168 js_free(ctx, s->idx_to_atom);
33537 *psize = s->dbuf.size;34169 *psize = s->dbuf.size;
34170 if (psab_tab)
34171 *psab_tab = s->sab_tab;
34172 if (psab_tab_len)
34173 *psab_tab_len = s->sab_tab_len;
33538 return s->dbuf.buf;34174 return s->dbuf.buf;
33539 fail:34175 fail:
34176 js_object_list_end(ctx, &s->object_list);
33540 js_free(ctx, s->atom_to_idx);34177 js_free(ctx, s->atom_to_idx);
33541 js_free(ctx, s->idx_to_atom);34178 js_free(ctx, s->idx_to_atom);
33542 dbuf_free(&s->dbuf);34179 dbuf_free(&s->dbuf);
33543 *psize = 0;34180 *psize = 0;
34181 if (psab_tab)
34182 *psab_tab = NULL;
34183 if (psab_tab_len)
34184 *psab_tab_len = 0;
33544 return NULL;34185 return NULL;
33545}34186}
33546 34187
34188uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,
34189 int flags)
34190{
34191 return JS_WriteObject2(ctx, psize, obj, flags, NULL, NULL);
34192}
34193
33547typedef struct BCReaderState {34194typedef struct BCReaderState {
33548 JSContext *ctx;34195 JSContext *ctx;
33549 const uint8_t *buf_start, *ptr, *buf_end;34196 const uint8_t *buf_start, *ptr, *buf_end;
@@ -33551,8 +34198,15 @@ typedef struct BCReaderState { · 1 unmodified line
33551 uint32_t idx_to_atom_count;34198 uint32_t idx_to_atom_count;
33552 JSAtom *idx_to_atom;34199 JSAtom *idx_to_atom;
33553 int error_state;34200 int error_state;
33554 BOOL allow_bytecode;34201 BOOL allow_sab : 8;
33555 BOOL is_rom_data;34202 BOOL allow_bytecode : 8;
34203 BOOL is_rom_data : 8;
34204 BOOL allow_reference : 8;
34205 /* object references */
34206 JSObject **objects;
34207 int objects_count;
34208 int objects_size;
34209
33556#ifdef DUMP_READ_OBJECT34210#ifdef DUMP_READ_OBJECT
33557 const uint8_t *ptr_last;34211 const uint8_t *ptr_last;
33558 int level;34212 int level;
@@ -33756,7 +34410,7 @@ static JSString *JS_ReadString(BCReaderState *s) · 197 unmodified lines
33756 p->u.str8[size] = '\0'; /* add the trailing zero for 8 bit strings */34410 p->u.str8[size] = '\0'; /* add the trailing zero for 8 bit strings */
33757 }34411 }
33758#ifdef DUMP_READ_OBJECT34412#ifdef DUMP_READ_OBJECT
33759 bc_read_trace(s, "string: "); JS_DumpString(s->ctx->rt, p); printf("\n");34413 JS_DumpString(s->ctx->rt, p); printf("\n");
33760#endif34414#endif
33761 return p;34415 return p;
33762}34416}
@@ -33838,8 +34492,6 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag) · 75 unmodified lines
33838 bf_t *a;34492 bf_t *a;
33839 int bpos, d;34493 int bpos, d;
33840 34494
33841 bc_read_trace(s, "%s {\n", bc_tag_str[tag]);
33842
33843 p = js_new_bf(s->ctx);34495 p = js_new_bf(s->ctx);
33844 if (!p)34496 if (!p)
33845 goto fail;34497 goto fail;
@@ -33961,28 +34613,560 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag) · 115 unmodified lines
33961}34613}
33962#endif /* CONFIG_BIGNUM */34614#endif /* CONFIG_BIGNUM */
33963 34615
34616static JSValue JS_ReadObjectRec(BCReaderState *s);
34617
34618static int BC_add_object_ref1(BCReaderState *s, JSObject *p)
34619{
34620 if (s->allow_reference) {
34621 if (js_resize_array(s->ctx, (void *)&s->objects,
34622 sizeof(s->objects[0]),
34623 &s->objects_size, s->objects_count + 1))
34624 return -1;
34625 s->objects[s->objects_count++] = p;
34626 }
34627 return 0;
34628}
34629
34630static int BC_add_object_ref(BCReaderState *s, JSValueConst obj)
34631{
34632 return BC_add_object_ref1(s, JS_VALUE_GET_OBJ(obj));
34633}
34634
34635static JSValue JS_ReadFunctionTag(BCReaderState *s)
34636{
34637 JSContext *ctx = s->ctx;
34638 JSFunctionBytecode bc, *b;
34639 JSValue obj = JS_UNDEFINED;
34640 uint16_t v16;
34641 uint8_t v8;
34642 int idx, i, local_count;
34643 int function_size, cpool_offset, byte_code_offset;
34644 int closure_var_offset, vardefs_offset;
34645
34646 memset(&bc, 0, sizeof(bc));
34647 bc.header.ref_count = 1;
34648 //bc.gc_header.mark = 0;
34649
34650 if (bc_get_u16(s, &v16))
34651 goto fail;
34652 idx = 0;
34653 bc.has_prototype = bc_get_flags(v16, &idx, 1);
34654 bc.has_simple_parameter_list = bc_get_flags(v16, &idx, 1);
34655 bc.is_derived_class_constructor = bc_get_flags(v16, &idx, 1);
34656 bc.need_home_object = bc_get_flags(v16, &idx, 1);
34657 bc.func_kind = bc_get_flags(v16, &idx, 2);
34658 bc.new_target_allowed = bc_get_flags(v16, &idx, 1);
34659 bc.super_call_allowed = bc_get_flags(v16, &idx, 1);
34660 bc.super_allowed = bc_get_flags(v16, &idx, 1);
34661 bc.arguments_allowed = bc_get_flags(v16, &idx, 1);
34662 bc.has_debug = bc_get_flags(v16, &idx, 1);
34663 bc.backtrace_barrier = bc_get_flags(v16, &idx, 1);
34664 bc.read_only_bytecode = s->is_rom_data;
34665 if (bc_get_u8(s, &v8))
34666 goto fail;
34667 bc.js_mode = v8;
34668 if (bc_get_atom(s, &bc.func_name)) //@ atom leak if failure
34669 goto fail;
34670 if (bc_get_leb128_u16(s, &bc.arg_count))
34671 goto fail;
34672 if (bc_get_leb128_u16(s, &bc.var_count))
34673 goto fail;
34674 if (bc_get_leb128_u16(s, &bc.defined_arg_count))
34675 goto fail;
34676 if (bc_get_leb128_u16(s, &bc.stack_size))
34677 goto fail;
34678 if (bc_get_leb128_int(s, &bc.closure_var_count))
34679 goto fail;
34680 if (bc_get_leb128_int(s, &bc.cpool_count))
34681 goto fail;
34682 if (bc_get_leb128_int(s, &bc.byte_code_len))
34683 goto fail;
34684 if (bc_get_leb128_int(s, &local_count))
34685 goto fail;
34686
34687 if (bc.has_debug) {
34688 function_size = sizeof(*b);
34689 } else {
34690 function_size = offsetof(JSFunctionBytecode, debug);
34691 }
34692 cpool_offset = function_size;
34693 function_size += bc.cpool_count * sizeof(*bc.cpool);
34694 vardefs_offset = function_size;
34695 function_size += local_count * sizeof(*bc.vardefs);
34696 closure_var_offset = function_size;
34697 function_size += bc.closure_var_count * sizeof(*bc.closure_var);
34698 byte_code_offset = function_size;
34699 if (!bc.read_only_bytecode) {
34700 function_size += bc.byte_code_len;
34701 }
34702
34703 b = js_mallocz(ctx, function_size);
34704 if (!b)
34705 return JS_EXCEPTION;
34706
34707 memcpy(b, &bc, offsetof(JSFunctionBytecode, debug));
34708 b->header.ref_count = 1;
34709 add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
34710
34711 obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b);
34712
34713#ifdef DUMP_READ_OBJECT
34714 bc_read_trace(s, "name: "); print_atom(s->ctx, b->func_name); printf("\n");
34715#endif
34716 bc_read_trace(s, "args=%d vars=%d defargs=%d closures=%d cpool=%d\n",
34717 b->arg_count, b->var_count, b->defined_arg_count,
34718 b->closure_var_count, b->cpool_count);
34719 bc_read_trace(s, "stack=%d bclen=%d locals=%d\n",
34720 b->stack_size, b->byte_code_len, local_count);
34721
34722 if (local_count != 0) {
34723 bc_read_trace(s, "vars {\n");
34724 b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
34725 for(i = 0; i < local_count; i++) {
34726 JSVarDef *vd = &b->vardefs[i];
34727 if (bc_get_atom(s, &vd->var_name))
34728 goto fail;
34729 if (bc_get_leb128_int(s, &vd->scope_level))
34730 goto fail;
34731 if (bc_get_leb128_int(s, &vd->scope_next))
34732 goto fail;
34733 vd->scope_next--;
34734 if (bc_get_u8(s, &v8))
34735 goto fail;
34736 idx = 0;
34737 vd->var_kind = bc_get_flags(v8, &idx, 4);
34738 vd->is_func_var = bc_get_flags(v8, &idx, 1);
34739 vd->is_const = bc_get_flags(v8, &idx, 1);
34740 vd->is_lexical = bc_get_flags(v8, &idx, 1);
34741 vd->is_captured = bc_get_flags(v8, &idx, 1);
34742#ifdef DUMP_READ_OBJECT
34743 bc_read_trace(s, "name: "); print_atom(s->ctx, vd->var_name); printf("\n");
34744#endif
34745 }
34746 bc_read_trace(s, "}\n");
34747 }
34748 if (b->closure_var_count != 0) {
34749 bc_read_trace(s, "closure vars {\n");
34750 b->closure_var = (void *)((uint8_t*)b + closure_var_offset);
34751 for(i = 0; i < b->closure_var_count; i++) {
34752 JSClosureVar *cv = &b->closure_var[i];
34753 int var_idx;
34754 if (bc_get_atom(s, &cv->var_name))
34755 goto fail;
34756 if (bc_get_leb128_int(s, &var_idx))
34757 goto fail;
34758 cv->var_idx = var_idx;
34759 if (bc_get_u8(s, &v8))
34760 goto fail;
34761 idx = 0;
34762 cv->is_local = bc_get_flags(v8, &idx, 1);
34763 cv->is_arg = bc_get_flags(v8, &idx, 1);
34764 cv->is_const = bc_get_flags(v8, &idx, 1);
34765 cv->is_lexical = bc_get_flags(v8, &idx, 1);
34766 cv->var_kind = bc_get_flags(v8, &idx, 4);
34767#ifdef DUMP_READ_OBJECT
34768 bc_read_trace(s, "name: "); print_atom(s->ctx, cv->var_name); printf("\n");
34769#endif
34770 }
34771 bc_read_trace(s, "}\n");
34772 }
34773 {
34774 bc_read_trace(s, "bytecode {\n");
34775 if (JS_ReadFunctionBytecode(s, b, byte_code_offset, b->byte_code_len))
34776 goto fail;
34777 bc_read_trace(s, "}\n");
34778 }
34779 if (b->has_debug) {
34780 /* read optional debug information */
34781 bc_read_trace(s, "debug {\n");
34782 if (bc_get_atom(s, &b->debug.filename))
34783 goto fail;
34784 if (bc_get_leb128_int(s, &b->debug.line_num))
34785 goto fail;
34786 if (bc_get_leb128_int(s, &b->debug.pc2line_len))
34787 goto fail;
34788 if (b->debug.pc2line_len) {
34789 b->debug.pc2line_buf = js_mallocz(ctx, b->debug.pc2line_len);
34790 if (!b->debug.pc2line_buf)
34791 goto fail;
34792 if (bc_get_buf(s, b->debug.pc2line_buf, b->debug.pc2line_len))
34793 goto fail;
34794 }
34795#ifdef DUMP_READ_OBJECT
34796 bc_read_trace(s, "filename: "); print_atom(s->ctx, b->debug.filename); printf("\n");
34797#endif
34798 bc_read_trace(s, "}\n");
34799 }
34800 if (b->cpool_count != 0) {
34801 bc_read_trace(s, "cpool {\n");
34802 b->cpool = (void *)((uint8_t*)b + cpool_offset);
34803 for(i = 0; i < b->cpool_count; i++) {
34804 JSValue val;
34805 val = JS_ReadObjectRec(s);
34806 if (JS_IsException(val))
34807 goto fail;
34808 b->cpool[i] = val;
34809 }
34810 bc_read_trace(s, "}\n");
34811 }
34812 b->realm = JS_DupContext(ctx);
34813 return obj;
34814 fail:
34815 JS_FreeValue(ctx, obj);
34816 return JS_EXCEPTION;
34817}
34818
34819static JSValue JS_ReadModule(BCReaderState *s)
34820{
34821 JSContext *ctx = s->ctx;
34822 JSValue obj;
34823 JSModuleDef *m = NULL;
34824 JSAtom module_name;
34825 int i;
34826 uint8_t v8;
34827
34828 if (bc_get_atom(s, &module_name))
34829 goto fail;
34830#ifdef DUMP_READ_OBJECT
34831 bc_read_trace(s, "name: "); print_atom(s->ctx, module_name); printf("\n");
34832#endif
34833 m = js_new_module_def(ctx, module_name);
34834 if (!m)
34835 goto fail;
34836 obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
34837 if (bc_get_leb128_int(s, &m->req_module_entries_count))
34838 goto fail;
34839 if (m->req_module_entries_count != 0) {
34840 m->req_module_entries_size = m->req_module_entries_count;
34841 m->req_module_entries = js_mallocz(ctx, sizeof(m->req_module_entries[0]) * m->req_module_entries_size);
34842 if (!m->req_module_entries)
34843 goto fail;
34844 for(i = 0; i < m->req_module_entries_count; i++) {
34845 JSReqModuleEntry *rme = &m->req_module_entries[i];
34846 if (bc_get_atom(s, &rme->module_name))
34847 goto fail;
34848 }
34849 }
34850
34851 if (bc_get_leb128_int(s, &m->export_entries_count))
34852 goto fail;
34853 if (m->export_entries_count != 0) {
34854 m->export_entries_size = m->export_entries_count;
34855 m->export_entries = js_mallocz(ctx, sizeof(m->export_entries[0]) * m->export_entries_size);
34856 if (!m->export_entries)
34857 goto fail;
34858 for(i = 0; i < m->export_entries_count; i++) {
34859 JSExportEntry *me = &m->export_entries[i];
34860 if (bc_get_u8(s, &v8))
34861 goto fail;
34862 me->export_type = v8;
34863 if (me->export_type == JS_EXPORT_TYPE_LOCAL) {
34864 if (bc_get_leb128_int(s, &me->u.local.var_idx))
34865 goto fail;
34866 } else {
34867 if (bc_get_leb128_int(s, &me->u.req_module_idx))
34868 goto fail;
34869 if (bc_get_atom(s, &me->local_name))
34870 goto fail;
34871 }
34872 if (bc_get_atom(s, &me->export_name))
34873 goto fail;
34874 }
34875 }
34876
34877 if (bc_get_leb128_int(s, &m->star_export_entries_count))
34878 goto fail;
34879 if (m->star_export_entries_count != 0) {
34880 m->star_export_entries_size = m->star_export_entries_count;
34881 m->star_export_entries = js_mallocz(ctx, sizeof(m->star_export_entries[0]) * m->star_export_entries_size);
34882 if (!m->star_export_entries)
34883 goto fail;
34884 for(i = 0; i < m->star_export_entries_count; i++) {
34885 JSStarExportEntry *se = &m->star_export_entries[i];
34886 if (bc_get_leb128_int(s, &se->req_module_idx))
34887 goto fail;
34888 }
34889 }
34890
34891 if (bc_get_leb128_int(s, &m->import_entries_count))
34892 goto fail;
34893 if (m->import_entries_count != 0) {
34894 m->import_entries_size = m->import_entries_count;
34895 m->import_entries = js_mallocz(ctx, sizeof(m->import_entries[0]) * m->import_entries_size);
34896 if (!m->import_entries)
34897 goto fail;
34898 for(i = 0; i < m->import_entries_count; i++) {
34899 JSImportEntry *mi = &m->import_entries[i];
34900 if (bc_get_leb128_int(s, &mi->var_idx))
34901 goto fail;
34902 if (bc_get_atom(s, &mi->import_name))
34903 goto fail;
34904 if (bc_get_leb128_int(s, &mi->req_module_idx))
34905 goto fail;
34906 }
34907 }
34908
34909 m->func_obj = JS_ReadObjectRec(s);
34910 if (JS_IsException(m->func_obj))
34911 goto fail;
34912 return obj;
34913 fail:
34914 if (m) {
34915 js_free_module_def(ctx, m);
34916 }
34917 return JS_EXCEPTION;
34918}
34919
34920static JSValue JS_ReadObjectTag(BCReaderState *s)
34921{
34922 JSContext *ctx = s->ctx;
34923 JSValue obj;
34924 uint32_t prop_count, i;
34925 JSAtom atom;
34926 JSValue val;
34927 int ret;
34928
34929 obj = JS_NewObject(ctx);
34930 if (BC_add_object_ref(s, obj))
34931 goto fail;
34932 if (bc_get_leb128(s, &prop_count))
34933 goto fail;
34934 for(i = 0; i < prop_count; i++) {
34935 if (bc_get_atom(s, &atom))
34936 goto fail;
34937#ifdef DUMP_READ_OBJECT
34938 bc_read_trace(s, "propname: "); print_atom(s->ctx, atom); printf("\n");
34939#endif
34940 val = JS_ReadObjectRec(s);
34941 if (JS_IsException(val)) {
34942 JS_FreeAtom(ctx, atom);
34943 goto fail;
34944 }
34945 ret = JS_DefinePropertyValue(ctx, obj, atom, val, JS_PROP_C_W_E);
34946 JS_FreeAtom(ctx, atom);
34947 if (ret < 0)
34948 goto fail;
34949 }
34950 return obj;
34951 fail:
34952 JS_FreeValue(ctx, obj);
34953 return JS_EXCEPTION;
34954}
34955
34956static JSValue JS_ReadArray(BCReaderState *s, int tag)
34957{
34958 JSContext *ctx = s->ctx;
34959 JSValue obj;
34960 uint32_t len, i;
34961 JSValue val;
34962 int ret, prop_flags;
34963 BOOL is_template;
34964
34965 obj = JS_NewArray(ctx);
34966 if (BC_add_object_ref(s, obj))
34967 goto fail;
34968 is_template = (tag == BC_TAG_TEMPLATE_OBJECT);
34969 if (bc_get_leb128(s, &len))
34970 goto fail;
34971 for(i = 0; i < len; i++) {
34972 val = JS_ReadObjectRec(s);
34973 if (JS_IsException(val))
34974 goto fail;
34975 if (is_template)
34976 prop_flags = JS_PROP_ENUMERABLE;
34977 else
34978 prop_flags = JS_PROP_C_W_E;
34979 ret = JS_DefinePropertyValueUint32(ctx, obj, i, val,
34980 prop_flags);
34981 if (ret < 0)
34982 goto fail;
34983 }
34984 if (is_template) {
34985 val = JS_ReadObjectRec(s);
34986 if (JS_IsException(val))
34987 goto fail;
34988 if (!JS_IsUndefined(val)) {
34989 ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_raw, val, 0);
34990 if (ret < 0)
34991 goto fail;
34992 }
34993 JS_PreventExtensions(ctx, obj);
34994 }
34995 return obj;
34996 fail:
34997 JS_FreeValue(ctx, obj);
34998 return JS_EXCEPTION;
34999}
35000
35001static JSValue JS_ReadTypedArray(BCReaderState *s)
35002{
35003 JSContext *ctx = s->ctx;
35004 JSValue obj = JS_UNDEFINED, array_buffer = JS_UNDEFINED;
35005 uint8_t array_tag;
35006 JSValueConst args[3];
35007 uint32_t offset, len, idx;
35008
35009 if (bc_get_u8(s, &array_tag))
35010 return JS_EXCEPTION;
35011 if (array_tag >= JS_TYPED_ARRAY_COUNT)
35012 return JS_ThrowTypeError(ctx, "invalid typed array");
35013 if (bc_get_leb128(s, &len))
35014 return JS_EXCEPTION;
35015 if (bc_get_leb128(s, &offset))
35016 return JS_EXCEPTION;
35017 /* XXX: this hack could be avoided if the typed array could be
35018 created before the array buffer */
35019 idx = s->objects_count;
35020 if (BC_add_object_ref1(s, NULL))
35021 goto fail;
35022 array_buffer = JS_ReadObjectRec(s);
35023 if (JS_IsException(array_buffer))
35024 return JS_EXCEPTION;
35025 if (!js_get_array_buffer(ctx, array_buffer)) {
35026 JS_FreeValue(ctx, array_buffer);
35027 return JS_EXCEPTION;
35028 }
35029 args[0] = array_buffer;
35030 args[1] = JS_NewInt64(ctx, offset);
35031 args[2] = JS_NewInt64(ctx, len);
35032 obj = js_typed_array_constructor(ctx, JS_UNDEFINED,
35033 3, args,
35034 JS_CLASS_UINT8C_ARRAY + array_tag);
35035 if (JS_IsException(obj))
35036 goto fail;
35037 if (s->allow_reference) {
35038 s->objects[idx] = JS_VALUE_GET_OBJ(obj);
35039 }
35040 JS_FreeValue(ctx, array_buffer);
35041 return obj;
35042 fail:
35043 JS_FreeValue(ctx, array_buffer);
35044 JS_FreeValue(ctx, obj);
35045 return JS_EXCEPTION;
35046}
35047
35048static JSValue JS_ReadArrayBuffer(BCReaderState *s)
35049{
35050 JSContext *ctx = s->ctx;
35051 uint32_t byte_length;
35052 JSValue obj;
35053
35054 if (bc_get_leb128(s, &byte_length))
35055 return JS_EXCEPTION;
35056 if (unlikely(s->buf_end - s->ptr < byte_length)) {
35057 bc_read_error_end(s);
35058 return JS_EXCEPTION;
35059 }
35060 obj = JS_NewArrayBufferCopy(ctx, s->ptr, byte_length);
35061 if (JS_IsException(obj))
35062 goto fail;
35063 if (BC_add_object_ref(s, obj))
35064 goto fail;
35065 s->ptr += byte_length;
35066 return obj;
35067 fail:
35068 JS_FreeValue(ctx, obj);
35069 return JS_EXCEPTION;
35070}
35071
35072static JSValue JS_ReadSharedArrayBuffer(BCReaderState *s)
35073{
35074 JSContext *ctx = s->ctx;
35075 uint32_t byte_length;
35076 uint8_t *data_ptr;
35077 JSValue obj;
35078 uint64_t u64;
35079
35080 if (bc_get_leb128(s, &byte_length))
35081 return JS_EXCEPTION;
35082 if (bc_get_u64(s, &u64))
35083 return JS_EXCEPTION;
35084 data_ptr = (uint8_t *)(uintptr_t)u64;
35085 /* the SharedArrayBuffer is cloned */
35086 obj = js_array_buffer_constructor3(ctx, JS_UNDEFINED, byte_length,
35087 JS_CLASS_SHARED_ARRAY_BUFFER,
35088 data_ptr,
35089 NULL, NULL, FALSE);
35090 if (JS_IsException(obj))
35091 goto fail;
35092 if (BC_add_object_ref(s, obj))
35093 goto fail;
35094 return obj;
35095 fail:
35096 JS_FreeValue(ctx, obj);
35097 return JS_EXCEPTION;
35098}
35099
35100static JSValue JS_ReadDate(BCReaderState *s)
35101{
35102 JSContext *ctx = s->ctx;
35103 JSValue val, obj = JS_UNDEFINED;
35104
35105 val = JS_ReadObjectRec(s);
35106 if (JS_IsException(val))
35107 goto fail;
35108 if (!JS_IsNumber(val)) {
35109 JS_ThrowTypeError(ctx, "Number tag expected for date");
35110 goto fail;
35111 }
35112 obj = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_DATE],
35113 JS_CLASS_DATE);
35114 if (JS_IsException(obj))
35115 goto fail;
35116 if (BC_add_object_ref(s, obj))
35117 goto fail;
35118 JS_SetObjectData(ctx, obj, val);
35119 return obj;
35120 fail:
35121 JS_FreeValue(ctx, val);
35122 JS_FreeValue(ctx, obj);
35123 return JS_EXCEPTION;
35124}
35125
35126static JSValue JS_ReadObjectValue(BCReaderState *s)
35127{
35128 JSContext *ctx = s->ctx;
35129 JSValue val, obj = JS_UNDEFINED;
35130
35131 val = JS_ReadObjectRec(s);
35132 if (JS_IsException(val))
35133 goto fail;
35134 obj = JS_ToObject(ctx, val);
35135 if (JS_IsException(obj))
35136 goto fail;
35137 if (BC_add_object_ref(s, obj))
35138 goto fail;
35139 JS_FreeValue(ctx, val);
35140 return obj;
35141 fail:
35142 JS_FreeValue(ctx, val);
35143 JS_FreeValue(ctx, obj);
35144 return JS_EXCEPTION;
35145}
35146
33964static JSValue JS_ReadObjectRec(BCReaderState *s)35147static JSValue JS_ReadObjectRec(BCReaderState *s)
33965{35148{
33966 JSContext *ctx = s->ctx;35149 JSContext *ctx = s->ctx;
33967 uint8_t tag;35150 uint8_t tag;
33968 JSValue obj = JS_UNDEFINED;35151 JSValue obj = JS_UNDEFINED;
33969 JSModuleDef *m = NULL;35152
35153 if (js_check_stack_overflow(ctx->rt, 0))
35154 return JS_ThrowStackOverflow(ctx);
33970 35155
33971 if (bc_get_u8(s, &tag))35156 if (bc_get_u8(s, &tag))
33972 return JS_EXCEPTION;35157 return JS_EXCEPTION;
33973 35158
35159 bc_read_trace(s, "%s {\n", bc_tag_str[tag]);
35160
33974 switch(tag) {35161 switch(tag) {
33975 case BC_TAG_NULL:35162 case BC_TAG_NULL:
33976 bc_read_trace(s, "null\n");
33977 obj = JS_NULL;35163 obj = JS_NULL;
33978 break;35164 break;
33979 case BC_TAG_UNDEFINED:35165 case BC_TAG_UNDEFINED:
33980 bc_read_trace(s, "undefined\n");
33981 obj = JS_UNDEFINED;35166 obj = JS_UNDEFINED;
33982 break;35167 break;
33983 case BC_TAG_BOOL_FALSE:35168 case BC_TAG_BOOL_FALSE:
33984 case BC_TAG_BOOL_TRUE:35169 case BC_TAG_BOOL_TRUE:
33985 bc_read_trace(s, "%s\n", bc_tag_str[tag]);
33986 obj = JS_NewBool(ctx, tag - BC_TAG_BOOL_FALSE);35170 obj = JS_NewBool(ctx, tag - BC_TAG_BOOL_FALSE);
33987 break;35171 break;
33988 case BC_TAG_INT32:35172 case BC_TAG_INT32:
@@ -33990,7 +35174,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) · 1 unmodified line
33990 int32_t val;35174 int32_t val;
33991 if (bc_get_sleb128(s, &val))35175 if (bc_get_sleb128(s, &val))
33992 return JS_EXCEPTION;35176 return JS_EXCEPTION;
33993 bc_read_trace(s, "int32 %d\n", val);35177 bc_read_trace(s, "%d\n", val);
33994 obj = JS_NewInt32(ctx, val);35178 obj = JS_NewInt32(ctx, val);
33995 }35179 }
33996 break;35180 break;
@@ -33999,7 +35183,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) · 2 unmodified lines
33999 JSFloat64Union u;35183 JSFloat64Union u;
34000 if (bc_get_u64(s, &u.u64))35184 if (bc_get_u64(s, &u.u64))
34001 return JS_EXCEPTION;35185 return JS_EXCEPTION;
34002 bc_read_trace(s, "float64 %g\n", u.d);35186 bc_read_trace(s, "%g\n", u.d);
34003 obj = __JS_NewFloat64(ctx, u.d);35187 obj = __JS_NewFloat64(ctx, u.d);
34004 }35188 }
34005 break;35189 break;
@@ -34013,378 +35197,68 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) · 7 unmodified lines
34013 }35197 }
34014 break;35198 break;
34015 case BC_TAG_FUNCTION_BYTECODE:35199 case BC_TAG_FUNCTION_BYTECODE:
34016 {35200 if (!s->allow_bytecode)
34017 JSFunctionBytecode bc, *b;35201 goto invalid_tag;
34018 uint16_t v16;35202 obj = JS_ReadFunctionTag(s);
34019 uint8_t v8;
34020 int idx, i, local_count;
34021 int function_size, cpool_offset, byte_code_offset;
34022 int closure_var_offset, vardefs_offset;
34023
34024 if (!s->allow_bytecode)
34025 goto invalid_tag;
34026 bc_read_trace(s, "%s {\n", bc_tag_str[tag]);
34027
34028 memset(&bc, 0, sizeof(bc));
34029 bc.header.ref_count = 1;
34030 //bc.gc_header.mark = 0;
34031
34032 if (bc_get_u16(s, &v16))
34033 goto fail;
34034 idx = 0;
34035 bc.has_prototype = bc_get_flags(v16, &idx, 1);
34036 bc.has_simple_parameter_list = bc_get_flags(v16, &idx, 1);
34037 bc.is_derived_class_constructor = bc_get_flags(v16, &idx, 1);
34038 bc.need_home_object = bc_get_flags(v16, &idx, 1);
34039 bc.func_kind = bc_get_flags(v16, &idx, 2);
34040 bc.new_target_allowed = bc_get_flags(v16, &idx, 1);
34041 bc.super_call_allowed = bc_get_flags(v16, &idx, 1);
34042 bc.super_allowed = bc_get_flags(v16, &idx, 1);
34043 bc.arguments_allowed = bc_get_flags(v16, &idx, 1);
34044 bc.has_debug = bc_get_flags(v16, &idx, 1);
34045 bc.backtrace_barrier = bc_get_flags(v16, &idx, 1);
34046 bc.read_only_bytecode = s->is_rom_data;
34047 if (bc_get_u8(s, &v8))
34048 goto fail;
34049 bc.js_mode = v8;
34050 if (bc_get_atom(s, &bc.func_name)) //@ atom leak if failure
34051 goto fail;
34052 if (bc_get_leb128_u16(s, &bc.arg_count))
34053 goto fail;
34054 if (bc_get_leb128_u16(s, &bc.var_count))
34055 goto fail;
34056 if (bc_get_leb128_u16(s, &bc.defined_arg_count))
34057 goto fail;
34058 if (bc_get_leb128_u16(s, &bc.stack_size))
34059 goto fail;
34060 if (bc_get_leb128_int(s, &bc.closure_var_count))
34061 goto fail;
34062 if (bc_get_leb128_int(s, &bc.cpool_count))
34063 goto fail;
34064 if (bc_get_leb128_int(s, &bc.byte_code_len))
34065 goto fail;
34066 if (bc_get_leb128_int(s, &local_count))
34067 goto fail;
34068
34069 if (bc.has_debug) {
34070 function_size = sizeof(*b);
34071 } else {
34072 function_size = offsetof(JSFunctionBytecode, debug);
34073 }
34074 cpool_offset = function_size;
34075 function_size += bc.cpool_count * sizeof(*bc.cpool);
34076 vardefs_offset = function_size;
34077 function_size += local_count * sizeof(*bc.vardefs);
34078 closure_var_offset = function_size;
34079 function_size += bc.closure_var_count * sizeof(*bc.closure_var);
34080 byte_code_offset = function_size;
34081 if (!bc.read_only_bytecode) {
34082 function_size += bc.byte_code_len;
34083 }
34084
34085 b = js_mallocz(ctx, function_size);
34086 if (!b)
34087 return JS_EXCEPTION;
34088
34089 memcpy(b, &bc, offsetof(JSFunctionBytecode, debug));
34090 b->header.ref_count = 1;
34091 add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
34092
34093 obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b);
34094
34095#ifdef DUMP_READ_OBJECT
34096 bc_read_trace(s, "name: "); print_atom(s->ctx, b->func_name); printf("\n");
34097#endif
34098 bc_read_trace(s, "args=%d vars=%d defargs=%d closures=%d cpool=%d\n",
34099 b->arg_count, b->var_count, b->defined_arg_count,
34100 b->closure_var_count, b->cpool_count);
34101 bc_read_trace(s, "stack=%d bclen=%d locals=%d\n",
34102 b->stack_size, b->byte_code_len, local_count);
34103
34104 if (local_count != 0) {
34105 bc_read_trace(s, "vars {\n");
34106 b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
34107 for(i = 0; i < local_count; i++) {
34108 JSVarDef *vd = &b->vardefs[i];
34109 if (bc_get_atom(s, &vd->var_name))
34110 goto fail;
34111 if (bc_get_leb128_int(s, &vd->scope_level))
34112 goto fail;
34113 if (bc_get_leb128_int(s, &vd->scope_next))
34114 goto fail;
34115 vd->scope_next--;
34116 if (bc_get_u8(s, &v8))
34117 goto fail;
34118 idx = 0;
34119 vd->var_kind = bc_get_flags(v8, &idx, 4);
34120 vd->is_func_var = bc_get_flags(v8, &idx, 1);
34121 vd->is_const = bc_get_flags(v8, &idx, 1);
34122 vd->is_lexical = bc_get_flags(v8, &idx, 1);
34123 vd->is_captured = bc_get_flags(v8, &idx, 1);
34124#ifdef DUMP_READ_OBJECT
34125 bc_read_trace(s, "name: "); print_atom(s->ctx, vd->var_name); printf("\n");
34126#endif
34127 }
34128 bc_read_trace(s, "}\n");
34129 }
34130 if (b->closure_var_count != 0) {
34131 bc_read_trace(s, "closure vars {\n");
34132 b->closure_var = (void *)((uint8_t*)b + closure_var_offset);
34133 for(i = 0; i < b->closure_var_count; i++) {
34134 JSClosureVar *cv = &b->closure_var[i];
34135 int var_idx;
34136 if (bc_get_atom(s, &cv->var_name))
34137 goto fail;
34138 if (bc_get_leb128_int(s, &var_idx))
34139 goto fail;
34140 cv->var_idx = var_idx;
34141 if (bc_get_u8(s, &v8))
34142 goto fail;
34143 idx = 0;
34144 cv->is_local = bc_get_flags(v8, &idx, 1);
34145 cv->is_arg = bc_get_flags(v8, &idx, 1);
34146 cv->is_const = bc_get_flags(v8, &idx, 1);
34147 cv->is_lexical = bc_get_flags(v8, &idx, 1);
34148 cv->var_kind = bc_get_flags(v8, &idx, 4);
34149#ifdef DUMP_READ_OBJECT
34150 bc_read_trace(s, "name: "); print_atom(s->ctx, cv->var_name); printf("\n");
34151#endif
34152 }
34153 bc_read_trace(s, "}\n");
34154 }
34155 {
34156 bc_read_trace(s, "bytecode {\n");
34157 if (JS_ReadFunctionBytecode(s, b, byte_code_offset, b->byte_code_len))
34158 goto fail;
34159 bc_read_trace(s, "}\n");
34160 }
34161 if (b->has_debug) {
34162 /* read optional debug information */
34163 bc_read_trace(s, "debug {\n");
34164 if (bc_get_atom(s, &b->debug.filename))
34165 goto fail;
34166 if (bc_get_leb128_int(s, &b->debug.line_num))
34167 goto fail;
34168 if (bc_get_leb128_int(s, &b->debug.pc2line_len))
34169 goto fail;
34170 if (b->debug.pc2line_len) {
34171 b->debug.pc2line_buf = js_mallocz(ctx, b->debug.pc2line_len);
34172 if (!b->debug.pc2line_buf)
34173 goto fail;
34174 if (bc_get_buf(s, b->debug.pc2line_buf, b->debug.pc2line_len))
34175 goto fail;
34176 }
34177#ifdef DUMP_READ_OBJECT
34178 bc_read_trace(s, "filename: "); print_atom(s->ctx, b->debug.filename); printf("\n");
34179#endif
34180 bc_read_trace(s, "}\n");
34181 }
34182 if (b->cpool_count != 0) {
34183 bc_read_trace(s, "cpool {\n");
34184 b->cpool = (void *)((uint8_t*)b + cpool_offset);
34185 for(i = 0; i < b->cpool_count; i++) {
34186 JSValue val;
34187 val = JS_ReadObjectRec(s);
34188 if (JS_IsException(val))
34189 goto fail;
34190 b->cpool[i] = val;
34191 }
34192 bc_read_trace(s, "}\n");
34193 }
34194 bc_read_trace(s, "}\n");
34195 b->realm = JS_DupContext(ctx);
34196 }
34197 break;35203 break;
34198 case BC_TAG_MODULE:35204 case BC_TAG_MODULE:
34199 {35205 if (!s->allow_bytecode)
34200 JSAtom module_name;35206 goto invalid_tag;
34201 int i;35207 obj = JS_ReadModule(s);
34202 uint8_t v8;
34203
34204 if (!s->allow_bytecode)
34205 goto invalid_tag;
34206 bc_read_trace(s, "%s {\n", bc_tag_str[tag]);
34207 if (bc_get_atom(s, &module_name))
34208 goto fail;
34209#ifdef DUMP_READ_OBJECT
34210 bc_read_trace(s, "name: "); print_atom(s->ctx, module_name); printf("\n");
34211#endif
34212 m = js_new_module_def(ctx, module_name);
34213 if (!m)
34214 goto fail;
34215 obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
34216 if (bc_get_leb128_int(s, &m->req_module_entries_count))
34217 goto fail;
34218 if (m->req_module_entries_count != 0) {
34219 m->req_module_entries_size = m->req_module_entries_count;
34220 m->req_module_entries = js_mallocz(ctx, sizeof(m->req_module_entries[0]) * m->req_module_entries_size);
34221 if (!m->req_module_entries)
34222 goto fail;
34223 for(i = 0; i < m->req_module_entries_count; i++) {
34224 JSReqModuleEntry *rme = &m->req_module_entries[i];
34225 if (bc_get_atom(s, &rme->module_name))
34226 goto fail;
34227 }
34228 }
34229
34230 if (bc_get_leb128_int(s, &m->export_entries_count))
34231 goto fail;
34232 if (m->export_entries_count != 0) {
34233 m->export_entries_size = m->export_entries_count;
34234 m->export_entries = js_mallocz(ctx, sizeof(m->export_entries[0]) * m->export_entries_size);
34235 if (!m->export_entries)
34236 goto fail;
34237 for(i = 0; i < m->export_entries_count; i++) {
34238 JSExportEntry *me = &m->export_entries[i];
34239 if (bc_get_u8(s, &v8))
34240 goto fail;
34241 me->export_type = v8;
34242 if (me->export_type == JS_EXPORT_TYPE_LOCAL) {
34243 if (bc_get_leb128_int(s, &me->u.local.var_idx))
34244 goto fail;
34245 } else {
34246 if (bc_get_leb128_int(s, &me->u.req_module_idx))
34247 goto fail;
34248 if (bc_get_atom(s, &me->local_name))
34249 goto fail;
34250 }
34251 if (bc_get_atom(s, &me->export_name))
34252 goto fail;
34253 }
34254 }
34255
34256 if (bc_get_leb128_int(s, &m->star_export_entries_count))
34257 goto fail;
34258 if (m->star_export_entries_count != 0) {
34259 m->star_export_entries_size = m->star_export_entries_count;
34260 m->star_export_entries = js_mallocz(ctx, sizeof(m->star_export_entries[0]) * m->star_export_entries_size);
34261 if (!m->star_export_entries)
34262 goto fail;
34263 for(i = 0; i < m->star_export_entries_count; i++) {
34264 JSStarExportEntry *se = &m->star_export_entries[i];
34265 if (bc_get_leb128_int(s, &se->req_module_idx))
34266 goto fail;
34267 }
34268 }
34269
34270 if (bc_get_leb128_int(s, &m->import_entries_count))
34271 goto fail;
34272 if (m->import_entries_count != 0) {
34273 m->import_entries_size = m->import_entries_count;
34274 m->import_entries = js_mallocz(ctx, sizeof(m->import_entries[0]) * m->import_entries_size);
34275 if (!m->import_entries)
34276 goto fail;
34277 for(i = 0; i < m->import_entries_count; i++) {
34278 JSImportEntry *mi = &m->import_entries[i];
34279 if (bc_get_leb128_int(s, &mi->var_idx))
34280 goto fail;
34281 if (bc_get_atom(s, &mi->import_name))
34282 goto fail;
34283 if (bc_get_leb128_int(s, &mi->req_module_idx))
34284 goto fail;
34285 }
34286 }
34287
34288 m->func_obj = JS_ReadObjectRec(s);
34289 if (JS_IsException(m->func_obj))
34290 goto fail;
34291 bc_read_trace(s, "}\n");
34292 }
34293 break;35208 break;
34294 case BC_TAG_OBJECT:35209 case BC_TAG_OBJECT:
34295 {35210 obj = JS_ReadObjectTag(s);
34296 uint32_t prop_count, i;
34297 JSAtom atom;
34298 JSValue val;
34299 int ret;
34300
34301 bc_read_trace(s, "%s {\n", bc_tag_str[tag]);
34302
34303 obj = JS_NewObject(ctx);
34304 if (bc_get_leb128(s, &prop_count))
34305 goto fail;
34306 for(i = 0; i < prop_count; i++) {
34307 if (bc_get_atom(s, &atom))
34308 goto fail;
34309#ifdef DUMP_READ_OBJECT
34310 bc_read_trace(s, "propname: "); print_atom(s->ctx, atom); printf("\n");
34311#endif
34312 val = JS_ReadObjectRec(s);
34313 if (JS_IsException(val)) {
34314 JS_FreeAtom(ctx, atom);
34315 goto fail;
34316 }
34317 ret = JS_DefinePropertyValue(ctx, obj, atom, val, JS_PROP_C_W_E);
34318 JS_FreeAtom(ctx, atom);
34319 if (ret < 0)
34320 goto fail;
34321 }
34322 bc_read_trace(s, "}\n");
34323 }
34324 break;35211 break;
34325 case BC_TAG_ARRAY:35212 case BC_TAG_ARRAY:
34326 case BC_TAG_TEMPLATE_OBJECT:35213 case BC_TAG_TEMPLATE_OBJECT:
34327 {35214 obj = JS_ReadArray(s, tag);
34328 uint32_t len, i;35215 break;
34329 JSValue val;35216 case BC_TAG_TYPED_ARRAY:
34330 int ret, prop_flags;35217 obj = JS_ReadTypedArray(s);
34331 BOOL is_template;35218 break;
34332 35219 case BC_TAG_ARRAY_BUFFER:
34333 bc_read_trace(s, "%s {\n", bc_tag_str[tag]);35220 obj = JS_ReadArrayBuffer(s);
34334 35221 break;
34335 obj = JS_NewArray(ctx);35222 case BC_TAG_SHARED_ARRAY_BUFFER:
34336 is_template = (tag == BC_TAG_TEMPLATE_OBJECT);35223 if (!s->allow_sab || !ctx->rt->sab_funcs.sab_dup)
34337 if (bc_get_leb128(s, &len))35224 goto invalid_tag;
34338 goto fail;35225 obj = JS_ReadSharedArrayBuffer(s);
34339 for(i = 0; i < len; i++) {35226 break;
34340 val = JS_ReadObjectRec(s);35227 case BC_TAG_DATE:
34341 if (JS_IsException(val))35228 obj = JS_ReadDate(s);
34342 goto fail;35229 break;
34343 if (is_template)35230 case BC_TAG_OBJECT_VALUE:
34344 prop_flags = JS_PROP_ENUMERABLE;35231 obj = JS_ReadObjectValue(s);
34345 else
34346 prop_flags = JS_PROP_C_W_E;
34347 ret = JS_DefinePropertyValueUint32(ctx, obj, i, val,
34348 prop_flags);
34349 if (ret < 0)
34350 goto fail;
34351 }
34352 if (is_template) {
34353 val = JS_ReadObjectRec(s);
34354 if (JS_IsException(val))
34355 goto fail;
34356 if (!JS_IsUndefined(val)) {
34357 ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_raw, val, 0);
34358 if (ret < 0)
34359 goto fail;
34360 }
34361 JS_PreventExtensions(ctx, obj);
34362 }
34363 bc_read_trace(s, "}\n");
34364 }
34365 break;35232 break;
34366#ifdef CONFIG_BIGNUM35233#ifdef CONFIG_BIGNUM
34367 case BC_TAG_BIG_INT:35234 case BC_TAG_BIG_INT:
34368 case BC_TAG_BIG_FLOAT:35235 case BC_TAG_BIG_FLOAT:
34369 case BC_TAG_BIG_DECIMAL:35236 case BC_TAG_BIG_DECIMAL:
34370 obj = JS_ReadBigNum(s, tag);35237 obj = JS_ReadBigNum(s, tag);
34371 if (JS_IsException(obj))
34372 goto fail;
34373 break;35238 break;
34374#endif35239#endif
35240 case BC_TAG_OBJECT_REFERENCE:
35241 {
35242 uint32_t val;
35243 if (!s->allow_reference)
35244 return JS_ThrowSyntaxError(ctx, "object references are not allowed");
35245 if (bc_get_leb128(s, &val))
35246 return JS_EXCEPTION;
35247 bc_read_trace(s, "%u\n", val);
35248 if (val >= s->objects_count) {
35249 return JS_ThrowSyntaxError(ctx, "invalid object reference (%u >= %u)",
35250 val, s->objects_count);
35251 }
35252 obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, s->objects[val]));
35253 }
35254 break;
34375 default:35255 default:
34376 invalid_tag:35256 invalid_tag:
34377 return JS_ThrowSyntaxError(ctx, "invalid tag (tag=%d pos=%u)",35257 return JS_ThrowSyntaxError(ctx, "invalid tag (tag=%d pos=%u)",
34378 tag, (unsigned int)(s->ptr - s->buf_start));35258 tag, (unsigned int)(s->ptr - s->buf_start));
34379 }35259 }
35260 bc_read_trace(s, "}\n");
34380 return obj;35261 return obj;
34381 fail:
34382 if (m) {
34383 js_free_module_def(ctx, m);
34384 } else {
34385 JS_FreeValue(ctx, obj);
34386 }
34387 return JS_EXCEPTION;
34388}35262}
34389 35263
34390static int JS_ReadObjectAtoms(BCReaderState *s)35264static int JS_ReadObjectAtoms(BCReaderState *s)
@@ -34437,10 +35311,11 @@ static void bc_reader_free(BCReaderState *s) · 46 unmodified lines
34437 }35311 }
34438 js_free(s->ctx, s->idx_to_atom);35312 js_free(s->ctx, s->idx_to_atom);
34439 }35313 }
35314 js_free(s->ctx, s->objects);
34440}35315}
34441 35316
34442JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,35317JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
34443 int flags)35318 int flags)
34444{35319{
34445 BCReaderState ss, *s = &ss;35320 BCReaderState ss, *s = &ss;
34446 JSValue obj;35321 JSValue obj;
@@ -34455,6 +35330,8 @@ JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, · 8 unmodified lines
34455 s->ptr = buf;35330 s->ptr = buf;
34456 s->allow_bytecode = ((flags & JS_READ_OBJ_BYTECODE) != 0);35331 s->allow_bytecode = ((flags & JS_READ_OBJ_BYTECODE) != 0);
34457 s->is_rom_data = ((flags & JS_READ_OBJ_ROM_DATA) != 0);35332 s->is_rom_data = ((flags & JS_READ_OBJ_ROM_DATA) != 0);
35333 s->allow_sab = ((flags & JS_READ_OBJ_SAB) != 0);
35334 s->allow_reference = ((flags & JS_READ_OBJ_REFERENCE) != 0);
34458 if (s->allow_bytecode)35335 if (s->allow_bytecode)
34459 s->first_atom = JS_ATOM_END;35336 s->first_atom = JS_ATOM_END;
34460 else35337 else
@@ -34944,7 +35821,7 @@ static __exception int JS_ObjectDefineProperties(JSContext *ctx, · 483 unmodified lines
34944 if (JS_IsException(props))35821 if (JS_IsException(props))
34945 return -1;35822 return -1;
34946 p = JS_VALUE_GET_OBJ(props);35823 p = JS_VALUE_GET_OBJ(props);
34947 if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK) < 0)35824 if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK) < 0)
34948 goto exception;35825 goto exception;
34949 for(i = 0; i < len; i++) {35826 for(i = 0; i < len; i++) {
34950 JS_FreeValue(ctx, desc);35827 JS_FreeValue(ctx, desc);
@@ -35021,7 +35898,7 @@ static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValueConst this_val, · 70 unmodified lines
35021 JS_VALUE_GET_TAG(val) == JS_TAG_UNDEFINED)35898 JS_VALUE_GET_TAG(val) == JS_TAG_UNDEFINED)
35022 return JS_ThrowTypeErrorNotAnObject(ctx);35899 return JS_ThrowTypeErrorNotAnObject(ctx);
35023 }35900 }
35024 return JS_DupValue(ctx, JS_GetPrototype(ctx, val));35901 return JS_GetPrototype(ctx, val);
35025}35902}
35026 35903
35027static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValueConst this_val,35904static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValueConst this_val,
@@ -35815,7 +36692,7 @@ static JSValue js_object_get___proto__(JSContext *ctx, JSValueConst this_val) · 787 unmodified lines
35815 val = JS_ToObject(ctx, this_val);36692 val = JS_ToObject(ctx, this_val);
35816 if (JS_IsException(val))36693 if (JS_IsException(val))
35817 return val;36694 return val;
35818 ret = JS_DupValue(ctx, JS_GetPrototype(ctx, val));36695 ret = JS_GetPrototype(ctx, val);
35819 JS_FreeValue(ctx, val);36696 JS_FreeValue(ctx, val);
35820 return ret;36697 return ret;
35821}36698}
@@ -35836,9 +36713,9 @@ static JSValue js_object_set___proto__(JSContext *ctx, JSValueConst this_val, · 14 unmodified lines
35836static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val,36713static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val,
35837 int argc, JSValueConst *argv)36714 int argc, JSValueConst *argv)
35838{36715{
35839 JSValue obj;36716 JSValue obj, v1;
35840 JSValueConst v;36717 JSValueConst v;
35841 int max_depth = 1000, res = -1;36718 int res;
35842 36719
35843 v = argv[0];36720 v = argv[0];
35844 if (!JS_IsObject(v))36721 if (!JS_IsObject(v))
@@ -35846,27 +36723,29 @@ static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val, · 1 unmodified line
35846 obj = JS_ToObject(ctx, this_val);36723 obj = JS_ToObject(ctx, this_val);
35847 if (JS_IsException(obj))36724 if (JS_IsException(obj))
35848 return JS_EXCEPTION;36725 return JS_EXCEPTION;
35849 while (--max_depth > 0) {36726 v1 = JS_DupValue(ctx, v);
35850 v = JS_GetPrototype(ctx, v);36727 for(;;) {
35851 if (JS_IsException(v))36728 v1 = JS_GetPrototypeFree(ctx, v1);
36729 if (JS_IsException(v1))
35852 goto exception;36730 goto exception;
35853 if (JS_IsNull(v)) {36731 if (JS_IsNull(v1)) {
35854 res = FALSE;36732 res = FALSE;
35855 break;36733 break;
35856 }36734 }
35857 if (js_strict_eq2(ctx, JS_DupValue(ctx, obj), JS_DupValue(ctx, v),36735 if (JS_VALUE_GET_OBJ(obj) == JS_VALUE_GET_OBJ(v1)) {
35858 JS_EQ_STRICT)) {
35859 res = TRUE;36736 res = TRUE;
35860 break;36737 break;
35861 }36738 }
36739 /* avoid infinite loop (possible with proxies) */
36740 if (js_poll_interrupts(ctx))
36741 goto exception;
35862 }36742 }
36743 JS_FreeValue(ctx, v1);
35863 JS_FreeValue(ctx, obj);36744 JS_FreeValue(ctx, obj);
35864 if (res < 0)36745 return JS_NewBool(ctx, res);
35865 return JS_ThrowInternalError(ctx, "prototype chain cycle");
35866 else
35867 return JS_NewBool(ctx, res);
35868 36746
35869exception:36747exception:
36748 JS_FreeValue(ctx, v1);
35870 JS_FreeValue(ctx, obj);36749 JS_FreeValue(ctx, obj);
35871 return JS_EXCEPTION;36750 return JS_EXCEPTION;
35872}36751}
@@ -35906,7 +36785,6 @@ static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val, · 33 unmodified lines
35906 int argc, JSValueConst *argv, int setter)36785 int argc, JSValueConst *argv, int setter)
35907{36786{
35908 JSValue obj, res = JS_EXCEPTION;36787 JSValue obj, res = JS_EXCEPTION;
35909 JSValueConst v;
35910 JSAtom prop = JS_ATOM_NULL;36788 JSAtom prop = JS_ATOM_NULL;
35911 JSPropertyDescriptor desc;36789 JSPropertyDescriptor desc;
35912 int has_prop;36790 int has_prop;
@@ -35918,8 +36796,8 @@ static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val, · 5 unmodified lines
35918 if (unlikely(prop == JS_ATOM_NULL))36796 if (unlikely(prop == JS_ATOM_NULL))
35919 goto exception;36797 goto exception;
35920 36798
35921 for (v = obj;;) {36799 for (;;) {
35922 has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(v), prop);36800 has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), prop);
35923 if (has_prop < 0)36801 if (has_prop < 0)
35924 goto exception;36802 goto exception;
35925 if (has_prop) {36803 if (has_prop) {
@@ -35930,13 +36808,16 @@ static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val, · 4 unmodified lines
35930 js_free_desc(ctx, &desc);36808 js_free_desc(ctx, &desc);
35931 break;36809 break;
35932 }36810 }
35933 v = JS_GetPrototype(ctx, v);36811 obj = JS_GetPrototypeFree(ctx, obj);
35934 if (JS_IsException(v))36812 if (JS_IsException(obj))
35935 goto exception;36813 goto exception;
35936 if (JS_IsNull(v)) {36814 if (JS_IsNull(obj)) {
35937 res = JS_UNDEFINED;36815 res = JS_UNDEFINED;
35938 break;36816 break;
35939 }36817 }
36818 /* avoid infinite loop (possible with proxies) */
36819 if (js_poll_interrupts(ctx))
36820 goto exception;
35940 }36821 }
35941 36822
35942exception:36823exception:
@@ -36002,59 +36883,12 @@ static JSValue js_function_proto(JSContext *ctx, JSValueConst this_val, · 59 unmodified lines
36002 return JS_UNDEFINED;36883 return JS_UNDEFINED;
36003}36884}
36004 36885
36005/* insert a '\n' at unicode character position 'pos' in the source of
36006 'func_obj' */
36007static int patch_function_constructor_source(JSContext *ctx,
36008 JSValueConst func_obj,
36009 size_t pos)
36010{
36011 JSObject *p;
36012 JSFunctionBytecode *b;
36013 char *r, *r_end, *new_source;
36014 int c;
36015 size_t idx, len;
36016
36017 if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)
36018 return 0;
36019 p = JS_VALUE_GET_OBJ(func_obj);
36020 if (!js_class_has_bytecode(p->class_id))
36021 return 0;
36022 b = p->u.func.function_bytecode;
36023 if (!b->has_debug)
36024 return 0;
36025 r = b->debug.source;
36026 r_end = b->debug.source + b->debug.source_len;
36027 idx = 0;
36028 while (r < r_end) {
36029 if (idx == pos) {
36030 /* add the '\n' */
36031 new_source = js_realloc(ctx, b->debug.source,
36032 b->debug.source_len + 2);
36033 if (!new_source)
36034 return -1;
36035 len = r - b->debug.source;
36036 memmove(new_source + len + 1, new_source + len,
36037 b->debug.source_len + 1 - len);
36038 new_source[len] = '\n';
36039 b->debug.source = new_source;
36040 b->debug.source_len++;
36041 break;
36042 }
36043 c = unicode_from_utf8((const uint8_t *)r, UTF8_CHAR_LEN_MAX,
36044 (const uint8_t **)&r);
36045 if (c < 0)
36046 break;
36047 idx++;
36048 }
36049 return 0;
36050}
36051
36052/* XXX: add a specific eval mode so that Function("}), ({") is rejected */36886/* XXX: add a specific eval mode so that Function("}), ({") is rejected */
36053static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,36887static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,
36054 int argc, JSValueConst *argv, int magic)36888 int argc, JSValueConst *argv, int magic)
36055{36889{
36056 JSFunctionKindEnum func_kind = magic;36890 JSFunctionKindEnum func_kind = magic;
36057 int i, n, ret, func_start_pos;36891 int i, n, ret;
36058 JSValue s, proto, obj = JS_UNDEFINED;36892 JSValue s, proto, obj = JS_UNDEFINED;
36059 StringBuffer b_s, *b = &b_s;36893 StringBuffer b_s, *b = &b_s;
36060 36894
@@ -36079,13 +36913,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, · 18 unmodified lines
36079 if (string_buffer_concat_value(b, argv[i]))36913 if (string_buffer_concat_value(b, argv[i]))
36080 goto fail;36914 goto fail;
36081 }36915 }
36082 string_buffer_puts8(b, "\n) {");36916 string_buffer_puts8(b, "\n) {\n");
36083 /* Annex B HTML comments: We don't add a '\n' after "{" so that
36084 "-->" is not considered as an HTML comment. It is necessary
36085 because in the spec the function body is parsed separately. */
36086 /* XXX: find a simpler way or be deliberately incompatible to
36087 simplify the code ? */
36088 func_start_pos = b->len - 1; /* the leading '(' is not in the source */
36089 if (n >= 0) {36917 if (n >= 0) {
36090 if (string_buffer_concat_value(b, argv[n]))36918 if (string_buffer_concat_value(b, argv[n]))
36091 goto fail;36919 goto fail;
@@ -36099,8 +36927,6 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, · 7 unmodified lines
36099 JS_FreeValue(ctx, s);36927 JS_FreeValue(ctx, s);
36100 if (JS_IsException(obj))36928 if (JS_IsException(obj))
36101 goto fail1;36929 goto fail1;
36102 if (patch_function_constructor_source(ctx, obj, func_start_pos) < 0)
36103 goto fail1;
36104 if (!JS_IsUndefined(new_target)) {36930 if (!JS_IsUndefined(new_target)) {
36105 /* set the prototype */36931 /* set the prototype */
36106 proto = JS_GetProperty(ctx, new_target, JS_ATOM_prototype);36932 proto = JS_GetProperty(ctx, new_target, JS_ATOM_prototype);
@@ -36315,27 +37141,22 @@ static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val, · 208 unmodified lines
36315 JSValue name;37141 JSValue name;
36316 const char *pref, *suff;37142 const char *pref, *suff;
36317 37143
36318 if (p->is_class) {37144 switch(func_kind) {
36319 pref = "class ";37145 default:
36320 suff = " {\n [native code]\n}";37146 case JS_FUNC_NORMAL:
36321 } else {37147 pref = "function ";
36322 switch(func_kind) {37148 break;
36323 default:37149 case JS_FUNC_GENERATOR:
36324 case JS_FUNC_NORMAL:37150 pref = "function *";
36325 pref = "function ";37151 break;
36326 break;37152 case JS_FUNC_ASYNC:
36327 case JS_FUNC_GENERATOR:37153 pref = "async function ";
36328 pref = "function *";37154 break;
36329 break;37155 case JS_FUNC_ASYNC_GENERATOR:
36330 case JS_FUNC_ASYNC:37156 pref = "async function *";
36331 pref = "async function ";37157 break;
36332 break;
36333 case JS_FUNC_ASYNC_GENERATOR:
36334 pref = "async function *";
36335 break;
36336 }
36337 suff = "() {\n [native code]\n}";
36338 }37158 }
37159 suff = "() {\n [native code]\n}";
36339 name = JS_GetProperty(ctx, this_val, JS_ATOM_name);37160 name = JS_GetProperty(ctx, this_val, JS_ATOM_name);
36340 if (JS_IsUndefined(name))37161 if (JS_IsUndefined(name))
36341 name = JS_AtomToString(ctx, JS_ATOM_empty_string);37162 name = JS_AtomToString(ctx, JS_ATOM_empty_string);
@@ -36435,12 +37256,6 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, · 93 unmodified lines
36435 if (JS_IsException(obj))37256 if (JS_IsException(obj))
36436 return obj;37257 return obj;
36437 if (magic == JS_AGGREGATE_ERROR) {37258 if (magic == JS_AGGREGATE_ERROR) {
36438 JSObject *p;
36439 JSValue error_list = iterator_to_array(ctx, argv[0]);
36440 if (JS_IsException(error_list))
36441 goto exception;
36442 p = JS_VALUE_GET_OBJ(obj);
36443 p->u.object_data = error_list;
36444 message = argv[1];37259 message = argv[1];
36445 } else {37260 } else {
36446 message = argv[0];37261 message = argv[0];
@@ -36448,17 +37263,26 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, · 1 unmodified line
36448 37263
36449 if (!JS_IsUndefined(message)) {37264 if (!JS_IsUndefined(message)) {
36450 msg = JS_ToString(ctx, message);37265 msg = JS_ToString(ctx, message);
36451 if (unlikely(JS_IsException(msg))) {37266 if (unlikely(JS_IsException(msg)))
36452 exception:37267 goto exception;
36453 JS_FreeValue(ctx, obj);
36454 return JS_EXCEPTION;
36455 }
36456 JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, msg,37268 JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, msg,
36457 JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);37269 JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
36458 }37270 }
37271
37272 if (magic == JS_AGGREGATE_ERROR) {
37273 JSValue error_list = iterator_to_array(ctx, argv[0]);
37274 if (JS_IsException(error_list))
37275 goto exception;
37276 JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, error_list,
37277 JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
37278 }
37279
36459 /* skip the Error() function in the backtrace */37280 /* skip the Error() function in the backtrace */
36460 build_backtrace(ctx, obj, NULL, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL);37281 build_backtrace(ctx, obj, NULL, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL);
36461 return obj;37282 return obj;
37283 exception:
37284 JS_FreeValue(ctx, obj);
37285 return JS_EXCEPTION;
36462}37286}
36463 37287
36464static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val,37288static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val,
@@ -36498,56 +37322,22 @@ static const JSCFunctionListEntry js_error_proto_funcs[] = { · 33 unmodified lines
36498 37322
36499/* AggregateError */37323/* AggregateError */
36500 37324
36501/* used by C code. 'errors' must be a fast array. */37325/* used by C code. */
36502static JSValue js_aggregate_error_constructor(JSContext *ctx,37326static JSValue js_aggregate_error_constructor(JSContext *ctx,
36503 JSValueConst errors)37327 JSValueConst errors)
36504{37328{
36505 JSValue obj;37329 JSValue obj;
36506 JSObject *p;
36507 37330
36508 obj = JS_NewObjectProtoClass(ctx,37331 obj = JS_NewObjectProtoClass(ctx,
36509 ctx->native_error_proto[JS_AGGREGATE_ERROR],37332 ctx->native_error_proto[JS_AGGREGATE_ERROR],
36510 JS_CLASS_ERROR);37333 JS_CLASS_ERROR);
36511 if (JS_IsException(obj))37334 if (JS_IsException(obj))
36512 return obj;37335 return obj;
36513 p = JS_VALUE_GET_OBJ(obj);37336 JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, JS_DupValue(ctx, errors),
36514 p->u.object_data = JS_DupValue(ctx, errors);37337 JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
36515 return obj;37338 return obj;
36516}37339}
36517 37340
36518static JSValue js_aggregate_error_errors(JSContext *ctx, JSValueConst this_val)
36519{
36520 JSObject *p;
36521 JSValue r, *arr;
36522 uint32_t len, i;
36523
36524 if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)
36525 goto invalid_type;
36526 p = JS_VALUE_GET_OBJ(this_val);
36527 if (p->class_id != JS_CLASS_ERROR)
36528 goto invalid_type;
36529 if (!js_get_fast_array(ctx, p->u.object_data, &arr, &len)) {
36530 invalid_type:
36531 return JS_ThrowTypeError(ctx, "not an AggregateError");
36532 }
36533 r = JS_NewArray(ctx);
36534 if (JS_IsException(r))
36535 goto exception;
36536 for(i = 0; i < len; i++) {
36537 if (JS_DefinePropertyValueInt64(ctx, r, i, JS_DupValue(ctx, arr[i]),
36538 JS_PROP_C_W_E | JS_PROP_THROW) < 0)
36539 goto exception;
36540 }
36541 return r;
36542 exception:
36543 JS_FreeValue(ctx, r);
36544 return JS_EXCEPTION;
36545}
36546
36547static const JSCFunctionListEntry js_aggregate_error_proto_funcs[] = {
36548 JS_CGETSET_DEF("errors", js_aggregate_error_errors, NULL),
36549};
36550
36551/* Array */37341/* Array */
36552 37342
36553static int JS_CopySubArray(JSContext *ctx,37343static int JS_CopySubArray(JSContext *ctx,
@@ -39130,22 +39920,25 @@ static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val, · 2576 unmodified lines
39130 p1 = JS_VALUE_GET_STRING(v);39920 p1 = JS_VALUE_GET_STRING(v);
39131 len = p->len;39921 len = p->len;
39132 v_len = p1->len;39922 v_len = p1->len;
39133 pos = (magic & 2) ? len : 0;39923 pos = (magic == 2) ? len : 0;
39134 if (argc > 1 && !JS_IsUndefined(argv[1])) {39924 if (argc > 1 && !JS_IsUndefined(argv[1])) {
39135 if (JS_ToInt32Clamp(ctx, &pos, argv[1], 0, len, 0))39925 if (JS_ToInt32Clamp(ctx, &pos, argv[1], 0, len, 0))
39136 goto fail;39926 goto fail;
39137 }39927 }
39138 len -= v_len;39928 len -= v_len;
39139 start = pos;39929 ret = 0;
39140 stop = len;39930 if (magic == 0) {
39141 if (magic & 1) {39931 start = pos;
39142 stop = pos;39932 stop = len;
39143 }39933 } else {
39144 if (magic & 2) {39934 if (magic == 1) {
39145 pos -= v_len;39935 if (pos > len)
39936 goto done;
39937 } else {
39938 pos -= v_len;
39939 }
39146 start = stop = pos;39940 start = stop = pos;
39147 }39941 }
39148 ret = 0;
39149 if (start >= 0 && start <= stop) {39942 if (start >= 0 && start <= stop) {
39150 for (i = start;; i++) {39943 for (i = start;; i++) {
39151 if (!string_cmp(p, p1, i, 0, v_len)) {39944 if (!string_cmp(p, p1, i, 0, v_len)) {
@@ -39156,6 +39949,7 @@ static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val, · 4 unmodified lines
39156 break;39949 break;
39157 }39950 }
39158 }39951 }
39952 done:
39159 JS_FreeValue(ctx, str);39953 JS_FreeValue(ctx, str);
39160 JS_FreeValue(ctx, v);39954 JS_FreeValue(ctx, v);
39161 return JS_NewBool(ctx, ret);39955 return JS_NewBool(ctx, ret);
@@ -40372,46 +41166,23 @@ static double js_math_round(double a) · 1210 unmodified lines
40372static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val,41166static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val,
40373 int argc, JSValueConst *argv)41167 int argc, JSValueConst *argv)
40374{41168{
40375 double r, a, b;41169 double r, a;
40376 int i;41170 int i;
40377 41171
40378 if (argc == 2) {41172 r = 0;
40379 /* use the more precise built-in function when possible */41173 if (argc > 0) {
40380 if (JS_ToFloat64(ctx, &a, argv[0]))41174 if (JS_ToFloat64(ctx, &r, argv[0]))
40381 return JS_EXCEPTION;
40382 if (JS_ToFloat64(ctx, &b, argv[1]))
40383 return JS_EXCEPTION;
40384 r = hypot(a, b);
40385 } else if (argc == 0) {
40386 r = 0;
40387 } else {
40388 double *tab, a_max;
40389 tab = js_malloc(ctx, sizeof(tab[0]) * argc);
40390 if (!tab)
40391 return JS_EXCEPTION;41175 return JS_EXCEPTION;
40392 /* avoid overflow by taking the maximum */41176 if (argc == 1) {
40393 a_max = 0;41177 r = fabs(r);
40394 for(i = 0; i < argc; i++) {
40395 if (JS_ToFloat64(ctx, &a, argv[i])) {
40396 js_free(ctx, tab);
40397 return JS_EXCEPTION;
40398 }
40399 a = fabs(a);
40400 tab[i] = a;
40401 if (a > a_max)
40402 a_max = a;
40403 }
40404 if (a_max == 0 || !isfinite(a_max)) {
40405 r = a_max;
40406 } else {41178 } else {
40407 r = 0;41179 /* use the built-in function to minimize precision loss */
40408 for(i = 0; i < argc; i++) {41180 for (i = 1; i < argc; i++) {
40409 a = tab[i] / a_max;41181 if (JS_ToFloat64(ctx, &a, argv[i]))
40410 r += a * a;41182 return JS_EXCEPTION;
41183 r = hypot(r, a);
40411 }41184 }
40412 r = a_max * sqrt(r);
40413 }41185 }
40414 js_free(ctx, tab);
40415 }41186 }
40416 return JS_NewFloat64(ctx, r);41187 return JS_NewFloat64(ctx, r);
40417}41188}
@@ -42093,58 +42864,69 @@ void JS_AddIntrinsicRegExp(JSContext *ctx) · 1675 unmodified lines
42093 42864
42094/* JSON */42865/* JSON */
42095 42866
42096/* XXX: this parser is less strict than the JSON standard because we42867static int json_parse_expect(JSParseState *s, int tok)
42097 reuse the Javascript tokenizer. It could be improved by adding a42868{
42098 specific JSON parse flag. */42869 if (s->token.val != tok) {
42870 /* XXX: dump token correctly in all cases */
42871 return js_parse_error(s, "expecting '%c'", tok);
42872 }
42873 return json_next_token(s);
42874}
42875
42099static JSValue json_parse_value(JSParseState *s)42876static JSValue json_parse_value(JSParseState *s)
42100{42877{
42101 JSContext *ctx = s->ctx;42878 JSContext *ctx = s->ctx;
42102 JSValue val = JS_NULL;42879 JSValue val = JS_NULL;
42103 BOOL is_neg;
42104 int ret;42880 int ret;
42105 42881
42106 switch(s->token.val) {42882 switch(s->token.val) {
42107 case '{':42883 case '{':
42108 {42884 {
42109 JSValue prop_val, prop_str;42885 JSValue prop_val;
42110 42886 JSAtom prop_name;
42111 if (next_token(s))42887
42888 if (json_next_token(s))
42112 goto fail;42889 goto fail;
42113 val = JS_NewObject(ctx);42890 val = JS_NewObject(ctx);
42114 if (JS_IsException(val))42891 if (JS_IsException(val))
42115 goto fail;42892 goto fail;
42116 if (s->token.val != '}') {42893 if (s->token.val != '}') {
42117 for(;;) {42894 for(;;) {
42118 if (s->token.val != TOK_STRING) {42895 if (s->token.val == TOK_STRING) {
42896 prop_name = JS_ValueToAtom(ctx, s->token.u.str.str);
42897 if (prop_name == JS_ATOM_NULL)
42898 goto fail;
42899 } else if (s->ext_json && s->token.val == TOK_IDENT) {
42900 prop_name = JS_DupAtom(ctx, s->token.u.ident.atom);
42901 } else {
42119 js_parse_error(s, "expecting property name");42902 js_parse_error(s, "expecting property name");
42120 goto fail;42903 goto fail;
42121 }42904 }
42122 prop_str = JS_DupValue(ctx, s->token.u.str.str);42905 if (json_next_token(s))
42123 if (next_token(s)) {42906 goto fail1;
42124 JS_FreeValue(ctx, prop_str);42907 if (json_parse_expect(s, ':'))
42125 goto fail;42908 goto fail1;
42126 }
42127 if (js_parse_expect(s, ':')) {
42128 JS_FreeValue(ctx, prop_str);
42129 goto fail;
42130 }
42131 prop_val = json_parse_value(s);42909 prop_val = json_parse_value(s);
42132 if (JS_IsException(prop_val)) {42910 if (JS_IsException(prop_val)) {
42133 JS_FreeValue(ctx, prop_str);42911 fail1:
42912 JS_FreeAtom(ctx, prop_name);
42134 goto fail;42913 goto fail;
42135 }42914 }
42136 ret = JS_DefinePropertyValueValue(ctx, val, prop_str,42915 ret = JS_DefinePropertyValue(ctx, val, prop_name,
42137 prop_val, JS_PROP_C_W_E);42916 prop_val, JS_PROP_C_W_E);
42917 JS_FreeAtom(ctx, prop_name);
42138 if (ret < 0)42918 if (ret < 0)
42139 goto fail;42919 goto fail;
42140 42920
42141 if (s->token.val != ',')42921 if (s->token.val != ',')
42142 break;42922 break;
42143 if (next_token(s))42923 if (json_next_token(s))
42144 goto fail;42924 goto fail;
42925 if (s->ext_json && s->token.val == '}')
42926 break;
42145 }42927 }
42146 }42928 }
42147 if (js_parse_expect(s, '}'))42929 if (json_parse_expect(s, '}'))
42148 goto fail;42930 goto fail;
42149 }42931 }
42150 break;42932 break;
@@ -42153,7 +42935,7 @@ static JSValue json_parse_value(JSParseState *s) · 2 unmodified lines
42153 JSValue el;42935 JSValue el;
42154 uint32_t idx;42936 uint32_t idx;
42155 42937
42156 if (next_token(s))42938 if (json_next_token(s))
42157 goto fail;42939 goto fail;
42158 val = JS_NewArray(ctx);42940 val = JS_NewArray(ctx);
42159 if (JS_IsException(val))42941 if (JS_IsException(val))
@@ -42169,52 +42951,41 @@ static JSValue json_parse_value(JSParseState *s) · 9 unmodified lines
42169 goto fail;42951 goto fail;
42170 if (s->token.val != ',')42952 if (s->token.val != ',')
42171 break;42953 break;
42172 if (next_token(s))42954 if (json_next_token(s))
42173 goto fail;42955 goto fail;
42174 idx++;42956 idx++;
42957 if (s->ext_json && s->token.val == ']')
42958 break;
42175 }42959 }
42176 }42960 }
42177 if (js_parse_expect(s, ']'))42961 if (json_parse_expect(s, ']'))
42178 goto fail;42962 goto fail;
42179 }42963 }
42180 break;42964 break;
42181 case TOK_STRING:42965 case TOK_STRING:
42182 val = JS_DupValue(ctx, s->token.u.str.str);42966 val = JS_DupValue(ctx, s->token.u.str.str);
42183 if (next_token(s))42967 if (json_next_token(s))
42184 goto fail;42968 goto fail;
42185 break;42969 break;
42186 case TOK_NUMBER:42970 case TOK_NUMBER:
42187 is_neg = 0;
42188 goto number;
42189 case '-':
42190 if (next_token(s))
42191 goto fail;
42192 if (s->token.val != TOK_NUMBER) {
42193 js_parse_error(s, "number expected");
42194 goto fail;
42195 }
42196 is_neg = 1;
42197 number:
42198 val = s->token.u.num.val;42971 val = s->token.u.num.val;
42199 if (is_neg) {42972 if (json_next_token(s))
42200 double d;
42201 JS_ToFloat64(ctx, &d, val); /* no exception possible */
42202 val = JS_NewFloat64(ctx, -d);
42203 }
42204 if (next_token(s))
42205 goto fail;42973 goto fail;
42206 break;42974 break;
42207 case TOK_FALSE:42975 case TOK_IDENT:
42208 case TOK_TRUE:42976 if (s->token.u.ident.atom == JS_ATOM_false ||
42209 val = JS_NewBool(ctx, s->token.val - TOK_FALSE);42977 s->token.u.ident.atom == JS_ATOM_true) {
42210 if (next_token(s))42978 val = JS_NewBool(ctx, (s->token.u.ident.atom == JS_ATOM_true));
42211 goto fail;42979 } else if (s->token.u.ident.atom == JS_ATOM_null) {
42212 break;42980 val = JS_NULL;
42213 case TOK_NULL:42981 } else {
42214 if (next_token(s))42982 goto def_token;
42983 }
42984 if (json_next_token(s))
42215 goto fail;42985 goto fail;
42216 break;42986 break;
42217 default:42987 default:
42988 def_token:
42218 if (s->token.val == TOK_EOF) {42989 if (s->token.val == TOK_EOF) {
42219 js_parse_error(s, "unexpected end of input");42990 js_parse_error(s, "unexpected end of input");
42220 } else {42991 } else {
@@ -42229,15 +43000,15 @@ static JSValue json_parse_value(JSParseState *s) · 8 unmodified lines
42229 return JS_EXCEPTION;43000 return JS_EXCEPTION;
42230}43001}
42231 43002
42232JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,43003JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len,
42233 const char *filename)43004 const char *filename, int flags)
42234{43005{
42235 JSParseState s1, *s = &s1;43006 JSParseState s1, *s = &s1;
42236 JSValue val;43007 JSValue val = JS_UNDEFINED;
42237 43008
42238 js_parse_init(ctx, s, buf, buf_len, filename);43009 js_parse_init(ctx, s, buf, buf_len, filename);
42239 43010 s->ext_json = ((flags & JS_PARSE_JSON_EXT) != 0);
42240 if (next_token(s))43011 if (json_next_token(s))
42241 goto fail;43012 goto fail;
42242 val = json_parse_value(s);43013 val = json_parse_value(s);
42243 if (JS_IsException(val))43014 if (JS_IsException(val))
@@ -42248,10 +43019,17 @@ JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, · 4 unmodified lines
42248 }43019 }
42249 return val;43020 return val;
42250 fail:43021 fail:
43022 JS_FreeValue(ctx, val);
42251 free_token(s, &s->token);43023 free_token(s, &s->token);
42252 return JS_EXCEPTION;43024 return JS_EXCEPTION;
42253}43025}
42254 43026
43027JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,
43028 const char *filename)
43029{
43030 return JS_ParseJSON2(ctx, buf, buf_len, filename, 0);
43031}
43032
42255static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,43033static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,
42256 JSAtom name, JSValueConst reviver)43034 JSAtom name, JSValueConst reviver)
42257{43035{
@@ -42960,7 +43738,6 @@ static void js_proxy_finalizer(JSRuntime *rt, JSValue val) · 702 unmodified lines
42960 if (s) {43738 if (s) {
42961 JS_FreeValueRT(rt, s->target);43739 JS_FreeValueRT(rt, s->target);
42962 JS_FreeValueRT(rt, s->handler);43740 JS_FreeValueRT(rt, s->handler);
42963 JS_FreeValueRT(rt, s->proto);
42964 js_free_rt(rt, s);43741 js_free_rt(rt, s);
42965 }43742 }
42966}43743}
@@ -42972,7 +43749,6 @@ static void js_proxy_mark(JSRuntime *rt, JSValueConst val, · 5 unmodified lines
42972 if (s) {43749 if (s) {
42973 JS_MarkValue(rt, s->target, mark_func);43750 JS_MarkValue(rt, s->target, mark_func);
42974 JS_MarkValue(rt, s->handler, mark_func);43751 JS_MarkValue(rt, s->handler, mark_func);
42975 JS_MarkValue(rt, s->proto, mark_func);
42976 }43752 }
42977}43753}
42978 43754
@@ -43007,17 +43783,12 @@ static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod, · 28 unmodified lines
43007 return s;43783 return s;
43008}43784}
43009 43785
43010static JSValueConst js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj)43786static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj)
43011{43787{
43012 JSProxyData *s;43788 JSProxyData *s;
43013 JSValue method, ret;43789 JSValue method, ret, proto1;
43014 JSValueConst proto1;
43015 int res;43790 int res;
43016 43791
43017 /* must check for timeout to avoid infinite loop in instanceof */
43018 if (js_poll_interrupts(ctx))
43019 return JS_EXCEPTION;
43020
43021 s = get_proxy_method(ctx, &method, obj, JS_ATOM_getPrototypeOf);43792 s = get_proxy_method(ctx, &method, obj, JS_ATOM_getPrototypeOf);
43022 if (!s)43793 if (!s)
43023 return JS_EXCEPTION;43794 return JS_EXCEPTION;
@@ -43043,22 +43814,22 @@ static JSValueConst js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj) · 19 unmodified lines
43043 return JS_EXCEPTION;43814 return JS_EXCEPTION;
43044 }43815 }
43045 if (JS_VALUE_GET_OBJ(proto1) != JS_VALUE_GET_OBJ(ret)) {43816 if (JS_VALUE_GET_OBJ(proto1) != JS_VALUE_GET_OBJ(ret)) {
43817 JS_FreeValue(ctx, proto1);
43046 fail:43818 fail:
43047 JS_FreeValue(ctx, ret);43819 JS_FreeValue(ctx, ret);
43048 return JS_ThrowTypeError(ctx, "proxy: inconsistent prototype");43820 return JS_ThrowTypeError(ctx, "proxy: inconsistent prototype");
43049 }43821 }
43822 JS_FreeValue(ctx, proto1);
43050 }43823 }
43051 /* store the prototype in the proxy so that its refcount is at least 1 */43824 return ret;
43052 set_value(ctx, &s->proto, ret);
43053 return (JSValueConst)ret;
43054}43825}
43055 43826
43056static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,43827static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
43057 JSValueConst proto_val, BOOL throw_flag)43828 JSValueConst proto_val, BOOL throw_flag)
43058{43829{
43059 JSProxyData *s;43830 JSProxyData *s;
43060 JSValue method, ret;43831 JSValue method, ret, proto1;
43061 JSValueConst args[2], proto1;43832 JSValueConst args[2];
43062 BOOL res;43833 BOOL res;
43063 int res2;43834 int res2;
43064 43835
@@ -43089,9 +43860,11 @@ static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, · 24 unmodified lines
43089 if (JS_IsException(proto1))43860 if (JS_IsException(proto1))
43090 return -1;43861 return -1;
43091 if (JS_VALUE_GET_OBJ(proto_val) != JS_VALUE_GET_OBJ(proto1)) {43862 if (JS_VALUE_GET_OBJ(proto_val) != JS_VALUE_GET_OBJ(proto1)) {
43863 JS_FreeValue(ctx, proto1);
43092 JS_ThrowTypeError(ctx, "proxy: inconsistent prototype");43864 JS_ThrowTypeError(ctx, "proxy: inconsistent prototype");
43093 return -1;43865 return -1;
43094 }43866 }
43867 JS_FreeValue(ctx, proto1);
43095 }43868 }
43096 return TRUE;43869 return TRUE;
43097}43870}
@@ -43829,7 +44602,6 @@ static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, · 731 unmodified lines
43829 }44602 }
43830 s->target = JS_DupValue(ctx, target);44603 s->target = JS_DupValue(ctx, target);
43831 s->handler = JS_DupValue(ctx, handler);44604 s->handler = JS_DupValue(ctx, handler);
43832 s->proto = JS_NULL;
43833 s->is_func = JS_IsFunction(ctx, target);44605 s->is_func = JS_IsFunction(ctx, target);
43834 s->is_revoked = FALSE;44606 s->is_revoked = FALSE;
43835 JS_SetOpaque(obj, s);44607 JS_SetOpaque(obj, s);
@@ -45414,10 +46186,10 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, · 1578 unmodified lines
45414static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,46186static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
45415 int argc, JSValueConst *argv, int magic)46187 int argc, JSValueConst *argv, int magic)
45416{46188{
45417 JSValue result_promise, resolving_funcs[2], iter, item, next_promise, ret;46189 JSValue result_promise, resolving_funcs[2], item, next_promise, ret;
45418 JSValue next_method = JS_UNDEFINED, values = JS_UNDEFINED;46190 JSValue next_method = JS_UNDEFINED, values = JS_UNDEFINED;
45419 JSValue resolve_element_env = JS_UNDEFINED, resolve_element, reject_element;46191 JSValue resolve_element_env = JS_UNDEFINED, resolve_element, reject_element;
45420 JSValue promise_resolve = JS_UNDEFINED;46192 JSValue promise_resolve = JS_UNDEFINED, iter = JS_UNDEFINED;
45421 JSValueConst then_args[2], resolve_element_data[5];46193 JSValueConst then_args[2], resolve_element_data[5];
45422 BOOL done;46194 BOOL done;
45423 int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any);46195 int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any);
@@ -45427,6 +46199,10 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, · 3 unmodified lines
45427 result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);46199 result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);
45428 if (JS_IsException(result_promise))46200 if (JS_IsException(result_promise))
45429 return result_promise;46201 return result_promise;
46202 promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve);
46203 if (JS_IsException(promise_resolve) ||
46204 check_function(ctx, promise_resolve))
46205 goto fail_reject;
45430 iter = JS_GetIterator(ctx, argv[0], FALSE);46206 iter = JS_GetIterator(ctx, argv[0], FALSE);
45431 if (JS_IsException(iter)) {46207 if (JS_IsException(iter)) {
45432 JSValue error;46208 JSValue error;
@@ -45454,11 +46230,6 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, · 21 unmodified lines
45454 JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0)46230 JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0)
45455 goto fail_reject;46231 goto fail_reject;
45456 46232
45457 promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve);
45458 if (JS_IsException(promise_resolve) ||
45459 check_function(ctx, promise_resolve))
45460 goto fail_reject1;
45461
45462 index = 0;46233 index = 0;
45463 for(;;) {46234 for(;;) {
45464 /* XXX: conformance: should close the iterator if error on 'done'46235 /* XXX: conformance: should close the iterator if error on 'done'
@@ -45560,8 +46331,8 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, · 95 unmodified lines
45560static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,46331static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
45561 int argc, JSValueConst *argv)46332 int argc, JSValueConst *argv)
45562{46333{
45563 JSValue result_promise, resolving_funcs[2], iter, item, next_promise, ret;46334 JSValue result_promise, resolving_funcs[2], item, next_promise, ret;
45564 JSValue next_method = JS_UNDEFINED;46335 JSValue next_method = JS_UNDEFINED, iter = JS_UNDEFINED;
45565 JSValue promise_resolve = JS_UNDEFINED;46336 JSValue promise_resolve = JS_UNDEFINED;
45566 BOOL done;46337 BOOL done;
45567 46338
@@ -45570,6 +46341,10 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, · 2 unmodified lines
45570 result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);46341 result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);
45571 if (JS_IsException(result_promise))46342 if (JS_IsException(result_promise))
45572 return result_promise;46343 return result_promise;
46344 promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve);
46345 if (JS_IsException(promise_resolve) ||
46346 check_function(ctx, promise_resolve))
46347 goto fail_reject;
45573 iter = JS_GetIterator(ctx, argv[0], FALSE);46348 iter = JS_GetIterator(ctx, argv[0], FALSE);
45574 if (JS_IsException(iter)) {46349 if (JS_IsException(iter)) {
45575 JSValue error;46350 JSValue error;
@@ -45586,11 +46361,6 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, · 10 unmodified lines
45586 if (JS_IsException(next_method))46361 if (JS_IsException(next_method))
45587 goto fail_reject;46362 goto fail_reject;
45588 46363
45589 promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve);
45590 if (JS_IsException(promise_resolve) ||
45591 check_function(ctx, promise_resolve))
45592 goto fail_reject1;
45593
45594 for(;;) {46364 for(;;) {
45595 /* XXX: conformance: should close the iterator if error on 'done'46365 /* XXX: conformance: should close the iterator if error on 'done'
45596 access, but not on 'value' access */46366 access, but not on 'value' access */
@@ -49385,9 +50155,6 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx) · 3788 unmodified lines
49385 JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);50155 JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
49386 ctx->native_error_proto[i] = proto;50156 ctx->native_error_proto[i] = proto;
49387 }50157 }
49388 JS_SetPropertyFunctionList(ctx, ctx->native_error_proto[JS_AGGREGATE_ERROR],
49389 js_aggregate_error_proto_funcs,
49390 countof(js_aggregate_error_proto_funcs));
49391 50158
49392 /* the array prototype is an array */50159 /* the array prototype is an array */
49393 ctx->class_proto[JS_CLASS_ARRAY] =50160 ctx->class_proto[JS_CLASS_ARRAY] =
@@ -49621,6 +50388,7 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, · 227 unmodified lines
49621 JSFreeArrayBufferDataFunc *free_func,50388 JSFreeArrayBufferDataFunc *free_func,
49622 void *opaque, BOOL alloc_flag)50389 void *opaque, BOOL alloc_flag)
49623{50390{
50391 JSRuntime *rt = ctx->rt;
49624 JSValue obj;50392 JSValue obj;
49625 JSArrayBuffer *abuf = NULL;50393 JSArrayBuffer *abuf = NULL;
49626 50394
@@ -49637,11 +50405,24 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, · 10 unmodified lines
49637 goto fail;50405 goto fail;
49638 abuf->byte_length = len;50406 abuf->byte_length = len;
49639 if (alloc_flag) {50407 if (alloc_flag) {
49640 /* the allocation must be done after the object creation */50408 if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER &&
49641 abuf->data = js_mallocz(ctx, max_int(len, 1));50409 rt->sab_funcs.sab_alloc) {
49642 if (!abuf->data)50410 abuf->data = rt->sab_funcs.sab_alloc(rt->sab_funcs.sab_opaque,
49643 goto fail;50411 max_int(len, 1));
50412 if (!abuf->data)
50413 goto fail;
50414 memset(abuf->data, 0, len);
50415 } else {
50416 /* the allocation must be done after the object creation */
50417 abuf->data = js_mallocz(ctx, max_int(len, 1));
50418 if (!abuf->data)
50419 goto fail;
50420 }
49644 } else {50421 } else {
50422 if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER &&
50423 rt->sab_funcs.sab_dup) {
50424 rt->sab_funcs.sab_dup(rt->sab_funcs.sab_opaque, buf);
50425 }
49645 abuf->data = buf;50426 abuf->data = buf;
49646 }50427 }
49647 init_list_head(&abuf->array_list);50428 init_list_head(&abuf->array_list);
@@ -49731,8 +50512,12 @@ static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val) · 83 unmodified lines
49731 array finalizers using it, so abuf->array_list is not50512 array finalizers using it, so abuf->array_list is not
49732 necessarily empty. */50513 necessarily empty. */
49733 // assert(list_empty(&abuf->array_list));50514 // assert(list_empty(&abuf->array_list));
49734 if (abuf->free_func)50515 if (abuf->shared && rt->sab_funcs.sab_free) {
49735 abuf->free_func(rt, abuf->opaque, abuf->data);50516 rt->sab_funcs.sab_free(rt->sab_funcs.sab_opaque, abuf->data);
50517 } else {
50518 if (abuf->free_func)
50519 abuf->free_func(rt, abuf->opaque, abuf->data);
50520 }
49736 js_free_rt(rt, abuf);50521 js_free_rt(rt, abuf);
49737 }50522 }
49738}50523}
@@ -50208,11 +50993,6 @@ static JSValue js_typed_array___getLength(JSContext *ctx, · 469 unmodified lines
50208}50993}
50209#endif50994#endif
50210 50995
50211static JSValue js_typed_array_constructor(JSContext *ctx,
50212 JSValueConst this_val,
50213 int argc, JSValueConst *argv,
50214 int classid);
50215
50216static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor,50996static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor,
50217 int argc, JSValueConst *argv)50997 int argc, JSValueConst *argv)
50218{50998{
@@ -51967,9 +52747,10 @@ typedef enum AtomicsOpEnum { · 1748 unmodified lines
51967} AtomicsOpEnum;52747} AtomicsOpEnum;
51968 52748
51969static void *js_atomics_get_ptr(JSContext *ctx,52749static void *js_atomics_get_ptr(JSContext *ctx,
52750 JSArrayBuffer **pabuf,
51970 int *psize_log2, JSClassID *pclass_id,52751 int *psize_log2, JSClassID *pclass_id,
51971 JSValueConst obj, JSValueConst idx_val,52752 JSValueConst obj, JSValueConst idx_val,
51972 BOOL is_waitable)52753 int is_waitable)
51973{52754{
51974 JSObject *p;52755 JSObject *p;
51975 JSTypedArray *ta;52756 JSTypedArray *ta;
@@ -52004,18 +52785,27 @@ static void *js_atomics_get_ptr(JSContext *ctx, · 28 unmodified lines
52004 ta = p->u.typed_array;52785 ta = p->u.typed_array;
52005 abuf = ta->buffer->u.array_buffer;52786 abuf = ta->buffer->u.array_buffer;
52006 if (!abuf->shared) {52787 if (!abuf->shared) {
52007 JS_ThrowTypeError(ctx, "not a SharedArrayBuffer TypedArray");52788 if (is_waitable == 2) {
52008 return NULL;52789 JS_ThrowTypeError(ctx, "not a SharedArrayBuffer TypedArray");
52790 return NULL;
52791 }
52792 if (abuf->detached) {
52793 JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
52794 return NULL;
52795 }
52009 }52796 }
52010 if (JS_ToIndex(ctx, &idx, idx_val)) {52797 if (JS_ToIndex(ctx, &idx, idx_val)) {
52011 return NULL;52798 return NULL;
52012 }52799 }
52800 /* if the array buffer is detached, p->u.array.count = 0 */
52013 if (idx >= p->u.array.count) {52801 if (idx >= p->u.array.count) {
52014 JS_ThrowRangeError(ctx, "out-of-bound access");52802 JS_ThrowRangeError(ctx, "out-of-bound access");
52015 return NULL;52803 return NULL;
52016 }52804 }
52017 size_log2 = typed_array_size_log2(p->class_id);52805 size_log2 = typed_array_size_log2(p->class_id);
52018 ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2);52806 ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2);
52807 if (pabuf)
52808 *pabuf = abuf;
52019 if (psize_log2)52809 if (psize_log2)
52020 *psize_log2 = size_log2;52810 *psize_log2 = size_log2;
52021 if (pclass_id)52811 if (pclass_id)
@@ -52036,17 +52826,18 @@ static JSValue js_atomics_op(JSContext *ctx, · 14 unmodified lines
52036 void *ptr;52826 void *ptr;
52037 JSValue ret;52827 JSValue ret;
52038 JSClassID class_id;52828 JSClassID class_id;
52829 JSArrayBuffer *abuf;
52039 52830
52040 ptr = js_atomics_get_ptr(ctx, &size_log2, &class_id,52831 ptr = js_atomics_get_ptr(ctx, &abuf, &size_log2, &class_id,
52041 argv[0], argv[1], FALSE);52832 argv[0], argv[1], 0);
52042 if (!ptr)52833 if (!ptr)
52043 return JS_EXCEPTION;52834 return JS_EXCEPTION;
52044 rep_val = 0;52835 rep_val = 0;
52045 if (op == ATOMICS_OP_LOAD) {52836 if (op == ATOMICS_OP_LOAD) {
52046 v = 0;52837 v = 0;
52047 } else52838 } else {
52048#ifdef CONFIG_BIGNUM52839#ifdef CONFIG_BIGNUM
52049 if (size_log2 == 3) {52840 if (size_log2 == 3) {
52050 int64_t v64;52841 int64_t v64;
52051 if (JS_ToBigInt64(ctx, &v64, argv[2]))52842 if (JS_ToBigInt64(ctx, &v64, argv[2]))
52052 return JS_EXCEPTION;52843 return JS_EXCEPTION;
@@ -52056,19 +52847,23 @@ static JSValue js_atomics_op(JSContext *ctx, · 3 unmodified lines
52056 return JS_EXCEPTION;52847 return JS_EXCEPTION;
52057 rep_val = v64;52848 rep_val = v64;
52058 }52849 }
52059 } else52850 } else
52060#endif52851#endif
52061 {52852 {
52062 uint32_t v32;52853 uint32_t v32;
52063 if (JS_ToUint32(ctx, &v32, argv[2]))52854 if (JS_ToUint32(ctx, &v32, argv[2]))
52064 return JS_EXCEPTION;52855 return JS_EXCEPTION;
52065 v = v32;52856 v = v32;
52066 if (op == ATOMICS_OP_COMPARE_EXCHANGE) {52857 if (op == ATOMICS_OP_COMPARE_EXCHANGE) {
52067 if (JS_ToUint32(ctx, &v32, argv[3]))52858 if (JS_ToUint32(ctx, &v32, argv[3]))
52068 return JS_EXCEPTION;52859 return JS_EXCEPTION;
52069 rep_val = v32;52860 rep_val = v32;
52070 }52861 }
52862 }
52863 if (abuf->detached)
52864 return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
52071 }52865 }
52866
52072 switch(op | (size_log2 << 3)) {52867 switch(op | (size_log2 << 3)) {
52073 52868
52074#ifdef CONFIG_BIGNUM52869#ifdef CONFIG_BIGNUM
@@ -52195,8 +52990,10 @@ static JSValue js_atomics_store(JSContext *ctx, · 120 unmodified lines
52195 int size_log2;52990 int size_log2;
52196 void *ptr;52991 void *ptr;
52197 JSValue ret;52992 JSValue ret;
52993 JSArrayBuffer *abuf;
52198 52994
52199 ptr = js_atomics_get_ptr(ctx, &size_log2, NULL, argv[0], argv[1], FALSE);52995 ptr = js_atomics_get_ptr(ctx, &abuf, &size_log2, NULL,
52996 argv[0], argv[1], 0);
52200 if (!ptr)52997 if (!ptr)
52201 return JS_EXCEPTION;52998 return JS_EXCEPTION;
52202#ifdef CONFIG_BIGNUM52999#ifdef CONFIG_BIGNUM
@@ -52209,6 +53006,8 @@ static JSValue js_atomics_store(JSContext *ctx, · 6 unmodified lines
52209 JS_FreeValue(ctx, ret);53006 JS_FreeValue(ctx, ret);
52210 return JS_EXCEPTION;53007 return JS_EXCEPTION;
52211 }53008 }
53009 if (abuf->detached)
53010 return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
52212 atomic_store((_Atomic(uint64_t) *)ptr, v64);53011 atomic_store((_Atomic(uint64_t) *)ptr, v64);
52213 } else53012 } else
52214#endif53013#endif
@@ -52222,6 +53021,8 @@ static JSValue js_atomics_store(JSContext *ctx, · 7 unmodified lines
52222 JS_FreeValue(ctx, ret);53021 JS_FreeValue(ctx, ret);
52223 return JS_EXCEPTION;53022 return JS_EXCEPTION;
52224 }53023 }
53024 if (abuf->detached)
53025 return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
52225 switch(size_log2) {53026 switch(size_log2) {
52226 case 0:53027 case 0:
52227 atomic_store((_Atomic(uint8_t) *)ptr, v);53028 atomic_store((_Atomic(uint8_t) *)ptr, v);
@@ -52278,7 +53079,8 @@ static JSValue js_atomics_wait(JSContext *ctx, · 50 unmodified lines
52278 int ret, size_log2, res;53079 int ret, size_log2, res;
52279 double d;53080 double d;
52280 53081
52281 ptr = js_atomics_get_ptr(ctx, &size_log2, NULL, argv[0], argv[1], TRUE);53082 ptr = js_atomics_get_ptr(ctx, NULL, &size_log2, NULL,
53083 argv[0], argv[1], 2);
52282 if (!ptr)53084 if (!ptr)
52283 return JS_EXCEPTION;53085 return JS_EXCEPTION;
52284#ifdef CONFIG_BIGNUM53086#ifdef CONFIG_BIGNUM
@@ -52357,8 +53159,9 @@ static JSValue js_atomics_notify(JSContext *ctx, · 72 unmodified lines
52357 int32_t count, n;53159 int32_t count, n;
52358 void *ptr;53160 void *ptr;
52359 JSAtomicsWaiter *waiter;53161 JSAtomicsWaiter *waiter;
53162 JSArrayBuffer *abuf;
52360 53163
52361 ptr = js_atomics_get_ptr(ctx, NULL, NULL, argv[0], argv[1], TRUE);53164 ptr = js_atomics_get_ptr(ctx, &abuf, NULL, NULL, argv[0], argv[1], 1);
52362 if (!ptr)53165 if (!ptr)
52363 return JS_EXCEPTION;53166 return JS_EXCEPTION;
52364 53167
@@ -52368,9 +53171,11 @@ static JSValue js_atomics_notify(JSContext *ctx, · 3 unmodified lines
52368 if (JS_ToInt32Clamp(ctx, &count, argv[2], 0, INT32_MAX, 0))53171 if (JS_ToInt32Clamp(ctx, &count, argv[2], 0, INT32_MAX, 0))
52369 return JS_EXCEPTION;53172 return JS_EXCEPTION;
52370 }53173 }
53174 if (abuf->detached)
53175 return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
52371 53176
52372 n = 0;53177 n = 0;
52373 if (count > 0) {53178 if (abuf->shared && count > 0) {
52374 pthread_mutex_lock(&js_atomics_mutex);53179 pthread_mutex_lock(&js_atomics_mutex);
52375 init_list_head(&waiter_list);53180 init_list_head(&waiter_list);
52376 list_for_each_safe(el, el1, &js_atomics_waiter_list) {53181 list_for_each_safe(el, el1, &js_atomics_waiter_list) {
quickjs.h+25−4
@@ -498,7 +498,7 @@ int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id); · 497 unmodified lines
498 498
499static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val)499static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val)
500{500{
501 return JS_MKVAL(JS_TAG_BOOL, val);501 return JS_MKVAL(JS_TAG_BOOL, (val != 0));
502}502}
503 503
504static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val)504static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val)
@@ -746,7 +746,7 @@ int JS_IsExtensible(JSContext *ctx, JSValueConst obj); · 241 unmodified lines
746int JS_PreventExtensions(JSContext *ctx, JSValueConst obj);746int JS_PreventExtensions(JSContext *ctx, JSValueConst obj);
747int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags);747int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags);
748int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val);748int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val);
749JSValueConst JS_GetPrototype(JSContext *ctx, JSValueConst val);749JSValue JS_GetPrototype(JSContext *ctx, JSValueConst val);
750 750
751#define JS_GPN_STRING_MASK (1 << 0)751#define JS_GPN_STRING_MASK (1 << 0)
752#define JS_GPN_SYMBOL_MASK (1 << 1)752#define JS_GPN_SYMBOL_MASK (1 << 1)
@@ -796,6 +796,9 @@ void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id); · 43 unmodified lines
796/* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */796/* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */
797JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,797JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,
798 const char *filename);798 const char *filename);
799#define JS_PARSE_JSON_EXT (1 << 0) /* allow extended JSON */
800JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len,
801 const char *filename, int flags);
799JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,802JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
800 JSValueConst replacer, JSValueConst space0);803 JSValueConst replacer, JSValueConst space0);
801 804
@@ -810,6 +813,14 @@ JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, · 8 unmodified lines
810 size_t *pbyte_offset,813 size_t *pbyte_offset,
811 size_t *pbyte_length,814 size_t *pbyte_length,
812 size_t *pbytes_per_element);815 size_t *pbytes_per_element);
816typedef struct {
817 void *(*sab_alloc)(void *opaque, size_t size);
818 void (*sab_free)(void *opaque, void *ptr);
819 void (*sab_dup)(void *opaque, void *ptr);
820 void *sab_opaque;
821} JSSharedArrayBufferFunctions;
822void JS_SetSharedArrayBufferFunctions(JSRuntime *rt,
823 const JSSharedArrayBufferFunctions *sf);
813 824
814JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs);825JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs);
815 826
@@ -853,14 +864,24 @@ JS_BOOL JS_IsJobPending(JSRuntime *rt); · 37 unmodified lines
853int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx);864int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx);
854 865
855/* Object Writer/Reader (currently only used to handle precompiled code) */866/* Object Writer/Reader (currently only used to handle precompiled code) */
856#define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */867#define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */
857#define JS_WRITE_OBJ_BSWAP (1 << 1) /* byte swapped output */868#define JS_WRITE_OBJ_BSWAP (1 << 1) /* byte swapped output */
869#define JS_WRITE_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */
870#define JS_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to
871 encode arbitrary object
872 graph */
858uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,873uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,
859 int flags);874 int flags);
875uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
876 int flags, uint8_t ***psab_tab, size_t *psab_tab_len);
877
860#define JS_READ_OBJ_BYTECODE (1 << 0) /* allow function/module */878#define JS_READ_OBJ_BYTECODE (1 << 0) /* allow function/module */
861#define JS_READ_OBJ_ROM_DATA (1 << 1) /* avoid duplicating 'buf' data */879#define JS_READ_OBJ_ROM_DATA (1 << 1) /* avoid duplicating 'buf' data */
880#define JS_READ_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */
881#define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */
862JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,882JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
863 int flags);883 int flags);
884
864/* load the dependencies of the module 'obj'. Useful when JS_ReadObject()885/* load the dependencies of the module 'obj'. Useful when JS_ReadObject()
865 returns a module. */886 returns a module. */
866int JS_ResolveModule(JSContext *ctx, JSValueConst obj);887int JS_ResolveModule(JSContext *ctx, JSValueConst obj);
repl.js+58−14
@@ -209,6 +209,29 @@ import * as os from "os"; · 208 unmodified lines
209 (is_alpha(c) || is_digit(c) || c == '_' || c == '$');209 (is_alpha(c) || is_digit(c) || c == '_' || c == '$');
210 }210 }
211 211
212 function ucs_length(str) {
213 var len, c, i, str_len = str.length;
214 len = 0;
215 /* we never count the trailing surrogate to have the
216 following property: ucs_length(str) =
217 ucs_length(str.substring(0, a)) + ucs_length(str.substring(a,
218 str.length)) for 0 <= a <= str.length */
219 for(i = 0; i < str_len; i++) {
220 c = str.charCodeAt(i);
221 if (c < 0xdc00 || c >= 0xe000)
222 len++;
223 }
224 return len;
225 }
226
227 function is_trailing_surrogate(c) {
228 var d;
229 if (typeof c !== "string")
230 return false;
231 d = c.codePointAt(0); /* can be NaN if empty string */
232 return d >= 0xdc00 && d < 0xe000;
233 }
234
212 function is_balanced(a, b) {235 function is_balanced(a, b) {
213 switch (a + b) {236 switch (a + b) {
214 case "()":237 case "()":
@@ -235,6 +258,7 @@ import * as os from "os"; · 20 unmodified lines
235 std.puts("\x1b[" + ((n != 1) ? n : "") + code);258 std.puts("\x1b[" + ((n != 1) ? n : "") + code);
236 }259 }
237 260
261 /* XXX: handle double-width characters */
238 function move_cursor(delta) {262 function move_cursor(delta) {
239 var i, l;263 var i, l;
240 if (delta > 0) {264 if (delta > 0) {
@@ -269,15 +293,16 @@ import * as os from "os"; · 28 unmodified lines
269 }293 }
270 294
271 function update() {295 function update() {
272 var i;296 var i, cmd_len;
273 297 /* cursor_pos is the position in 16 bit characters inside the
298 UTF-16 string 'cmd' */
274 if (cmd != last_cmd) {299 if (cmd != last_cmd) {
275 if (!show_colors && last_cmd.substring(0, last_cursor_pos) == cmd.substring(0, last_cursor_pos)) {300 if (!show_colors && last_cmd.substring(0, last_cursor_pos) == cmd.substring(0, last_cursor_pos)) {
276 /* optimize common case */301 /* optimize common case */
277 std.puts(cmd.substring(last_cursor_pos));302 std.puts(cmd.substring(last_cursor_pos));
278 } else {303 } else {
279 /* goto the start of the line */304 /* goto the start of the line */
280 move_cursor(-last_cursor_pos);305 move_cursor(-ucs_length(last_cmd.substring(0, last_cursor_pos)));
281 if (show_colors) {306 if (show_colors) {
282 var str = mexpr ? mexpr + '\n' + cmd : cmd;307 var str = mexpr ? mexpr + '\n' + cmd : cmd;
283 var start = str.length - cmd.length;308 var start = str.length - cmd.length;
@@ -287,8 +312,7 @@ import * as os from "os"; · 3 unmodified lines
287 std.puts(cmd);312 std.puts(cmd);
288 }313 }
289 }314 }
290 /* Note: assuming no surrogate pairs */315 term_cursor_x = (term_cursor_x + ucs_length(cmd)) % term_width;
291 term_cursor_x = (term_cursor_x + cmd.length) % term_width;
292 if (term_cursor_x == 0) {316 if (term_cursor_x == 0) {
293 /* show the cursor on the next line */317 /* show the cursor on the next line */
294 std.puts(" \x08");318 std.puts(" \x08");
@@ -298,7 +322,11 @@ import * as os from "os"; · 3 unmodified lines
298 last_cmd = cmd;322 last_cmd = cmd;
299 last_cursor_pos = cmd.length;323 last_cursor_pos = cmd.length;
300 }324 }
301 move_cursor(cursor_pos - last_cursor_pos);325 if (cursor_pos > last_cursor_pos) {
326 move_cursor(ucs_length(cmd.substring(last_cursor_pos, cursor_pos)));
327 } else if (cursor_pos < last_cursor_pos) {
328 move_cursor(-ucs_length(cmd.substring(cursor_pos, last_cursor_pos)));
329 }
302 last_cursor_pos = cursor_pos;330 last_cursor_pos = cursor_pos;
303 std.out.flush();331 std.out.flush();
304 }332 }
@@ -333,13 +361,19 @@ import * as os from "os"; · 28 unmodified lines
333 }361 }
334 362
335 function forward_char() {363 function forward_char() {
336 if (cursor_pos < cmd.length)364 if (cursor_pos < cmd.length) {
337 cursor_pos++;365 cursor_pos++;
366 while (is_trailing_surrogate(cmd.charAt(cursor_pos)))
367 cursor_pos++;
368 }
338 }369 }
339 370
340 function backward_char() {371 function backward_char() {
341 if (cursor_pos > 0)372 if (cursor_pos > 0) {
342 cursor_pos--;373 cursor_pos--;
374 while (is_trailing_surrogate(cmd.charAt(cursor_pos)))
375 cursor_pos--;
376 }
343 }377 }
344 378
345 function skip_word_forward(pos) {379 function skip_word_forward(pos) {
@@ -419,8 +453,18 @@ import * as os from "os"; · 73 unmodified lines
419 }453 }
420 454
421 function delete_char_dir(dir) {455 function delete_char_dir(dir) {
422 var start = cursor_pos - (dir < 0);456 var start, end;
423 var end = start + 1;457
458 start = cursor_pos;
459 if (dir < 0) {
460 start--;
461 while (is_trailing_surrogate(cmd.charAt(start)))
462 start--;
463 }
464 end = start + 1;
465 while (is_trailing_surrogate(cmd.charAt(end)))
466 end++;
467
424 if (start >= 0 && start < cmd.length) {468 if (start >= 0 && start < cmd.length) {
425 if (last_fun === kill_region) {469 if (last_fun === kill_region) {
426 kill_region(start, end, dir);470 kill_region(start, end, dir);
@@ -752,7 +796,7 @@ import * as os from "os"; · 325 unmodified lines
752 function readline_print_prompt()796 function readline_print_prompt()
753 {797 {
754 std.puts(prompt);798 std.puts(prompt);
755 term_cursor_x = prompt.length % term_width;799 term_cursor_x = ucs_length(prompt) % term_width;
756 last_cmd = "";800 last_cmd = "";
757 last_cursor_pos = 0;801 last_cursor_pos = 0;
758 }802 }
@@ -785,7 +829,7 @@ import * as os from "os"; · 26 unmodified lines
785 829
786 function handle_char(c1) {830 function handle_char(c1) {
787 var c;831 var c;
788 c = String.fromCharCode(c1);832 c = String.fromCodePoint(c1);
789 switch(readline_state) {833 switch(readline_state) {
790 case 0:834 case 0:
791 if (c == '\x1b') { /* '^[' - ESC */835 if (c == '\x1b') { /* '^[' - ESC */
@@ -825,7 +869,7 @@ import * as os from "os"; · 33 unmodified lines
825 var fun;869 var fun;
826 870
827 if (quote_flag) {871 if (quote_flag) {
828 if (keys.length === 1)872 if (ucs_length(keys) === 1)
829 insert(keys);873 insert(keys);
830 quote_flag = false;874 quote_flag = false;
831 } else if (fun = commands[keys]) {875 } else if (fun = commands[keys]) {
@@ -845,7 +889,7 @@ import * as os from "os"; · 13 unmodified lines
845 return;889 return;
846 }890 }
847 last_fun = this_fun;891 last_fun = this_fun;
848 } else if (keys.length === 1 && keys >= ' ') {892 } else if (ucs_length(keys) === 1 && keys >= ' ') {
849 insert(keys);893 insert(keys);
850 last_fun = insert;894 last_fun = insert;
851 } else {895 } else {
test262.conf+1−0
@@ -58,6 +58,7 @@ arrow-function · 57 unmodified lines
58async-functions58async-functions
59async-iteration59async-iteration
60Atomics60Atomics
61Atomics.waitAsync=skip
61BigInt62BigInt
62caller63caller
63class64class
test262_errors.txt+4−2
@@ -2,6 +2,8 @@ test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-r · 1 unmodified line
2test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: strict mode: Test262Error: Expected a ReferenceError but got a ReferenceError2test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: strict mode: Test262Error: Expected a ReferenceError but got a ReferenceError
3test262/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. 3test262/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.
4test262/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. 4test262/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.
5test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js:46: SyntaxError: invalid group name
6test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js:46: strict mode: SyntaxError: invalid group name
5test262/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 all7test262/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
6test262/test/language/expressions/async-arrow-function/eval-var-scope-syntax-err.js:49: TypeError: $DONE() not called8test262/test/language/expressions/async-arrow-function/eval-var-scope-syntax-err.js:49: TypeError: $DONE() not called
7test262/test/language/expressions/async-function/named-eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called9test262/test/language/expressions/async-function/named-eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called
@@ -18,8 +20,8 @@ test262/test/language/expressions/object/method-definition/async-gen-meth-eval-v · 10 unmodified lines
18test262/test/language/expressions/object/method-definition/async-meth-eval-var-scope-syntax-err.js:36: TypeError: $DONE() not called20test262/test/language/expressions/object/method-definition/async-meth-eval-var-scope-syntax-err.js:36: TypeError: $DONE() not called
19test262/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 all21test262/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
20test262/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 all22test262/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
21test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:21: TypeError: value has no property23test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:21: TypeError: cannot read property 'c' of undefined
22test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:15: strict mode: TypeError: value has no property24test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:15: strict mode: TypeError: cannot read property '_b' of undefined
23test262/test/language/statements/async-function/eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called25test262/test/language/statements/async-function/eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called
24test262/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 all26test262/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
25test262/test/language/statements/class/elements/grammar-private-field-optional-chaining.js:26: SyntaxError: expecting field name27test262/test/language/statements/class/elements/grammar-private-field-optional-chaining.js:26: SyntaxError: expecting field name
tests/bjson.c+12−4
@@ -31,6 +31,7 @@ static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val, · 30 unmodified lines
31 uint64_t pos, len;31 uint64_t pos, len;
32 JSValue obj;32 JSValue obj;
33 size_t size;33 size_t size;
34 int flags;
34 35
35 if (JS_ToIndex(ctx, &pos, argv[1]))36 if (JS_ToIndex(ctx, &pos, argv[1]))
36 return JS_EXCEPTION;37 return JS_EXCEPTION;
@@ -41,7 +42,10 @@ static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val, · 4 unmodified lines
41 return JS_EXCEPTION;42 return JS_EXCEPTION;
42 if (pos + len > size)43 if (pos + len > size)
43 return JS_ThrowRangeError(ctx, "array buffer overflow");44 return JS_ThrowRangeError(ctx, "array buffer overflow");
44 obj = JS_ReadObject(ctx, buf + pos, len, 0);45 flags = 0;
46 if (JS_ToBool(ctx, argv[3]))
47 flags |= JS_READ_OBJ_REFERENCE;
48 obj = JS_ReadObject(ctx, buf + pos, len, flags);
45 return obj;49 return obj;
46}50}
47 51
@@ -51,8 +55,12 @@ static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val, · 3 unmodified lines
51 size_t len;55 size_t len;
52 uint8_t *buf;56 uint8_t *buf;
53 JSValue array;57 JSValue array;
58 int flags;
54 59
55 buf = JS_WriteObject(ctx, &len, argv[0], 0);60 flags = 0;
61 if (JS_ToBool(ctx, argv[1]))
62 flags |= JS_WRITE_OBJ_REFERENCE;
63 buf = JS_WriteObject(ctx, &len, argv[0], flags);
56 if (!buf)64 if (!buf)
57 return JS_EXCEPTION;65 return JS_EXCEPTION;
58 array = JS_NewArrayBufferCopy(ctx, buf, len);66 array = JS_NewArrayBufferCopy(ctx, buf, len);
@@ -61,8 +69,8 @@ static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val, · 2 unmodified lines
61}69}
62 70
63static const JSCFunctionListEntry js_bjson_funcs[] = {71static const JSCFunctionListEntry js_bjson_funcs[] = {
64 JS_CFUNC_DEF("read", 3, js_bjson_read ),72 JS_CFUNC_DEF("read", 4, js_bjson_read ),
65 JS_CFUNC_DEF("write", 1, js_bjson_write ),73 JS_CFUNC_DEF("write", 2, js_bjson_write ),
66};74};
67 75
68static int js_bjson_init(JSContext *ctx, JSModuleDef *m)76static int js_bjson_init(JSContext *ctx, JSModuleDef *m)
tests/microbench.js+14−0
@@ -228,6 +228,19 @@ function prop_create(n) · 227 unmodified lines
228 return n * 4;228 return n * 4;
229}229}
230 230
231function prop_delete(n)
232{
233 var obj, j;
234 obj = {};
235 for(j = 0; j < n; j++) {
236 obj[j] = 1;
237 }
238 for(j = 0; j < n; j++) {
239 delete obj[j];
240 }
241 return n;
242}
243
231function array_read(n)244function array_read(n)
232{245{
233 var tab, len, sum, i, j;246 var tab, len, sum, i, j;
@@ -945,6 +958,7 @@ function main(argc, argv, g) · 711 unmodified lines
945 prop_read,958 prop_read,
946 prop_write,959 prop_write,
947 prop_create,960 prop_create,
961 prop_delete,
948 array_read,962 array_read,
949 array_write,963 array_write,
950 array_prop_create,964 array_prop_create,
tests/test_bjson.js+73−7
@@ -1,12 +1,20 @@
1import * as bjson from "./bjson.so";1import * as bjson from "./bjson.so";
2 2
3function assert(b, str)3function assert(actual, expected, message) {
4{4 if (arguments.length == 1)
5 if (b) {5 expected = true;
6
7 if (actual === expected)
6 return;8 return;
7 } else {9
8 throw Error("assertion failed: " + str);10 if (actual !== null && expected !== null
9 }11 && typeof actual == 'object' && typeof expected == 'object'
12 && actual.toString() === expected.toString())
13 return;
14
15 throw Error("assertion failed: got |" + actual + "|" +
16 ", expected |" + expected + "|" +
17 (message ? " (" + message + ")" : ""));
10}18}
11 19
12function toHex(a)20function toHex(a)
@@ -24,6 +32,20 @@ function toHex(a) · 11 unmodified lines
24 return s;32 return s;
25}33}
26 34
35function isArrayLike(a)
36{
37 return Array.isArray(a) ||
38 (a instanceof Uint8ClampedArray) ||
39 (a instanceof Uint8Array) ||
40 (a instanceof Uint16Array) ||
41 (a instanceof Uint32Array) ||
42 (a instanceof Int8Array) ||
43 (a instanceof Int16Array) ||
44 (a instanceof Int32Array) ||
45 (a instanceof Float32Array) ||
46 (a instanceof Float64Array);
47}
48
27function toStr(a)49function toStr(a)
28{50{
29 var s, i, props, prop;51 var s, i, props, prop;
@@ -32,7 +54,15 @@ function toStr(a) · 2 unmodified lines
32 case "object":54 case "object":
33 if (a === null)55 if (a === null)
34 return "null";56 return "null";
35 if (Array.isArray(a)) {57 if (a instanceof Date) {
58 s = "Date(" + toStr(a.valueOf()) + ")";
59 } else if (a instanceof Number) {
60 s = "Number(" + toStr(a.valueOf()) + ")";
61 } else if (a instanceof String) {
62 s = "String(" + toStr(a.valueOf()) + ")";
63 } else if (a instanceof Boolean) {
64 s = "Boolean(" + toStr(a.valueOf()) + ")";
65 } else if (isArrayLike(a)) {
36 s = "[";66 s = "[";
37 for(i = 0; i < a.length; i++) {67 for(i = 0; i < a.length; i++) {
38 if (i != 0)68 if (i != 0)
@@ -85,6 +115,35 @@ function bjson_test(a) · 46 unmodified lines
85 }115 }
86}116}
87 117
118/* test multiple references to an object including circular
119 references */
120function bjson_test_reference()
121{
122 var array, buf, i, n, array_buffer;
123 n = 16;
124 array = [];
125 for(i = 0; i < n; i++)
126 array[i] = {};
127 array_buffer = new ArrayBuffer(n);
128 for(i = 0; i < n; i++) {
129 array[i].next = array[(i + 1) % n];
130 array[i].idx = i;
131 array[i].typed_array = new Uint8Array(array_buffer, i, 1);
132 }
133 buf = bjson.write(array, true);
134
135 array = bjson.read(buf, 0, buf.byteLength, true);
136
137 /* check the result */
138 for(i = 0; i < n; i++) {
139 assert(array[i].next, array[(i + 1) % n]);
140 assert(array[i].idx, i);
141 assert(array[i].typed_array.buffer, array_buffer);
142 assert(array[i].typed_array.length, 1);
143 assert(array[i].typed_array.byteOffset, i);
144 }
145}
146
88function bjson_test_all()147function bjson_test_all()
89{148{
90 var obj;149 var obj;
@@ -111,6 +170,11 @@ function bjson_test_all() · 20 unmodified lines
111 BigDecimal("1.233e-1000")]);170 BigDecimal("1.233e-1000")]);
112 }171 }
113 172
173 bjson_test([new Date(1234), new String("abc"), new Number(-12.1), new Boolean(true)]);
174
175 bjson_test(new Int32Array([123123, 222111, -32222]));
176 bjson_test(new Float64Array([123123, 222111.5]));
177
114 /* tested with a circular reference */178 /* tested with a circular reference */
115 obj = {};179 obj = {};
116 obj.x = obj;180 obj.x = obj;
@@ -120,6 +184,8 @@ function bjson_test_all() · 3 unmodified lines
120 } catch(e) {184 } catch(e) {
121 assert(e instanceof TypeError);185 assert(e instanceof TypeError);
122 }186 }
187
188 bjson_test_reference();
123}189}
124 190
125bjson_test_all();191bjson_test_all();
tests/test_builtin.js+4−0
@@ -287,6 +287,10 @@ function test_math() · 286 unmodified lines
287 assert(Math.ceil(a), 2);287 assert(Math.ceil(a), 2);
288 assert(Math.imul(0x12345678, 123), -1088058456);288 assert(Math.imul(0x12345678, 123), -1088058456);
289 assert(Math.fround(0.1), 0.10000000149011612);289 assert(Math.fround(0.1), 0.10000000149011612);
290 assert(Math.hypot() == 0);
291 assert(Math.hypot(-2) == 2);
292 assert(Math.hypot(3, 4) == 5);
293 assert(Math.abs(Math.hypot(3, 4, 5) - 7.0710678118654755) <= 1e-15);
290}294}
291 295
292function test_number()296function test_number()
tests/test_language.jsrenamed from tests/test_op.js+14−2
@@ -311,10 +311,21 @@ function test_template() · 310 unmodified lines
311 var a, b;311 var a, b;
312 b = 123;312 b = 123;
313 a = `abc${b}d`;313 a = `abc${b}d`;
314 assert(a === "abc123d");314 assert(a, "abc123d");
315 315
316 a = String.raw `abc${b}d`;316 a = String.raw `abc${b}d`;
317 assert(a === "abc123d");317 assert(a, "abc123d");
318
319 a = "aaa";
320 b = "bbb";
321 assert(`aaa${a, b}ccc`, "aaabbbccc");
322}
323
324function test_template_skip()
325{
326 var a = "Bar";
327 var { b = `${a + `a${a}` }baz` } = {};
328 assert(b, "BaraBarbaz");
318}329}
319 330
320function test_object_literal()331function test_object_literal()
@@ -358,6 +369,7 @@ test_prototype(); · 37 unmodified lines
358test_arguments();369test_arguments();
359test_class();370test_class();
360test_template();371test_template();
372test_template_skip();
361test_object_literal();373test_object_literal();
362test_regexp_skip();374test_regexp_skip();
363test_labels();375test_labels();
tests/test_std.js+21−0
@@ -26,6 +26,12 @@ try { std.loadScript("test_assert.js"); } catch(e) {} · 25 unmodified lines
26function test_printf()26function test_printf()
27{27{
28 assert(std.sprintf("a=%d s=%s", 123, "abc"), "a=123 s=abc");28 assert(std.sprintf("a=%d s=%s", 123, "abc"), "a=123 s=abc");
29 assert(std.sprintf("%010d", 123), "0000000123");
30 assert(std.sprintf("%x", -2), "fffffffe");
31 assert(std.sprintf("%lx", -2), "fffffffffffffffe");
32 assert(std.sprintf("%10.1f", 2.1), " 2.1");
33 assert(std.sprintf("%*.*f", 10, 2, -2.13), " -2.13");
34 assert(std.sprintf("%#lx", 0x7fffffffffffffffn), "0x7fffffffffffffff");
29}35}
30 36
31function test_file1()37function test_file1()
@@ -119,6 +125,20 @@ function test_popen() · 87 unmodified lines
119 os.remove(fname);125 os.remove(fname);
120}126}
121 127
128function test_ext_json()
129{
130 var expected, input, obj;
131 expected = '{"x":false,"y":true,"z2":null,"a":[1,8,160],"s":"str"}';
132 input = `{ "x":false, /*comments are allowed */
133 "y":true, // also a comment
134 z2:null, // unquoted property names
135 "a":[+1,0o10,0xa0,], // plus prefix, octal, hexadecimal
136 "s":"str",} // trailing comma in objects and arrays
137 `;
138 obj = std.parseExtJSON(input);
139 assert(JSON.stringify(obj), expected);
140}
141
122function test_os()142function test_os()
123{143{
124 var fd, fpath, fname, fdir, buf, buf2, i, files, err, fdate, st, link_path;144 var fd, fpath, fname, fdir, buf, buf2, i, files, err, fdate, st, link_path;
@@ -258,3 +278,4 @@ test_popen(); · 133 unmodified lines
258test_os();278test_os();
259test_os_exec();279test_os_exec();
260test_timer();280test_timer();
281test_ext_json();
tests/test_worker.js+93−0
@@ -0,0 +1,93 @@
1/* os.Worker API test */
2import * as std from "std";
3import * as os from "os";
4
5function assert(actual, expected, message) {
6 if (arguments.length == 1)
7 expected = true;
8
9 if (actual === expected)
10 return;
11
12 if (actual !== null && expected !== null
13 && typeof actual == 'object' && typeof expected == 'object'
14 && actual.toString() === expected.toString())
15 return;
16
17 throw Error("assertion failed: got |" + actual + "|" +
18 ", expected |" + expected + "|" +
19 (message ? " (" + message + ")" : ""));
20}
21
22var worker;
23
24function test_worker()
25{
26 var counter;
27
28 /* Note: can use std.loadFile() to read from a file */
29 worker = new os.Worker(`
30 import * as std from "std";
31 import * as os from "os";
32
33 var parent = os.Worker.parent;
34
35 function handle_msg(e) {
36 var ev = e.data;
37// print("child_recv", JSON.stringify(ev));
38 switch(ev.type) {
39 case "abort":
40 parent.postMessage({ type: "done" });
41 break;
42 case "sab":
43 /* modify the SharedArrayBuffer */
44 ev.buf[2] = 10;
45 parent.postMessage({ type: "sab_done", buf: ev.buf });
46 break;
47 }
48 }
49
50 function worker_main() {
51 var i;
52
53 parent.onmessage = handle_msg;
54 for(i = 0; i < 10; i++) {
55 parent.postMessage({ type: "num", num: i });
56 }
57 }
58 worker_main();
59`);
60
61 counter = 0;
62 worker.onmessage = function (e) {
63 var ev = e.data;
64// print("recv", JSON.stringify(ev));
65 switch(ev.type) {
66 case "num":
67 assert(ev.num, counter);
68 counter++;
69 if (counter == 10) {
70 /* test SharedArrayBuffer modification */
71 let sab = new SharedArrayBuffer(10);
72 let buf = new Uint8Array(sab);
73 worker.postMessage({ type: "sab", buf: buf });
74 }
75 break;
76 case "sab_done":
77 {
78 let buf = ev.buf;
79 /* check that the SharedArrayBuffer was modified */
80 assert(buf[2], 10);
81 worker.postMessage({ type: "abort" });
82 }
83 break;
84 case "done":
85 /* terminate */
86 worker.onmessage = null;
87 break;
88 }
89 };
90}
91
92
93test_worker();

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t