mirror of
				https://github.com/bellard/quickjs.git
				synced 2025-05-29 01:49:18 +08:00 
			
		
		
		
	fixed destructuring operation order when defining variables - optimized more cases of variable definition in destructuring
This commit is contained in:
		
							parent
							
								
									1d5e7cf300
								
							
						
					
					
						commit
						83530ac9a7
					
				
							
								
								
									
										77
									
								
								quickjs.c
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								quickjs.c
									
									
									
									
									
								
							@ -24019,6 +24019,25 @@ duplicate:
 | 
				
			|||||||
    return js_parse_error(s, "duplicate parameter names not allowed in this context");
 | 
					    return js_parse_error(s, "duplicate parameter names not allowed in this context");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* tok = TOK_VAR, TOK_LET or TOK_CONST. Return whether a reference
 | 
				
			||||||
 | 
					   must be taken to the variable for proper 'with' or global variable
 | 
				
			||||||
 | 
					   evaluation */
 | 
				
			||||||
 | 
					/* Note: this function is needed only because variable references are
 | 
				
			||||||
 | 
					   not yet optimized in destructuring */
 | 
				
			||||||
 | 
					static BOOL need_var_reference(JSParseState *s, int tok)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    JSFunctionDef *fd = s->cur_func;
 | 
				
			||||||
 | 
					    if (tok != TOK_VAR)
 | 
				
			||||||
 | 
					        return FALSE; /* no reference for let/const */
 | 
				
			||||||
 | 
					    if (fd->js_mode & JS_MODE_STRICT) {
 | 
				
			||||||
 | 
					        if (!fd->is_global_var)
 | 
				
			||||||
 | 
					            return FALSE; /* local definitions in strict mode in function or direct eval */
 | 
				
			||||||
 | 
					        if (s->is_module)
 | 
				
			||||||
 | 
					            return FALSE; /* in a module global variables are like closure variables */
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)
 | 
					static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    JSAtom name;
 | 
					    JSAtom name;
 | 
				
			||||||
