From 7adeb5c56e18858ab92337c59b393f0704538e22 Mon Sep 17 00:00:00 2001 From: Fabrice Bellard Date: Thu, 10 Apr 2025 16:23:25 +0200 Subject: [PATCH] Fix exporting destructured variables (saghul) (#382) --- TODO | 2 +- quickjs.c | 23 ++++++++++++++--------- test262_errors.txt | 1 - 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/TODO b/TODO index fd74852..0cefa97 100644 --- a/TODO +++ b/TODO @@ -62,6 +62,6 @@ Optimization ideas: Test262o: 0/11262 errors, 463 excluded Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch) -Result: 31/76964 errors, 3147 excluded, 6912 skipped +Result: 30/76964 errors, 3147 excluded, 6912 skipped Test262 commit: 56e77d6325067a545ea7e8ff5be5d9284334e33c diff --git a/quickjs.c b/quickjs.c index 7642d7d..fd464c9 100644 --- a/quickjs.c +++ b/quickjs.c @@ -23874,7 +23874,7 @@ fail: present at the top level. */ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, int hasval, int has_ellipsis, - BOOL allow_initializer) + BOOL allow_initializer, BOOL export_flag) { int label_parse, label_assign, label_done, label_lvalue, depth_lvalue; int start_addr, assign_addr; @@ -23990,7 +23990,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, emit_op(s, OP_get_field2); emit_u32(s, prop_name); } - if (js_parse_destructuring_element(s, tok, is_arg, TRUE, -1, TRUE) < 0) + if (js_parse_destructuring_element(s, tok, is_arg, TRUE, -1, TRUE, export_flag) < 0) return -1; if (s->token.val == '}') break; @@ -24114,6 +24114,11 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, if (tok) { if (js_define_var(s, var_name, tok)) goto var_error; + if (export_flag) { + if (!add_export_entry(s, s->cur_func->module, var_name, var_name, + JS_EXPORT_TYPE_LOCAL)) + goto var_error; + } scope = s->cur_func->scope_level; } if (s->token.val == '=') { /* handle optional default value */ @@ -24189,7 +24194,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, emit_u8(s, 0); emit_op(s, OP_drop); } - if (js_parse_destructuring_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0) + if (js_parse_destructuring_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE, export_flag) < 0) return -1; } else { var_name = JS_ATOM_NULL; @@ -24479,7 +24484,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) { int skip_bits; if (js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') { - if (js_parse_destructuring_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0) + if (js_parse_destructuring_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE, FALSE) < 0) return -1; } else { if (s->token.val == '{') { @@ -26031,7 +26036,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok, if ((s->token.val == '[' || s->token.val == '{') && js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') { emit_op(s, OP_undefined); - if (js_parse_destructuring_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0) + if (js_parse_destructuring_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE, export_flag) < 0) return -1; } else { return js_parse_error(s, "variable name expected"); @@ -26153,7 +26158,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) { if (s->token.val == '[' || s->token.val == '{') { - if (js_parse_destructuring_element(s, tok, 0, TRUE, -1, FALSE) < 0) + if (js_parse_destructuring_element(s, tok, 0, TRUE, -1, FALSE, FALSE) < 0) return -1; has_destructuring = TRUE; } else { @@ -26182,7 +26187,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, int skip_bits; if ((s->token.val == '[' || s->token.val == '{') && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == TOK_IN || tok1 == TOK_OF)) { - if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0) + if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE, FALSE) < 0) return -1; } else { int lvalue_label; @@ -26857,7 +26862,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) { if (s->token.val == '[' || s->token.val == '{') { /* XXX: TOK_LET is not completely correct */ - if (js_parse_destructuring_element(s, TOK_LET, 0, TRUE, -1, TRUE) < 0) + if (js_parse_destructuring_element(s, TOK_LET, 0, TRUE, -1, TRUE, FALSE) < 0) goto fail; } else { js_parse_error(s, "identifier expected"); @@ -33802,7 +33807,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, emit_op(s, OP_get_arg); emit_u16(s, idx); } - has_initializer = js_parse_destructuring_element(s, fd->has_parameter_expressions ? TOK_LET : TOK_VAR, 1, TRUE, -1, TRUE); + has_initializer = js_parse_destructuring_element(s, fd->has_parameter_expressions ? TOK_LET : TOK_VAR, 1, TRUE, -1, TRUE, FALSE); if (has_initializer < 0) goto fail; if (has_initializer) diff --git a/test262_errors.txt b/test262_errors.txt index ff805df..de18e57 100644 --- a/test262_errors.txt +++ b/test262_errors.txt @@ -21,7 +21,6 @@ test262/test/language/expressions/member-expression/computed-reference-null-or-u test262/test/language/expressions/member-expression/computed-reference-null-or-undefined.js:28: strict mode: Test262Error: Expected a TypeError but got a Test262Error test262/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js:31: Test262Error: Expected SameValue(«"bad"», «"ok"») to be true test262/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js:31: strict mode: Test262Error: Expected SameValue(«"bad"», «"ok"») to be true -test262/test/language/module-code/top-level-await/async-module-does-not-block-sibling-modules.js:13: SyntaxError: Could not find export 'check' in module 'test262/test/language/module-code/top-level-await/async-module-sync_FIXTURE.js' test262/test/language/module-code/top-level-await/module-graphs-does-not-hang.js:10: TypeError: $DONE() not called test262/test/language/statements/with/get-binding-value-call-with-proxy-env.js:39: Test262Error: Actual [has:Object, get:Symbol(Symbol.unscopables), get:Object] and expected [has:Object, get:Symbol(Symbol.unscopables), has:Object, get:Object] should have the same contents. test262/test/language/statements/with/get-binding-value-idref-with-proxy-env.js:39: Test262Error: Actual [has:Object, get:Symbol(Symbol.unscopables), get:Object] and expected [has:Object, get:Symbol(Symbol.unscopables), has:Object, get:Object] should have the same contents.