@@ -25143,18 +25143,19 @@ static __exception int js_parse_array_literal(JSParseState *s)
2514325143 return js_parse_expect(s, ']');
2514425144}
2514525145
25146- /* XXX: remove */
25146+ /* check if scope chain contains a with statement */
2514725147static BOOL has_with_scope(JSFunctionDef *s, int scope_level)
2514825148{
25149- /* check if scope chain contains a with statement */
2515025149 while (s) {
25151- int scope_idx = s->scopes[scope_level].first;
25152- while (scope_idx >= 0) {
25153- JSVarDef *vd = &s->vars[scope_idx];
25154-
25155- if (vd->var_name == JS_ATOM__with_)
25156- return TRUE;
25157- scope_idx = vd->scope_next;
25150+ /* no with in strict mode */
25151+ if (!(s->js_mode & JS_MODE_STRICT)) {
25152+ int scope_idx = s->scopes[scope_level].first;
25153+ while (scope_idx >= 0) {
25154+ JSVarDef *vd = &s->vars[scope_idx];
25155+ if (vd->var_name == JS_ATOM__with_)
25156+ return TRUE;
25157+ scope_idx = vd->scope_next;
25158+ }
2515825159 }
2515925160 /* check parent scopes */
2516025161 scope_level = s->parent_scope_level;
@@ -25187,7 +25188,11 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
2518725188 }
2518825189 if (name == JS_ATOM_this || name == JS_ATOM_new_target)
2518925190 goto invalid_lvalue;
25190- depth = 2; /* will generate OP_get_ref_value */
25191+ if (has_with_scope(fd, scope)) {
25192+ depth = 2; /* will generate OP_get_ref_value */
25193+ } else {
25194+ depth = 0;
25195+ }
2519125196 break;
2519225197 case OP_get_field:
2519325198 name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);
@@ -25224,16 +25229,22 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
2522425229 /* get the value but keep the object/fields on the stack */
2522525230 switch(opcode) {
2522625231 case OP_scope_get_var:
25227- label = new_label(s);
25228- if (label < 0)
25229- return -1;
25230- emit_op(s, OP_scope_make_ref);
25231- emit_atom(s, name);
25232- emit_u32(s, label);
25233- emit_u16(s, scope);
25234- update_label(fd, label, 1);
25235- emit_op(s, OP_get_ref_value);
25236- opcode = OP_get_ref_value;
25232+ if (depth != 0) {
25233+ label = new_label(s);
25234+ if (label < 0)
25235+ return -1;
25236+ emit_op(s, OP_scope_make_ref);
25237+ emit_atom(s, name);
25238+ emit_u32(s, label);
25239+ emit_u16(s, scope);
25240+ update_label(fd, label, 1);
25241+ emit_op(s, OP_get_ref_value);
25242+ opcode = OP_get_ref_value;
25243+ } else {
25244+ emit_op(s, OP_scope_get_var);
25245+ emit_atom(s, name);
25246+ emit_u16(s, scope);
25247+ }
2523725248 break;
2523825249 case OP_get_field:
2523925250 emit_op(s, OP_get_field2);
@@ -25258,15 +25269,17 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
2525825269 } else {
2525925270 switch(opcode) {
2526025271 case OP_scope_get_var:
25261- label = new_label(s);
25262- if (label < 0)
25263- return -1;
25264- emit_op(s, OP_scope_make_ref);
25265- emit_atom(s, name);
25266- emit_u32(s, label);
25267- emit_u16(s, scope);
25268- update_label(fd, label, 1);
25269- opcode = OP_get_ref_value;
25272+ if (depth != 0) {
25273+ label = new_label(s);
25274+ if (label < 0)
25275+ return -1;
25276+ emit_op(s, OP_scope_make_ref);
25277+ emit_atom(s, name);
25278+ emit_u32(s, label);
25279+ emit_u16(s, scope);
25280+ update_label(fd, label, 1);
25281+ opcode = OP_get_ref_value;
25282+ }
2527025283 break;
2527125284 default:
2527225285 break;
@@ -25300,6 +25313,21 @@ static void put_lvalue(JSParseState *s, int opcode, int scope,
2530025313 BOOL is_let)
2530125314{
2530225315 switch(opcode) {
25316+ case OP_scope_get_var:
25317+ /* depth = 0 */
25318+ switch(special) {
25319+ case PUT_LVALUE_NOKEEP:
25320+ case PUT_LVALUE_NOKEEP_DEPTH:
25321+ case PUT_LVALUE_KEEP_SECOND:
25322+ case PUT_LVALUE_NOKEEP_BOTTOM:
25323+ break;
25324+ case PUT_LVALUE_KEEP_TOP:
25325+ emit_op(s, OP_dup);
25326+ break;
25327+ default:
25328+ abort();
25329+ }
25330+ break;
2530325331 case OP_get_field:
2530425332 case OP_scope_get_private_field:
2530525333 /* depth = 1 */
@@ -25371,8 +25399,6 @@ static void put_lvalue(JSParseState *s, int opcode, int scope,
2537125399
2537225400 switch(opcode) {
2537325401 case OP_scope_get_var: /* val -- */
25374- assert(special == PUT_LVALUE_NOKEEP ||
25375- special == PUT_LVALUE_NOKEEP_DEPTH);
2537625402 emit_op(s, is_let ? OP_scope_put_var_init : OP_scope_put_var);
2537725403 emit_u32(s, name); /* has refcount */
2537825404 emit_u16(s, scope);
@@ -25726,6 +25752,8 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
2572625752 /* swap ref and lvalue object if any */
2572725753 if (prop_name == JS_ATOM_NULL) {
2572825754 switch(depth_lvalue) {
25755+ case 0:
25756+ break;
2572925757 case 1:
2573025758 /* source prop x -> x source prop */
2573125759 emit_op(s, OP_rot3r);
@@ -25739,9 +25767,13 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
2573925767 emit_op(s, OP_rot5l);
2574025768 emit_op(s, OP_rot5l);
2574125769 break;
25770+ default:
25771+ abort();
2574225772 }
2574325773 } else {
2574425774 switch(depth_lvalue) {
25775+ case 0:
25776+ break;
2574525777 case 1:
2574625778 /* source x -> x source */
2574725779 emit_op(s, OP_swap);
@@ -25754,6 +25786,8 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
2575425786 /* source x y z -> x y z source */
2575525787 emit_op(s, OP_rot4l);
2575625788 break;
25789+ default:
25790+ abort();
2575725791 }
2575825792 }
2575925793 }
@@ -27405,7 +27439,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
2740527439 }
2740627440
2740727441 if (op == '=') {
27408- if (opcode == OP_get_ref_value && name == name0) {
27442+ if (( opcode == OP_get_ref_value || opcode == OP_scope_get_var) && name == name0) {
2740927443 set_object_name(s, name);
2741027444 }
2741127445 } else {
@@ -27440,11 +27474,14 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
2744027474 return -1;
2744127475 }
2744227476
27443- if (opcode == OP_get_ref_value && name == name0) {
27477+ if (( opcode == OP_get_ref_value || opcode == OP_scope_get_var) && name == name0) {
2744427478 set_object_name(s, name);
2744527479 }
2744627480
2744727481 switch(depth_lvalue) {
27482+ case 0:
27483+ emit_op(s, OP_dup);
27484+ break;
2744827485 case 1:
2744927486 emit_op(s, OP_insert2);
2745027487 break;
@@ -32202,14 +32239,22 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
3220232239 }
3220332240 }
3220432241 break;
32242+ case OP_scope_put_var:
32243+ if (!(var_idx & ARGUMENT_VAR_OFFSET) &&
32244+ s->vars[var_idx].var_kind == JS_VAR_FUNCTION_NAME) {
32245+ /* in non strict mode, modifying the function name is ignored */
32246+ dbuf_putc(bc, OP_drop);
32247+ goto done;
32248+ }
32249+ goto local_scope_var;
3220532250 case OP_scope_get_ref:
3220632251 dbuf_putc(bc, OP_undefined);
32207- /* fall thru */
32252+ goto local_scope_var;
3220832253 case OP_scope_get_var_checkthis:
3220932254 case OP_scope_get_var_undef:
3221032255 case OP_scope_get_var:
32211- case OP_scope_put_var:
3221232256 case OP_scope_put_var_init:
32257+ local_scope_var:
3221332258 is_put = (op == OP_scope_put_var || op == OP_scope_put_var_init);
3221432259 if (var_idx & ARGUMENT_VAR_OFFSET) {
3221532260 dbuf_putc(bc, OP_get_arg + is_put);
@@ -32497,15 +32542,22 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
3249732542 dbuf_put_u16(bc, idx);
3249832543 }
3249932544 break;
32545+ case OP_scope_put_var:
32546+ if (s->closure_var[idx].var_kind == JS_VAR_FUNCTION_NAME) {
32547+ /* in non strict mode, modifying the function name is ignored */
32548+ dbuf_putc(bc, OP_drop);
32549+ goto done;
32550+ }
32551+ goto closure_scope_var;
3250032552 case OP_scope_get_ref:
3250132553 /* XXX: should create a dummy object with a named slot that is
3250232554 a reference to the closure variable */
3250332555 dbuf_putc(bc, OP_undefined);
32504- /* fall thru */
32556+ goto closure_scope_var;
3250532557 case OP_scope_get_var_undef:
3250632558 case OP_scope_get_var:
32507- case OP_scope_put_var:
3250832559 case OP_scope_put_var_init:
32560+ closure_scope_var:
3250932561 is_put = (op == OP_scope_put_var ||
3251032562 op == OP_scope_put_var_init);
3251132563 if (is_put) {
0 commit comments