@ -24100,14 +24119,22 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
 | 
				
			|||||||
                    var_name = js_parse_destructuring_var(s, tok, is_arg);
 | 
					                    var_name = js_parse_destructuring_var(s, tok, is_arg);
 | 
				
			||||||
                    if (var_name == JS_ATOM_NULL)
 | 
					                    if (var_name == JS_ATOM_NULL)
 | 
				
			||||||
                        return -1;
 | 
					                        return -1;
 | 
				
			||||||
 | 
					                    if (need_var_reference(s, tok)) {
 | 
				
			||||||
 | 
					                        /* Must make a reference for proper `with` semantics */
 | 
				
			||||||
 | 
					                        emit_op(s, OP_scope_get_var);
 | 
				
			||||||
 | 
					                        emit_atom(s, var_name);
 | 
				
			||||||
 | 
					                        emit_u16(s, s->cur_func->scope_level);
 | 
				
			||||||
 | 
					                        goto lvalue0;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
                        opcode = OP_scope_get_var;
 | 
					                        opcode = OP_scope_get_var;
 | 
				
			||||||
                        scope = s->cur_func->scope_level;
 | 
					                        scope = s->cur_func->scope_level;
 | 
				
			||||||
                        label_lvalue = -1;
 | 
					                        label_lvalue = -1;
 | 
				
			||||||
                        depth_lvalue = 0;
 | 
					                        depth_lvalue = 0;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    if (js_parse_left_hand_side_expr(s))
 | 
					                    if (js_parse_left_hand_side_expr(s))
 | 
				
			||||||
                        return -1;
 | 
					                        return -1;
 | 
				
			||||||
 | 
					                lvalue0:
 | 
				
			||||||
                    if (get_lvalue(s, &opcode, &scope, &var_name,
 | 
					                    if (get_lvalue(s, &opcode, &scope, &var_name,
 | 
				
			||||||
                                   &label_lvalue, &depth_lvalue, FALSE, '{'))
 | 
					                                   &label_lvalue, &depth_lvalue, FALSE, '{'))
 | 
				
			||||||
                        return -1;
 | 
					                        return -1;
 | 
				
			||||||
@ -24125,10 +24152,6 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
 | 
				
			|||||||
            if (prop_type < 0)
 | 
					            if (prop_type < 0)
 | 
				
			||||||
                return -1;
 | 
					                return -1;
 | 
				
			||||||
            var_name = JS_ATOM_NULL;
 | 
					            var_name = JS_ATOM_NULL;
 | 
				
			||||||
            opcode = OP_scope_get_var;
 | 
					 | 
				
			||||||
            scope = s->cur_func->scope_level;
 | 
					 | 
				
			||||||
            label_lvalue = -1;
 | 
					 | 
				
			||||||
            depth_lvalue = 0;
 | 
					 | 
				
			||||||
            if (prop_type == PROP_TYPE_IDENT) {
 | 
					            if (prop_type == PROP_TYPE_IDENT) {
 | 
				
			||||||
                if (next_token(s))
 | 
					                if (next_token(s))
 | 
				
			||||||
                    goto prop_error;
 | 
					                    goto prop_error;
 | 
				
			||||||
@ -24197,10 +24220,23 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
 | 
				
			|||||||
                    var_name = js_parse_destructuring_var(s, tok, is_arg);
 | 
					                    var_name = js_parse_destructuring_var(s, tok, is_arg);
 | 
				
			||||||
                    if (var_name == JS_ATOM_NULL)
 | 
					                    if (var_name == JS_ATOM_NULL)
 | 
				
			||||||
                        goto prop_error;
 | 
					                        goto prop_error;
 | 
				
			||||||
 | 
					                    if (need_var_reference(s, tok)) {
 | 
				
			||||||
 | 
					                        /* Must make a reference for proper `with` semantics */
 | 
				
			||||||
 | 
					                        emit_op(s, OP_scope_get_var);
 | 
				
			||||||
 | 
					                        emit_atom(s, var_name);
 | 
				
			||||||
 | 
					                        emit_u16(s, s->cur_func->scope_level);
 | 
				
			||||||
 | 
					                        goto lvalue1;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        /* no need to make a reference for let/const */
 | 
				
			||||||
 | 
					                        opcode = OP_scope_get_var;
 | 
				
			||||||
 | 
					                        scope = s->cur_func->scope_level;
 | 
				
			||||||
 | 
					                        label_lvalue = -1;
 | 
				
			||||||
 | 
					                        depth_lvalue = 0;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    if (js_parse_left_hand_side_expr(s))
 | 
					                    if (js_parse_left_hand_side_expr(s))
 | 
				
			||||||
                        goto prop_error;
 | 
					                        goto prop_error;
 | 
				
			||||||
                lvalue:
 | 
					                lvalue1:
 | 
				
			||||||
                    if (get_lvalue(s, &opcode, &scope, &var_name,
 | 
					                    if (get_lvalue(s, &opcode, &scope, &var_name,
 | 
				
			||||||
                                   &label_lvalue, &depth_lvalue, FALSE, '{'))
 | 
					                                   &label_lvalue, &depth_lvalue, FALSE, '{'))
 | 
				
			||||||
                        goto prop_error;
 | 
					                        goto prop_error;
 | 
				
			||||||
@ -24267,20 +24303,27 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
 | 
				
			|||||||
                    emit_atom(s, prop_name);
 | 
					                    emit_atom(s, prop_name);
 | 
				
			||||||
                    emit_op(s, OP_swap);
 | 
					                    emit_op(s, OP_swap);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (!tok || tok == TOK_VAR) {
 | 
					                if (!tok || need_var_reference(s, tok)) {
 | 
				
			||||||
                    /* generate reference */
 | 
					                    /* generate reference */
 | 
				
			||||||
                    /* source -- source source */
 | 
					                    /* source -- source source */
 | 
				
			||||||
                    emit_op(s, OP_dup);
 | 
					                    emit_op(s, OP_dup);
 | 
				
			||||||
                    emit_op(s, OP_scope_get_var);
 | 
					                    emit_op(s, OP_scope_get_var);
 | 
				
			||||||
                    emit_atom(s, prop_name);
 | 
					                    emit_atom(s, prop_name);
 | 
				
			||||||
                    emit_u16(s, s->cur_func->scope_level);
 | 
					                    emit_u16(s, s->cur_func->scope_level);
 | 
				
			||||||
                    goto lvalue;
 | 
					                    goto lvalue1;
 | 
				
			||||||
                }
 | 
					                } else {
 | 
				
			||||||
 | 
					                    /* no need to make a reference for let/const */
 | 
				
			||||||
                    var_name = JS_DupAtom(s->ctx, prop_name);
 | 
					                    var_name = JS_DupAtom(s->ctx, prop_name);
 | 
				
			||||||
 | 
					                    opcode = OP_scope_get_var;
 | 
				
			||||||
 | 
					                    scope = s->cur_func->scope_level;
 | 
				
			||||||
 | 
					                    label_lvalue = -1;
 | 
				
			||||||
 | 
					                    depth_lvalue = 0;
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
                    /* source -- source val */
 | 
					                    /* source -- source val */
 | 
				
			||||||
                    emit_op(s, OP_get_field2);
 | 
					                    emit_op(s, OP_get_field2);
 | 
				
			||||||
                    emit_u32(s, prop_name);
 | 
					                    emit_u32(s, prop_name);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        set_val:
 | 
					        set_val:
 | 
				
			||||||
            if (tok) {
 | 
					            if (tok) {
 | 
				
			||||||
                if (js_define_var(s, var_name, tok))
 | 
					                if (js_define_var(s, var_name, tok))
 | 
				
			||||||
@ -24290,7 +24333,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
 | 
				
			|||||||
                                          JS_EXPORT_TYPE_LOCAL))
 | 
					                                          JS_EXPORT_TYPE_LOCAL))
 | 
				
			||||||
                        goto var_error;
 | 
					                        goto var_error;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                scope = s->cur_func->scope_level;
 | 
					                scope = s->cur_func->scope_level; /* XXX: check */
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (s->token.val == '=') {  /* handle optional default value */
 | 
					            if (s->token.val == '=') {  /* handle optional default value */
 | 
				
			||||||
                int label_hasval;
 | 
					                int label_hasval;
 | 
				
			||||||
@ -24369,19 +24412,29 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
 | 
				
			|||||||
                    return -1;
 | 
					                    return -1;
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                var_name = JS_ATOM_NULL;
 | 
					                var_name = JS_ATOM_NULL;
 | 
				
			||||||
                enum_depth = 0;
 | 
					 | 
				
			||||||
                if (tok) {
 | 
					                if (tok) {
 | 
				
			||||||
                    var_name = js_parse_destructuring_var(s, tok, is_arg);
 | 
					                    var_name = js_parse_destructuring_var(s, tok, is_arg);
 | 
				
			||||||
                    if (var_name == JS_ATOM_NULL)
 | 
					                    if (var_name == JS_ATOM_NULL)
 | 
				
			||||||
                        goto var_error;
 | 
					                        goto var_error;
 | 
				
			||||||
                    if (js_define_var(s, var_name, tok))
 | 
					                    if (js_define_var(s, var_name, tok))
 | 
				
			||||||
                        goto var_error;
 | 
					                        goto var_error;
 | 
				
			||||||
 | 
					                    if (need_var_reference(s, tok)) {
 | 
				
			||||||
 | 
					                        /* Must make a reference for proper `with` semantics */
 | 
				
			||||||
 | 
					                        emit_op(s, OP_scope_get_var);
 | 
				
			||||||
 | 
					                        emit_atom(s, var_name);
 | 
				
			||||||
 | 
					                        emit_u16(s, s->cur_func->scope_level);
 | 
				
			||||||
 | 
					                        goto lvalue2;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        /* no need to make a reference for let/const */
 | 
				
			||||||
                        opcode = OP_scope_get_var;
 | 
					                        opcode = OP_scope_get_var;
 | 
				
			||||||
                        scope = s->cur_func->scope_level;
 | 
					                        scope = s->cur_func->scope_level;
 | 
				
			||||||
                        label_lvalue = -1;
 | 
					                        label_lvalue = -1;
 | 
				
			||||||
 | 
					                        enum_depth = 0;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    if (js_parse_left_hand_side_expr(s))
 | 
					                    if (js_parse_left_hand_side_expr(s))
 | 
				
			||||||
                        return -1;
 | 
					                        return -1;
 | 
				
			||||||
 | 
					                lvalue2:
 | 
				
			||||||
                    if (get_lvalue(s, &opcode, &scope, &var_name,
 | 
					                    if (get_lvalue(s, &opcode, &scope, &var_name,
 | 
				
			||||||
                                   &label_lvalue, &enum_depth, FALSE, '[')) {
 | 
					                                   &label_lvalue, &enum_depth, FALSE, '[')) {
 | 
				
			||||||
                        return -1;
 | 
					                        return -1;
 | 
				
			||||||
@ -26169,7 +26222,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
 | 
				
			|||||||
            if (s->token.val == '=') {
 | 
					            if (s->token.val == '=') {
 | 
				
			||||||
                if (next_token(s))
 | 
					                if (next_token(s))
 | 
				
			||||||
                    goto var_error;
 | 
					                    goto var_error;
 | 
				
			||||||
                if (tok == TOK_VAR) {
 | 
					                if (need_var_reference(s, tok)) {
 | 
				
			||||||
                    /* Must make a reference for proper `with` semantics */
 | 
					                    /* Must make a reference for proper `with` semantics */
 | 
				
			||||||
                    int opcode, scope, label;
 | 
					                    int opcode, scope, label;
 | 
				
			||||||
                    JSAtom name1;
 | 
					                    JSAtom name1;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
test262/test/language/destructuring/binding/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js:73: Test262Error: Actual [binding::source, binding::sourceKey, sourceKey, get source, binding::defaultValue, binding::varTarget] and expected [binding::source, binding::sourceKey, sourceKey, binding::varTarget, get source, binding::defaultValue] should have the same contents. 
 | 
					 | 
				
			||||||
test262/test/language/module-code/top-level-await/module-graphs-does-not-hang.js:10: TypeError: $DONE() not called
 | 
					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-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. 
 | 
					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. 
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user