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 @@
12020-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
12020-07-05:102020-07-05:
2 11
3- modified JS_GetPrototype() to return a live value12- modified JS_GetPrototype() to return a live value
TODO+2−2
@@ -74,5 +74,5 @@ REPL: · 73 unmodified lines
74Test262o: 0/11262 errors, 463 excluded74Test262o: 0/11262 errors, 463 excluded
75Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)75Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
76 76
77Test262: 30/71095 errors, 870 excluded, 549 skipped77Test262: 30/71748 errors, 868 excluded, 474 skipped
78Test262 commit: 281eb10b2844929a7c0ac04527f5b42ce56509fd78Test262 commit: 24c67328062383079ada85f4d253eb0526fd209b
VERSION+1−1
@@ -1 +1 @@
12020-07-0512020-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
258 return c;258 return c;
259 }259 }
260 switch(c) {260 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:
262 l = 1;269 l = 1;
263 break;270 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:
265 l = 2;275 l = 2;
266 break;276 break;
267 case 0xf0 ... 0xf7:277 case 0xf0: case 0xf1: case 0xf2: case 0xf3:
278 case 0xf4: case 0xf5: case 0xf6: case 0xf7:
268 l = 3;279 l = 3;
269 break;280 break;
270 case 0xf8 ... 0xfb:281 case 0xf8: case 0xf9: case 0xfa: case 0xfb:
271 l = 4;282 l = 4;
272 break;283 break;
273 case 0xfc ... 0xfd:284 case 0xfc: case 0xfd:
274 l = 5;285 l = 5;
275 break;286 break;
276 default:287 default:
doc/jsbignum.html+2−2
@@ -1,8 +1,7 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2<html>2<html>
3<!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ -->3<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->
4<head>4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6<title>Javascript Bignum Extensions</title>5<title>Javascript Bignum Extensions</title>
7 6
8<meta name="description" content="Javascript Bignum Extensions">7<meta name="description" content="Javascript Bignum Extensions">
@@ -10,6 +9,7 @@ · 1 unmodified line
10<meta name="resource-type" content="document">9<meta name="resource-type" content="document">
11<meta name="distribution" content="global">10<meta name="distribution" content="global">
12<meta name="Generator" content="makeinfo">11<meta name="Generator" content="makeinfo">
12<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
13<link href="#SEC_Contents" rel="contents" title="Table of Contents">13<link href="#SEC_Contents" rel="contents" title="Table of Contents">
14<style type="text/css">14<style type="text/css">
15<!--15<!--
doc/jsbignum.pdf+0−0

Binary file not shown.

doc/quickjs.html+18−10
@@ -1,8 +1,7 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2<html>2<html>
3<!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ -->3<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->
4<head>4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6<title>QuickJS Javascript Engine</title>5<title>QuickJS Javascript Engine</title>
7 6
8<meta name="description" content="QuickJS Javascript Engine">7<meta name="description" content="QuickJS Javascript Engine">
@@ -10,6 +9,7 @@ · 1 unmodified line
10<meta name="resource-type" content="document">9<meta name="resource-type" content="document">
11<meta name="distribution" content="global">10<meta name="distribution" content="global">
12<meta name="Generator" content="makeinfo">11<meta name="Generator" content="makeinfo">
12<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
13<link href="#SEC_Contents" rel="contents" title="Table of Contents">13<link href="#SEC_Contents" rel="contents" title="Table of Contents">
14<style type="text/css">14<style type="text/css">
15<!--15<!--
@@ -237,7 +237,7 @@ source is <code>import</code>. · 221 unmodified lines
237</dd>237</dd>
238<dt><code>--bignum</code></dt>238<dt><code>--bignum</code></dt>
239<dd><p>Enable the bignum extensions: BigDecimal object, BigFloat object and239<dd><p>Enable the bignum extensions: BigDecimal object, BigFloat object and
240the <code>&quot;use bigint&quot;</code> and <code>&quot;use math&quot;</code> directives.240the <code>&quot;use math&quot;</code> directive.
241</p>241</p>
242</dd>242</dd>
243<dt><code>-I file</code></dt>243<dt><code>-I file</code></dt>
@@ -293,6 +293,13 @@ executable file. · 49 unmodified lines
293<dd><p>Compile as Javascript module (default=autodetect).293<dd><p>Compile as Javascript module (default=autodetect).
294</p>294</p>
295</dd>295</dd>
296<dt><code>-D module_name</code></dt>
297<dd><p>Compile a dynamically loaded module and its dependencies. This option
298is needed when your code uses the <code>import</code> keyword or the
299<code>os.Worker</code> constructor because the compiler cannot statically
300find the name of the dynamically loaded modules.
301</p>
302</dd>
296<dt><code>-M module_name[,cname]</code></dt>303<dt><code>-M module_name[,cname]</code></dt>
297<dd><p>Add initialization code for an external C module. See the304<dd><p>Add initialization code for an external C module. See the
298<code>c_module</code> example.305<code>c_module</code> example.
@@ -314,7 +321,7 @@ when the <code>-fno-x</code> options are used. · 15 unmodified lines
314</dd>321</dd>
315<dt><code>-fbignum</code></dt>322<dt><code>-fbignum</code></dt>
316<dd><p>Enable the bignum extensions: BigDecimal object, BigFloat object and323<dd><p>Enable the bignum extensions: BigDecimal object, BigFloat object and
317the <code>&quot;use bigint&quot;</code> and <code>&quot;use math&quot;</code> directives.324the <code>&quot;use math&quot;</code> directive.
318</p>325</p>
319</dd>326</dd>
320</dl>327</dl>
@@ -989,13 +996,14 @@ to the timer. · 668 unmodified lines
989<code>&quot;win32&quot;</code> or <code>&quot;js&quot;</code>.996<code>&quot;win32&quot;</code> or <code>&quot;js&quot;</code>.
990</p>997</p>
991</dd>998</dd>
992<dt><code>Worker(source)</code></dt>999<dt><code>Worker(module_filename)</code></dt>
993<dd><p>Constructor to create a new thread (worker) with an API close to the1000<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 module1001<code>WebWorkers</code>. <code>module_filename</code> is a string specifying the
995source which is executed in the newly created thread. Threads normally1002module filename which is executed in the newly created thread. As for
996don&rsquo;t share any data and communicate between each other with1003dynamically imported module, it is relative to the current script or
997messages. Nested workers are not supported. An example is available in1004module path. Threads normally don&rsquo;t share any data and communicate
998<samp>tests/test_worker.js</samp>.1005between each other with messages. Nested workers are not supported. An
1006example is available in <samp>tests/test_worker.js</samp>.
999</p>1007</p>
1000<p>The worker class has the following static properties:1008<p>The worker class has the following static properties:
1001</p>1009</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
120 120
121@item --bignum121@item --bignum
122Enable the bignum extensions: BigDecimal object, BigFloat object and122Enable the bignum extensions: BigDecimal object, BigFloat object and
123the @code{"use bigint"} and @code{"use math"} directives.123the @code{"use math"} directive.
124 124
125@item -I file125@item -I file
126@item --include file126@item --include file
@@ -167,6 +167,12 @@ Set the C name of the generated data. · 40 unmodified lines
167@item -m167@item -m
168Compile as Javascript module (default=autodetect).168Compile as Javascript module (default=autodetect).
169 169
170@item -D module_name
171Compile a dynamically loaded module and its dependencies. This option
172is needed when your code uses the @code{import} keyword or the
173@code{os.Worker} constructor because the compiler cannot statically
174find the name of the dynamically loaded modules.
175
170@item -M module_name[,cname]176@item -M module_name[,cname]
171Add initialization code for an external C module. See the177Add initialization code for an external C module. See the
172@code{c_module} example.178@code{c_module} example.
@@ -184,7 +190,7 @@ Disable selected language features to produce a smaller executable file. · 11 unmodified lines
184 190
185@item -fbignum191@item -fbignum
186Enable the bignum extensions: BigDecimal object, BigFloat object and192Enable the bignum extensions: BigDecimal object, BigFloat object and
187the @code{"use bigint"} and @code{"use math"} directives.193the @code{"use math"} directive.
188 194
189@end table195@end table
190 196
@@ -764,13 +770,14 @@ Cancel a timer. · 573 unmodified lines
764Return a string representing the platform: @code{"linux"}, @code{"darwin"},770Return a string representing the platform: @code{"linux"}, @code{"darwin"},
765@code{"win32"} or @code{"js"}.771@code{"win32"} or @code{"js"}.
766 772
767@item Worker(source)773@item Worker(module_filename)
768Constructor to create a new thread (worker) with an API close to the774Constructor to create a new thread (worker) with an API close to the
769@code{WebWorkers}. @code{source} is a string containing the module775@code{WebWorkers}. @code{module_filename} is a string specifying the
770source which is executed in the newly created thread. Threads normally776module filename which is executed in the newly created thread. As for
771don't share any data and communicate between each other with777dynamically imported module, it is relative to the current script or
772messages. Nested workers are not supported. An example is available in778module path. Threads normally don't share any data and communicate
773@file{tests/test_worker.js}.779between each other with messages. Nested workers are not supported. An
780example is available in @file{tests/test_worker.js}.
774 781
775The worker class has the following static properties:782The worker class has the following static properties:
776 783
libregexp.c+17−3
@@ -569,7 +569,8 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16) · 568 unmodified lines
569 }569 }
570 }570 }
571 break;571 break;
572 case '0' ... '7':572 case '0': case '1': case '2': case '3':
573 case '4': case '5': case '6': case '7':
573 c -= '0';574 c -= '0';
574 if (allow_utf16 == 2) {575 if (allow_utf16 == 2) {
575 /* only accept \0 not followed by digit */576 /* 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
1410 }1411 }
1411 }1412 }
1412 goto normal_char;1413 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':
1414 {1417 {
1415 const uint8_t *q = ++p;1418 const uint8_t *q = ++p;
1416 1419
@@ -1434,7 +1437,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) · 17 unmodified lines
1434 }1437 }
1435 goto normal_char;1438 goto normal_char;
1436 }1439 }
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");
1438 }1441 }
1439 emit_back_reference:1442 emit_back_reference:
1440 last_atom_start = s->byte_code.size;1443 last_atom_start = s->byte_code.size;
@@ -2533,6 +2536,17 @@ int lre_get_flags(const uint8_t *bc_buf) · 1092 unmodified lines
2533 return bc_buf[RE_HEADER_FLAGS];2536 return bc_buf[RE_HEADER_FLAGS];
2534}2537}
2535 2538
2539/* Return NULL if no group names. Otherwise, return a pointer to
2540 'capture_count - 1' zero terminated UTF-8 strings. */
2541const 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
2536#ifdef TEST2550#ifdef TEST
2537 2551
2538BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size)2552BOOL 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
44 void *opaque);44 void *opaque);
45int lre_get_capture_count(const uint8_t *bc_buf);45int lre_get_capture_count(const uint8_t *bc_buf);
46int lre_get_flags(const uint8_t *bc_buf);46int lre_get_flags(const uint8_t *bc_buf);
47const char *lre_get_groupnames(const uint8_t *bc_buf);
47int lre_exec(uint8_t **capture,48int lre_exec(uint8_t **capture,
48 const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,49 const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
49 int cbuf_type, void *opaque);50 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
527 } else {527 } else {
528 d = unicode_decomp_data + unicode_decomp_table2[idx];528 d = unicode_decomp_data + unicode_decomp_table2[idx];
529 switch(type) {529 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:
531 l = type - DECOMP_TYPE_L1 + 1;537 l = type - DECOMP_TYPE_L1 + 1;
532 d += (c - code) * l * 2;538 d += (c - code) * l * 2;
533 for(i = 0; i < l; i++) {539 for(i = 0; i < l; i++) {
@@ -535,7 +541,8 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c, · 1 unmodified line
535 return 0;541 return 0;
536 }542 }
537 return l;543 return l;
538 case DECOMP_TYPE_LL1 ... DECOMP_TYPE_LL2:544 case DECOMP_TYPE_LL1:
545 case DECOMP_TYPE_LL2:
539 {546 {
540 uint32_t k, p;547 uint32_t k, p;
541 l = type - DECOMP_TYPE_LL1 + 1;548 l = type - DECOMP_TYPE_LL1 + 1;
@@ -551,7 +558,11 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c, · 9 unmodified lines
551 }558 }
552 }559 }
553 return l;560 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:
555 l = type - DECOMP_TYPE_S1 + 1;566 l = type - DECOMP_TYPE_S1 + 1;
556 d += (c - code) * l;567 d += (c - code) * l;
557 for(i = 0; i < l; i++) {568 for(i = 0; i < l; i++) {
@@ -582,7 +593,14 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c, · 24 unmodified lines
582 case DECOMP_TYPE_B18:593 case DECOMP_TYPE_B18:
583 l = 18;594 l = 18;
584 goto decomp_type_b;595 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:
586 l = type - DECOMP_TYPE_B1 + 1;604 l = type - DECOMP_TYPE_B1 + 1;
587 decomp_type_b:605 decomp_type_b:
588 {606 {
qjs.c+28−15
@@ -46,6 +46,7 @@ extern const uint32_t qjsc_repl_size; · 45 unmodified lines
46#ifdef CONFIG_BIGNUM46#ifdef CONFIG_BIGNUM
47extern const uint8_t qjsc_qjscalc[];47extern const uint8_t qjsc_qjscalc[];
48extern const uint32_t qjsc_qjscalc_size;48extern const uint32_t qjsc_qjscalc_size;
49static int bignum_ext;
49#endif50#endif
50 51
51static int eval_buf(JSContext *ctx, const void *buf, int buf_len,52static 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
101 return ret;102 return ret;
102}103}
103 104
105/* also used to initialize the worker context */
106static 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
104#if defined(__APPLE__)126#if defined(__APPLE__)
105#define MALLOC_OVERHEAD 0127#define MALLOC_OVERHEAD 0
106#else128#else
@@ -294,7 +316,7 @@ int main(int argc, char **argv) · 187 unmodified lines
294 char *include_list[32];316 char *include_list[32];
295 int i, include_count = 0;317 int i, include_count = 0;
296#ifdef CONFIG_BIGNUM318#ifdef CONFIG_BIGNUM
297 int load_jscalc, bignum_ext = 0;319 int load_jscalc;
298#endif320#endif
299 size_t stack_size = 0;321 size_t stack_size = 0;
300 322
@@ -426,6 +448,9 @@ int main(int argc, char **argv) · 125 unmodified lines
426 }448 }
427 }449 }
428 450
451 if (load_jscalc)
452 bignum_ext = 1;
453
429 if (trace_memory) {454 if (trace_memory) {
430 js_trace_malloc_init(&trace_data);455 js_trace_malloc_init(&trace_data);
431 rt = JS_NewRuntime2(&trace_mf, &trace_data);456 rt = JS_NewRuntime2(&trace_mf, &trace_data);
@@ -440,22 +465,14 @@ int main(int argc, char **argv) · 8 unmodified lines
440 JS_SetMemoryLimit(rt, memory_limit);465 JS_SetMemoryLimit(rt, memory_limit);
441 if (stack_size != 0)466 if (stack_size != 0)
442 JS_SetMaxStackSize(rt, stack_size);467 JS_SetMaxStackSize(rt, stack_size);
468 js_std_set_worker_new_context_func(JS_NewCustomContext);
443 js_std_init_handlers(rt);469 js_std_init_handlers(rt);
444 ctx = JS_NewContext(rt);470 ctx = JS_NewCustomContext(rt);
445 if (!ctx) {471 if (!ctx) {
446 fprintf(stderr, "qjs: cannot allocate JS context\n");472 fprintf(stderr, "qjs: cannot allocate JS context\n");
447 exit(2);473 exit(2);
448 }474 }
449 475
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
459 /* loader for ES6 modules */476 /* loader for ES6 modules */
460 JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);477 JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
461 478
@@ -472,10 +489,6 @@ int main(int argc, char **argv) · 10 unmodified lines
472#endif489#endif
473 js_std_add_helpers(ctx, argc - optind, argv + optind);490 js_std_add_helpers(ctx, argc - optind, argv + optind);
474 491
475 /* system modules */
476 js_init_module_std(ctx, "std");
477 js_init_module_os(ctx, "os");
478
479 /* make 'std' and 'os' visible to non module code */492 /* make 'std' and 'os' visible to non module code */
480 if (load_std) {493 if (load_std) {
481 const char *str = "import * as std from 'std';\n"494 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
326 " JSRuntime *rt;\n"326 " JSRuntime *rt;\n"
327 " JSContext *ctx;\n"327 " JSContext *ctx;\n"
328 " rt = JS_NewRuntime();\n"328 " rt = JS_NewRuntime();\n"
329 " js_std_set_worker_new_context_func(JS_NewCustomContext);\n"
329 " js_std_init_handlers(rt);\n"330 " js_std_init_handlers(rt);\n"
330 ;331 ;
331 332
@@ -349,6 +350,7 @@ void help(void) · 17 unmodified lines
349 "-o output set the output filename\n"350 "-o output set the output filename\n"
350 "-N cname set the C name of the generated data\n"351 "-N cname set the C name of the generated data\n"
351 "-m compile as Javascript module (default=autodetect)\n"352 "-m compile as Javascript module (default=autodetect)\n"
353 "-D module_name compile a dynamically loaded module or worker\n"
352 "-M module_name[,cname] add initialization code for an external C module\n"354 "-M module_name[,cname] add initialization code for an external C module\n"
353 "-x byte swapped output\n"355 "-x byte swapped output\n"
354 "-p prefix set the prefix of the generated C names\n"356 "-p prefix set the prefix of the generated C names\n"
@@ -494,6 +496,7 @@ int main(int argc, char **argv) · 139 unmodified lines
494#ifdef CONFIG_BIGNUM496#ifdef CONFIG_BIGNUM
495 BOOL bignum_ext = FALSE;497 BOOL bignum_ext = FALSE;
496#endif498#endif
499 namelist_t dynamic_module_list;
497 500
498 out_filename = NULL;501 out_filename = NULL;
499 output_type = OUTPUT_EXECUTABLE;502 output_type = OUTPUT_EXECUTABLE;
@@ -504,13 +507,14 @@ int main(int argc, char **argv) · 4 unmodified lines
504 verbose = 0;507 verbose = 0;
505 use_lto = FALSE;508 use_lto = FALSE;
506 stack_size = 0;509 stack_size = 0;
510 memset(&dynamic_module_list, 0, sizeof(dynamic_module_list));
507 511
508 /* add system modules */512 /* add system modules */
509 namelist_add(&cmodule_list, "std", "std", 0);513 namelist_add(&cmodule_list, "std", "std", 0);
510 namelist_add(&cmodule_list, "os", "os", 0);514 namelist_add(&cmodule_list, "os", "os", 0);
511 515
512 for(;;) {516 for(;;) {
513 c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:");517 c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:");
514 if (c == -1)518 if (c == -1)
515 break;519 break;
516 switch(c) {520 switch(c) {
@@ -576,6 +580,9 @@ int main(int argc, char **argv) · 59 unmodified lines
576 namelist_add(&cmodule_list, path, cname, 0);580 namelist_add(&cmodule_list, path, cname, 0);
577 }581 }
578 break;582 break;
583 case 'D':
584 namelist_add(&dynamic_module_list, optarg, NULL, 0);
585 break;
579 case 'x':586 case 'x':
580 byte_swap = TRUE;587 byte_swap = TRUE;
581 break;588 break;
@@ -656,22 +663,22 @@ int main(int argc, char **argv) · 74 unmodified lines
656 cname = NULL;663 cname = NULL;
657 }664 }
658 665
659 if (output_type != OUTPUT_C) {666 for(i = 0; i < dynamic_module_list.count; i++) {
660 fputs(main_c_template1, fo);667 if (!jsc_module_loader(ctx, dynamic_module_list.array[i].name, NULL)) {
661 fprintf(fo, " ctx = JS_NewContextRaw(rt);\n");668 fprintf(stderr, "Could not load dynamic module '%s'\n",
662 669 dynamic_module_list.array[i].name);
663 if (stack_size != 0) {670 exit(1);
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");
671 }671 }
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");
673 /* add the basic objects */681 /* add the basic objects */
674
675 fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n");682 fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n");
676 for(i = 0; i < countof(feature_list); i++) {683 for(i = 0; i < countof(feature_list); i++) {
677 if ((feature_bitmap & ((uint64_t)1 << i)) &&684 if ((feature_bitmap & ((uint64_t)1 << i)) &&
@@ -689,8 +696,8 @@ int main(int argc, char **argv) · 11 unmodified lines
689 " JS_EnableBignumExt(ctx, 1);\n");696 " JS_EnableBignumExt(ctx, 1);\n");
690 }697 }
691#endif698#endif
692 fprintf(fo, " js_std_add_helpers(ctx, argc, argv);\n");699 /* add the precompiled modules (XXX: could modify the module
693 700 loader instead) */
694 for(i = 0; i < init_module_list.count; i++) {701 for(i = 0; i < init_module_list.count; i++) {
695 namelist_entry_t *e = &init_module_list.array[i];702 namelist_entry_t *e = &init_module_list.array[i];
696 /* initialize the static C modules */703 /* initialize the static C modules */
@@ -702,12 +709,39 @@ int main(int argc, char **argv) · 5 unmodified lines
702 " }\n",709 " }\n",
703 e->short_name, e->short_name, e->name);710 e->short_name, e->short_name, e->name);
704 }711 }
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");
705 738
706 for(i = 0; i < cname_list.count; i++) {739 for(i = 0; i < cname_list.count; i++) {
707 namelist_entry_t *e = &cname_list.array[i];740 namelist_entry_t *e = &cname_list.array[i];
708 fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, %s);\n",741 if (!e->flags) {
709 e->name, e->name,742 fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 0);\n",
710 e->flags ? "1" : "0");743 e->name, e->name);
744 }
711 }745 }
712 fputs(main_c_template2, fo);746 fputs(main_c_template2, fo);
713 }747 }
qjscalc.js+2−2
@@ -1826,7 +1826,7 @@ var Integer, Float, Fraction, Complex, Mod, Polynomial, PolyMod, RationalFunctio · 1825 unmodified lines
1826 j = emin + i;1826 j = emin + i;
1827 if (j == -1) {1827 if (j == -1) {
1828 if (a[i] != 0)1828 if (a[i] != 0)
1829 throw RangError("cannot represent integ(1/X)");1829 throw RangeError("cannot represent integ(1/X)");
1830 } else {1830 } else {
1831 r[i] = a[i] / (j + 1);1831 r[i] = a[i] / (j + 1);
1832 }1832 }
@@ -1853,7 +1853,7 @@ var Integer, Float, Fraction, Complex, Mod, Polynomial, PolyMod, RationalFunctio · 20 unmodified lines
1853 log() {1853 log() {
1854 var a = this, r;1854 var a = this, r;
1855 if (a.emin != 0)1855 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");
1857 r = integ(deriv(a) / a);1857 r = integ(deriv(a) / a);
1858 /* add the constant term */1858 /* add the constant term */
1859 r += global.log(a[0]);1859 r += global.log(a[0]);
quickjs-libc.c+58−42
@@ -2993,9 +2993,8 @@ typedef struct { · 2992 unmodified lines
2993} JSWorkerData;2993} JSWorkerData;
2994 2994
2995typedef struct {2995typedef struct {
2996 /* source code of the worker */2996 char *filename; /* module filename */
2997 char *eval_buf;2997 char *basename; /* module base name */
2998 size_t eval_buf_len;
2999 JSWorkerMessagePipe *recv_pipe, *send_pipe;2998 JSWorkerMessagePipe *recv_pipe, *send_pipe;
3000} WorkerFuncArgs;2999} WorkerFuncArgs;
3001 3000
@@ -3005,6 +3004,7 @@ typedef struct { · 3 unmodified lines
3005} JSSABHeader;3004} JSSABHeader;
3006 3005
3007static JSClassID js_worker_class_id;3006static JSClassID js_worker_class_id;
3007static JSContext *(*js_worker_new_context_func)(JSRuntime *rt);
3008 3008
3009static int atomic_add_int(int *ptr, int v)3009static int atomic_add_int(int *ptr, int v)
3010{3010{
@@ -3136,7 +3136,6 @@ static void *worker_func(void *opaque) · 125 unmodified lines
3136 JSRuntime *rt;3136 JSRuntime *rt;
3137 JSThreadState *ts;3137 JSThreadState *ts;
3138 JSContext *ctx;3138 JSContext *ctx;
3139 JSValue retval;
3140 3139
3141 rt = JS_NewRuntime();3140 rt = JS_NewRuntime();
3142 if (rt == NULL) {3141 if (rt == NULL) {
@@ -3145,12 +3144,16 @@ static void *worker_func(void *opaque) · 2 unmodified lines
3145 } 3144 }
3146 js_std_init_handlers(rt);3145 js_std_init_handlers(rt);
3147 3146
3147 JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
3148
3148 /* set the pipe to communicate with the parent */3149 /* set the pipe to communicate with the parent */
3149 ts = JS_GetRuntimeOpaque(rt);3150 ts = JS_GetRuntimeOpaque(rt);
3150 ts->recv_pipe = args->recv_pipe;3151 ts->recv_pipe = args->recv_pipe;
3151 ts->send_pipe = args->send_pipe;3152 ts->send_pipe = args->send_pipe;
3152 3153
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);
3154 if (ctx == NULL) {3157 if (ctx == NULL) {
3155 fprintf(stderr, "JS_NewContext failure");3158 fprintf(stderr, "JS_NewContext failure");
3156 }3159 }
@@ -3159,18 +3162,11 @@ static void *worker_func(void *opaque) · 2 unmodified lines
3159 3162
3160 js_std_add_helpers(ctx, -1, NULL);3163 js_std_add_helpers(ctx, -1, NULL);
3161 3164
3162 /* system modules */3165 if (!JS_RunModule(ctx, args->basename, args->filename))
3163 js_init_module_std(ctx, "std");
3164 js_init_module_os(ctx, "os");
3165
3166 retval = JS_Eval(ctx, args->eval_buf, args->eval_buf_len,
3167 "<worker>", JS_EVAL_TYPE_MODULE);
3168 free(args->eval_buf);
3169 free(args);
3170
3171 if (JS_IsException(retval))
3172 js_std_dump_error(ctx);3166 js_std_dump_error(ctx);
3173 JS_FreeValue(ctx, retval);3167 free(args->filename);
3168 free(args->basename);
3169 free(args);
3174 3170
3175 js_std_loop(ctx);3171 js_std_loop(ctx);
3176 3172
@@ -3216,52 +3212,53 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, · 39 unmodified lines
3216 int argc, JSValueConst *argv)3212 int argc, JSValueConst *argv)
3217{3213{
3218 JSRuntime *rt = JS_GetRuntime(ctx);3214 JSRuntime *rt = JS_GetRuntime(ctx);
3219 WorkerFuncArgs *args;3215 WorkerFuncArgs *args = NULL;
3220 const char *str;
3221 size_t str_len;
3222 pthread_t tid;3216 pthread_t tid;
3223 pthread_attr_t attr;3217 pthread_attr_t attr;
3224 JSValue obj = JS_UNDEFINED;3218 JSValue obj = JS_UNDEFINED;
3225 int ret;3219 int ret;
3220 const char *filename = NULL, *basename;
3221 JSAtom basename_atom;
3226 3222
3227 /* XXX: in order to avoid problems with resource liberation, we3223 /* XXX: in order to avoid problems with resource liberation, we
3228 don't support creating workers inside workers */3224 don't support creating workers inside workers */
3229 if (!is_main_thread(rt))3225 if (!is_main_thread(rt))
3230 return JS_ThrowTypeError(ctx, "cannot create a worker inside a worker");3226 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;
3231 3238
3232 /* script source */3239 /* module name */
3233 3240 filename = JS_ToCString(ctx, argv[0]);
3234 str = JS_ToCStringLen(ctx, &str_len, argv[0]);3241 if (!filename)
3235 if (!str)3242 goto fail;
3236 return JS_EXCEPTION;
3237 3243
3238 args = malloc(sizeof(*args));3244 args = malloc(sizeof(*args));
3239 if (!args) {3245 if (!args)
3240 JS_ThrowOutOfMemory(ctx);3246 goto oom_fail;
3241 goto fail;
3242 }
3243 memset(args, 0, sizeof(*args));3247 memset(args, 0, sizeof(*args));
3244 args->eval_buf = malloc(str_len + 1);3248 args->filename = strdup(filename);
3245 if (!args->eval_buf) {3249 args->basename = strdup(basename);
3246 JS_ThrowOutOfMemory(ctx);
3247 goto fail;
3248 }
3249 memcpy(args->eval_buf, str, str_len + 1);
3250 args->eval_buf_len = str_len;
3251 JS_FreeCString(ctx, str);
3252 str = NULL;
3253 3250
3254 /* ports */3251 /* ports */
3255 args->recv_pipe = js_new_message_pipe();3252 args->recv_pipe = js_new_message_pipe();
3256 if (!args->recv_pipe)3253 if (!args->recv_pipe)
3257 goto fail;3254 goto oom_fail;
3258 args->send_pipe = js_new_message_pipe();3255 args->send_pipe = js_new_message_pipe();
3259 if (!args->send_pipe)3256 if (!args->send_pipe)
3260 goto fail;3257 goto oom_fail;
3261 3258
3262 obj = js_worker_ctor_internal(ctx, new_target,3259 obj = js_worker_ctor_internal(ctx, new_target,
3263 args->send_pipe, args->recv_pipe);3260 args->send_pipe, args->recv_pipe);
3264 if (JS_IsUndefined(obj))3261 if (JS_IsException(obj))
3265 goto fail;3262 goto fail;
3266 3263
3267 pthread_attr_init(&attr);3264 pthread_attr_init(&attr);
@@ -3273,11 +3270,17 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, · 5 unmodified lines
3273 JS_ThrowTypeError(ctx, "could not create worker");3270 JS_ThrowTypeError(ctx, "could not create worker");
3274 goto fail;3271 goto fail;
3275 }3272 }
3273 JS_FreeCString(ctx, basename);
3274 JS_FreeCString(ctx, filename);
3276 return obj;3275 return obj;
3276 oom_fail:
3277 JS_ThrowOutOfMemory(ctx);
3277 fail:3278 fail:
3278 JS_FreeCString(ctx, str);3279 JS_FreeCString(ctx, basename);
3280 JS_FreeCString(ctx, filename);
3279 if (args) {3281 if (args) {
3280 free(args->eval_buf);3282 free(args->filename);
3283 free(args->basename);
3281 js_free_message_pipe(args->recv_pipe);3284 js_free_message_pipe(args->recv_pipe);
3282 js_free_message_pipe(args->send_pipe);3285 js_free_message_pipe(args->send_pipe);
3283 free(args);3286 free(args);
@@ -3417,6 +3420,13 @@ static const JSCFunctionListEntry js_worker_proto_funcs[] = { · 133 unmodified lines
3417 3420
3418#endif /* USE_WORKER */3421#endif /* USE_WORKER */
3419 3422
3423void 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
3420#if defined(_WIN32)3430#if defined(_WIN32)
3421#define OS_PLATFORM "win32"3431#define OS_PLATFORM "win32"
3422#elif defined(__APPLE__)3432#elif defined(__APPLE__)
@@ -3668,6 +3678,12 @@ void js_std_free_handlers(JSRuntime *rt) · 245 unmodified lines
3668 free_timer(rt, th);3678 free_timer(rt, th);
3669 }3679 }
3670 3680
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
3671 free(ts);3687 free(ts);
3672 JS_SetRuntimeOpaque(rt, NULL); /* fail safe */3688 JS_SetRuntimeOpaque(rt, NULL); /* fail safe */
3673}3689}
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
50void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise,50void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise,
51 JSValueConst reason,51 JSValueConst reason,
52 JS_BOOL is_handled, void *opaque);52 JS_BOOL is_handled, void *opaque);
53 53void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt));
54
54#ifdef __cplusplus55#ifdef __cplusplus
55} /* extern "C" { */56} /* extern "C" { */
56#endif57#endif
quickjs-opcode.h+2−1
@@ -359,7 +359,8 @@ DEF( call3, 1, 1, 1, npopx) · 358 unmodified lines
359 359
360DEF( is_undefined, 1, 1, 1, none)360DEF( is_undefined, 1, 1, 1, none)
361DEF( is_null, 1, 1, 1, none)361DEF( is_null, 1, 1, 1, none)
362DEF( is_function, 1, 1, 1, none)362DEF(typeof_is_undefined, 1, 1, 1, none)
363DEF( typeof_is_function, 1, 1, 1, none)
363#endif364#endif
364 365
365#undef DEF366#undef DEF
quickjs.c+573−311
@@ -825,8 +825,8 @@ typedef struct JSShapeProperty { · 824 unmodified lines
825} JSShapeProperty;825} JSShapeProperty;
826 826
827struct JSShape {827struct JSShape {
828 uint32_t prop_hash_end[0]; /* hash table of size hash_mask + 1828 /* hash table of size hash_mask + 1 before the start of the
829 before the start of the structure. */829 structure (see prop_hash_end()). */
830 JSGCObjectHeader header;830 JSGCObjectHeader header;
831 /* true if the shape is inserted in the shape hash table. If not,831 /* true if the shape is inserted in the shape hash table. If not,
832 JSShape.hash is not valid */832 JSShape.hash is not valid */
@@ -859,6 +859,7 @@ struct JSObject { · 26 unmodified lines
859 uint8_t is_constructor : 1; /* TRUE if object is a constructor function */859 uint8_t is_constructor : 1; /* TRUE if object is a constructor function */
860 uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */860 uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */
861 uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */861 uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */
862 uint8_t is_HTMLDDA : 1; /* specific annex B IsHtmlDDA behavior */
862 uint16_t class_id; /* see JS_CLASS_x */863 uint16_t class_id; /* see JS_CLASS_x */
863 };864 };
864 };865 };
@@ -931,7 +932,7 @@ struct JSObject { · 66 unmodified lines
931 /* byte sizes: 40/48/72 */932 /* byte sizes: 40/48/72 */
932};933};
933enum {934enum {
934 JS_ATOM_NULL,935 __JS_ATOM_NULL = JS_ATOM_NULL,
935#define DEF(name, str) JS_ATOM_ ## name,936#define DEF(name, str) JS_ATOM_ ## name,
936#include "quickjs-atom.h"937#include "quickjs-atom.h"
937#undef DEF938#undef DEF
@@ -4198,9 +4199,14 @@ static inline JSShape *get_shape_from_alloc(void *sh_alloc, size_t hash_size) · 3260 unmodified lines
4198 return (JSShape *)(void *)((uint32_t *)sh_alloc + hash_size);4199 return (JSShape *)(void *)((uint32_t *)sh_alloc + hash_size);
4199}4200}
4200 4201
4202static inline uint32_t *prop_hash_end(JSShape *sh)
4203{
4204 return (uint32_t *)sh;
4205}
4206
4201static inline void *get_alloc_from_shape(JSShape *sh)4207static inline void *get_alloc_from_shape(JSShape *sh)
4202{4208{
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);
4204}4210}
4205 4211
4206static inline JSShapeProperty *get_shape_prop(JSShape *sh)4212static 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
4311 if (proto)4317 if (proto)
4312 JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, proto));4318 JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, proto));
4313 sh->proto = proto;4319 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]) *
4315 hash_size);4321 hash_size);
4316 sh->prop_hash_mask = hash_size - 1;4322 sh->prop_hash_mask = hash_size - 1;
4317 sh->prop_size = prop_size;4323 sh->prop_size = prop_size;
@@ -4440,13 +4446,13 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh, · 122 unmodified lines
4440 list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);4446 list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
4441 new_hash_mask = new_hash_size - 1;4447 new_hash_mask = new_hash_size - 1;
4442 sh->prop_hash_mask = new_hash_mask;4448 sh->prop_hash_mask = new_hash_mask;
4443 memset(sh->prop_hash_end - new_hash_size, 0,4449 memset(prop_hash_end(sh) - new_hash_size, 0,
4444 sizeof(sh->prop_hash_end[0]) * new_hash_size);4450 sizeof(prop_hash_end(sh)[0]) * new_hash_size);
4445 for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) {4451 for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) {
4446 if (pr->atom != JS_ATOM_NULL) {4452 if (pr->atom != JS_ATOM_NULL) {
4447 h = ((uintptr_t)pr->atom & new_hash_mask);4453 h = ((uintptr_t)pr->atom & new_hash_mask);
4448 pr->hash_next = sh->prop_hash_end[-h - 1];4454 pr->hash_next = prop_hash_end(sh)[-h - 1];
4449 sh->prop_hash_end[-h - 1] = i + 1;4455 prop_hash_end(sh)[-h - 1] = i + 1;
4450 }4456 }
4451 }4457 }
4452 js_free(ctx, get_alloc_from_shape(old_sh));4458 js_free(ctx, get_alloc_from_shape(old_sh));
@@ -4500,8 +4506,8 @@ static int compact_properties(JSContext *ctx, JSObject *p) · 47 unmodified lines
4500 memcpy(sh, old_sh, sizeof(JSShape));4506 memcpy(sh, old_sh, sizeof(JSShape));
4501 list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);4507 list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
4502 4508
4503 memset(sh->prop_hash_end - new_hash_size, 0,4509 memset(prop_hash_end(sh) - new_hash_size, 0,
4504 sizeof(sh->prop_hash_end[0]) * new_hash_size);4510 sizeof(prop_hash_end(sh)[0]) * new_hash_size);
4505 4511
4506 j = 0;4512 j = 0;
4507 old_pr = old_sh->prop;4513 old_pr = old_sh->prop;
@@ -4512,8 +4518,8 @@ static int compact_properties(JSContext *ctx, JSObject *p) · 4 unmodified lines
4512 pr->atom = old_pr->atom;4518 pr->atom = old_pr->atom;
4513 pr->flags = old_pr->flags;4519 pr->flags = old_pr->flags;
4514 h = ((uintptr_t)old_pr->atom & new_hash_mask);4520 h = ((uintptr_t)old_pr->atom & new_hash_mask);
4515 pr->hash_next = sh->prop_hash_end[-h - 1];4521 pr->hash_next = prop_hash_end(sh)[-h - 1];
4516 sh->prop_hash_end[-h - 1] = j + 1;4522 prop_hash_end(sh)[-h - 1] = j + 1;
4517 prop[j] = prop[i];4523 prop[j] = prop[i];
4518 j++;4524 j++;
4519 pr++;4525 pr++;
@@ -4575,8 +4581,8 @@ static int add_shape_property(JSContext *ctx, JSShape **psh, · 55 unmodified lines
4575 /* add in hash table */4581 /* add in hash table */
4576 hash_mask = sh->prop_hash_mask;4582 hash_mask = sh->prop_hash_mask;
4577 h = atom & hash_mask;4583 h = atom & hash_mask;
4578 pr->hash_next = sh->prop_hash_end[-h - 1];4584 pr->hash_next = prop_hash_end(sh)[-h - 1];
4579 sh->prop_hash_end[-h - 1] = sh->prop_count;4585 prop_hash_end(sh)[-h - 1] = sh->prop_count;
4580 return 0;4586 return 0;
4581}4587}
4582 4588
@@ -4693,6 +4699,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas · 110 unmodified lines
4693 p->is_constructor = 0;4699 p->is_constructor = 0;
4694 p->is_uncatchable_error = 0;4700 p->is_uncatchable_error = 0;
4695 p->tmp_mark = 0;4701 p->tmp_mark = 0;
4702 p->is_HTMLDDA = 0;
4696 p->first_weak_ref = NULL;4703 p->first_weak_ref = NULL;
4697 p->u.opaque = NULL;4704 p->u.opaque = NULL;
4698 p->shape = sh;4705 p->shape = sh;
@@ -4731,7 +4738,19 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas · 32 unmodified lines
4731 p->prop[0].u.value = JS_UNDEFINED;4738 p->prop[0].u.value = JS_UNDEFINED;
4732 break;4739 break;
4733 case JS_CLASS_ARGUMENTS:4740 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:
4735 p->is_exotic = 1;4754 p->is_exotic = 1;
4736 p->fast_array = 1;4755 p->fast_array = 1;
4737 p->u.array.u.ptr = NULL;4756 p->u.array.u.ptr = NULL;
@@ -5133,7 +5152,7 @@ static force_inline JSShapeProperty *find_own_property1(JSObject *p, · 395 unmodified lines
5133 intptr_t h;5152 intptr_t h;
5134 sh = p->shape;5153 sh = p->shape;
5135 h = (uintptr_t)atom & sh->prop_hash_mask;5154 h = (uintptr_t)atom & sh->prop_hash_mask;
5136 h = sh->prop_hash_end[-h - 1];5155 h = prop_hash_end(sh)[-h - 1];
5137 prop = get_shape_prop(sh);5156 prop = get_shape_prop(sh);
5138 while (h) {5157 while (h) {
5139 pr = &prop[h - 1];5158 pr = &prop[h - 1];
@@ -5154,7 +5173,7 @@ static force_inline JSShapeProperty *find_own_property(JSProperty **ppr, · 14 unmodified lines
5154 intptr_t h;5173 intptr_t h;
5155 sh = p->shape;5174 sh = p->shape;
5156 h = (uintptr_t)atom & sh->prop_hash_mask;5175 h = (uintptr_t)atom & sh->prop_hash_mask;
5157 h = sh->prop_hash_end[-h - 1];5176 h = prop_hash_end(sh)[-h - 1];
5158 prop = get_shape_prop(sh);5177 prop = get_shape_prop(sh);
5159 while (h) {5178 while (h) {
5160 pr = &prop[h - 1];5179 pr = &prop[h - 1];
@@ -7994,7 +8013,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) · 2833 unmodified lines
7994 redo:8013 redo:
7995 sh = p->shape;8014 sh = p->shape;
7996 h1 = atom & sh->prop_hash_mask;8015 h1 = atom & sh->prop_hash_mask;
7997 h = sh->prop_hash_end[-h1 - 1];8016 h = prop_hash_end(sh)[-h1 - 1];
7998 prop = get_shape_prop(sh);8017 prop = get_shape_prop(sh);
7999 lpr = NULL;8018 lpr = NULL;
8000 lpr_idx = 0; /* prevent warning */8019 lpr_idx = 0; /* prevent warning */
@@ -8015,7 +8034,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) · 14 unmodified lines
8015 lpr = get_shape_prop(sh) + lpr_idx;8034 lpr = get_shape_prop(sh) + lpr_idx;
8016 lpr->hash_next = pr->hash_next;8035 lpr->hash_next = pr->hash_next;
8017 } else {8036 } else {
8018 sh->prop_hash_end[-h1 - 1] = pr->hash_next;8037 prop_hash_end(sh)[-h1 - 1] = pr->hash_next;
8019 }8038 }
8020 sh->deleted_prop_count++;8039 sh->deleted_prop_count++;
8021 /* free the entry */8040 /* free the entry */
@@ -8095,15 +8114,16 @@ static int call_setter(JSContext *ctx, JSObject *setter, · 73 unmodified lines
8095}8114}
8096 8115
8097/* set the array length and remove the array elements if necessary. */8116/* set the array length and remove the array elements if necessary. */
8098static int set_array_length(JSContext *ctx, JSObject *p, JSProperty *prop,8117static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, int flags)
8099 JSValue val, int flags)
8100{8118{
8101 uint32_t len, idx, cur_len;8119 uint32_t len, idx, cur_len;
8102 int i, ret;8120 int i, ret;
8103 8121
8122 /* Note: this call can reallocate the properties of 'p' */
8104 ret = JS_ToArrayLengthFree(ctx, &len, val);8123 ret = JS_ToArrayLengthFree(ctx, &len, val);
8105 if (ret)8124 if (ret)
8106 return -1;8125 return -1;
8126
8107 if (likely(p->fast_array)) {8127 if (likely(p->fast_array)) {
8108 uint32_t old_len = p->u.array.count;8128 uint32_t old_len = p->u.array.count;
8109 if (len < old_len) {8129 if (len < old_len) {
@@ -8112,11 +8132,11 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSProperty *prop, · 2 unmodified lines
8112 }8132 }
8113 p->u.array.count = len;8133 p->u.array.count = len;
8114 }8134 }
8115 prop->u.value = JS_NewUint32(ctx, len);8135 p->prop[0].u.value = JS_NewUint32(ctx, len);
8116 } else {8136 } else {
8117 /* Note: length is always a uint32 because the object is an8137 /* Note: length is always a uint32 because the object is an
8118 array */8138 array */
8119 JS_ToUint32(ctx, &cur_len, prop->u.value);8139 JS_ToUint32(ctx, &cur_len, p->prop[0].u.value);
8120 if (len < cur_len) {8140 if (len < cur_len) {
8121 uint32_t d;8141 uint32_t d;
8122 JSShape *sh;8142 JSShape *sh;
@@ -8366,7 +8386,7 @@ retry: · 243 unmodified lines
8366 (JS_PROP_LENGTH | JS_PROP_WRITABLE)) {8386 (JS_PROP_LENGTH | JS_PROP_WRITABLE)) {
8367 assert(p->class_id == JS_CLASS_ARRAY);8387 assert(p->class_id == JS_CLASS_ARRAY);
8368 assert(prop == JS_ATOM_length);8388 assert(prop == JS_ATOM_length);
8369 return set_array_length(ctx, p, pr, val, flags);8389 return set_array_length(ctx, p, val, flags);
8370 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {8390 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {
8371 return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags);8391 return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags);
8372 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {8392 } 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
9047 }9067 }
9048 if (prs->flags & JS_PROP_LENGTH) {9068 if (prs->flags & JS_PROP_LENGTH) {
9049 if (flags & JS_PROP_HAS_VALUE) {9069 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),
9051 flags);9071 flags);
9052 } else {9072 } else {
9053 res = TRUE;9073 res = TRUE;
@@ -9806,6 +9826,24 @@ static JSValue JS_ToPrimitive(JSContext *ctx, JSValueConst val, int hint) · 752 unmodified lines
9806 return JS_ToPrimitiveFree(ctx, JS_DupValue(ctx, val), hint);9826 return JS_ToPrimitiveFree(ctx, JS_DupValue(ctx, val), hint);
9807}9827}
9808 9828
9829void 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
9838static 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
9809static int JS_ToBoolFree(JSContext *ctx, JSValue val)9847static int JS_ToBoolFree(JSContext *ctx, JSValue val)
9810{9848{
9811 uint32_t tag = JS_VALUE_GET_TAG(val);9849 uint32_t tag = JS_VALUE_GET_TAG(val);
@@ -9843,6 +9881,15 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val) · 31 unmodified lines
9843 return ret;9881 return ret;
9844 }9882 }
9845#endif9883#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;
9846 default:9893 default:
9847 if (JS_TAG_IS_FLOAT64(tag)) {9894 if (JS_TAG_IS_FLOAT64(tag)) {
9848 double d = JS_VALUE_GET_FLOAT64(val);9895 double d = JS_VALUE_GET_FLOAT64(val);
@@ -11602,7 +11649,19 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) · 1753 unmodified lines
11602 case JS_CLASS_ARGUMENTS:11649 case JS_CLASS_ARGUMENTS:
11603 JS_DumpValueShort(rt, p->u.array.u.values[i]);11650 JS_DumpValueShort(rt, p->u.array.u.values[i]);
11604 break;11651 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:
11606 {11665 {
11607 int size = 1 << typed_array_size_log2(p->class_id);11666 int size = 1 << typed_array_size_log2(p->class_id);
11608 const uint8_t *b = p->u.array.u.uint8_ptr + i * size;11667 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
13668 JS_FreeValue(ctx, op2);13727 JS_FreeValue(ctx, op2);
13669 } else if ((tag1 <= JS_TAG_NULL || tag1 == JS_TAG_FLOAT64) &&13728 } else if ((tag1 <= JS_TAG_NULL || tag1 == JS_TAG_FLOAT64) &&
13670 (tag2 <= JS_TAG_NULL || tag2 == JS_TAG_FLOAT64)) {13729 (tag2 <= JS_TAG_NULL || tag2 == JS_TAG_FLOAT64)) {
13671 /* can use floating point comparison */13730 /* fast path for float64/int */
13672 double d1, d2;13731 goto float64_compare;
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 }
13698 } else {13732 } else {
13699 if (((tag1 == JS_TAG_BIG_INT && tag2 == JS_TAG_STRING) ||13733 if (((tag1 == JS_TAG_BIG_INT && tag2 == JS_TAG_STRING) ||
13700 (tag2 == JS_TAG_BIG_INT && tag1 == JS_TAG_STRING)) &&13734 (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
13727 }13761 }
13728 }13762 }
13729 13763
13730 if (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_DECIMAL ||13764 tag1 = JS_VALUE_GET_NORM_TAG(op1);
13731 JS_VALUE_GET_TAG(op2) == JS_TAG_BIG_DECIMAL) {13765 tag2 = JS_VALUE_GET_NORM_TAG(op2);
13766
13767 if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
13732 res = ctx->rt->bigdecimal_ops.compare(ctx, op, op1, op2);13768 res = ctx->rt->bigdecimal_ops.compare(ctx, op, op1, op2);
13733 if (res < 0)13769 if (res < 0)
13734 goto exception;13770 goto exception;
13735 } else if (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_FLOAT ||13771 } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
13736 JS_VALUE_GET_TAG(op2) == JS_TAG_BIG_FLOAT) {
13737 res = ctx->rt->bigfloat_ops.compare(ctx, op, op1, op2);13772 res = ctx->rt->bigfloat_ops.compare(ctx, op, op1, op2);
13738 if (res < 0)13773 if (res < 0)
13739 goto exception;13774 goto exception;
13740 } else {13775 } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
13741 res = ctx->rt->bigint_ops.compare(ctx, op, op1, op2);13776 res = ctx->rt->bigint_ops.compare(ctx, op, op1, op2);
13742 if (res < 0)13777 if (res < 0)
13743 goto exception;13778 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 }
13744 }13809 }
13745 }13810 }
13746 done:13811 done:
@@ -13895,9 +13960,17 @@ static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, · 148 unmodified lines
13895 }13960 }
13896 goto redo;13961 goto redo;
13897 } else {13962 } 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 }
13898 JS_FreeValue(ctx, op1);13972 JS_FreeValue(ctx, op1);
13899 JS_FreeValue(ctx, op2);13973 JS_FreeValue(ctx, op2);
13900 res = FALSE;
13901 }13974 }
13902 done:13975 done:
13903 sp[-2] = JS_NewBool(ctx, res ^ is_neq);13976 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
14348 }14421 }
14349 goto redo;14422 goto redo;
14350 } else {14423 } 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 }
14351 JS_FreeValue(ctx, op1);14433 JS_FreeValue(ctx, op1);
14352 JS_FreeValue(ctx, op2);14434 JS_FreeValue(ctx, op2);
14353 res = FALSE;
14354 }14435 }
14355 sp[-2] = JS_NewBool(ctx, res ^ is_neq);14436 sp[-2] = JS_NewBool(ctx, res ^ is_neq);
14356 return 0;14437 return 0;
@@ -14631,7 +14712,7 @@ static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp) · 274 unmodified lines
14631 return 0;14712 return 0;
14632}14713}
14633 14714
14634static __exception int js_operator_typeof(JSContext *ctx, JSValue op1)14715static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)
14635{14716{
14636 JSAtom atom;14717 JSAtom atom;
14637 uint32_t tag;14718 uint32_t tag;
@@ -14663,10 +14744,16 @@ static __exception int js_operator_typeof(JSContext *ctx, JSValue op1) · 25 unmodified lines
14663 atom = JS_ATOM_string;14744 atom = JS_ATOM_string;
14664 break;14745 break;
14665 case JS_TAG_OBJECT:14746 case JS_TAG_OBJECT:
14666 if (JS_IsFunction(ctx, op1))14747 {
14667 atom = JS_ATOM_function;14748 JSObject *p;
14668 else14749 p = JS_VALUE_GET_OBJ(op1);
14669 goto obj_type;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 }
14670 break;14757 break;
14671 case JS_TAG_NULL:14758 case JS_TAG_NULL:
14672 obj_type:14759 obj_type:
@@ -15231,7 +15318,10 @@ static __exception int js_for_of_start(JSContext *ctx, JSValue *sp, · 558 unmodified lines
15231 return 0;15318 return 0;
15232}15319}
15233 15320
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. */
15235static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)15325static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
15236{15326{
15237 JSValue value = JS_UNDEFINED;15327 JSValue value = JS_UNDEFINED;
@@ -15246,8 +15336,12 @@ static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset) · 8 unmodified lines
15246 /* replace the iteration object with undefined */15336 /* replace the iteration object with undefined */
15247 JS_FreeValue(ctx, sp[offset]);15337 JS_FreeValue(ctx, sp[offset]);
15248 sp[offset] = JS_UNDEFINED;15338 sp[offset] = JS_UNDEFINED;
15249 if (done < 0)15339 if (done < 0) {
15250 return -1;15340 return -1;
15341 } else {
15342 JS_FreeValue(ctx, value);
15343 value = JS_UNDEFINED;
15344 }
15251 }15345 }
15252 }15346 }
15253 sp[0] = value;15347 sp[0] = value;
@@ -15363,10 +15457,10 @@ static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj, · 109 unmodified lines
15363static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)15457static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
15364{15458{
15365 JSValue iterator, enumobj, method, value;15459 JSValue iterator, enumobj, method, value;
15366 int pos, is_array_iterator;15460 int is_array_iterator;
15367 JSValue *arrp;15461 JSValue *arrp;
15368 uint32_t i, count32;15462 uint32_t i, count32, pos;
15369 15463
15370 if (JS_VALUE_GET_TAG(sp[-2]) != JS_TAG_INT) {15464 if (JS_VALUE_GET_TAG(sp[-2]) != JS_TAG_INT) {
15371 JS_ThrowInternalError(ctx, "invalid index for append");15465 JS_ThrowInternalError(ctx, "invalid index for append");
15372 return -1;15466 return -1;
@@ -15399,24 +15493,21 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) · 26 unmodified lines
15399 if (is_array_iterator15493 if (is_array_iterator
15400 && JS_IsCFunction(ctx, method, (JSCFunction *)js_array_iterator_next, 0)15494 && JS_IsCFunction(ctx, method, (JSCFunction *)js_array_iterator_next, 0)
15401 && js_get_fast_array(ctx, sp[-1], &arrp, &count32)) {15495 && js_get_fast_array(ctx, sp[-1], &arrp, &count32)) {
15402 int64_t len;15496 uint32_t len;
15403 /* Handle fast arrays explicitly */15497 if (js_get_length32(ctx, &len, sp[-1]))
15404 if (js_get_length64(ctx, &len, sp[-1]))
15405 goto exception;15498 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 */
15406 for (i = 0; i < count32; i++) {15504 for (i = 0; i < count32; i++) {
15407 if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++,15505 if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++,
15408 JS_DupValue(ctx, arrp[i]), JS_PROP_C_W_E) < 0)15506 JS_DupValue(ctx, arrp[i]), JS_PROP_C_W_E) < 0)
15409 goto exception;15507 goto exception;
15410 }15508 }
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 }
15419 } else {15509 } else {
15510 general_case:
15420 for (;;) {15511 for (;;) {
15421 BOOL done;15512 BOOL done;
15422 value = JS_IteratorNext(ctx, enumobj, method, 0, NULL, &done);15513 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
15430 goto exception;15521 goto exception;
15431 }15522 }
15432 }15523 }
15524 /* Note: could raise an error if too many elements */
15433 sp[-2] = JS_NewInt32(ctx, pos);15525 sp[-2] = JS_NewInt32(ctx, pos);
15434 JS_FreeValue(ctx, enumobj);15526 JS_FreeValue(ctx, enumobj);
15435 JS_FreeValue(ctx, method);15527 JS_FreeValue(ctx, method);
@@ -17742,47 +17834,42 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, · 2306 unmodified lines
17742 BREAK;17834 BREAK;
17743 CASE(OP_add_loc):17835 CASE(OP_add_loc):
17744 {17836 {
17745 JSValue ops[2];17837 JSValue *pv;
17746 int idx;17838 int idx;
17747 idx = *pc;17839 idx = *pc;
17748 pc += 1;17840 pc += 1;
17749 17841
17750 ops[0] = var_buf[idx];17842 pv = &var_buf[idx];
17751 ops[1] = sp[-1];17843 if (likely(JS_VALUE_IS_BOTH_INT(*pv, sp[-1]))) {
17752 if (likely(JS_VALUE_IS_BOTH_INT(ops[0], ops[1]))) {
17753 int64_t r;17844 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]);
17755 if (unlikely((int)r != r))17847 if (unlikely((int)r != r))
17756 goto add_loc_slow;17848 goto add_loc_slow;
17757 var_buf[idx] = JS_NewInt32(ctx, r);17849 *pv = JS_NewInt32(ctx, r);
17758 sp--;17850 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];
17760 sp--;17854 sp--;
17761 ops[1] = JS_ToPrimitiveFree(ctx, ops[1], HINT_NONE);17855 op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
17762 if (JS_IsException(ops[1])) {17856 if (JS_IsException(op1))
17763 goto exception;17857 goto exception;
17764 }17858 op1 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op1);
17765 /* XXX: should not modify the variable in case of17859 if (JS_IsException(op1))
17766 exception */
17767 ops[0] = JS_ConcatString(ctx, ops[0], ops[1]);
17768 if (JS_IsException(ops[0])) {
17769 var_buf[idx] = JS_UNDEFINED;
17770 goto exception;17860 goto exception;
17771 }17861 set_value(ctx, pv, op1);
17772 var_buf[idx] = ops[0];
17773 } else {17862 } else {
17863 JSValue ops[2];
17774 add_loc_slow:17864 add_loc_slow:
17775 /* XXX: should not modify the variable in case of
17776 exception */
17777 sp--;
17778 /* In case of exception, js_add_slow frees ops[0]17865 /* In case of exception, js_add_slow frees ops[0]
17779 and ops[1]. */17866 and ops[1], so we must duplicate *pv */
17780 /* XXX: change API */17867 ops[0] = JS_DupValue(ctx, *pv);
17781 if (js_add_slow(ctx, ops + 2)) {17868 ops[1] = sp[-1];
17782 var_buf[idx] = JS_UNDEFINED;17869 sp--;
17870 if (js_add_slow(ctx, ops + 2))
17783 goto exception;17871 goto exception;
17784 }17872 set_value(ctx, pv, ops[0]);
17785 var_buf[idx] = ops[0];
17786 }17873 }
17787 }17874 }
17788 BREAK;17875 BREAK;
@@ -18427,7 +18514,15 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, · 638 unmodified lines
18427 } else {18514 } else {
18428 goto free_and_set_false;18515 goto free_and_set_false;
18429 }18516 }
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):
18431 if (js_operator_typeof(ctx, sp[-1]) == JS_ATOM_function) {18526 if (js_operator_typeof(ctx, sp[-1]) == JS_ATOM_function) {
18432 goto free_and_set_true;18527 goto free_and_set_true;
18433 } else {18528 } else {
@@ -19656,6 +19751,9 @@ enum { · 1222 unmodified lines
19656 TOK_MATH_POW_ASSIGN,19751 TOK_MATH_POW_ASSIGN,
19657#endif19752#endif
19658 TOK_POW_ASSIGN,19753 TOK_POW_ASSIGN,
19754 TOK_LAND_ASSIGN,
19755 TOK_LOR_ASSIGN,
19756 TOK_DOUBLE_QUESTION_MARK_ASSIGN,
19659 TOK_DEC,19757 TOK_DEC,
19660 TOK_INC,19758 TOK_INC,
19661 TOK_SHL,19759 TOK_SHL,
@@ -20015,11 +20113,14 @@ static void free_token(JSParseState *s, JSToken *token) · 353 unmodified lines
20015 JS_FreeValue(s->ctx, token->u.regexp.flags);20113 JS_FreeValue(s->ctx, token->u.regexp.flags);
20016 break;20114 break;
20017 case TOK_IDENT:20115 case TOK_IDENT:
20018 case TOK_FIRST_KEYWORD ... TOK_LAST_KEYWORD:
20019 case TOK_PRIVATE_NAME:20116 case TOK_PRIVATE_NAME:
20020 JS_FreeAtom(s->ctx, token->u.ident.atom);20117 JS_FreeAtom(s->ctx, token->u.ident.atom);
20021 break;20118 break;
20022 default:20119 default:
20120 if (token->val >= TOK_FIRST_KEYWORD &&
20121 token->val <= TOK_LAST_KEYWORD) {
20122 JS_FreeAtom(s->ctx, token->u.ident.atom);
20123 }
20023 break;20124 break;
20024 }20125 }
20025}20126}
@@ -20233,6 +20334,8 @@ static __exception int js_parse_string(JSParseState *s, int sep, · 207 unmodified lines
20233 }20334 }
20234 if (c == '\\') {20335 if (c == '\\') {
20235 c = *p;20336 c = *p;
20337 /* XXX: need a specific JSON case to avoid
20338 accepting invalid escapes */
20236 switch(c) {20339 switch(c) {
20237 case '\0':20340 case '\0':
20238 if (p >= s->buf_end)20341 if (p >= s->buf_end)
@@ -20256,18 +20359,23 @@ static __exception int js_parse_string(JSParseState *s, int sep, · 17 unmodified lines
20256 s->line_num++;20359 s->line_num++;
20257 continue;20360 continue;
20258 default:20361 default:
20259 if (c >= '0' && c <= '7') {20362 if (c >= '0' && c <= '9') {
20260 if (!s->cur_func)20363 if (!s->cur_func)
20261 goto invalid_octal; /* JSON case */20364 goto invalid_escape; /* JSON case */
20262 if (!(s->cur_func->js_mode & JS_MODE_STRICT) && sep != '`')20365 if (!(s->cur_func->js_mode & JS_MODE_STRICT) && sep != '`')
20263 goto parse_escape;20366 goto parse_escape;
20264 if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) {20367 if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) {
20265 p++;20368 p++;
20266 c = '\0';20369 c = '\0';
20267 } else {20370 } else {
20268 invalid_octal:20371 if (c >= '8' || sep == '`') {
20269 if (do_throw)20372 /* Note: according to ES2021, \8 and \9 are not
20270 js_parse_error(s, "invalid octal syntax in strict mode");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 }
20271 goto fail;20379 goto fail;
20272 }20380 }
20273 } else if (c >= 0x80) {20381 } else if (c >= 0x80) {
@@ -20284,6 +20392,7 @@ static __exception int js_parse_string(JSParseState *s, int sep, · 10 unmodified lines
20284 parse_escape:20392 parse_escape:
20285 ret = lre_parse_escape(&p, TRUE);20393 ret = lre_parse_escape(&p, TRUE);
20286 if (ret == -1) {20394 if (ret == -1) {
20395 invalid_escape:
20287 if (do_throw)20396 if (do_throw)
20288 js_parse_error(s, "malformed escape sequence in string literal");20397 js_parse_error(s, "malformed escape sequence in string literal");
20289 goto fail;20398 goto fail;
@@ -20634,8 +20743,20 @@ static __exception int next_token(JSParseState *s) · 344 unmodified lines
20634 }20743 }
20635 }20744 }
20636 goto def_token;20745 goto def_token;
20637 case 'a' ... 'z':20746 case 'a': case 'b': case 'c': case 'd':
20638 case 'A' ... 'Z':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':
20639 case '_':20760 case '_':
20640 case '$':20761 case '$':
20641 /* identifier */20762 /* identifier */
@@ -20717,7 +20838,9 @@ static __exception int next_token(JSParseState *s) · 75 unmodified lines
20717 goto fail;20838 goto fail;
20718 }20839 }
20719 goto parse_number;20840 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':
20721 /* number */20844 /* number */
20722 parse_number:20845 parse_number:
20723 {20846 {
@@ -20887,8 +21010,13 @@ static __exception int next_token(JSParseState *s) · 163 unmodified lines
20887 p += 2;21010 p += 2;
20888 s->token.val = TOK_AND_ASSIGN;21011 s->token.val = TOK_AND_ASSIGN;
20889 } else if (p[1] == '&') {21012 } else if (p[1] == '&') {
20890 p += 2;21013 if (p[2] == '=') {
20891 s->token.val = TOK_LAND;21014 p += 3;
21015 s->token.val = TOK_LAND_ASSIGN;
21016 } else {
21017 p += 2;
21018 s->token.val = TOK_LAND;
21019 }
20892 } else {21020 } else {
20893 goto def_token;21021 goto def_token;
20894 }21022 }
@@ -20934,16 +21062,26 @@ static __exception int next_token(JSParseState *s) · 39 unmodified lines
20934 p += 2;21062 p += 2;
20935 s->token.val = TOK_OR_ASSIGN;21063 s->token.val = TOK_OR_ASSIGN;
20936 } else if (p[1] == '|') {21064 } else if (p[1] == '|') {
20937 p += 2;21065 if (p[2] == '=') {
20938 s->token.val = TOK_LOR;21066 p += 3;
21067 s->token.val = TOK_LOR_ASSIGN;
21068 } else {
21069 p += 2;
21070 s->token.val = TOK_LOR;
21071 }
20939 } else {21072 } else {
20940 goto def_token;21073 goto def_token;
20941 }21074 }
20942 break;21075 break;
20943 case '?':21076 case '?':
20944 if (p[1] == '?') {21077 if (p[1] == '?') {
20945 p += 2;21078 if (p[2] == '=') {
20946 s->token.val = TOK_DOUBLE_QUESTION_MARK;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 }
20947 } else if (p[1] == '.' && !(p[2] >= '0' && p[2] <= '9')) {21085 } else if (p[1] == '.' && !(p[2] >= '0' && p[2] <= '9')) {
20948 p += 2;21086 p += 2;
20949 s->token.val = TOK_QUESTION_MARK_DOT;21087 s->token.val = TOK_QUESTION_MARK_DOT;
@@ -21135,8 +21273,20 @@ static __exception int json_next_token(JSParseState *s) · 185 unmodified lines
21135 goto def_token;21273 goto def_token;
21136 }21274 }
21137 break;21275 break;
21138 case 'a' ... 'z':21276 case 'a': case 'b': case 'c': case 'd':
21139 case 'A' ... 'Z':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':
21140 case '_':21290 case '_':
21141 case '$':21291 case '$':
21142 /* identifier : only pure ascii characters are accepted */21292 /* identifier : only pure ascii characters are accepted */
@@ -21161,7 +21311,9 @@ static __exception int json_next_token(JSParseState *s) · 18 unmodified lines
21161 if (!is_digit(p[1]))21311 if (!is_digit(p[1]))
21162 goto def_token;21312 goto def_token;
21163 goto parse_number;21313 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':
21165 /* number */21317 /* number */
21166 parse_number:21318 parse_number:
21167 {21319 {
@@ -23267,15 +23419,6 @@ static BOOL has_with_scope(JSFunctionDef *s, int scope_level) · 2099 unmodified lines
23267 return FALSE;23419 return FALSE;
23268}23420}
23269 23421
23270typedef struct JSLValue {
23271 int opcode;
23272 int scope;
23273 int label;
23274 int depth;
23275 int tok;
23276 JSAtom name;
23277} JSLValue;
23278
23279static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,23422static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
23280 JSAtom *pname, int *plabel, int *pdepth, BOOL keep,23423 JSAtom *pname, int *plabel, int *pdepth, BOOL keep,
23281 int tok)23424 int tok)
@@ -23400,84 +23543,112 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, · 118 unmodified lines
23400 return 0;23543 return 0;
23401}23544}
23402 23545
23403/* if special = TRUE: specific post inc/dec case */23546typedef enum {
23404/* name has a live reference */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(). */
23405static void put_lvalue(JSParseState *s, int opcode, int scope,23557static 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)
23407{23560{
23408 switch(opcode) {23561 switch(opcode) {
23409 case OP_get_field:23562 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;
23417 case OP_scope_get_private_field:23563 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:
23419 emit_op(s, OP_insert2); /* obj v -> v obj v */23570 emit_op(s, OP_insert2); /* obj v -> v obj v */
23420 else23571 break;
23572 case PUT_LVALUE_KEEP_SECOND:
23421 emit_op(s, OP_perm3); /* obj v0 v -> v0 obj v */23573 emit_op(s, OP_perm3); /* obj v0 v -> v0 obj v */
23422 emit_op(s, OP_scope_put_private_field);23574 break;
23423 emit_u32(s, name); /* name has refcount */23575 case PUT_LVALUE_NOKEEP_BOTTOM:
23424 emit_u16(s, scope);23576 emit_op(s, OP_swap);
23577 break;
23578 default:
23579 abort();
23580 }
23425 break;23581 break;
23426 case OP_get_array_el:23582 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;
23433 case OP_get_ref_value:23583 case OP_get_ref_value:
23434 JS_FreeAtom(s->ctx, name);23584 /* depth = 2 */
23435 emit_label(s, label);23585 if (opcode == OP_get_ref_value) {
23436 if (!special)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:
23437 emit_op(s, OP_insert3); /* obj prop v -> v obj prop v */23596 emit_op(s, OP_insert3); /* obj prop v -> v obj prop v */
23438 else23597 break;
23598 case PUT_LVALUE_KEEP_SECOND:
23439 emit_op(s, OP_perm4); /* obj prop v0 v -> v0 obj prop v */23599 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 }
23441 break;23607 break;
23442 case OP_get_super_value:23608 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:
23444 emit_op(s, OP_insert4); /* this obj prop v -> v this obj prop v */23615 emit_op(s, OP_insert4); /* this obj prop v -> v this obj prop v */
23445 else23616 break;
23617 case PUT_LVALUE_KEEP_SECOND:
23446 emit_op(s, OP_perm5); /* this obj prop v0 v -> v0 this obj prop v */23618 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 }
23448 break;23626 break;
23449 default:23627 default:
23450 abort();23628 break;
23451 }23629 }
23452}23630
23453
23454static void put_lvalue_nokeep(JSParseState *s, int opcode, int scope,
23455 JSAtom name, int label, int var_tok)
23456{
23457 switch(opcode) {23631 switch(opcode) {
23458 case OP_scope_get_var: /* val -- */23632 case OP_scope_get_var: /* val -- */
23459 emit_op(s, (var_tok == TOK_CONST || var_tok == TOK_LET) ?23633 assert(special == PUT_LVALUE_NOKEEP ||
23460 OP_scope_put_var_init : OP_scope_put_var);23634 special == PUT_LVALUE_NOKEEP_DEPTH);
23635 emit_op(s, is_let ? OP_scope_put_var_init : OP_scope_put_var);
23461 emit_u32(s, name); /* has refcount */23636 emit_u32(s, name); /* has refcount */
23462 emit_u16(s, scope);23637 emit_u16(s, scope);
23463 break;23638 break;
23464 case OP_get_field: /* obj val -- */23639 case OP_get_field:
23465 emit_op(s, OP_put_field);23640 emit_op(s, OP_put_field);
23466 emit_u32(s, name); /* has refcount */23641 emit_u32(s, name); /* name has refcount */
23467 break;23642 break;
23468 case OP_scope_get_private_field:23643 case OP_scope_get_private_field:
23469 emit_op(s, OP_scope_put_private_field);23644 emit_op(s, OP_scope_put_private_field);
23470 emit_u32(s, name); /* has refcount */23645 emit_u32(s, name); /* name has refcount */
23471 emit_u16(s, scope);23646 emit_u16(s, scope);
23472 break;23647 break;
23473 case OP_get_array_el: /* obj prop val -- */23648 case OP_get_array_el:
23474 emit_op(s, OP_put_array_el);23649 emit_op(s, OP_put_array_el);
23475 break;23650 break;
23476 case OP_get_ref_value: /* obj prop val -- */23651 case OP_get_ref_value:
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 */
23481 emit_op(s, OP_put_ref_value);23652 emit_op(s, OP_put_ref_value);
23482 break;23653 break;
23483 case OP_get_super_value:23654 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
23869 emit_label(s, label_hasval);24040 emit_label(s, label_hasval);
23870 }24041 }
23871 /* store value into lvalue object */24042 /* 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));
23873 if (s->token.val == '}')24046 if (s->token.val == '}')
23874 break;24047 break;
23875 /* accept a trailing comma before the '}' */24048 /* 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
23969 emit_label(s, label_hasval);24142 emit_label(s, label_hasval);
23970 }24143 }
23971 /* store value into lvalue object */24144 /* store value into lvalue object */
23972 put_lvalue_nokeep(s, opcode, scope, var_name,24145 put_lvalue(s, opcode, scope, var_name,
23973 label_lvalue, tok);24146 label_lvalue, PUT_LVALUE_NOKEEP_DEPTH,
24147 (tok == TOK_CONST || tok == TOK_LET));
23974 }24148 }
23975 if (s->token.val == ']')24149 if (s->token.val == ']')
23976 break;24150 break;
@@ -24786,7 +24960,8 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag) · 809 unmodified lines
24786 if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))24960 if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))
24787 return -1;24961 return -1;
24788 emit_op(s, OP_dec + op - TOK_DEC);24962 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);
24790 }24965 }
24791 break;24966 break;
24792 case TOK_TYPEOF:24967 case TOK_TYPEOF:
@@ -24834,7 +25009,8 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag) · 41 unmodified lines
24834 if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))25009 if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))
24835 return -1;25010 return -1;
24836 emit_op(s, OP_post_dec + op - TOK_DEC);25011 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);
24838 if (next_token(s))25014 if (next_token(s))
24839 return -1; 25015 return -1;
24840 }25016 }
@@ -25298,7 +25474,61 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted) · 457 unmodified lines
25298#endif25474#endif
25299 emit_op(s, op);25475 emit_op(s, op);
25300 }25476 }
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);
25302 }25532 }
25303 return 0;25533 return 0;
25304}25534}
@@ -25563,8 +25793,8 @@ static __exception int js_parse_var(JSParseState *s, BOOL in_accepted, int tok, · 258 unmodified lines
25563 goto var_error;25793 goto var_error;
25564 }25794 }
25565 set_object_name(s, name);25795 set_object_name(s, name);
25566 put_lvalue(s, opcode, scope, name1, label, FALSE);25796 put_lvalue(s, opcode, scope, name1, label,
25567 emit_op(s, OP_drop);25797 PUT_LVALUE_NOKEEP, FALSE);
25568 } else {25798 } else {
25569 if (js_parse_assign_expr(s, in_accepted))25799 if (js_parse_assign_expr(s, in_accepted))
25570 goto var_error;25800 goto var_error;
@@ -25751,29 +25981,14 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, · 180 unmodified lines
25751 if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))25981 if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
25752 return -1;25982 return -1;
25753 } else {25983 } else {
25754 int lvalue_label, depth;25984 int lvalue_label;
25755 if (js_parse_postfix_expr(s, TRUE))25985 if (js_parse_postfix_expr(s, TRUE))
25756 return -1;25986 return -1;
25757 if (get_lvalue(s, &opcode, &scope, &var_name, &lvalue_label,25987 if (get_lvalue(s, &opcode, &scope, &var_name, &lvalue_label,
25758 &depth, FALSE, TOK_FOR))25988 NULL, FALSE, TOK_FOR))
25759 return -1;25989 return -1;
25760 /* swap value and lvalue object and store it into lvalue object */25990 put_lvalue(s, opcode, scope, var_name, lvalue_label,
25761 /* enum_rec val [depth] -- enum_rec */25991 PUT_LVALUE_NOKEEP_BOTTOM, FALSE);
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 */);
25777 }25992 }
25778 var_name = JS_ATOM_NULL;25993 var_name = JS_ATOM_NULL;
25779 }25994 }
@@ -26933,32 +27148,20 @@ static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name) · 1153 unmodified lines
26933 27148
26934/* return NULL in case of exception (e.g. module could not be loaded) */27149/* return NULL in case of exception (e.g. module could not be loaded) */
26935static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx,27150static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx,
26936 JSAtom base_module_name,27151 const char *base_cname,
26937 JSAtom module_name1)27152 const char *cname1)
26938{27153{
26939 JSRuntime *rt = ctx->rt;27154 JSRuntime *rt = ctx->rt;
26940 JSModuleDef *m;27155 JSModuleDef *m;
26941 char *cname;27156 char *cname;
26942 const char *base_cname, *cname1;
26943 JSAtom module_name;27157 JSAtom module_name;
26944 27158
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
26954 if (!rt->module_normalize_func) {27159 if (!rt->module_normalize_func) {
26955 cname = js_default_module_normalize_name(ctx, base_cname, cname1);27160 cname = js_default_module_normalize_name(ctx, base_cname, cname1);
26956 } else {27161 } else {
26957 cname = rt->module_normalize_func(ctx, base_cname, cname1,27162 cname = rt->module_normalize_func(ctx, base_cname, cname1,
26958 rt->module_loader_opaque);27163 rt->module_loader_opaque);
26959 }27164 }
26960 JS_FreeCString(ctx, base_cname);
26961 JS_FreeCString(ctx, cname1);
26962 if (!cname)27165 if (!cname)
26963 return NULL;27166 return NULL;
26964 27167
@@ -26992,6 +27195,27 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, · 27 unmodified lines
26992 return m;27195 return m;
26993}27196}
26994 27197
27198static 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
26995typedef struct JSResolveEntry {27219typedef struct JSResolveEntry {
26996 JSModuleDef *module;27220 JSModuleDef *module;
26997 JSAtom name;27221 JSAtom name;
@@ -27435,8 +27659,8 @@ static int js_resolve_module(JSContext *ctx, JSModuleDef *m) · 437 unmodified lines
27435 /* resolve each requested module */27659 /* resolve each requested module */
27436 for(i = 0; i < m->req_module_entries_count; i++) {27660 for(i = 0; i < m->req_module_entries_count; i++) {
27437 JSReqModuleEntry *rme = &m->req_module_entries[i];27661 JSReqModuleEntry *rme = &m->req_module_entries[i];
27438 m1 = js_host_resolve_imported_module(ctx, m->module_name,27662 m1 = js_host_resolve_imported_module_atom(ctx, m->module_name,
27439 rme->module_name);27663 rme->module_name);
27440 if (!m1)27664 if (!m1)
27441 return -1;27665 return -1;
27442 rme->module = m1;27666 rme->module = m1;
@@ -27711,8 +27935,9 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) · 268 unmodified lines
27711 return -1;27935 return -1;
27712}27936}
27713 27937
27714/* warning: the returned atom is not allocated */27938/* return JS_ATOM_NULL if the name cannot be found. Only works with
27715static JSAtom js_get_script_or_module_name(JSContext *ctx)27939 not striped bytecode functions. */
27940JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)
27716{27941{
27717 JSStackFrame *sf;27942 JSStackFrame *sf;
27718 JSFunctionBytecode *b;27943 JSFunctionBytecode *b;
@@ -27721,14 +27946,22 @@ static JSAtom js_get_script_or_module_name(JSContext *ctx) · 2 unmodified lines
27721 function. It does not work for eval(). Need to add a27946 function. It does not work for eval(). Need to add a
27722 ScriptOrModule info in JSFunctionBytecode */27947 ScriptOrModule info in JSFunctionBytecode */
27723 sf = ctx->rt->current_stack_frame;27948 sf = ctx->rt->current_stack_frame;
27724 assert(sf != NULL);27949 if (!sf)
27725 assert(JS_VALUE_GET_TAG(sf->cur_func) == JS_TAG_OBJECT);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;
27726 p = JS_VALUE_GET_OBJ(sf->cur_func);27958 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;
27728 b = p->u.func.function_bytecode;27961 b = p->u.func.function_bytecode;
27729 if (!b->has_debug)27962 if (!b->has_debug)
27730 return JS_ATOM_NULL;27963 return JS_ATOM_NULL;
27731 return b->debug.filename;27964 return JS_DupAtom(ctx, b->debug.filename);
27732}27965}
27733 27966
27734JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m)27967JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m)
@@ -27755,13 +27988,14 @@ static JSValue js_import_meta(JSContext *ctx) · 20 unmodified lines
27755 JSAtom filename;27988 JSAtom filename;
27756 JSModuleDef *m;27989 JSModuleDef *m;
27757 27990
27758 filename = js_get_script_or_module_name(ctx);27991 filename = JS_GetScriptOrModuleName(ctx, 0);
27759 if (filename == JS_ATOM_NULL)27992 if (filename == JS_ATOM_NULL)
27760 goto fail;27993 goto fail;
27761 27994
27762 /* XXX: inefficient, need to add a module or script pointer in27995 /* XXX: inefficient, need to add a module or script pointer in
27763 JSFunctionBytecode */27996 JSFunctionBytecode */
27764 m = js_find_loaded_module(ctx, filename);27997 m = js_find_loaded_module(ctx, filename);
27998 JS_FreeAtom(ctx, filename);
27765 if (!m) {27999 if (!m) {
27766 fail:28000 fail:
27767 JS_ThrowTypeError(ctx, "import.meta not supported in this context");28001 JS_ThrowTypeError(ctx, "import.meta not supported in this context");
@@ -27770,6 +28004,31 @@ static JSValue js_import_meta(JSContext *ctx) · 2 unmodified lines
27770 return JS_GetImportMeta(ctx, m);28004 return JS_GetImportMeta(ctx, m);
27771}28005}
27772 28006
28007/* used by os.Worker() and import() */
28008JSModuleDef *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
27773static JSValue js_dynamic_import_job(JSContext *ctx,28032static JSValue js_dynamic_import_job(JSContext *ctx,
27774 int argc, JSValueConst *argv)28033 int argc, JSValueConst *argv)
27775{28034{
@@ -27777,53 +28036,36 @@ static JSValue js_dynamic_import_job(JSContext *ctx, · 1 unmodified line
27777 JSValueConst basename_val = argv[2];28036 JSValueConst basename_val = argv[2];
27778 JSValueConst specifier = argv[3];28037 JSValueConst specifier = argv[3];
27779 JSModuleDef *m;28038 JSModuleDef *m;
27780 JSAtom basename = JS_ATOM_NULL, filename;28039 const char *basename = NULL, *filename;
27781 JSValue specifierString, ret, func_obj, err, ns;28040 JSValue ret, err, ns;
27782 28041
27783 if (!JS_IsString(basename_val)) {28042 if (!JS_IsString(basename_val)) {
27784 JS_ThrowTypeError(ctx, "no function filename for import()");28043 JS_ThrowTypeError(ctx, "no function filename for import()");
27785 goto exception;28044 goto exception;
27786 }28045 }
27787 basename = JS_ValueToAtom(ctx, basename_val);28046 basename = JS_ToCString(ctx, basename_val);
27788 if (basename == JS_ATOM_NULL)28047 if (!basename)
27789 goto exception;28048 goto exception;
27790 28049
27791 specifierString = JS_ToString(ctx, specifier);28050 filename = JS_ToCString(ctx, specifier);
27792 if (JS_IsException(specifierString))28051 if (!filename)
27793 goto exception;
27794 filename = JS_ValueToAtom(ctx, specifierString);
27795 JS_FreeValue(ctx, specifierString);
27796 if (filename == JS_ATOM_NULL)
27797 goto exception;28052 goto exception;
27798 28053
27799 m = js_host_resolve_imported_module(ctx, basename, filename);28054 m = JS_RunModule(ctx, basename, filename);
27800 JS_FreeAtom(ctx, filename);28055 JS_FreeCString(ctx, filename);
27801 if (!m) {28056 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))
27814 goto exception;28057 goto exception;
27815 JS_FreeValue(ctx, ret);
27816 28058
27817 /* return the module namespace */28059 /* return the module namespace */
27818 ns = js_get_module_ns(ctx, m);28060 ns = js_get_module_ns(ctx, m);
27819 if (JS_IsException(ret))28061 if (JS_IsException(ns))
27820 goto exception;28062 goto exception;
27821 28063
27822 ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,28064 ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,
27823 1, (JSValueConst *)&ns);28065 1, (JSValueConst *)&ns);
27824 JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */28066 JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
27825 JS_FreeValue(ctx, ns);28067 JS_FreeValue(ctx, ns);
27826 JS_FreeAtom(ctx, basename);28068 JS_FreeCString(ctx, basename);
27827 return JS_UNDEFINED;28069 return JS_UNDEFINED;
27828 exception:28070 exception:
27829 28071
@@ -27832,7 +28074,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx, · 2 unmodified lines
27832 1, (JSValueConst *)&err);28074 1, (JSValueConst *)&err);
27833 JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */28075 JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
27834 JS_FreeValue(ctx, err);28076 JS_FreeValue(ctx, err);
27835 JS_FreeAtom(ctx, basename);28077 JS_FreeCString(ctx, basename);
27836 return JS_UNDEFINED;28078 return JS_UNDEFINED;
27837}28079}
27838 28080
@@ -27842,11 +28084,12 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) · 3 unmodified lines
27842 JSValue promise, resolving_funcs[2], basename_val;28084 JSValue promise, resolving_funcs[2], basename_val;
27843 JSValueConst args[4];28085 JSValueConst args[4];
27844 28086
27845 basename = js_get_script_or_module_name(ctx);28087 basename = JS_GetScriptOrModuleName(ctx, 0);
27846 if (basename == JS_ATOM_NULL)28088 if (basename == JS_ATOM_NULL)
27847 basename_val = JS_NULL;28089 basename_val = JS_NULL;
27848 else28090 else
27849 basename_val = JS_AtomToValue(ctx, basename);28091 basename_val = JS_AtomToValue(ctx, basename);
28092 JS_FreeAtom(ctx, basename);
27850 if (JS_IsException(basename_val))28093 if (JS_IsException(basename_val))
27851 return basename_val;28094 return basename_val;
27852 28095
@@ -28957,7 +29200,7 @@ static BOOL can_opt_put_ref_value(const uint8_t *bc_buf, int pos) · 1104 unmodified lines
28957 return (bc_buf[pos + 1] == OP_put_ref_value &&29200 return (bc_buf[pos + 1] == OP_put_ref_value &&
28958 (opcode == OP_insert3 ||29201 (opcode == OP_insert3 ||
28959 opcode == OP_perm4 ||29202 opcode == OP_perm4 ||
28960 //opcode == OP_nop ||29203 opcode == OP_nop ||
28961 opcode == OP_rot3l));29204 opcode == OP_rot3l));
28962}29205}
28963 29206
@@ -28967,7 +29210,7 @@ static BOOL can_opt_put_global_ref_value(const uint8_t *bc_buf, int pos) · 3 unmodified lines
28967 return (bc_buf[pos + 1] == OP_put_ref_value &&29210 return (bc_buf[pos + 1] == OP_put_ref_value &&
28968 (opcode == OP_insert3 ||29211 (opcode == OP_insert3 ||
28969 opcode == OP_perm4 ||29212 opcode == OP_perm4 ||
28970 //opcode == OP_nop ||29213 opcode == OP_nop ||
28971 opcode == OP_rot3l));29214 opcode == OP_rot3l));
28972}29215}
28973 29216
@@ -29049,20 +29292,22 @@ static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s, · 75 unmodified lines
29049 end_pos = label_pos + 2;29292 end_pos = label_pos + 2;
29050 op = bc_buf[label_pos];29293 op = bc_buf[label_pos];
29051 if (is_strict) {29294 if (is_strict) {
29052 switch(op) {29295 if (op != OP_nop) {
29053 case OP_insert3:29296 switch(op) {
29054 op = OP_insert2;29297 case OP_insert3:
29055 break;29298 op = OP_insert2;
29056 case OP_perm4:29299 break;
29057 op = OP_perm3;29300 case OP_perm4:
29058 break;29301 op = OP_perm3;
29059 case OP_rot3l:29302 break;
29060 op = OP_swap;29303 case OP_rot3l:
29061 break;29304 op = OP_swap;
29062 default:29305 break;
29063 abort();29306 default:
29307 abort();
29308 }
29309 bc_buf[pos++] = op;
29064 }29310 }
29065 bc_buf[pos++] = op;
29066 } else {29311 } else {
29067 if (op == OP_insert3)29312 if (op == OP_insert3)
29068 bc_buf[pos++] = OP_dup;29313 bc_buf[pos++] = OP_dup;
@@ -31567,20 +31812,20 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) · 2498 unmodified lines
31567 }31812 }
31568 goto no_change;31813 goto no_change;
31569 31814
31815#if SHORT_OPCODES
31570 case OP_typeof:31816 case OP_typeof:
31571 if (OPTIMIZE) {31817 if (OPTIMIZE) {
31572 /* simplify typeof tests */31818 /* simplify typeof tests */
31573 if (code_match(&cc, pos_next, OP_push_atom_value, M4(OP_strict_eq, OP_strict_neq, OP_eq, OP_neq), -1)) {31819 if (code_match(&cc, pos_next, OP_push_atom_value, M4(OP_strict_eq, OP_strict_neq, OP_eq, OP_neq), -1)) {
31574 if (cc.line_num >= 0) line_num = cc.line_num;31820 if (cc.line_num >= 0) line_num = cc.line_num;
31575 int op1 = (cc.op == OP_strict_eq || cc.op == OP_eq) ? OP_strict_eq : OP_strict_neq;31821 int op1 = (cc.op == OP_strict_eq || cc.op == OP_eq) ? OP_strict_eq : OP_strict_neq;
31576#if SHORT_OPCODES
31577 int op2 = -1;31822 int op2 = -1;
31578 switch (cc.atom) {31823 switch (cc.atom) {
31579 case JS_ATOM_undefined:31824 case JS_ATOM_undefined:
31580 op2 = OP_is_undefined;31825 op2 = OP_typeof_is_undefined;
31581 break;31826 break;
31582 case JS_ATOM_function:31827 case JS_ATOM_function:
31583 op2 = OP_is_function;31828 op2 = OP_typeof_is_function;
31584 break;31829 break;
31585 }31830 }
31586 if (op2 >= 0) {31831 if (op2 >= 0) {
@@ -31604,19 +31849,10 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) · 17 unmodified lines
31604 goto has_label;31849 goto has_label;
31605 }31850 }
31606 }31851 }
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 }
31617 }31852 }
31618 }31853 }
31619 goto no_change;31854 goto no_change;
31855#endif
31620 31856
31621 default:31857 default:
31622 no_change:31858 no_change:
@@ -37067,10 +37303,9 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, · 5444 unmodified lines
37067 int argc, JSValueConst *argv)37303 int argc, JSValueConst *argv)
37068{37304{
37069 JSBoundFunction *bf;37305 JSBoundFunction *bf;
37070 JSValue func_obj, name1;37306 JSValue func_obj, name1, len_val;
37071 JSObject *p;37307 JSObject *p;
37072 int arg_count, i;37308 int arg_count, i, ret;
37073 uint32_t len1;
37074 37309
37075 if (check_function(ctx, this_val))37310 if (check_function(ctx, this_val))
37076 return JS_EXCEPTION;37311 return JS_EXCEPTION;
@@ -37093,6 +37328,44 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, · 16 unmodified lines
37093 }37328 }
37094 p->u.bound_function = bf;37329 p->u.bound_function = bf;
37095 37330
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
37096 name1 = JS_GetProperty(ctx, this_val, JS_ATOM_name);37369 name1 = JS_GetProperty(ctx, this_val, JS_ATOM_name);
37097 if (JS_IsException(name1))37370 if (JS_IsException(name1))
37098 goto exception;37371 goto exception;
@@ -37105,15 +37378,6 @@ static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val, · 6 unmodified lines
37105 goto exception;37378 goto exception;
37106 JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, name1,37379 JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, name1,
37107 JS_PROP_CONFIGURABLE);37380 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);
37117 return func_obj;37381 return func_obj;
37118 exception:37382 exception:
37119 JS_FreeValue(ctx, func_obj);37383 JS_FreeValue(ctx, func_obj);
@@ -40455,10 +40719,6 @@ static JSValue js_string_pad(JSContext *ctx, JSValueConst this_val, · 3335 unmodified lines
40455 len = p->len;40719 len = p->len;
40456 if (len >= n)40720 if (len >= n)
40457 return str;40721 return str;
40458 if (n > JS_STRING_LEN_MAX) {
40459 JS_ThrowInternalError(ctx, "string too long");
40460 goto fail2;
40461 }
40462 if (argc > 1 && !JS_IsUndefined(argv[1])) {40722 if (argc > 1 && !JS_IsUndefined(argv[1])) {
40463 v = JS_ToString(ctx, argv[1]);40723 v = JS_ToString(ctx, argv[1]);
40464 if (JS_IsException(v))40724 if (JS_IsException(v))
@@ -40473,6 +40733,10 @@ static JSValue js_string_pad(JSContext *ctx, JSValueConst this_val, · 8 unmodified lines
40473 p1 = NULL;40733 p1 = NULL;
40474 }40734 }
40475 }40735 }
40736 if (n > JS_STRING_LEN_MAX) {
40737 JS_ThrowInternalError(ctx, "string too long");
40738 goto fail2;
40739 }
40476 if (string_buffer_init(ctx, b, n))40740 if (string_buffer_init(ctx, b, n))
40477 goto fail3;40741 goto fail3;
40478 n -= len;40742 n -= len;
@@ -41932,14 +42196,11 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, · 1453 unmodified lines
41932 if (JS_IsException(obj))42196 if (JS_IsException(obj))
41933 goto fail;42197 goto fail;
41934 prop_flags = JS_PROP_C_W_E | JS_PROP_THROW;42198 prop_flags = JS_PROP_C_W_E | JS_PROP_THROW;
41935 group_name_ptr = NULL;42199 group_name_ptr = lre_get_groupnames(re_bytecode);
41936 if (re_flags & LRE_FLAG_NAMED_GROUPS) {42200 if (group_name_ptr) {
41937 uint32_t re_bytecode_len;
41938 groups = JS_NewObjectProto(ctx, JS_NULL);42201 groups = JS_NewObjectProto(ctx, JS_NULL);
41939 if (JS_IsException(groups))42202 if (JS_IsException(groups))
41940 goto fail;42203 goto fail;
41941 re_bytecode_len = get_u32(re_bytecode + 3);
41942 group_name_ptr = (char *)(re_bytecode + 7 + re_bytecode_len);
41943 }42204 }
41944 42205
41945 for(i = 0; i < capture_count; i++) {42206 for(i = 0; i < capture_count; i++) {
@@ -43724,6 +43985,7 @@ static const JSCFunctionListEntry js_reflect_funcs[] = { · 1778 unmodified lines
43724 JS_CFUNC_MAGIC_DEF("preventExtensions", 1, js_object_preventExtensions, 1 ),43985 JS_CFUNC_MAGIC_DEF("preventExtensions", 1, js_object_preventExtensions, 1 ),
43725 JS_CFUNC_DEF("set", 3, js_reflect_set ),43986 JS_CFUNC_DEF("set", 3, js_reflect_set ),
43726 JS_CFUNC_DEF("setPrototypeOf", 2, js_reflect_setPrototypeOf ),43987 JS_CFUNC_DEF("setPrototypeOf", 2, js_reflect_setPrototypeOf ),
43988 JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Reflect", JS_PROP_CONFIGURABLE ),
43727};43989};
43728 43990
43729static const JSCFunctionListEntry js_reflect_obj[] = {43991static const JSCFunctionListEntry js_reflect_obj[] = {
quickjs.h+10−0
@@ -412,6 +412,8 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s); · 411 unmodified lines
412void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);412void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);
413 413
414/* atom support */414/* atom support */
415#define JS_ATOM_NULL 0
416
415JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len);417JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len);
416JSAtom JS_NewAtom(JSContext *ctx, const char *str);418JSAtom JS_NewAtom(JSContext *ctx, const char *str);
417JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n);419JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n);
@@ -835,6 +837,8 @@ typedef int JSInterruptHandler(JSRuntime *rt, void *opaque); · 417 unmodified lines
835void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque);837void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque);
836/* if can_block is TRUE, Atomics.wait() can be used */838/* if can_block is TRUE, Atomics.wait() can be used */
837void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block);839void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block);
840/* set the [IsHTMLDDA] internal slot */
841void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj);
838 842
839typedef struct JSModuleDef JSModuleDef;843typedef struct JSModuleDef JSModuleDef;
840 844
@@ -886,6 +890,12 @@ JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, · 45 unmodified lines
886 returns a module. */890 returns a module. */
887int JS_ResolveModule(JSContext *ctx, JSValueConst obj);891int JS_ResolveModule(JSContext *ctx, JSValueConst obj);
888 892
893/* only exported for os.Worker() */
894JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels);
895/* only exported for os.Worker() */
896JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename,
897 const char *filename);
898
889/* C function definition */899/* C function definition */
890typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */900typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */
891 JS_CFUNC_generic,901 JS_CFUNC_generic,
run-test262.c+10−1
@@ -743,10 +743,16 @@ static JSValue js_createRealm(JSContext *ctx, JSValue this_val, · 742 unmodified lines
743 return ret;743 return ret;
744}744}
745 745
746static JSValue js_IsHTMLDDA(JSContext *ctx, JSValue this_val,
747 int argc, JSValue *argv)
748{
749 return JS_NULL;
750}
751
746static JSValue add_helpers1(JSContext *ctx)752static JSValue add_helpers1(JSContext *ctx)
747{753{
748 JSValue global_obj;754 JSValue global_obj;
749 JSValue obj262;755 JSValue obj262, obj;
750 756
751 global_obj = JS_GetGlobalObject(ctx);757 global_obj = JS_GetGlobalObject(ctx);
752 758
@@ -773,6 +779,9 @@ static JSValue add_helpers1(JSContext *ctx) · 20 unmodified lines
773 JS_SetPropertyStr(ctx, obj262, "createRealm",779 JS_SetPropertyStr(ctx, obj262, "createRealm",
774 JS_NewCFunction(ctx, js_createRealm,780 JS_NewCFunction(ctx, js_createRealm,
775 "createRealm", 0));781 "createRealm", 0));
782 obj = JS_NewCFunction(ctx, js_IsHTMLDDA, "IsHTMLDDA", 0);
783 JS_SetIsHTMLDDA(ctx, obj);
784 JS_SetPropertyStr(ctx, obj262, "IsHTMLDDA", obj);
776 785
777 JS_SetPropertyStr(ctx, global_obj, "$262", JS_DupValue(ctx, obj262));786 JS_SetPropertyStr(ctx, global_obj, "$262", JS_DupValue(ctx, obj262));
778 787
test262.conf+3−2
@@ -68,6 +68,7 @@ class-methods-private · 67 unmodified lines
68class-static-fields-public68class-static-fields-public
69class-static-fields-private69class-static-fields-private
70class-static-methods-private70class-static-methods-private
71cleanupSome=skip
71coalesce-expression72coalesce-expression
72computed-property-names73computed-property-names
73const74const
@@ -100,10 +101,10 @@ host-gc-required=skip · 26 unmodified lines
100import.meta101import.meta
101Int32Array102Int32Array
102Int8Array103Int8Array
103IsHTMLDDA=skip104IsHTMLDDA
104json-superset105json-superset
105let106let
106logical-assignment-operators=skip107logical-assignment-operators
107Map108Map
108new.target109new.target
109numeric-separator-literal110numeric-separator-literal
tests/test_builtin.js+2−0
@@ -277,6 +277,8 @@ function test_string() · 276 unmodified lines
277 assert("aaaa".split("aaaaa", 1), [ "aaaa" ]);277 assert("aaaa".split("aaaaa", 1), [ "aaaa" ]);
278 278
279 assert(eval('"\0"'), "\0");279 assert(eval('"\0"'), "\0");
280
281 assert("abc".padStart(Infinity, ""), "abc");
280}282}
281 283
282function test_math()284function test_math()
tests/test_language.js+19−0
@@ -359,6 +359,23 @@ function test_labels() · 358 unmodified lines
359 while (0) x: { break x; };359 while (0) x: { break x; };
360}360}
361 361
362function test_destructuring()
363{
364 function * g () { return 0; };
365 var [x] = g();
366 assert(x, void 0);
367}
368
369function 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
362test_op1();379test_op1();
363test_cvt();380test_cvt();
364test_eq();381test_eq();
@@ -373,3 +390,5 @@ test_template_skip(); · 8 unmodified lines
373test_object_literal();390test_object_literal();
374test_regexp_skip();391test_regexp_skip();
375test_labels();392test_labels();
393test_destructuring();
394test_spread();
tests/test_worker.js+1−32
@@ -25,38 +25,7 @@ function test_worker() · 24 unmodified lines
25{25{
26 var counter;26 var counter;
27 27
28 /* Note: can use std.loadFile() to read from a file */28 worker = new os.Worker("./test_worker_module.js");
29 worker = new os.Worker(`
30 import * as std from "std";
31 import * as os from "os";
32
33 var parent = os.Worker.parent;
34
35 function handle_msg(e) {
36 var ev = e.data;
37// print("child_recv", JSON.stringify(ev));
38 switch(ev.type) {
39 case "abort":
40 parent.postMessage({ type: "done" });
41 break;
42 case "sab":
43 /* modify the SharedArrayBuffer */
44 ev.buf[2] = 10;
45 parent.postMessage({ type: "sab_done", buf: ev.buf });
46 break;
47 }
48 }
49
50 function worker_main() {
51 var i;
52
53 parent.onmessage = handle_msg;
54 for(i = 0; i < 10; i++) {
55 parent.postMessage({ type: "num", num: i });
56 }
57 }
58 worker_main();
59`);
60 29
61 counter = 0;30 counter = 0;
62 worker.onmessage = function (e) {31 worker.onmessage = function (e) {
tests/test_worker_module.js+31−0
@@ -0,0 +1,31 @@
1/* Worker code for test_worker.js */
2import * as std from "std";
3import * as os from "os";
4
5var parent = os.Worker.parent;
6
7function 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
22function 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
31worker_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