History

2020-09-06 release

bellard committed 6 years ago

Commit 7c312df1 parent 890076626 files · +896 −460Browse files

Unified · Split

26 files
  1. Changelog +9 −0
  2. TODO +2 −2
  3. VERSION +1 −1
  4. cutils.c +16 −5
  5. doc/jsbignum.html +2 −2
  6. doc/jsbignum.pdf +0 −0
  7. doc/quickjs.html +18 −10
  8. doc/quickjs.pdf +0 −0
  9. doc/quickjs.texi +15 −8
  10. libregexp.c +17 −3
  11. libregexp.h +1 −0
  12. libunicode.c +22 −4
  13. qjs.c +28 −15
  14. qjsc.c +54 −20
  15. qjscalc.js +2 −2
  16. quickjs-libc.c +58 −42
  17. quickjs-libc.h +2 −1
  18. quickjs-opcode.h +2 −1
  19. quickjs.c +573 −311
  20. quickjs.h +10 −0
  21. run-test262.c +10 −1
  22. test262.conf +3 −2
  23. tests/test_builtin.js +2 −0
  24. tests/test_language.js +19 −0
  25. tests/test_worker.js +1 −32
  26. tests/test_worker_module.js +31 −0
Changelog+9−0
@@ -1,3 +1,12 @@
1+2020-09-06:
2+
3+- added logical assignment operators
4+- added IsHTMLDDA support
5+- faster for-of loops
6+- os.Worker now takes a module filename as parameter
7+- qjsc: added -D option to compile dynamically loaded modules or workers
8+- misc bug fixes
9+
110 2020-07-05:
211
312 - modified JS_GetPrototype() to return a live value
TODO+2−2
@@ -74,5 +74,5 @@ REPL: · 73 unmodified lines
7474 Test262o: 0/11262 errors, 463 excluded
7575 Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
7676
77−Test262: 30/71095 errors, 870 excluded, 549 skipped
78−Test262 commit: 281eb10b2844929a7c0ac04527f5b42ce56509fd
77+Test262: 30/71748 errors, 868 excluded, 474 skipped
78+Test262 commit: 24c67328062383079ada85f4d253eb0526fd209b
VERSION+1−1
@@ -1 +1 @@
1−2020-07-05
1+2020-09-06
cutils.c+16−5
@@ -258,19 +258,30 @@ int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp) · 257 unmodified lines
258258 return c;
259259 }
260260 switch(c) {
261− case 0xc0 ... 0xdf:
261+ case 0xc0: case 0xc1: case 0xc2: case 0xc3:
262+ case 0xc4: case 0xc5: case 0xc6: case 0xc7:
263+ case 0xc8: case 0xc9: case 0xca: case 0xcb:
264+ case 0xcc: case 0xcd: case 0xce: case 0xcf:
265+ case 0xd0: case 0xd1: case 0xd2: case 0xd3:
266+ case 0xd4: case 0xd5: case 0xd6: case 0xd7:
267+ case 0xd8: case 0xd9: case 0xda: case 0xdb:
268+ case 0xdc: case 0xdd: case 0xde: case 0xdf:
262269 l = 1;
263270 break;
264− case 0xe0 ... 0xef:
271+ case 0xe0: case 0xe1: case 0xe2: case 0xe3:
272+ case 0xe4: case 0xe5: case 0xe6: case 0xe7:
273+ case 0xe8: case 0xe9: case 0xea: case 0xeb:
274+ case 0xec: case 0xed: case 0xee: case 0xef:
265275 l = 2;
266276 break;
267− case 0xf0 ... 0xf7:
277+ case 0xf0: case 0xf1: case 0xf2: case 0xf3:
278+ case 0xf4: case 0xf5: case 0xf6: case 0xf7:
268279 l = 3;
269280 break;
270− case 0xf8 ... 0xfb:
281+ case 0xf8: case 0xf9: case 0xfa: case 0xfb:
271282 l = 4;
272283 break;
273− case 0xfc ... 0xfd:
284+ case 0xfc: case 0xfd:
274285 l = 5;
275286 break;
276287 default:
doc/jsbignum.html+2−2
@@ -1,8 +1,7 @@
11 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
22 <html>
3−<!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ -->
3+<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->
44 <head>
5−<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
65 <title>Javascript Bignum Extensions</title>
76
87 <meta name="description" content="Javascript Bignum Extensions">
@@ -10,6 +9,7 @@ · 1 unmodified line
109 <meta name="resource-type" content="document">
1110 <meta name="distribution" content="global">
1211 <meta name="Generator" content="makeinfo">
12+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1313 <link href="#SEC_Contents" rel="contents" title="Table of Contents">
1414 <style type="text/css">
1515 <!--
doc/jsbignum.pdf+0−0

Binary file not shown.

doc/quickjs.html+18−10
@@ -1,8 +1,7 @@
11 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
22 <html>
3−<!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ -->
3+<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->
44 <head>
5−<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
65 <title>QuickJS Javascript Engine</title>
76
87 <meta name="description" content="QuickJS Javascript Engine">
@@ -10,6 +9,7 @@ · 1 unmodified line
109 <meta name="resource-type" content="document">
1110 <meta name="distribution" content="global">
1211 <meta name="Generator" content="makeinfo">
12+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1313 <link href="#SEC_Contents" rel="contents" title="Table of Contents">
1414 <style type="text/css">
1515 <!--
@@ -237,7 +237,7 @@ source is <code>import</code>. · 221 unmodified lines
237237 </dd>
238238 <dt><code>--bignum</code></dt>
239239 <dd><p>Enable the bignum extensions: BigDecimal object, BigFloat object and
240−the <code>&quot;use bigint&quot;</code> and <code>&quot;use math&quot;</code> directives.
240+the <code>&quot;use math&quot;</code> directive.
241241 </p>
242242 </dd>
243243 <dt><code>-I file</code></dt>
@@ -293,6 +293,13 @@ executable file. · 49 unmodified lines
293293 <dd><p>Compile as Javascript module (default=autodetect).
294294 </p>
295295 </dd>
296+<dt><code>-D module_name</code></dt>
297+<dd><p>Compile a dynamically loaded module and its dependencies. This option
298+is needed when your code uses the <code>import</code> keyword or the
299+<code>os.Worker</code> constructor because the compiler cannot statically
300+find the name of the dynamically loaded modules.
301+</p>
302+</dd>
296303 <dt><code>-M module_name[,cname]</code></dt>
297304 <dd><p>Add initialization code for an external C module. See the
298305 <code>c_module</code> example.
@@ -314,7 +321,7 @@ when the <code>-fno-x</code> options are used. · 15 unmodified lines
314321 </dd>
315322 <dt><code>-fbignum</code></dt>
316323 <dd><p>Enable the bignum extensions: BigDecimal object, BigFloat object and
317−the <code>&quot;use bigint&quot;</code> and <code>&quot;use math&quot;</code> directives.
324+the <code>&quot;use math&quot;</code> directive.
318325 </p>
319326 </dd>
320327 </dl>
@@ -989,13 +996,14 @@ to the timer. · 668 unmodified lines
989996 <code>&quot;win32&quot;</code> or <code>&quot;js&quot;</code>.
990997 </p>
991998 </dd>
992−<dt><code>Worker(source)</code></dt>
999+<dt><code>Worker(module_filename)</code></dt>
9931000 <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
995−source which is executed in the newly created thread. Threads normally
996−don&rsquo;t share any data and communicate between each other with
997−messages. Nested workers are not supported. An example is available in
998−<samp>tests/test_worker.js</samp>.
1001+<code>WebWorkers</code>. <code>module_filename</code> is a string specifying the
1002+module filename which is executed in the newly created thread. As for
1003+dynamically imported module, it is relative to the current script or
1004+module path. Threads normally don&rsquo;t share any data and communicate
1005+between each other with messages. Nested workers are not supported. An
1006+example is available in <samp>tests/test_worker.js</samp>.
9991007 </p>
10001008 <p>The worker class has the following static properties:
10011009 </p>
doc/quickjs.pdf+0−0

Binary file not shown.

doc/quickjs.texi+15−8
@@ -120,7 +120,7 @@ Load as ES6 script (default=autodetect). · 119 unmodified lines
120120
121121 @item --bignum
122122 Enable the bignum extensions: BigDecimal object, BigFloat object and
123−the @code{"use bigint"} and @code{"use math"} directives.
123+the @code{"use math"} directive.
124124
125125 @item -I file
126126 @item --include file
@@ -167,6 +167,12 @@ Set the C name of the generated data. · 40 unmodified lines
167167 @item -m
168168 Compile as Javascript module (default=autodetect).
169169
170+@item -D module_name
171+Compile a dynamically loaded module and its dependencies. This option
172+is needed when your code uses the @code{import} keyword or the
173+@code{os.Worker} constructor because the compiler cannot statically
174+find the name of the dynamically loaded modules.
175+
170176 @item -M module_name[,cname]
171177 Add initialization code for an external C module. See the
172178 @code{c_module} example.
@@ -184,7 +190,7 @@ Disable selected language features to produce a smaller executable file. · 11 unmodified lines
184190
185191 @item -fbignum
186192 Enable the bignum extensions: BigDecimal object, BigFloat object and
187−the @code{"use bigint"} and @code{"use math"} directives.
193+the @code{"use math"} directive.
188194
189195 @end table
190196
@@ -764,13 +770,14 @@ Cancel a timer. · 573 unmodified lines
764770 Return a string representing the platform: @code{"linux"}, @code{"darwin"},
765771 @code{"win32"} or @code{"js"}.
766772
767−@item Worker(source)
773+@item Worker(module_filename)
768774 Constructor to create a new thread (worker) with an API close to the
769−@code{WebWorkers}. @code{source} is a string containing the module
770−source which is executed in the newly created thread. Threads normally
771−don't share any data and communicate between each other with
772−messages. Nested workers are not supported. An example is available in
773−@file{tests/test_worker.js}.
775+@code{WebWorkers}. @code{module_filename} is a string specifying the
776+module filename which is executed in the newly created thread. As for
777+dynamically imported module, it is relative to the current script or
778+module path. Threads normally don't share any data and communicate
779+between each other with messages. Nested workers are not supported. An
780+example is available in @file{tests/test_worker.js}.
774781
775782 The worker class has the following static properties:
776783
libregexp.c+17−3
@@ -569,7 +569,8 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16) · 568 unmodified lines
569569 }
570570 }
571571 break;
572− case '0' ... '7':
572+ case '0': case '1': case '2': case '3':
573+ case '4': case '5': case '6': case '7':
573574 c -= '0';
574575 if (allow_utf16 == 2) {
575576 /* only accept \0 not followed by digit */
@@ -1410,7 +1411,9 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) · 834 unmodified lines
14101411 }
14111412 }
14121413 goto normal_char;
1413− case '1' ... '9':
1414+ case '1': case '2': case '3': case '4':
1415+ case '5': case '6': case '7': case '8':
1416+ case '9':
14141417 {
14151418 const uint8_t *q = ++p;
14161419
@@ -1434,7 +1437,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) · 17 unmodified lines
14341437 }
14351438 goto normal_char;
14361439 }
1437− return re_parse_error(s, "back reference out of range in reguar expression");
1440+ return re_parse_error(s, "back reference out of range in regular expression");
14381441 }
14391442 emit_back_reference:
14401443 last_atom_start = s->byte_code.size;
@@ -2533,6 +2536,17 @@ int lre_get_flags(const uint8_t *bc_buf) · 1092 unmodified lines
25332536 return bc_buf[RE_HEADER_FLAGS];
25342537 }
25352538
2539+/* Return NULL if no group names. Otherwise, return a pointer to
2540+ 'capture_count - 1' zero terminated UTF-8 strings. */
2541+const char *lre_get_groupnames(const uint8_t *bc_buf)
2542+{
2543+ uint32_t re_bytecode_len;
2544+ if ((lre_get_flags(bc_buf) & LRE_FLAG_NAMED_GROUPS) == 0)
2545+ return NULL;
2546+ re_bytecode_len = get_u32(bc_buf + 3);
2547+ return (const char *)(bc_buf + 7 + re_bytecode_len);
2548+}
2549+
25362550 #ifdef TEST
25372551
25382552 BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size)
libregexp.h+1−0
@@ -44,6 +44,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, · 43 unmodified lines
4444 void *opaque);
4545 int lre_get_capture_count(const uint8_t *bc_buf);
4646 int lre_get_flags(const uint8_t *bc_buf);
47+const char *lre_get_groupnames(const uint8_t *bc_buf);
4748 int lre_exec(uint8_t **capture,
4849 const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
4950 int cbuf_type, void *opaque);
libunicode.c+22−4
@@ -527,7 +527,13 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c, · 526 unmodified lines
527527 } else {
528528 d = unicode_decomp_data + unicode_decomp_table2[idx];
529529 switch(type) {
530− case DECOMP_TYPE_L1 ... DECOMP_TYPE_L7:
530+ case DECOMP_TYPE_L1:
531+ case DECOMP_TYPE_L2:
532+ case DECOMP_TYPE_L3:
533+ case DECOMP_TYPE_L4:
534+ case DECOMP_TYPE_L5:
535+ case DECOMP_TYPE_L6:
536+ case DECOMP_TYPE_L7:
531537 l = type - DECOMP_TYPE_L1 + 1;
532538 d += (c - code) * l * 2;
533539 for(i = 0; i < l; i++) {
@@ -535,7 +541,8 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c, · 1 unmodified line
535541 return 0;
536542 }
537543 return l;
538− case DECOMP_TYPE_LL1 ... DECOMP_TYPE_LL2:
544+ case DECOMP_TYPE_LL1:
545+ case DECOMP_TYPE_LL2:
539546 {
540547 uint32_t k, p;
541548 l = type - DECOMP_TYPE_LL1 + 1;
@@ -551,7 +558,11 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c, · 9 unmodified lines
551558 }
552559 }
553560 return l;
554− case DECOMP_TYPE_S1 ... DECOMP_TYPE_S5:
561+ case DECOMP_TYPE_S1:
562+ case DECOMP_TYPE_S2:
563+ case DECOMP_TYPE_S3:
564+ case DECOMP_TYPE_S4:
565+ case DECOMP_TYPE_S5:
555566 l = type - DECOMP_TYPE_S1 + 1;
556567 d += (c - code) * l;
557568 for(i = 0; i < l; i++) {
@@ -582,7 +593,14 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c, · 24 unmodified lines
582593 case DECOMP_TYPE_B18:
583594 l = 18;
584595 goto decomp_type_b;
585− case DECOMP_TYPE_B1 ... DECOMP_TYPE_B8:
596+ case DECOMP_TYPE_B1:
597+ case DECOMP_TYPE_B2:
598+ case DECOMP_TYPE_B3:
599+ case DECOMP_TYPE_B4:
600+ case DECOMP_TYPE_B5:
601+ case DECOMP_TYPE_B6:
602+ case DECOMP_TYPE_B7:
603+ case DECOMP_TYPE_B8:
586604 l = type - DECOMP_TYPE_B1 + 1;
587605 decomp_type_b:
588606 {
qjs.c+28−15
@@ -46,6 +46,7 @@ extern const uint32_t qjsc_repl_size; · 45 unmodified lines
4646 #ifdef CONFIG_BIGNUM
4747 extern const uint8_t qjsc_qjscalc[];
4848 extern const uint32_t qjsc_qjscalc_size;
49+static int bignum_ext;
4950 #endif
5051
5152 static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
@@ -101,6 +102,27 @@ static int eval_file(JSContext *ctx, const char *filename, int module) · 49 unmodified lines
101102 return ret;
102103 }
103104
105+/* also used to initialize the worker context */
106+static JSContext *JS_NewCustomContext(JSRuntime *rt)
107+{
108+ JSContext *ctx;
109+ ctx = JS_NewContext(rt);
110+ if (!ctx)
111+ return NULL;
112+#ifdef CONFIG_BIGNUM
113+ if (bignum_ext) {
114+ JS_AddIntrinsicBigFloat(ctx);
115+ JS_AddIntrinsicBigDecimal(ctx);
116+ JS_AddIntrinsicOperators(ctx);
117+ JS_EnableBignumExt(ctx, TRUE);
118+ }
119+#endif
120+ /* system modules */
121+ js_init_module_std(ctx, "std");
122+ js_init_module_os(ctx, "os");
123+ return ctx;
124+}
125+
104126 #if defined(__APPLE__)
105127 #define MALLOC_OVERHEAD 0
106128 #else
@@ -294,7 +316,7 @@ int main(int argc, char **argv) · 187 unmodified lines
294316 char *include_list[32];
295317 int i, include_count = 0;
296318 #ifdef CONFIG_BIGNUM
297− int load_jscalc, bignum_ext = 0;
319+ int load_jscalc;
298320 #endif
299321 size_t stack_size = 0;
300322
@@ -426,6 +448,9 @@ int main(int argc, char **argv) · 125 unmodified lines
426448 }
427449 }
428450
451+ if (load_jscalc)
452+ bignum_ext = 1;
453+
429454 if (trace_memory) {
430455 js_trace_malloc_init(&trace_data);
431456 rt = JS_NewRuntime2(&trace_mf, &trace_data);
@@ -440,22 +465,14 @@ int main(int argc, char **argv) · 8 unmodified lines
440465 JS_SetMemoryLimit(rt, memory_limit);
441466 if (stack_size != 0)
442467 JS_SetMaxStackSize(rt, stack_size);
468+ js_std_set_worker_new_context_func(JS_NewCustomContext);
443469 js_std_init_handlers(rt);
444− ctx = JS_NewContext(rt);
470+ ctx = JS_NewCustomContext(rt);
445471 if (!ctx) {
446472 fprintf(stderr, "qjs: cannot allocate JS context\n");
447473 exit(2);
448474 }
449475
450−#ifdef CONFIG_BIGNUM
451− if (bignum_ext || load_jscalc) {
452− JS_AddIntrinsicBigFloat(ctx);
453− JS_AddIntrinsicBigDecimal(ctx);
454− JS_AddIntrinsicOperators(ctx);
455− JS_EnableBignumExt(ctx, TRUE);
456− }
457−#endif
458−
459476 /* loader for ES6 modules */
460477 JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
461478
@@ -472,10 +489,6 @@ int main(int argc, char **argv) · 10 unmodified lines
472489 #endif
473490 js_std_add_helpers(ctx, argc - optind, argv + optind);
474491
475− /* system modules */
476− js_init_module_std(ctx, "std");
477− js_init_module_os(ctx, "os");
478−
479492 /* make 'std' and 'os' visible to non module code */
480493 if (load_std) {
481494 const char *str = "import * as std from 'std';\n"
qjsc.c+54−20
@@ -326,6 +326,7 @@ static const char main_c_template1[] = · 325 unmodified lines
326326 " JSRuntime *rt;\n"
327327 " JSContext *ctx;\n"
328328 " rt = JS_NewRuntime();\n"
329+ " js_std_set_worker_new_context_func(JS_NewCustomContext);\n"
329330 " js_std_init_handlers(rt);\n"
330331 ;
331332
@@ -349,6 +350,7 @@ void help(void) · 17 unmodified lines
349350 "-o output set the output filename\n"
350351 "-N cname set the C name of the generated data\n"
351352 "-m compile as Javascript module (default=autodetect)\n"
353+ "-D module_name compile a dynamically loaded module or worker\n"
352354 "-M module_name[,cname] add initialization code for an external C module\n"
353355 "-x byte swapped output\n"
354356 "-p prefix set the prefix of the generated C names\n"
@@ -494,6 +496,7 @@ int main(int argc, char **argv) · 139 unmodified lines
494496 #ifdef CONFIG_BIGNUM
495497 BOOL bignum_ext = FALSE;
496498 #endif
499+ namelist_t dynamic_module_list;
497500
498501 out_filename = NULL;
499502 output_type = OUTPUT_EXECUTABLE;
@@ -504,13 +507,14 @@ int main(int argc, char **argv) · 4 unmodified lines
504507 verbose = 0;
505508 use_lto = FALSE;
506509 stack_size = 0;
510+ memset(&dynamic_module_list, 0, sizeof(dynamic_module_list));
507511
508512 /* add system modules */
509513 namelist_add(&cmodule_list, "std", "std", 0);
510514 namelist_add(&cmodule_list, "os", "os", 0);
511515
512516 for(;;) {
513− c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:");
517+ c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:");
514518 if (c == -1)
515519 break;
516520 switch(c) {
@@ -576,6 +580,9 @@ int main(int argc, char **argv) · 59 unmodified lines
576580 namelist_add(&cmodule_list, path, cname, 0);
577581 }
578582 break;
583+ case 'D':
584+ namelist_add(&dynamic_module_list, optarg, NULL, 0);
585+ break;
579586 case 'x':
580587 byte_swap = TRUE;
581588 break;
@@ -656,22 +663,22 @@ int main(int argc, char **argv) · 74 unmodified lines
656663 cname = NULL;
657664 }
658665
659− if (output_type != OUTPUT_C) {
660− fputs(main_c_template1, fo);
661− fprintf(fo, " ctx = JS_NewContextRaw(rt);\n");
662−
663− if (stack_size != 0) {
664− fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n",
665− (unsigned int)stack_size);
666− }
667−
668− /* add the module loader if necessary */
669− if (feature_bitmap & (1 << FE_MODULE_LOADER)) {
670− fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
666+ for(i = 0; i < dynamic_module_list.count; i++) {
667+ if (!jsc_module_loader(ctx, dynamic_module_list.array[i].name, NULL)) {
668+ fprintf(stderr, "Could not load dynamic module '%s'\n",
669+ dynamic_module_list.array[i].name);
670+ exit(1);
671671 }
672−
672+ }
673+
674+ if (output_type != OUTPUT_C) {
675+ fprintf(fo,
676+ "static JSContext *JS_NewCustomContext(JSRuntime *rt)\n"
677+ "{\n"
678+ " JSContext *ctx = JS_NewContextRaw(rt);\n"
679+ " if (!ctx)\n"
680+ " return NULL;\n");
673681 /* add the basic objects */
674−
675682 fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n");
676683 for(i = 0; i < countof(feature_list); i++) {
677684 if ((feature_bitmap & ((uint64_t)1 << i)) &&
@@ -689,8 +696,8 @@ int main(int argc, char **argv) · 11 unmodified lines
689696 " JS_EnableBignumExt(ctx, 1);\n");
690697 }
691698 #endif
692− fprintf(fo, " js_std_add_helpers(ctx, argc, argv);\n");
693−
699+ /* add the precompiled modules (XXX: could modify the module
700+ loader instead) */
694701 for(i = 0; i < init_module_list.count; i++) {
695702 namelist_entry_t *e = &init_module_list.array[i];
696703 /* initialize the static C modules */
@@ -702,12 +709,39 @@ int main(int argc, char **argv) · 5 unmodified lines
702709 " }\n",
703710 e->short_name, e->short_name, e->name);
704711 }
712+ for(i = 0; i < cname_list.count; i++) {
713+ namelist_entry_t *e = &cname_list.array[i];
714+ if (e->flags) {
715+ fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 1);\n",
716+ e->name, e->name);
717+ }
718+ }
719+ fprintf(fo,
720+ " return ctx;\n"
721+ "}\n\n");
722+
723+ fputs(main_c_template1, fo);
724+
725+ if (stack_size != 0) {
726+ fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n",
727+ (unsigned int)stack_size);
728+ }
729+
730+ /* add the module loader if necessary */
731+ if (feature_bitmap & (1 << FE_MODULE_LOADER)) {
732+ fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
733+ }
734+
735+ fprintf(fo,
736+ " ctx = JS_NewCustomContext(rt);\n"
737+ " js_std_add_helpers(ctx, argc, argv);\n");
705738
706739 for(i = 0; i < cname_list.count; i++) {
707740 namelist_entry_t *e = &cname_list.array[i];
708− fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, %s);\n",
709− e->name, e->name,
710− e->flags ? "1" : "0");
741+ if (!e->flags) {
742+ fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 0);\n",
743+ e->name, e->name);
744+ }
711745 }
712746 fputs(main_c_template2, fo);
713747 }
qjscalc.js+2−2
@@ -1826,7 +1826,7 @@ var Integer, Float, Fraction, Complex, Mod, Polynomial, PolyMod, RationalFunctio · 1825 unmodified lines
18261826 j = emin + i;
18271827 if (j == -1) {
18281828 if (a[i] != 0)
1829− throw RangError("cannot represent integ(1/X)");
1829+ throw RangeError("cannot represent integ(1/X)");
18301830 } else {
18311831 r[i] = a[i] / (j + 1);
18321832 }
@@ -1853,7 +1853,7 @@ var Integer, Float, Fraction, Complex, Mod, Polynomial, PolyMod, RationalFunctio · 20 unmodified lines
18531853 log() {
18541854 var a = this, r;
18551855 if (a.emin != 0)
1856− throw Range("log argument must have a non zero constant term");
1856+ throw RangeError("log argument must have a non zero constant term");
18571857 r = integ(deriv(a) / a);
18581858 /* add the constant term */
18591859 r += global.log(a[0]);
quickjs-libc.c+58−42
@@ -2993,9 +2993,8 @@ typedef struct { · 2992 unmodified lines
29932993 } JSWorkerData;
29942994
29952995 typedef struct {
2996− /* source code of the worker */
2997− char *eval_buf;
2998− size_t eval_buf_len;
2996+ char *filename; /* module filename */
2997+ char *basename; /* module base name */
29992998 JSWorkerMessagePipe *recv_pipe, *send_pipe;
30002999 } WorkerFuncArgs;
30013000
@@ -3005,6 +3004,7 @@ typedef struct { · 3 unmodified lines
30053004 } JSSABHeader;
30063005
30073006 static JSClassID js_worker_class_id;
3007+static JSContext *(*js_worker_new_context_func)(JSRuntime *rt);
30083008
30093009 static int atomic_add_int(int *ptr, int v)
30103010 {
@@ -3136,7 +3136,6 @@ static void *worker_func(void *opaque) · 125 unmodified lines
31363136 JSRuntime *rt;
31373137 JSThreadState *ts;
31383138 JSContext *ctx;
3139− JSValue retval;
31403139
31413140 rt = JS_NewRuntime();
31423141 if (rt == NULL) {
@@ -3145,12 +3144,16 @@ static void *worker_func(void *opaque) · 2 unmodified lines
31453144 }
31463145 js_std_init_handlers(rt);
31473146
3147+ JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
3148+
31483149 /* set the pipe to communicate with the parent */
31493150 ts = JS_GetRuntimeOpaque(rt);
31503151 ts->recv_pipe = args->recv_pipe;
31513152 ts->send_pipe = args->send_pipe;
31523153
3153− ctx = JS_NewContext(rt);
3154+ /* function pointer to avoid linking the whole JS_NewContext() if
3155+ not needed */
3156+ ctx = js_worker_new_context_func(rt);
31543157 if (ctx == NULL) {
31553158 fprintf(stderr, "JS_NewContext failure");
31563159 }
@@ -3159,18 +3162,11 @@ static void *worker_func(void *opaque) · 2 unmodified lines
31593162
31603163 js_std_add_helpers(ctx, -1, NULL);
31613164
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))
3165+ if (!JS_RunModule(ctx, args->basename, args->filename))
31723166 js_std_dump_error(ctx);
3173− JS_FreeValue(ctx, retval);
3167+ free(args->filename);
3168+ free(args->basename);
3169+ free(args);
31743170
31753171 js_std_loop(ctx);
31763172
@@ -3216,52 +3212,53 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, · 39 unmodified lines
32163212 int argc, JSValueConst *argv)
32173213 {
32183214 JSRuntime *rt = JS_GetRuntime(ctx);
3219− WorkerFuncArgs *args;
3220− const char *str;
3221− size_t str_len;
3215+ WorkerFuncArgs *args = NULL;
32223216 pthread_t tid;
32233217 pthread_attr_t attr;
32243218 JSValue obj = JS_UNDEFINED;
32253219 int ret;
3220+ const char *filename = NULL, *basename;
3221+ JSAtom basename_atom;
32263222
32273223 /* XXX: in order to avoid problems with resource liberation, we
32283224 don't support creating workers inside workers */
32293225 if (!is_main_thread(rt))
32303226 return JS_ThrowTypeError(ctx, "cannot create a worker inside a worker");
3227+
3228+ /* base name, assuming the calling function is a normal JS
3229+ function */
3230+ basename_atom = JS_GetScriptOrModuleName(ctx, 1);
3231+ if (basename_atom == JS_ATOM_NULL) {
3232+ return JS_ThrowTypeError(ctx, "could not determine calling script or module name");
3233+ }
3234+ basename = JS_AtomToCString(ctx, basename_atom);
3235+ JS_FreeAtom(ctx, basename_atom);
3236+ if (!basename)
3237+ goto fail;
32313238
3232− /* script source */
3233−
3234− str = JS_ToCStringLen(ctx, &str_len, argv[0]);
3235− if (!str)
3236− return JS_EXCEPTION;
3239+ /* module name */
3240+ filename = JS_ToCString(ctx, argv[0]);
3241+ if (!filename)
3242+ goto fail;
32373243
32383244 args = malloc(sizeof(*args));
3239− if (!args) {
3240− JS_ThrowOutOfMemory(ctx);
3241− goto fail;
3242− }
3245+ if (!args)
3246+ goto oom_fail;
32433247 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;
3248+ args->filename = strdup(filename);
3249+ args->basename = strdup(basename);
32533250
32543251 /* ports */
32553252 args->recv_pipe = js_new_message_pipe();
32563253 if (!args->recv_pipe)
3257− goto fail;
3254+ goto oom_fail;
32583255 args->send_pipe = js_new_message_pipe();
32593256 if (!args->send_pipe)
3260− goto fail;
3257+ goto oom_fail;
32613258
32623259 obj = js_worker_ctor_internal(ctx, new_target,
32633260 args->send_pipe, args->recv_pipe);
3264− if (JS_IsUndefined(obj))
3261+ if (JS_IsException(obj))
32653262 goto fail;
32663263
32673264 pthread_attr_init(&attr);
@@ -3273,11 +3270,17 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, · 5 unmodified lines
32733270 JS_ThrowTypeError(ctx, "could not create worker");
32743271 goto fail;
32753272 }
3273+ JS_FreeCString(ctx, basename);
3274+ JS_FreeCString(ctx, filename);
32763275 return obj;
3276+ oom_fail:
3277+ JS_ThrowOutOfMemory(ctx);
32773278 fail:
3278− JS_FreeCString(ctx, str);
3279+ JS_FreeCString(ctx, basename);
3280+ JS_FreeCString(ctx, filename);
32793281 if (args) {
3280− free(args->eval_buf);
3282+ free(args->filename);
3283+ free(args->basename);
32813284 js_free_message_pipe(args->recv_pipe);
32823285 js_free_message_pipe(args->send_pipe);
32833286 free(args);
@@ -3417,6 +3420,13 @@ static const JSCFunctionListEntry js_worker_proto_funcs[] = { · 133 unmodified lines
34173420
34183421 #endif /* USE_WORKER */
34193422
3423+void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt))
3424+{
3425+#ifdef USE_WORKER
3426+ js_worker_new_context_func = func;
3427+#endif
3428+}
3429+
34203430 #if defined(_WIN32)
34213431 #define OS_PLATFORM "win32"
34223432 #elif defined(__APPLE__)
@@ -3668,6 +3678,12 @@ void js_std_free_handlers(JSRuntime *rt) · 245 unmodified lines
36683678 free_timer(rt, th);
36693679 }
36703680
3681+#ifdef USE_WORKER
3682+ /* XXX: free port_list ? */
3683+ js_free_message_pipe(ts->recv_pipe);
3684+ js_free_message_pipe(ts->send_pipe);
3685+#endif
3686+
36713687 free(ts);
36723688 JS_SetRuntimeOpaque(rt, NULL); /* fail safe */
36733689 }
quickjs-libc.h+2−1
@@ -50,7 +50,8 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, · 49 unmodified lines
5050 void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise,
5151 JSValueConst reason,
5252 JS_BOOL is_handled, void *opaque);
53−
53+void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt));
54+
5455 #ifdef __cplusplus
5556 } /* extern "C" { */
5657 #endif
quickjs-opcode.h+2−1
@@ -359,7 +359,8 @@ DEF( call3, 1, 1, 1, npopx) · 358 unmodified lines
359359
360360 DEF( is_undefined, 1, 1, 1, none)
361361 DEF( is_null, 1, 1, 1, none)
362−DEF( is_function, 1, 1, 1, none)
362+DEF(typeof_is_undefined, 1, 1, 1, none)
363+DEF( typeof_is_function, 1, 1, 1, none)
363364 #endif
364365
365366 #undef DEF
quickjs.c+573−311
@@ -825,8 +825,8 @@ typedef struct JSShapeProperty { · 824 unmodified lines
825825 } JSShapeProperty;
826826
827827 struct JSShape {
828− uint32_t prop_hash_end[0]; /* hash table of size hash_mask + 1
829− before the start of the structure. */
828+ /* hash table of size hash_mask + 1 before the start of the
829+ structure (see prop_hash_end()). */
830830 JSGCObjectHeader header;
831831 /* true if the shape is inserted in the shape hash table. If not,
832832 JSShape.hash is not valid */
@@ -859,6 +859,7 @@ struct JSObject { · 26 unmodified lines
859859 uint8_t is_constructor : 1; /* TRUE if object is a constructor function */
860860 uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */
861861 uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */
862+ uint8_t is_HTMLDDA : 1; /* specific annex B IsHtmlDDA behavior */
862863 uint16_t class_id; /* see JS_CLASS_x */
863864 };
864865 };
@@ -931,7 +932,7 @@ struct JSObject { · 66 unmodified lines
931932 /* byte sizes: 40/48/72 */
932933 };
933934 enum {
934− JS_ATOM_NULL,
935+ __JS_ATOM_NULL = JS_ATOM_NULL,
935936 #define DEF(name, str) JS_ATOM_ ## name,
936937 #include "quickjs-atom.h"
937938 #undef DEF
@@ -4198,9 +4199,14 @@ static inline JSShape *get_shape_from_alloc(void *sh_alloc, size_t hash_size) · 3260 unmodified lines
41984199 return (JSShape *)(void *)((uint32_t *)sh_alloc + hash_size);
41994200 }
42004201
4202+static inline uint32_t *prop_hash_end(JSShape *sh)
4203+{
4204+ return (uint32_t *)sh;
4205+}
4206+
42014207 static inline void *get_alloc_from_shape(JSShape *sh)
42024208 {
4203− return sh->prop_hash_end - ((intptr_t)sh->prop_hash_mask + 1);
4209+ return prop_hash_end(sh) - ((intptr_t)sh->prop_hash_mask + 1);
42044210 }
42054211
42064212 static inline JSShapeProperty *get_shape_prop(JSShape *sh)
@@ -4311,7 +4317,7 @@ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, · 104 unmodified lines
43114317 if (proto)
43124318 JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, proto));
43134319 sh->proto = proto;
4314− memset(sh->prop_hash_end - hash_size, 0, sizeof(sh->prop_hash_end[0]) *
4320+ memset(prop_hash_end(sh) - hash_size, 0, sizeof(prop_hash_end(sh)[0]) *
43154321 hash_size);
43164322 sh->prop_hash_mask = hash_size - 1;
43174323 sh->prop_size = prop_size;
@@ -4440,13 +4446,13 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh, · 122 unmodified lines
44404446 list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
44414447 new_hash_mask = new_hash_size - 1;
44424448 sh->prop_hash_mask = new_hash_mask;
4443− memset(sh->prop_hash_end - new_hash_size, 0,
4444− sizeof(sh->prop_hash_end[0]) * new_hash_size);
4449+ memset(prop_hash_end(sh) - new_hash_size, 0,
4450+ sizeof(prop_hash_end(sh)[0]) * new_hash_size);
44454451 for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) {
44464452 if (pr->atom != JS_ATOM_NULL) {
44474453 h = ((uintptr_t)pr->atom & new_hash_mask);
4448− pr->hash_next = sh->prop_hash_end[-h - 1];
4449− sh->prop_hash_end[-h - 1] = i + 1;
4454+ pr->hash_next = prop_hash_end(sh)[-h - 1];
4455+ prop_hash_end(sh)[-h - 1] = i + 1;
44504456 }
44514457 }
44524458 js_free(ctx, get_alloc_from_shape(old_sh));
@@ -4500,8 +4506,8 @@ static int compact_properties(JSContext *ctx, JSObject *p) · 47 unmodified lines
45004506 memcpy(sh, old_sh, sizeof(JSShape));
45014507 list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
45024508
4503− memset(sh->prop_hash_end - new_hash_size, 0,
4504− sizeof(sh->prop_hash_end[0]) * new_hash_size);
4509+ memset(prop_hash_end(sh) - new_hash_size, 0,
4510+ sizeof(prop_hash_end(sh)[0]) * new_hash_size);
45054511
45064512 j = 0;
45074513 old_pr = old_sh->prop;
@@ -4512,8 +4518,8 @@ static int compact_properties(JSContext *ctx, JSObject *p) · 4 unmodified lines
45124518 pr->atom = old_pr->atom;
45134519 pr->flags = old_pr->flags;
45144520 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;
4521+ pr->hash_next = prop_hash_end(sh)[-h - 1];
4522+ prop_hash_end(sh)[-h - 1] = j + 1;
45174523 prop[j] = prop[i];
45184524 j++;
45194525 pr++;
@@ -4575,8 +4581,8 @@ static int add_shape_property(JSContext *ctx, JSShape **psh, · 55 unmodified lines
45754581 /* add in hash table */
45764582 hash_mask = sh->prop_hash_mask;
45774583 h = atom & hash_mask;
4578− pr->hash_next = sh->prop_hash_end[-h - 1];
4579− sh->prop_hash_end[-h - 1] = sh->prop_count;
4584+ pr->hash_next = prop_hash_end(sh)[-h - 1];
4585+ prop_hash_end(sh)[-h - 1] = sh->prop_count;
45804586 return 0;
45814587 }
45824588
@@ -4693,6 +4699,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas · 110 unmodified lines
46934699 p->is_constructor = 0;
46944700 p->is_uncatchable_error = 0;
46954701 p->tmp_mark = 0;
4702+ p->is_HTMLDDA = 0;
46964703 p->first_weak_ref = NULL;
46974704 p->u.opaque = NULL;
46984705 p->shape = sh;
@@ -4731,7 +4738,19 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas · 32 unmodified lines
47314738 p->prop[0].u.value = JS_UNDEFINED;
47324739 break;
47334740 case JS_CLASS_ARGUMENTS:
4734− case JS_CLASS_UINT8C_ARRAY ... JS_CLASS_FLOAT64_ARRAY:
4741+ case JS_CLASS_UINT8C_ARRAY:
4742+ case JS_CLASS_INT8_ARRAY:
4743+ case JS_CLASS_UINT8_ARRAY:
4744+ case JS_CLASS_INT16_ARRAY:
4745+ case JS_CLASS_UINT16_ARRAY:
4746+ case JS_CLASS_INT32_ARRAY:
4747+ case JS_CLASS_UINT32_ARRAY:
4748+#ifdef CONFIG_BIGNUM
4749+ case JS_CLASS_BIG_INT64_ARRAY:
4750+ case JS_CLASS_BIG_UINT64_ARRAY:
4751+#endif
4752+ case JS_CLASS_FLOAT32_ARRAY:
4753+ case JS_CLASS_FLOAT64_ARRAY:
47354754 p->is_exotic = 1;
47364755 p->fast_array = 1;
47374756 p->u.array.u.ptr = NULL;
@@ -5133,7 +5152,7 @@ static force_inline JSShapeProperty *find_own_property1(JSObject *p, · 395 unmodified lines
51335152 intptr_t h;
51345153 sh = p->shape;
51355154 h = (uintptr_t)atom & sh->prop_hash_mask;
5136− h = sh->prop_hash_end[-h - 1];
5155+ h = prop_hash_end(sh)[-h - 1];
51375156 prop = get_shape_prop(sh);
51385157 while (h) {
51395158 pr = &prop[h - 1];
@@ -5154,7 +5173,7 @@ static force_inline JSShapeProperty *find_own_property(JSProperty **ppr, · 14 unmodified lines
51545173 intptr_t h;
51555174 sh = p->shape;
51565175 h = (uintptr_t)atom & sh->prop_hash_mask;
5157− h = sh->prop_hash_end[-h - 1];
5176+ h = prop_hash_end(sh)[-h - 1];
51585177 prop = get_shape_prop(sh);
51595178 while (h) {
51605179 pr = &prop[h - 1];
@@ -7994,7 +8013,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) · 2833 unmodified lines
79948013 redo:
79958014 sh = p->shape;
79968015 h1 = atom & sh->prop_hash_mask;
7997− h = sh->prop_hash_end[-h1 - 1];
8016+ h = prop_hash_end(sh)[-h1 - 1];
79988017 prop = get_shape_prop(sh);
79998018 lpr = NULL;
80008019 lpr_idx = 0; /* prevent warning */
@@ -8015,7 +8034,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) · 14 unmodified lines
80158034 lpr = get_shape_prop(sh) + lpr_idx;
80168035 lpr->hash_next = pr->hash_next;
80178036 } else {
8018− sh->prop_hash_end[-h1 - 1] = pr->hash_next;
8037+ prop_hash_end(sh)[-h1 - 1] = pr->hash_next;
80198038 }
80208039 sh->deleted_prop_count++;
80218040 /* free the entry */
@@ -8095,15 +8114,16 @@ static int call_setter(JSContext *ctx, JSObject *setter, · 73 unmodified lines
80958114 }
80968115
80978116 /* set the array length and remove the array elements if necessary. */
8098−static int set_array_length(JSContext *ctx, JSObject *p, JSProperty *prop,
8099− JSValue val, int flags)
8117+static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, int flags)
81008118 {
81018119 uint32_t len, idx, cur_len;
81028120 int i, ret;
81038121
8122+ /* Note: this call can reallocate the properties of 'p' */
81048123 ret = JS_ToArrayLengthFree(ctx, &len, val);
81058124 if (ret)
81068125 return -1;
8126+
81078127 if (likely(p->fast_array)) {
81088128 uint32_t old_len = p->u.array.count;
81098129 if (len < old_len) {
@@ -8112,11 +8132,11 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSProperty *prop, · 2 unmodified lines
81128132 }
81138133 p->u.array.count = len;
81148134 }
8115− prop->u.value = JS_NewUint32(ctx, len);
8135+ p->prop[0].u.value = JS_NewUint32(ctx, len);
81168136 } else {
81178137 /* Note: length is always a uint32 because the object is an
81188138 array */
8119− JS_ToUint32(ctx, &cur_len, prop->u.value);
8139+ JS_ToUint32(ctx, &cur_len, p->prop[0].u.value);
81208140 if (len < cur_len) {
81218141 uint32_t d;
81228142 JSShape *sh;
@@ -8366,7 +8386,7 @@ retry: · 243 unmodified lines
83668386 (JS_PROP_LENGTH | JS_PROP_WRITABLE)) {
83678387 assert(p->class_id == JS_CLASS_ARRAY);
83688388 assert(prop == JS_ATOM_length);
8369− return set_array_length(ctx, p, pr, val, flags);
8389+ return set_array_length(ctx, p, val, flags);
83708390 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {
83718391 return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags);
83728392 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
@@ -9047,7 +9067,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, · 674 unmodified lines
90479067 }
90489068 if (prs->flags & JS_PROP_LENGTH) {
90499069 if (flags & JS_PROP_HAS_VALUE) {
9050− res = set_array_length(ctx, p, pr, JS_DupValue(ctx, val),
9070+ res = set_array_length(ctx, p, JS_DupValue(ctx, val),
90519071 flags);
90529072 } else {
90539073 res = TRUE;
@@ -9806,6 +9826,24 @@ static JSValue JS_ToPrimitive(JSContext *ctx, JSValueConst val, int hint) · 752 unmodified lines
98069826 return JS_ToPrimitiveFree(ctx, JS_DupValue(ctx, val), hint);
98079827 }
98089828
9829+void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj)
9830+{
9831+ JSObject *p;
9832+ if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
9833+ return;
9834+ p = JS_VALUE_GET_OBJ(obj);
9835+ p->is_HTMLDDA = TRUE;
9836+}
9837+
9838+static inline BOOL JS_IsHTMLDDA(JSContext *ctx, JSValueConst obj)
9839+{
9840+ JSObject *p;
9841+ if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
9842+ return FALSE;
9843+ p = JS_VALUE_GET_OBJ(obj);
9844+ return p->is_HTMLDDA;
9845+}
9846+
98099847 static int JS_ToBoolFree(JSContext *ctx, JSValue val)
98109848 {
98119849 uint32_t tag = JS_VALUE_GET_TAG(val);
@@ -9843,6 +9881,15 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val) · 31 unmodified lines
98439881 return ret;
98449882 }
98459883 #endif
9884+ case JS_TAG_OBJECT:
9885+ {
9886+ JSObject *p = JS_VALUE_GET_OBJ(val);
9887+ BOOL ret;
9888+ ret = !p->is_HTMLDDA;
9889+ JS_FreeValue(ctx, val);
9890+ return ret;
9891+ }
9892+ break;
98469893 default:
98479894 if (JS_TAG_IS_FLOAT64(tag)) {
98489895 double d = JS_VALUE_GET_FLOAT64(val);
@@ -11602,7 +11649,19 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) · 1753 unmodified lines
1160211649 case JS_CLASS_ARGUMENTS:
1160311650 JS_DumpValueShort(rt, p->u.array.u.values[i]);
1160411651 break;
11605− case JS_CLASS_UINT8C_ARRAY ... JS_CLASS_FLOAT64_ARRAY:
11652+ case JS_CLASS_UINT8C_ARRAY:
11653+ case JS_CLASS_INT8_ARRAY:
11654+ case JS_CLASS_UINT8_ARRAY:
11655+ case JS_CLASS_INT16_ARRAY:
11656+ case JS_CLASS_UINT16_ARRAY:
11657+ case JS_CLASS_INT32_ARRAY:
11658+ case JS_CLASS_UINT32_ARRAY:
11659+#ifdef CONFIG_BIGNUM
11660+ case JS_CLASS_BIG_INT64_ARRAY:
11661+ case JS_CLASS_BIG_UINT64_ARRAY:
11662+#endif
11663+ case JS_CLASS_FLOAT32_ARRAY:
11664+ case JS_CLASS_FLOAT64_ARRAY:
1160611665 {
1160711666 int size = 1 << typed_array_size_log2(p->class_id);
1160811667 const uint8_t *b = p->u.array.u.uint8_ptr + i * size;
@@ -13668,33 +13727,8 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, · 2059 unmodified lines
1366813727 JS_FreeValue(ctx, op2);
1366913728 } else if ((tag1 <= JS_TAG_NULL || tag1 == JS_TAG_FLOAT64) &&
1367013729 (tag2 <= JS_TAG_NULL || tag2 == JS_TAG_FLOAT64)) {
13671− /* can use floating point comparison */
13672− double d1, d2;
13673− if (tag1 == JS_TAG_FLOAT64) {
13674− d1 = JS_VALUE_GET_FLOAT64(op1);
13675− } else {
13676− d1 = JS_VALUE_GET_INT(op1);
13677− }
13678− if (tag2 == JS_TAG_FLOAT64) {
13679− d2 = JS_VALUE_GET_FLOAT64(op2);
13680− } else {
13681− d2 = JS_VALUE_GET_INT(op2);
13682− }
13683− switch(op) {
13684− case OP_lt:
13685− res = (d1 < d2); /* if NaN return false */
13686− break;
13687− case OP_lte:
13688− res = (d1 <= d2); /* if NaN return false */
13689− break;
13690− case OP_gt:
13691− res = (d1 > d2); /* if NaN return false */
13692− break;
13693− default:
13694− case OP_gte:
13695− res = (d1 >= d2); /* if NaN return false */
13696− break;
13697− }
13730+ /* fast path for float64/int */
13731+ goto float64_compare;
1369813732 } else {
1369913733 if (((tag1 == JS_TAG_BIG_INT && tag2 == JS_TAG_STRING) ||
1370013734 (tag2 == JS_TAG_BIG_INT && tag1 == JS_TAG_STRING)) &&
@@ -13727,20 +13761,51 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, · 26 unmodified lines
1372713761 }
1372813762 }
1372913763
13730− if (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_DECIMAL ||
13731− JS_VALUE_GET_TAG(op2) == JS_TAG_BIG_DECIMAL) {
13764+ tag1 = JS_VALUE_GET_NORM_TAG(op1);
13765+ tag2 = JS_VALUE_GET_NORM_TAG(op2);
13766+
13767+ if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
1373213768 res = ctx->rt->bigdecimal_ops.compare(ctx, op, op1, op2);
1373313769 if (res < 0)
1373413770 goto exception;
13735− } else if (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_FLOAT ||
13736− JS_VALUE_GET_TAG(op2) == JS_TAG_BIG_FLOAT) {
13771+ } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
1373713772 res = ctx->rt->bigfloat_ops.compare(ctx, op, op1, op2);
1373813773 if (res < 0)
1373913774 goto exception;
13740− } else {
13775+ } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
1374113776 res = ctx->rt->bigint_ops.compare(ctx, op, op1, op2);
1374213777 if (res < 0)
1374313778 goto exception;
13779+ } else {
13780+ double d1, d2;
13781+
13782+ float64_compare:
13783+ /* can use floating point comparison */
13784+ if (tag1 == JS_TAG_FLOAT64) {
13785+ d1 = JS_VALUE_GET_FLOAT64(op1);
13786+ } else {
13787+ d1 = JS_VALUE_GET_INT(op1);
13788+ }
13789+ if (tag2 == JS_TAG_FLOAT64) {
13790+ d2 = JS_VALUE_GET_FLOAT64(op2);
13791+ } else {
13792+ d2 = JS_VALUE_GET_INT(op2);
13793+ }
13794+ switch(op) {
13795+ case OP_lt:
13796+ res = (d1 < d2); /* if NaN return false */
13797+ break;
13798+ case OP_lte:
13799+ res = (d1 <= d2); /* if NaN return false */
13800+ break;
13801+ case OP_gt:
13802+ res = (d1 > d2); /* if NaN return false */
13803+ break;
13804+ default:
13805+ case OP_gte:
13806+ res = (d1 >= d2); /* if NaN return false */
13807+ break;
13808+ }
1374413809 }
1374513810 }
1374613811 done:
@@ -13895,9 +13960,17 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, · 148 unmodified lines
1389513960 }
1389613961 goto redo;
1389713962 } else {
13963+ /* IsHTMLDDA object is equivalent to undefined for '==' and '!=' */
13964+ if ((JS_IsHTMLDDA(ctx, op1) &&
13965+ (tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) ||
13966+ (JS_IsHTMLDDA(ctx, op2) &&
13967+ (tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) {
13968+ res = TRUE;
13969+ } else {
13970+ res = FALSE;
13971+ }
1389813972 JS_FreeValue(ctx, op1);
1389913973 JS_FreeValue(ctx, op2);
13900− res = FALSE;
1390113974 }
1390213975 done:
1390313976 sp[-2] = JS_NewBool(ctx, res ^ is_neq);
@@ -14348,9 +14421,17 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, · 444 unmodified lines
1434814421 }
1434914422 goto redo;
1435014423 } else {
14424+ /* IsHTMLDDA object is equivalent to undefined for '==' and '!=' */
14425+ if ((JS_IsHTMLDDA(ctx, op1) &&
14426+ (tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) ||
14427+ (JS_IsHTMLDDA(ctx, op2) &&
14428+ (tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) {
14429+ res = TRUE;
14430+ } else {
14431+ res = FALSE;
14432+ }
1435114433 JS_FreeValue(ctx, op1);
1435214434 JS_FreeValue(ctx, op2);
14353− res = FALSE;
1435414435 }
1435514436 sp[-2] = JS_NewBool(ctx, res ^ is_neq);
1435614437 return 0;
@@ -14631,7 +14712,7 @@ static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp) · 274 unmodified lines
1463114712 return 0;
1463214713 }
1463314714
14634−static __exception int js_operator_typeof(JSContext *ctx, JSValue op1)
14715+static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)
1463514716 {
1463614717 JSAtom atom;
1463714718 uint32_t tag;
@@ -14663,10 +14744,16 @@ static __exception int js_operator_typeof(JSContext *ctx, JSValue op1) · 25 unmodified lines
1466314744 atom = JS_ATOM_string;
1466414745 break;
1466514746 case JS_TAG_OBJECT:
14666− if (JS_IsFunction(ctx, op1))
14667− atom = JS_ATOM_function;
14668− else
14669− goto obj_type;
14747+ {
14748+ JSObject *p;
14749+ p = JS_VALUE_GET_OBJ(op1);
14750+ if (unlikely(p->is_HTMLDDA))
14751+ atom = JS_ATOM_undefined;
14752+ else if (JS_IsFunction(ctx, op1))
14753+ atom = JS_ATOM_function;
14754+ else
14755+ goto obj_type;
14756+ }
1467014757 break;
1467114758 case JS_TAG_NULL:
1467214759 obj_type:
@@ -15231,7 +15318,10 @@ static __exception int js_for_of_start(JSContext *ctx, JSValue *sp, · 558 unmodified lines
1523115318 return 0;
1523215319 }
1523315320
15234−/* enum_rec -> enum_rec value done */
15321+/* enum_rec [objs] -> enum_rec [objs] value done. There are 'offset'
15322+ objs. If 'done' is true or in case of exception, 'enum_rec' is set
15323+ to undefined. If 'done' is true, 'value' is always set to
15324+ undefined. */
1523515325 static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
1523615326 {
1523715327 JSValue value = JS_UNDEFINED;
@@ -15246,8 +15336,12 @@ static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset) · 8 unmodified lines
1524615336 /* replace the iteration object with undefined */
1524715337 JS_FreeValue(ctx, sp[offset]);
1524815338 sp[offset] = JS_UNDEFINED;
15249− if (done < 0)
15339+ if (done < 0) {
1525015340 return -1;
15341+ } else {
15342+ JS_FreeValue(ctx, value);
15343+ value = JS_UNDEFINED;
15344+ }
1525115345 }
1525215346 }
1525315347 sp[0] = value;
@@ -15363,10 +15457,10 @@ static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj, · 109 unmodified lines
1536315457 static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
1536415458 {
1536515459 JSValue iterator, enumobj, method, value;
15366− int pos, is_array_iterator;
15460+ int is_array_iterator;
1536715461 JSValue *arrp;
15368− uint32_t i, count32;
15369−
15462+ uint32_t i, count32, pos;
15463+
1537015464 if (JS_VALUE_GET_TAG(sp[-2]) != JS_TAG_INT) {
1537115465 JS_ThrowInternalError(ctx, "invalid index for append");
1537215466 return -1;
@@ -15399,24 +15493,21 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) · 26 unmodified lines
1539915493 if (is_array_iterator
1540015494 && JS_IsCFunction(ctx, method, (JSCFunction *)js_array_iterator_next, 0)
1540115495 && js_get_fast_array(ctx, sp[-1], &arrp, &count32)) {
15402− int64_t len;
15403− /* Handle fast arrays explicitly */
15404− if (js_get_length64(ctx, &len, sp[-1]))
15496+ uint32_t len;
15497+ if (js_get_length32(ctx, &len, sp[-1]))
1540515498 goto exception;
15499+ /* if len > count32, the elements >= count32 might be read in
15500+ the prototypes and might have side effects */
15501+ if (len != count32)
15502+ goto general_case;
15503+ /* Handle fast arrays explicitly */
1540615504 for (i = 0; i < count32; i++) {
1540715505 if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++,
1540815506 JS_DupValue(ctx, arrp[i]), JS_PROP_C_W_E) < 0)
1540915507 goto exception;
1541015508 }
15411− if (len > count32) {
15412− /* This is not strictly correct because the trailing elements are
15413− empty instead of undefined. Append undefined entries instead.
15414− */
15415− pos += len - count32;
15416− if (JS_SetProperty(ctx, sp[-3], JS_ATOM_length, JS_NewUint32(ctx, pos)) < 0)
15417− goto exception;
15418− }
1541915509 } else {
15510+ general_case:
1542015511 for (;;) {
1542115512 BOOL done;
1542215513 value = JS_IteratorNext(ctx, enumobj, method, 0, NULL, &done);
@@ -15430,6 +15521,7 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) · 7 unmodified lines
1543015521 goto exception;
1543115522 }
1543215523 }
15524+ /* Note: could raise an error if too many elements */
1543315525 sp[-2] = JS_NewInt32(ctx, pos);
1543415526 JS_FreeValue(ctx, enumobj);
1543515527 JS_FreeValue(ctx, method);
@@ -17742,47 +17834,42 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, · 2306 unmodified lines
1774217834 BREAK;
1774317835 CASE(OP_add_loc):
1774417836 {
17745− JSValue ops[2];
17837+ JSValue *pv;
1774617838 int idx;
1774717839 idx = *pc;
1774817840 pc += 1;
1774917841
17750− ops[0] = var_buf[idx];
17751− ops[1] = sp[-1];
17752− if (likely(JS_VALUE_IS_BOTH_INT(ops[0], ops[1]))) {
17842+ pv = &var_buf[idx];
17843+ if (likely(JS_VALUE_IS_BOTH_INT(*pv, sp[-1]))) {
1775317844 int64_t r;
17754− r = (int64_t)JS_VALUE_GET_INT(ops[0]) + JS_VALUE_GET_INT(ops[1]);
17845+ r = (int64_t)JS_VALUE_GET_INT(*pv) +
17846+ JS_VALUE_GET_INT(sp[-1]);
1775517847 if (unlikely((int)r != r))
1775617848 goto add_loc_slow;
17757− var_buf[idx] = JS_NewInt32(ctx, r);
17849+ *pv = JS_NewInt32(ctx, r);
1775817850 sp--;
17759− } else if (JS_VALUE_GET_TAG(ops[0]) == JS_TAG_STRING) {
17851+ } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) {
17852+ JSValue op1;
17853+ op1 = sp[-1];
1776017854 sp--;
17761− ops[1] = JS_ToPrimitiveFree(ctx, ops[1], HINT_NONE);
17762− if (JS_IsException(ops[1])) {
17855+ op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
17856+ if (JS_IsException(op1))
1776317857 goto exception;
17764− }
17765− /* XXX: should not modify the variable in case of
17766− exception */
17767− ops[0] = JS_ConcatString(ctx, ops[0], ops[1]);
17768− if (JS_IsException(ops[0])) {
17769− var_buf[idx] = JS_UNDEFINED;
17858+ op1 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op1);
17859+ if (JS_IsException(op1))
1777017860 goto exception;
17771− }
17772− var_buf[idx] = ops[0];
17861+ set_value(ctx, pv, op1);
1777317862 } else {
17863+ JSValue ops[2];
1777417864 add_loc_slow:
17775− /* XXX: should not modify the variable in case of
17776− exception */
17777− sp--;
1777817865 /* In case of exception, js_add_slow frees ops[0]
17779− and ops[1]. */
17780− /* XXX: change API */
17781− if (js_add_slow(ctx, ops + 2)) {
17782− var_buf[idx] = JS_UNDEFINED;
17866+ and ops[1], so we must duplicate *pv */
17867+ ops[0] = JS_DupValue(ctx, *pv);
17868+ ops[1] = sp[-1];
17869+ sp--;
17870+ if (js_add_slow(ctx, ops + 2))
1778317871 goto exception;
17784− }
17785− var_buf[idx] = ops[0];
17872+ set_value(ctx, pv, ops[0]);
1778617873 }
1778717874 }
1778817875 BREAK;
@@ -18427,7 +18514,15 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, · 638 unmodified lines
1842718514 } else {
1842818515 goto free_and_set_false;
1842918516 }
18430− CASE(OP_is_function):
18517+ /* XXX: could merge to a single opcode */
18518+ CASE(OP_typeof_is_undefined):
18519+ /* different from OP_is_undefined because of isHTMLDDA */
18520+ if (js_operator_typeof(ctx, sp[-1]) == JS_ATOM_undefined) {
18521+ goto free_and_set_true;
18522+ } else {
18523+ goto free_and_set_false;
18524+ }
18525+ CASE(OP_typeof_is_function):
1843118526 if (js_operator_typeof(ctx, sp[-1]) == JS_ATOM_function) {
1843218527 goto free_and_set_true;
1843318528 } else {
@@ -19656,6 +19751,9 @@ enum { · 1222 unmodified lines
1965619751 TOK_MATH_POW_ASSIGN,
1965719752 #endif
1965819753 TOK_POW_ASSIGN,
19754+ TOK_LAND_ASSIGN,
19755+ TOK_LOR_ASSIGN,
19756+ TOK_DOUBLE_QUESTION_MARK_ASSIGN,
1965919757 TOK_DEC,
1966019758 TOK_INC,
1966119759 TOK_SHL,
@@ -20015,11 +20113,14 @@ static void free_token(JSParseState *s, JSToken *token) · 353 unmodified lines
2001520113 JS_FreeValue(s->ctx, token->u.regexp.flags);
2001620114 break;
2001720115 case TOK_IDENT:
20018− case TOK_FIRST_KEYWORD ... TOK_LAST_KEYWORD:
2001920116 case TOK_PRIVATE_NAME:
2002020117 JS_FreeAtom(s->ctx, token->u.ident.atom);
2002120118 break;
2002220119 default:
20120+ if (token->val >= TOK_FIRST_KEYWORD &&
20121+ token->val <= TOK_LAST_KEYWORD) {
20122+ JS_FreeAtom(s->ctx, token->u.ident.atom);
20123+ }
2002320124 break;
2002420125 }
2002520126 }
@@ -20233,6 +20334,8 @@ static __exception int js_parse_string(JSParseState *s, int sep, · 207 unmodified lines
2023320334 }
2023420335 if (c == '\\') {
2023520336 c = *p;
20337+ /* XXX: need a specific JSON case to avoid
20338+ accepting invalid escapes */
2023620339 switch(c) {
2023720340 case '\0':
2023820341 if (p >= s->buf_end)
@@ -20256,18 +20359,23 @@ static __exception int js_parse_string(JSParseState *s, int sep, · 17 unmodified lines
2025620359 s->line_num++;
2025720360 continue;
2025820361 default:
20259− if (c >= '0' && c <= '7') {
20362+ if (c >= '0' && c <= '9') {
2026020363 if (!s->cur_func)
20261− goto invalid_octal; /* JSON case */
20364+ goto invalid_escape; /* JSON case */
2026220365 if (!(s->cur_func->js_mode & JS_MODE_STRICT) && sep != '`')
2026320366 goto parse_escape;
2026420367 if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) {
2026520368 p++;
2026620369 c = '\0';
2026720370 } else {
20268− invalid_octal:
20269− if (do_throw)
20270− js_parse_error(s, "invalid octal syntax in strict mode");
20371+ if (c >= '8' || sep == '`') {
20372+ /* Note: according to ES2021, \8 and \9 are not
20373+ accepted in strict mode or in templates. */
20374+ goto invalid_escape;
20375+ } else {
20376+ if (do_throw)
20377+ js_parse_error(s, "octal escape sequences are not allowed in strict mode");
20378+ }
2027120379 goto fail;
2027220380 }
2027320381 } else if (c >= 0x80) {
@@ -20284,6 +20392,7 @@ static __exception int js_parse_string(JSParseState *s, int sep, · 10 unmodified lines
2028420392 parse_escape:
2028520393 ret = lre_parse_escape(&p, TRUE);
2028620394 if (ret == -1) {
20395+ invalid_escape:
2028720396 if (do_throw)
2028820397 js_parse_error(s, "malformed escape sequence in string literal");
2028920398 goto fail;
@@ -20634,8 +20743,20 @@ static __exception int next_token(JSParseState *s) · 344 unmodified lines
2063420743 }
2063520744 }
2063620745 goto def_token;
20637− case 'a' ... 'z':
20638− case 'A' ... 'Z':
20746+ case 'a': case 'b': case 'c': case 'd':
20747+ case 'e': case 'f': case 'g': case 'h':
20748+ case 'i': case 'j': case 'k': case 'l':
20749+ case 'm': case 'n': case 'o': case 'p':
20750+ case 'q': case 'r': case 's': case 't':
20751+ case 'u': case 'v': case 'w': case 'x':
20752+ case 'y': case 'z':
20753+ case 'A': case 'B': case 'C': case 'D':
20754+ case 'E': case 'F': case 'G': case 'H':
20755+ case 'I': case 'J': case 'K': case 'L':
20756+ case 'M': case 'N': case 'O': case 'P':
20757+ case 'Q': case 'R': case 'S': case 'T':
20758+ case 'U': case 'V': case 'W': case 'X':
20759+ case 'Y': case 'Z':
2063920760 case '_':
2064020761 case '$':
2064120762 /* identifier */
@@ -20717,7 +20838,9 @@ static __exception int next_token(JSParseState *s) · 75 unmodified lines
2071720838 goto fail;
2071820839 }
2071920840 goto parse_number;
20720− case '1' ... '9':
20841+ case '1': case '2': case '3': case '4':
20842+ case '5': case '6': case '7': case '8':
20843+ case '9':
2072120844 /* number */
2072220845 parse_number:
2072320846 {
@@ -20887,8 +21010,13 @@ static __exception int next_token(JSParseState *s) · 163 unmodified lines
2088721010 p += 2;
2088821011 s->token.val = TOK_AND_ASSIGN;
2088921012 } else if (p[1] == '&') {
20890− p += 2;
20891− s->token.val = TOK_LAND;
21013+ if (p[2] == '=') {
21014+ p += 3;
21015+ s->token.val = TOK_LAND_ASSIGN;
21016+ } else {
21017+ p += 2;
21018+ s->token.val = TOK_LAND;
21019+ }
2089221020 } else {
2089321021 goto def_token;
2089421022 }
@@ -20934,16 +21062,26 @@ static __exception int next_token(JSParseState *s) · 39 unmodified lines
2093421062 p += 2;
2093521063 s->token.val = TOK_OR_ASSIGN;
2093621064 } else if (p[1] == '|') {
20937− p += 2;
20938− s->token.val = TOK_LOR;
21065+ if (p[2] == '=') {
21066+ p += 3;
21067+ s->token.val = TOK_LOR_ASSIGN;
21068+ } else {
21069+ p += 2;
21070+ s->token.val = TOK_LOR;
21071+ }
2093921072 } else {
2094021073 goto def_token;
2094121074 }
2094221075 break;
2094321076 case '?':
2094421077 if (p[1] == '?') {
20945− p += 2;
20946− s->token.val = TOK_DOUBLE_QUESTION_MARK;
21078+ if (p[2] == '=') {
21079+ p += 3;
21080+ s->token.val = TOK_DOUBLE_QUESTION_MARK_ASSIGN;
21081+ } else {
21082+ p += 2;
21083+ s->token.val = TOK_DOUBLE_QUESTION_MARK;
21084+ }
2094721085 } else if (p[1] == '.' && !(p[2] >= '0' && p[2] <= '9')) {
2094821086 p += 2;
2094921087 s->token.val = TOK_QUESTION_MARK_DOT;
@@ -21135,8 +21273,20 @@ static __exception int json_next_token(JSParseState *s) · 185 unmodified lines
2113521273 goto def_token;
2113621274 }
2113721275 break;
21138− case 'a' ... 'z':
21139− case 'A' ... 'Z':
21276+ case 'a': case 'b': case 'c': case 'd':
21277+ case 'e': case 'f': case 'g': case 'h':
21278+ case 'i': case 'j': case 'k': case 'l':
21279+ case 'm': case 'n': case 'o': case 'p':
21280+ case 'q': case 'r': case 's': case 't':
21281+ case 'u': case 'v': case 'w': case 'x':
21282+ case 'y': case 'z':
21283+ case 'A': case 'B': case 'C': case 'D':
21284+ case 'E': case 'F': case 'G': case 'H':
21285+ case 'I': case 'J': case 'K': case 'L':
21286+ case 'M': case 'N': case 'O': case 'P':
21287+ case 'Q': case 'R': case 'S': case 'T':
21288+ case 'U': case 'V': case 'W': case 'X':
21289+ case 'Y': case 'Z':
2114021290 case '_':
2114121291 case '$':
2114221292 /* identifier : only pure ascii characters are accepted */
@@ -21161,7 +21311,9 @@ static __exception int json_next_token(JSParseState *s) · 18 unmodified lines
2116121311 if (!is_digit(p[1]))
2116221312 goto def_token;
2116321313 goto parse_number;
21164− case '1' ... '9':
21314+ case '1': case '2': case '3': case '4':
21315+ case '5': case '6': case '7': case '8':
21316+ case '9':
2116521317 /* number */
2116621318 parse_number:
2116721319 {
@@ -23267,15 +23419,6 @@ static BOOL has_with_scope(JSFunctionDef *s, int scope_level) · 2099 unmodified lines
2326723419 return FALSE;
2326823420 }
2326923421
23270−typedef struct JSLValue {
23271− int opcode;
23272− int scope;
23273− int label;
23274− int depth;
23275− int tok;
23276− JSAtom name;
23277−} JSLValue;
23278−
2327923422 static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
2328023423 JSAtom *pname, int *plabel, int *pdepth, BOOL keep,
2328123424 int tok)
@@ -23400,84 +23543,112 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, · 118 unmodified lines
2340023543 return 0;
2340123544 }
2340223545
23403−/* if special = TRUE: specific post inc/dec case */
23404−/* name has a live reference */
23546+typedef enum {
23547+ PUT_LVALUE_NOKEEP, /* [depth] v -> */
23548+ PUT_LVALUE_NOKEEP_DEPTH, /* [depth] v -> , keep depth (currently
23549+ just disable optimizations) */
23550+ PUT_LVALUE_KEEP_TOP, /* [depth] v -> v */
23551+ PUT_LVALUE_KEEP_SECOND, /* [depth] v0 v -> v0 */
23552+ PUT_LVALUE_NOKEEP_BOTTOM, /* v [depth] -> */
23553+} PutLValueEnum;
23554+
23555+/* name has a live reference. 'is_let' is only used with opcode =
23556+ OP_scope_get_var which is never generated by get_lvalue(). */
2340523557 static void put_lvalue(JSParseState *s, int opcode, int scope,
23406− JSAtom name, int label, BOOL special)
23558+ JSAtom name, int label, PutLValueEnum special,
23559+ BOOL is_let)
2340723560 {
2340823561 switch(opcode) {
2340923562 case OP_get_field:
23410− if (!special)
23411− emit_op(s, OP_insert2); /* obj v -> v obj v */
23412− else
23413− emit_op(s, OP_perm3); /* obj v0 v -> v0 obj v */
23414− emit_op(s, OP_put_field);
23415− emit_u32(s, name); /* name has refcount */
23416− break;
2341723563 case OP_scope_get_private_field:
23418− if (!special)
23564+ /* depth = 1 */
23565+ switch(special) {
23566+ case PUT_LVALUE_NOKEEP:
23567+ case PUT_LVALUE_NOKEEP_DEPTH:
23568+ break;
23569+ case PUT_LVALUE_KEEP_TOP:
2341923570 emit_op(s, OP_insert2); /* obj v -> v obj v */
23420− else
23571+ break;
23572+ case PUT_LVALUE_KEEP_SECOND:
2342123573 emit_op(s, OP_perm3); /* obj v0 v -> v0 obj v */
23422− emit_op(s, OP_scope_put_private_field);
23423− emit_u32(s, name); /* name has refcount */
23424− emit_u16(s, scope);
23574+ break;
23575+ case PUT_LVALUE_NOKEEP_BOTTOM:
23576+ emit_op(s, OP_swap);
23577+ break;
23578+ default:
23579+ abort();
23580+ }
2342523581 break;
2342623582 case OP_get_array_el:
23427− if (!special)
23428− emit_op(s, OP_insert3); /* obj prop v -> v obj prop v */
23429− else
23430− emit_op(s, OP_perm4); /* obj prop v0 v -> v0 obj prop v */
23431− emit_op(s, OP_put_array_el);
23432− break;
2343323583 case OP_get_ref_value:
23434− JS_FreeAtom(s->ctx, name);
23435− emit_label(s, label);
23436− if (!special)
23584+ /* depth = 2 */
23585+ if (opcode == OP_get_ref_value) {
23586+ JS_FreeAtom(s->ctx, name);
23587+ emit_label(s, label);
23588+ }
23589+ switch(special) {
23590+ case PUT_LVALUE_NOKEEP:
23591+ emit_op(s, OP_nop); /* will trigger optimization */
23592+ break;
23593+ case PUT_LVALUE_NOKEEP_DEPTH:
23594+ break;
23595+ case PUT_LVALUE_KEEP_TOP:
2343723596 emit_op(s, OP_insert3); /* obj prop v -> v obj prop v */
23438− else
23597+ break;
23598+ case PUT_LVALUE_KEEP_SECOND:
2343923599 emit_op(s, OP_perm4); /* obj prop v0 v -> v0 obj prop v */
23440− emit_op(s, OP_put_ref_value);
23600+ break;
23601+ case PUT_LVALUE_NOKEEP_BOTTOM:
23602+ emit_op(s, OP_rot3l);
23603+ break;
23604+ default:
23605+ abort();
23606+ }
2344123607 break;
2344223608 case OP_get_super_value:
23443− if (!special)
23609+ /* depth = 3 */
23610+ switch(special) {
23611+ case PUT_LVALUE_NOKEEP:
23612+ case PUT_LVALUE_NOKEEP_DEPTH:
23613+ break;
23614+ case PUT_LVALUE_KEEP_TOP:
2344423615 emit_op(s, OP_insert4); /* this obj prop v -> v this obj prop v */
23445− else
23616+ break;
23617+ case PUT_LVALUE_KEEP_SECOND:
2344623618 emit_op(s, OP_perm5); /* this obj prop v0 v -> v0 this obj prop v */
23447− emit_op(s, OP_put_super_value);
23619+ break;
23620+ case PUT_LVALUE_NOKEEP_BOTTOM:
23621+ emit_op(s, OP_rot4l);
23622+ break;
23623+ default:
23624+ abort();
23625+ }
2344823626 break;
2344923627 default:
23450− abort();
23628+ break;
2345123629 }
23452−}
23453−
23454−static void put_lvalue_nokeep(JSParseState *s, int opcode, int scope,
23455− JSAtom name, int label, int var_tok)
23456−{
23630+
2345723631 switch(opcode) {
2345823632 case OP_scope_get_var: /* val -- */
23459− emit_op(s, (var_tok == TOK_CONST || var_tok == TOK_LET) ?
23460− OP_scope_put_var_init : OP_scope_put_var);
23633+ assert(special == PUT_LVALUE_NOKEEP ||
23634+ special == PUT_LVALUE_NOKEEP_DEPTH);
23635+ emit_op(s, is_let ? OP_scope_put_var_init : OP_scope_put_var);
2346123636 emit_u32(s, name); /* has refcount */
2346223637 emit_u16(s, scope);
2346323638 break;
23464− case OP_get_field: /* obj val -- */
23639+ case OP_get_field:
2346523640 emit_op(s, OP_put_field);
23466− emit_u32(s, name); /* has refcount */
23641+ emit_u32(s, name); /* name has refcount */
2346723642 break;
2346823643 case OP_scope_get_private_field:
2346923644 emit_op(s, OP_scope_put_private_field);
23470− emit_u32(s, name); /* has refcount */
23645+ emit_u32(s, name); /* name has refcount */
2347123646 emit_u16(s, scope);
2347223647 break;
23473− case OP_get_array_el: /* obj prop val -- */
23648+ case OP_get_array_el:
2347423649 emit_op(s, OP_put_array_el);
2347523650 break;
23476− case OP_get_ref_value: /* obj prop val -- */
23477− /* XXX: currently this reference is never optimized */
23478− JS_FreeAtom(s->ctx, name);
23479− emit_label(s, label);
23480− //emit_op(s, OP_nop); /* emit 2 bytes for optimizer */
23651+ case OP_get_ref_value:
2348123652 emit_op(s, OP_put_ref_value);
2348223653 break;
2348323654 case OP_get_super_value:
@@ -23869,7 +24040,9 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, · 385 unmodified lines
2386924040 emit_label(s, label_hasval);
2387024041 }
2387124042 /* store value into lvalue object */
23872− put_lvalue_nokeep(s, opcode, scope, var_name, label_lvalue, tok);
24043+ put_lvalue(s, opcode, scope, var_name, label_lvalue,
24044+ PUT_LVALUE_NOKEEP_DEPTH,
24045+ (tok == TOK_CONST || tok == TOK_LET));
2387324046 if (s->token.val == '}')
2387424047 break;
2387524048 /* accept a trailing comma before the '}' */
@@ -23969,8 +24142,9 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, · 93 unmodified lines
2396924142 emit_label(s, label_hasval);
2397024143 }
2397124144 /* store value into lvalue object */
23972− put_lvalue_nokeep(s, opcode, scope, var_name,
23973− label_lvalue, tok);
24145+ put_lvalue(s, opcode, scope, var_name,
24146+ label_lvalue, PUT_LVALUE_NOKEEP_DEPTH,
24147+ (tok == TOK_CONST || tok == TOK_LET));
2397424148 }
2397524149 if (s->token.val == ']')
2397624150 break;
@@ -24786,7 +24960,8 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag) · 809 unmodified lines
2478624960 if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))
2478724961 return -1;
2478824962 emit_op(s, OP_dec + op - TOK_DEC);
24789− put_lvalue(s, opcode, scope, name, label, FALSE);
24963+ put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP,
24964+ FALSE);
2479024965 }
2479124966 break;
2479224967 case TOK_TYPEOF:
@@ -24834,7 +25009,8 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag) · 41 unmodified lines
2483425009 if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))
2483525010 return -1;
2483625011 emit_op(s, OP_post_dec + op - TOK_DEC);
24837− put_lvalue(s, opcode, scope, name, label, TRUE);
25012+ put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_SECOND,
25013+ FALSE);
2483825014 if (next_token(s))
2483925015 return -1;
2484025016 }
@@ -25298,7 +25474,61 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted) · 457 unmodified lines
2529825474 #endif
2529925475 emit_op(s, op);
2530025476 }
25301− put_lvalue(s, opcode, scope, name, label, FALSE);
25477+ put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, FALSE);
25478+ } else if (op >= TOK_LAND_ASSIGN && op <= TOK_DOUBLE_QUESTION_MARK_ASSIGN) {
25479+ int label, label1, depth_lvalue, label2;
25480+
25481+ if (next_token(s))
25482+ return -1;
25483+ if (get_lvalue(s, &opcode, &scope, &name, &label,
25484+ &depth_lvalue, TRUE, op) < 0)
25485+ return -1;
25486+
25487+ emit_op(s, OP_dup);
25488+ if (op == TOK_DOUBLE_QUESTION_MARK_ASSIGN)
25489+ emit_op(s, OP_is_undefined_or_null);
25490+ label1 = emit_goto(s, op == TOK_LOR_ASSIGN ? OP_if_true : OP_if_false,
25491+ -1);
25492+ emit_op(s, OP_drop);
25493+
25494+ if (js_parse_assign_expr(s, in_accepted)) {
25495+ JS_FreeAtom(s->ctx, name);
25496+ return -1;
25497+ }
25498+
25499+ if (opcode == OP_get_ref_value && name == name0) {
25500+ set_object_name(s, name);
25501+ }
25502+
25503+ switch(depth_lvalue) {
25504+ case 1:
25505+ emit_op(s, OP_insert2);
25506+ break;
25507+ case 2:
25508+ emit_op(s, OP_insert3);
25509+ break;
25510+ case 3:
25511+ emit_op(s, OP_insert4);
25512+ break;
25513+ default:
25514+ abort();
25515+ }
25516+
25517+ /* XXX: we disable the OP_put_ref_value optimization by not
25518+ using put_lvalue() otherwise depth_lvalue is not correct */
25519+ put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_NOKEEP_DEPTH,
25520+ FALSE);
25521+ label2 = emit_goto(s, OP_goto, -1);
25522+
25523+ emit_label(s, label1);
25524+
25525+ /* remove the lvalue stack entries */
25526+ while (depth_lvalue != 0) {
25527+ emit_op(s, OP_nip);
25528+ depth_lvalue--;
25529+ }
25530+
25531+ emit_label(s, label2);
2530225532 }
2530325533 return 0;
2530425534 }
@@ -25563,8 +25793,8 @@ static __exception int js_parse_var(JSParseState *s, BOOL in_accepted, int tok, · 258 unmodified lines
2556325793 goto var_error;
2556425794 }
2556525795 set_object_name(s, name);
25566− put_lvalue(s, opcode, scope, name1, label, FALSE);
25567− emit_op(s, OP_drop);
25796+ put_lvalue(s, opcode, scope, name1, label,
25797+ PUT_LVALUE_NOKEEP, FALSE);
2556825798 } else {
2556925799 if (js_parse_assign_expr(s, in_accepted))
2557025800 goto var_error;
@@ -25751,29 +25981,14 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, · 180 unmodified lines
2575125981 if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
2575225982 return -1;
2575325983 } else {
25754− int lvalue_label, depth;
25984+ int lvalue_label;
2575525985 if (js_parse_postfix_expr(s, TRUE))
2575625986 return -1;
2575725987 if (get_lvalue(s, &opcode, &scope, &var_name, &lvalue_label,
25758− &depth, FALSE, TOK_FOR))
25988+ NULL, FALSE, TOK_FOR))
2575925989 return -1;
25760− /* swap value and lvalue object and store it into lvalue object */
25761− /* enum_rec val [depth] -- enum_rec */
25762− switch(depth) {
25763− case 1:
25764− emit_op(s, OP_swap);
25765− break;
25766− case 2:
25767− emit_op(s, OP_rot3l);
25768− break;
25769− case 3:
25770− emit_op(s, OP_rot4l);
25771− break;
25772− default:
25773− abort();
25774− }
25775− put_lvalue_nokeep(s, opcode, scope, var_name, lvalue_label,
25776− TOK_FOR /* not used */);
25990+ put_lvalue(s, opcode, scope, var_name, lvalue_label,
25991+ PUT_LVALUE_NOKEEP_BOTTOM, FALSE);
2577725992 }
2577825993 var_name = JS_ATOM_NULL;
2577925994 }
@@ -26933,32 +27148,20 @@ static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name) · 1153 unmodified lines
2693327148
2693427149 /* return NULL in case of exception (e.g. module could not be loaded) */
2693527150 static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx,
26936− JSAtom base_module_name,
26937− JSAtom module_name1)
27151+ const char *base_cname,
27152+ const char *cname1)
2693827153 {
2693927154 JSRuntime *rt = ctx->rt;
2694027155 JSModuleDef *m;
2694127156 char *cname;
26942− const char *base_cname, *cname1;
2694327157 JSAtom module_name;
2694427158
26945− base_cname = JS_AtomToCString(ctx, base_module_name);
26946− if (!base_cname)
26947− return NULL;
26948− cname1 = JS_AtomToCString(ctx, module_name1);
26949− if (!cname1) {
26950− JS_FreeCString(ctx, base_cname);
26951− return NULL;
26952− }
26953−
2695427159 if (!rt->module_normalize_func) {
2695527160 cname = js_default_module_normalize_name(ctx, base_cname, cname1);
2695627161 } else {
2695727162 cname = rt->module_normalize_func(ctx, base_cname, cname1,
2695827163 rt->module_loader_opaque);
2695927164 }
26960− JS_FreeCString(ctx, base_cname);
26961− JS_FreeCString(ctx, cname1);
2696227165 if (!cname)
2696327166 return NULL;
2696427167
@@ -26992,6 +27195,27 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, · 27 unmodified lines
2699227195 return m;
2699327196 }
2699427197
27198+static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx,
27199+ JSAtom base_module_name,
27200+ JSAtom module_name1)
27201+{
27202+ const char *base_cname, *cname;
27203+ JSModuleDef *m;
27204+
27205+ base_cname = JS_AtomToCString(ctx, base_module_name);
27206+ if (!base_cname)
27207+ return NULL;
27208+ cname = JS_AtomToCString(ctx, module_name1);
27209+ if (!cname) {
27210+ JS_FreeCString(ctx, base_cname);
27211+ return NULL;
27212+ }
27213+ m = js_host_resolve_imported_module(ctx, base_cname, cname);
27214+ JS_FreeCString(ctx, base_cname);
27215+ JS_FreeCString(ctx, cname);
27216+ return m;
27217+}
27218+
2699527219 typedef struct JSResolveEntry {
2699627220 JSModuleDef *module;
2699727221 JSAtom name;
@@ -27435,8 +27659,8 @@ static int js_resolve_module(JSContext *ctx, JSModuleDef *m) · 437 unmodified lines
2743527659 /* resolve each requested module */
2743627660 for(i = 0; i < m->req_module_entries_count; i++) {
2743727661 JSReqModuleEntry *rme = &m->req_module_entries[i];
27438− m1 = js_host_resolve_imported_module(ctx, m->module_name,
27439− rme->module_name);
27662+ m1 = js_host_resolve_imported_module_atom(ctx, m->module_name,
27663+ rme->module_name);
2744027664 if (!m1)
2744127665 return -1;
2744227666 rme->module = m1;
@@ -27711,8 +27935,9 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) · 268 unmodified lines
2771127935 return -1;
2771227936 }
2771327937
27714−/* warning: the returned atom is not allocated */
27715−static JSAtom js_get_script_or_module_name(JSContext *ctx)
27938+/* return JS_ATOM_NULL if the name cannot be found. Only works with
27939+ not striped bytecode functions. */
27940+JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)
2771627941 {
2771727942 JSStackFrame *sf;
2771827943 JSFunctionBytecode *b;
@@ -27721,14 +27946,22 @@ static JSAtom js_get_script_or_module_name(JSContext *ctx) · 2 unmodified lines
2772127946 function. It does not work for eval(). Need to add a
2772227947 ScriptOrModule info in JSFunctionBytecode */
2772327948 sf = ctx->rt->current_stack_frame;
27724− assert(sf != NULL);
27725− assert(JS_VALUE_GET_TAG(sf->cur_func) == JS_TAG_OBJECT);
27949+ if (!sf)
27950+ return JS_ATOM_NULL;
27951+ while (n_stack_levels-- > 0) {
27952+ sf = sf->prev_frame;
27953+ if (!sf)
27954+ return JS_ATOM_NULL;
27955+ }
27956+ if (JS_VALUE_GET_TAG(sf->cur_func) != JS_TAG_OBJECT)
27957+ return JS_ATOM_NULL;
2772627958 p = JS_VALUE_GET_OBJ(sf->cur_func);
27727− assert(js_class_has_bytecode(p->class_id));
27959+ if (!js_class_has_bytecode(p->class_id))
27960+ return JS_ATOM_NULL;
2772827961 b = p->u.func.function_bytecode;
2772927962 if (!b->has_debug)
2773027963 return JS_ATOM_NULL;
27731− return b->debug.filename;
27964+ return JS_DupAtom(ctx, b->debug.filename);
2773227965 }
2773327966
2773427967 JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m)
@@ -27755,13 +27988,14 @@ static JSValue js_import_meta(JSContext *ctx) · 20 unmodified lines
2775527988 JSAtom filename;
2775627989 JSModuleDef *m;
2775727990
27758− filename = js_get_script_or_module_name(ctx);
27991+ filename = JS_GetScriptOrModuleName(ctx, 0);
2775927992 if (filename == JS_ATOM_NULL)
2776027993 goto fail;
2776127994
2776227995 /* XXX: inefficient, need to add a module or script pointer in
2776327996 JSFunctionBytecode */
2776427997 m = js_find_loaded_module(ctx, filename);
27998+ JS_FreeAtom(ctx, filename);
2776527999 if (!m) {
2776628000 fail:
2776728001 JS_ThrowTypeError(ctx, "import.meta not supported in this context");
@@ -27770,6 +28004,31 @@ static JSValue js_import_meta(JSContext *ctx) · 2 unmodified lines
2777028004 return JS_GetImportMeta(ctx, m);
2777128005 }
2777228006
28007+/* used by os.Worker() and import() */
28008+JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename,
28009+ const char *filename)
28010+{
28011+ JSModuleDef *m;
28012+ JSValue ret, func_obj;
28013+
28014+ m = js_host_resolve_imported_module(ctx, basename, filename);
28015+ if (!m)
28016+ return NULL;
28017+
28018+ if (js_resolve_module(ctx, m) < 0) {
28019+ js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED);
28020+ return NULL;
28021+ }
28022+
28023+ /* Evaluate the module code */
28024+ func_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
28025+ ret = JS_EvalFunction(ctx, func_obj);
28026+ if (JS_IsException(ret))
28027+ return NULL;
28028+ JS_FreeValue(ctx, ret);
28029+ return m;
28030+}
28031+
2777328032 static JSValue js_dynamic_import_job(JSContext *ctx,
2777428033 int argc, JSValueConst *argv)
2777528034 {
@@ -27777,53 +28036,36 @@ static JSValue js_dynamic_import_job(JSContext *ctx, · 1 unmodified line
2777728036 JSValueConst basename_val = argv[2];
2777828037 JSValueConst specifier = argv[3];
2777928038 JSModuleDef *m;
27780− JSAtom basename = JS_ATOM_NULL, filename;
27781− JSValue specifierString, ret, func_obj, err, ns;
28039+ const char *basename = NULL, *filename;
28040+ JSValue ret, err, ns;
2778228041
2778328042 if (!JS_IsString(basename_val)) {
2778428043 JS_ThrowTypeError(ctx, "no function filename for import()");
2778528044 goto exception;
2778628045 }
27787− basename = JS_ValueToAtom(ctx, basename_val);
27788− if (basename == JS_ATOM_NULL)
28046+ basename = JS_ToCString(ctx, basename_val);
28047+ if (!basename)
2778928048 goto exception;
2779028049
27791− specifierString = JS_ToString(ctx, specifier);
27792− if (JS_IsException(specifierString))
27793− goto exception;
27794− filename = JS_ValueToAtom(ctx, specifierString);
27795− JS_FreeValue(ctx, specifierString);
27796− if (filename == JS_ATOM_NULL)
28050+ filename = JS_ToCString(ctx, specifier);
28051+ if (!filename)
2779728052 goto exception;
2779828053
27799− m = js_host_resolve_imported_module(ctx, basename, filename);
27800− JS_FreeAtom(ctx, filename);
27801− if (!m) {
27802− goto exception;
27803− }
27804−
27805− if (js_resolve_module(ctx, m) < 0) {
27806− js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED);
27807− goto exception;
27808− }
27809−
27810− /* Evaluate the module code */
27811− func_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
27812− ret = JS_EvalFunction(ctx, func_obj);
27813− if (JS_IsException(ret))
28054+ m = JS_RunModule(ctx, basename, filename);
28055+ JS_FreeCString(ctx, filename);
28056+ if (!m)
2781428057 goto exception;
27815− JS_FreeValue(ctx, ret);
2781628058
2781728059 /* return the module namespace */
2781828060 ns = js_get_module_ns(ctx, m);
27819− if (JS_IsException(ret))
28061+ if (JS_IsException(ns))
2782028062 goto exception;
2782128063
2782228064 ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,
2782328065 1, (JSValueConst *)&ns);
2782428066 JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
2782528067 JS_FreeValue(ctx, ns);
27826− JS_FreeAtom(ctx, basename);
28068+ JS_FreeCString(ctx, basename);
2782728069 return JS_UNDEFINED;
2782828070 exception:
2782928071
@@ -27832,7 +28074,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx, · 2 unmodified lines
2783228074 1, (JSValueConst *)&err);
2783328075 JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
2783428076 JS_FreeValue(ctx, err);
27835− JS_FreeAtom(ctx, basename);
28077+ JS_FreeCString(ctx, basename);
2783628078 return JS_UNDEFINED;
2783728079 }
2783828080
@@ -27842,11 +28084,12 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) · 3 unmodified lines
2784228084 JSValue promise, resolving_funcs[2], basename_val;
2784328085 JSValueConst args[4];
2784428086
27845− basename = js_get_script_or_module_name(ctx);
28087+ basename = JS_GetScriptOrModuleName(ctx, 0);
2784628088 if (basename == JS_ATOM_NULL)
2784728089 basename_val = JS_NULL;
2784828090 else
2784928091 basename_val = JS_AtomToValue(ctx, basename);
28092+ JS_FreeAtom(ctx, basename);
2785028093 if (JS_IsException(basename_val))
2785128094 return basename_val;
2785228095
@@ -28957,7 +29200,7 @@ static BOOL can_opt_put_ref_value(const uint8_t *bc_buf, int pos) · 1104 unmodified lines
2895729200 return (bc_buf[pos + 1] == OP_put_ref_value &&
2895829201 (opcode == OP_insert3 ||
2895929202 opcode == OP_perm4 ||
28960− //opcode == OP_nop ||
29203+ opcode == OP_nop ||
2896129204 opcode == OP_rot3l));
2896229205 }
2896329206
@@ -28967,7 +29210,7 @@ static BOOL can_opt_put_global_ref_value(const uint8_t *bc_buf, int pos) · 3 unmodified lines
2896729210 return (bc_buf[pos + 1] == OP_put_ref_value &&
2896829211 (opcode == OP_insert3 ||
2896929212 opcode == OP_perm4 ||
28970− //opcode == OP_nop ||
29213+ opcode == OP_nop ||
2897129214 opcode == OP_rot3l));
2897229215 }
2897329216
@@ -29049,20 +29292,22 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s, · 75 unmodified lines
2904929292 end_pos = label_pos + 2;
2905029293 op = bc_buf[label_pos];
2905129294 if (is_strict) {
29052− switch(op) {
29053− case OP_insert3:
29054− op = OP_insert2;
29055− break;
29056− case OP_perm4:
29057− op = OP_perm3;
29058− break;
29059− case OP_rot3l:
29060− op = OP_swap;
29061− break;
29062− default:
29063− abort();
29295+ if (op != OP_nop) {
29296+ switch(op) {
29297+ case OP_insert3:
29298+ op = OP_insert2;
29299+ break;
29300+ case OP_perm4:
29301+ op = OP_perm3;
29302+ break;
29303+ case OP_rot3l:
29304+ op = OP_swap;
29305+ break;
29306+ default:
29307+ abort();
29308+ }
29309+ bc_buf[pos++] = op;
2906429310 }
29065− bc_buf[pos++] = op;
2906629311 } else {
2906729312 if (op == OP_insert3)
2906829313 bc_buf[pos++] = OP_dup;
@@ -31567,20 +31812,20 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) · 2498 unmodified lines
3156731812 }
3156831813 goto no_change;
3156931814
31815+#if SHORT_OPCODES
3157031816 case OP_typeof:
3157131817 if (OPTIMIZE) {
3157231818 /* simplify typeof tests */
3157331819 if (code_match(&cc, pos_next, OP_push_atom_value, M4(OP_strict_eq, OP_strict_neq, OP_eq, OP_neq), -1)) {
3157431820 if (cc.line_num >= 0) line_num = cc.line_num;
3157531821 int op1 = (cc.op == OP_strict_eq || cc.op == OP_eq) ? OP_strict_eq : OP_strict_neq;
31576−#if SHORT_OPCODES
3157731822 int op2 = -1;
3157831823 switch (cc.atom) {
3157931824 case JS_ATOM_undefined:
31580− op2 = OP_is_undefined;
31825+ op2 = OP_typeof_is_undefined;
3158131826 break;
3158231827 case JS_ATOM_function:
31583− op2 = OP_is_function;
31828+ op2 = OP_typeof_is_function;
3158431829 break;
3158531830 }
3158631831 if (op2 >= 0) {
@@ -31604,19 +31849,10 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) · 17 unmodified lines
3160431849 goto has_label;
3160531850 }
3160631851 }
31607−#endif
31608− if (cc.atom == JS_ATOM_undefined) {
31609− /* transform typeof(s) == "undefined" into s === void 0 */
31610− add_pc2line_info(s, bc_out.size, line_num);
31611− dbuf_putc(&bc_out, OP_undefined);
31612− dbuf_putc(&bc_out, op1);
31613− JS_FreeAtom(ctx, cc.atom);
31614− pos_next = cc.pos;
31615− break;
31616− }
3161731852 }
3161831853 }
3161931854 goto no_change;
31855+#endif
3162031856
3162131857 default:
3162231858 no_change:
@@ -37067,10 +37303,9 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, · 5444 unmodified lines
3706737303 int argc, JSValueConst *argv)
3706837304 {
3706937305 JSBoundFunction *bf;
37070− JSValue func_obj, name1;
37306+ JSValue func_obj, name1, len_val;
3707137307 JSObject *p;
37072− int arg_count, i;
37073− uint32_t len1;
37308+ int arg_count, i, ret;
3707437309
3707537310 if (check_function(ctx, this_val))
3707637311 return JS_EXCEPTION;
@@ -37093,6 +37328,44 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, · 16 unmodified lines
3709337328 }
3709437329 p->u.bound_function = bf;
3709537330
37331+ /* XXX: the spec could be simpler by only using GetOwnProperty */
37332+ ret = JS_GetOwnProperty(ctx, NULL, this_val, JS_ATOM_length);
37333+ if (ret < 0)
37334+ goto exception;
37335+ if (!ret) {
37336+ len_val = JS_NewInt32(ctx, 0);
37337+ } else {
37338+ len_val = JS_GetProperty(ctx, this_val, JS_ATOM_length);
37339+ if (JS_IsException(len_val))
37340+ goto exception;
37341+ if (JS_VALUE_GET_TAG(len_val) == JS_TAG_INT) {
37342+ /* most common case */
37343+ int len1 = JS_VALUE_GET_INT(len_val);
37344+ if (len1 <= arg_count)
37345+ len1 = 0;
37346+ else
37347+ len1 -= arg_count;
37348+ len_val = JS_NewInt32(ctx, len1);
37349+ } else if (JS_VALUE_GET_NORM_TAG(len_val) == JS_TAG_FLOAT64) {
37350+ double d = JS_VALUE_GET_FLOAT64(len_val);
37351+ if (isnan(d)) {
37352+ d = 0.0;
37353+ } else {
37354+ d = trunc(d);
37355+ if (d <= (double)arg_count)
37356+ d = 0.0;
37357+ else
37358+ d -= (double)arg_count; /* also converts -0 to +0 */
37359+ }
37360+ len_val = JS_NewFloat64(ctx, d);
37361+ } else {
37362+ JS_FreeValue(ctx, len_val);
37363+ len_val = JS_NewInt32(ctx, 0);
37364+ }
37365+ }
37366+ JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length,
37367+ len_val, JS_PROP_CONFIGURABLE);
37368+
3709637369 name1 = JS_GetProperty(ctx, this_val, JS_ATOM_name);
3709737370 if (JS_IsException(name1))
3709837371 goto exception;
@@ -37105,15 +37378,6 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, · 6 unmodified lines
3710537378 goto exception;
3710637379 JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, name1,
3710737380 JS_PROP_CONFIGURABLE);
37108− if (js_get_length32(ctx, &len1, this_val))
37109− goto exception;
37110− if (len1 <= (uint32_t)arg_count)
37111− len1 = 0;
37112− else
37113− len1 -= arg_count;
37114− JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length,
37115− JS_NewUint32(ctx, len1),
37116− JS_PROP_CONFIGURABLE);
3711737381 return func_obj;
3711837382 exception:
3711937383 JS_FreeValue(ctx, func_obj);
@@ -40455,10 +40719,6 @@ static JSValue js_string_pad(JSContext *ctx, JSValueConst this_val, · 3335 unmodified lines
4045540719 len = p->len;
4045640720 if (len >= n)
4045740721 return str;
40458− if (n > JS_STRING_LEN_MAX) {
40459− JS_ThrowInternalError(ctx, "string too long");
40460− goto fail2;
40461− }
4046240722 if (argc > 1 && !JS_IsUndefined(argv[1])) {
4046340723 v = JS_ToString(ctx, argv[1]);
4046440724 if (JS_IsException(v))
@@ -40473,6 +40733,10 @@ static JSValue js_string_pad(JSContext *ctx, JSValueConst this_val, · 8 unmodified lines
4047340733 p1 = NULL;
4047440734 }
4047540735 }
40736+ if (n > JS_STRING_LEN_MAX) {
40737+ JS_ThrowInternalError(ctx, "string too long");
40738+ goto fail2;
40739+ }
4047640740 if (string_buffer_init(ctx, b, n))
4047740741 goto fail3;
4047840742 n -= len;
@@ -41932,14 +42196,11 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, · 1453 unmodified lines
4193242196 if (JS_IsException(obj))
4193342197 goto fail;
4193442198 prop_flags = JS_PROP_C_W_E | JS_PROP_THROW;
41935− group_name_ptr = NULL;
41936− if (re_flags & LRE_FLAG_NAMED_GROUPS) {
41937− uint32_t re_bytecode_len;
42199+ group_name_ptr = lre_get_groupnames(re_bytecode);
42200+ if (group_name_ptr) {
4193842201 groups = JS_NewObjectProto(ctx, JS_NULL);
4193942202 if (JS_IsException(groups))
4194042203 goto fail;
41941− re_bytecode_len = get_u32(re_bytecode + 3);
41942− group_name_ptr = (char *)(re_bytecode + 7 + re_bytecode_len);
4194342204 }
4194442205
4194542206 for(i = 0; i < capture_count; i++) {
@@ -43724,6 +43985,7 @@ static const JSCFunctionListEntry js_reflect_funcs[] = { · 1778 unmodified lines
4372443985 JS_CFUNC_MAGIC_DEF("preventExtensions", 1, js_object_preventExtensions, 1 ),
4372543986 JS_CFUNC_DEF("set", 3, js_reflect_set ),
4372643987 JS_CFUNC_DEF("setPrototypeOf", 2, js_reflect_setPrototypeOf ),
43988+ JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Reflect", JS_PROP_CONFIGURABLE ),
4372743989 };
4372843990
4372943991 static const JSCFunctionListEntry js_reflect_obj[] = {
quickjs.h+10−0
@@ -412,6 +412,8 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s); · 411 unmodified lines
412412 void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);
413413
414414 /* atom support */
415+#define JS_ATOM_NULL 0
416+
415417 JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len);
416418 JSAtom JS_NewAtom(JSContext *ctx, const char *str);
417419 JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n);
@@ -835,6 +837,8 @@ typedef int JSInterruptHandler(JSRuntime *rt, void *opaque); · 417 unmodified lines
835837 void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque);
836838 /* if can_block is TRUE, Atomics.wait() can be used */
837839 void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block);
840+/* set the [IsHTMLDDA] internal slot */
841+void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj);
838842
839843 typedef struct JSModuleDef JSModuleDef;
840844
@@ -886,6 +890,12 @@ JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, · 45 unmodified lines
886890 returns a module. */
887891 int JS_ResolveModule(JSContext *ctx, JSValueConst obj);
888892
893+/* only exported for os.Worker() */
894+JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels);
895+/* only exported for os.Worker() */
896+JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename,
897+ const char *filename);
898+
889899 /* C function definition */
890900 typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */
891901 JS_CFUNC_generic,
run-test262.c+10−1
@@ -743,10 +743,16 @@ static JSValue js_createRealm(JSContext *ctx, JSValue this_val, · 742 unmodified lines
743743 return ret;
744744 }
745745
746+static JSValue js_IsHTMLDDA(JSContext *ctx, JSValue this_val,
747+ int argc, JSValue *argv)
748+{
749+ return JS_NULL;
750+}
751+
746752 static JSValue add_helpers1(JSContext *ctx)
747753 {
748754 JSValue global_obj;
749− JSValue obj262;
755+ JSValue obj262, obj;
750756
751757 global_obj = JS_GetGlobalObject(ctx);
752758
@@ -773,6 +779,9 @@ static JSValue add_helpers1(JSContext *ctx) · 20 unmodified lines
773779 JS_SetPropertyStr(ctx, obj262, "createRealm",
774780 JS_NewCFunction(ctx, js_createRealm,
775781 "createRealm", 0));
782+ obj = JS_NewCFunction(ctx, js_IsHTMLDDA, "IsHTMLDDA", 0);
783+ JS_SetIsHTMLDDA(ctx, obj);
784+ JS_SetPropertyStr(ctx, obj262, "IsHTMLDDA", obj);
776785
777786 JS_SetPropertyStr(ctx, global_obj, "$262", JS_DupValue(ctx, obj262));
778787
test262.conf+3−2
@@ -68,6 +68,7 @@ class-methods-private · 67 unmodified lines
6868 class-static-fields-public
6969 class-static-fields-private
7070 class-static-methods-private
71+cleanupSome=skip
7172 coalesce-expression
7273 computed-property-names
7374 const
@@ -100,10 +101,10 @@ host-gc-required=skip · 26 unmodified lines
100101 import.meta
101102 Int32Array
102103 Int8Array
103−IsHTMLDDA=skip
104+IsHTMLDDA
104105 json-superset
105106 let
106−logical-assignment-operators=skip
107+logical-assignment-operators
107108 Map
108109 new.target
109110 numeric-separator-literal
tests/test_builtin.js+2−0
@@ -277,6 +277,8 @@ function test_string() · 276 unmodified lines
277277 assert("aaaa".split("aaaaa", 1), [ "aaaa" ]);
278278
279279 assert(eval('"\0"'), "\0");
280+
281+ assert("abc".padStart(Infinity, ""), "abc");
280282 }
281283
282284 function test_math()
tests/test_language.js+19−0
@@ -359,6 +359,23 @@ function test_labels() · 358 unmodified lines
359359 while (0) x: { break x; };
360360 }
361361
362+function test_destructuring()
363+{
364+ function * g () { return 0; };
365+ var [x] = g();
366+ assert(x, void 0);
367+}
368+
369+function test_spread()
370+{
371+ var x;
372+ x = [1, 2, ...[3, 4]];
373+ assert(x.toString(), "1,2,3,4");
374+
375+ x = [ ...[ , ] ];
376+ assert(Object.getOwnPropertyNames(x).toString(), "0,length");
377+}
378+
362379 test_op1();
363380 test_cvt();
364381 test_eq();
@@ -373,3 +390,5 @@ test_template_skip(); · 8 unmodified lines
373390 test_object_literal();
374391 test_regexp_skip();
375392 test_labels();
393+test_destructuring();
394+test_spread();
tests/test_worker.js+1−32
@@ -25,38 +25,7 @@ function test_worker() · 24 unmodified lines
2525 {
2626 var counter;
2727
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−`);
28+ worker = new os.Worker("./test_worker_module.js");
6029
6130 counter = 0;
6231 worker.onmessage = function (e) {
tests/test_worker_module.js+31−0
@@ -0,0 +1,31 @@
1+/* Worker code for test_worker.js */
2+import * as std from "std";
3+import * as os from "os";
4+
5+var parent = os.Worker.parent;
6+
7+function handle_msg(e) {
8+ var ev = e.data;
9+ // print("child_recv", JSON.stringify(ev));
10+ switch(ev.type) {
11+ case "abort":
12+ parent.postMessage({ type: "done" });
13+ break;
14+ case "sab":
15+ /* modify the SharedArrayBuffer */
16+ ev.buf[2] = 10;
17+ parent.postMessage({ type: "sab_done", buf: ev.buf });
18+ break;
19+ }
20+}
21+
22+function worker_main() {
23+ var i;
24+
25+ parent.onmessage = handle_msg;
26+ for(i = 0; i < 10; i++) {
27+ parent.postMessage({ type: "num", num: i });
28+ }
29+}
30+
31+worker_main();

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