Summary: | [JSC] ReferenceError when using extra parens in class fields | ||||||||
---|---|---|---|---|---|---|---|---|---|
Product: | WebKit | Reporter: | Liam Mitchell <mitchell.liam> | ||||||
Component: | JavaScriptCore | Assignee: | Yusuke Suzuki <ysuzuki> | ||||||
Status: | RESOLVED FIXED | ||||||||
Severity: | Normal | CC: | ews-watchlist, keith_miller, mark.lam, msaboff, saam, tzagallo, webkit-bug-importer, ysuzuki | ||||||
Priority: | P2 | Keywords: | InRadar | ||||||
Version: | Safari Technology Preview | ||||||||
Hardware: | Mac (Intel) | ||||||||
OS: | macOS 11 | ||||||||
Attachments: |
|
This is only reproducible without dev tools. If dev tools is open, the code works as expected. Hi Liam, Thanks for the report! Given that it doesn't happen with the DevTools open it sounds like this could be a JIT bug. Actually I'm not so sure it's a JIT bug; you don't have any loops in the code you're running. Looks like we're failing to create a lexical environment when the extra parens are there for some reason... (function foo() { const a = (x) => x class B { // c = a('OK'); c = a(('OK')); } // Should write 'OK' print(new B().c) })() produces the following byte code: foo#CMKAuY:[0x1078f4130->0x107871300, NoneFunctionCall, 100]: 25 instructions (0 16-bit instructions, 0 32-bit instructions, 8 instructions with metadata); 216 bytes (116 metadata bytes); 1 parameter(s); 20 callee register(s); 7 variable(s); scope at loc4 bb#1 Predecessors: [ ] [ 0] enter [ 1] get_scope dst:loc4 [ 3] mov dst:loc5, src:loc4 [ 6] check_traps [ 7] mov dst:loc6, src:callee [ 10] mov dst:loc7, src:<JSValue()>(const0) [ 13] mov dst:loc8, src:<JSValue()>(const0) [ 16] new_func_exp dst:loc7, scope:loc4, functionDecl:0 [ 20] mov dst:loc9, src:<JSValue()>(const0) [ 23] new_func_exp dst:loc10, scope:loc4, functionDecl:1 [ 27] new_object dst:loc11, inlineCapacity:0 [ 31] define_data_property base:loc11, property:String (atomic),8Bit:(1),length:(11): constructor, StructureID: 16608(const1), value:loc10, attributes:Int32: 89(const2) [ 36] define_data_property base:loc10, property:String (atomic),8Bit:(1),length:(9): prototype, StructureID: 16608(const3), value:loc11, attributes:Int32: 74(const4) [ 41] new_func_exp dst:loc12, scope:loc4, functionDecl:2 [ 45] put_by_id base:loc12, property:0, value:loc11, flags:Strict [ 51] put_by_id base:loc10, property:1, value:loc12, flags:IsDirect|Strict [ 57] mov dst:loc9, src:loc10 [ 60] mov dst:loc8, src:loc10 [ 63] resolve_scope dst:loc12, scope:loc4, var:2, resolveType:GlobalProperty, localScopeDepth:0 [ 70] get_from_scope dst:loc9, scope:loc12, var:2, getPutInfo:2048<ThrowIfNotFound|GlobalProperty|NotInitialization|NotStrictMode>, localScopeDepth:0, offset:0 [ 78] mov dst:loc14, src:loc8 [ 81] construct dst:loc13, callee:loc8, argc:1, argv:20 [ 87] get_by_id dst:loc11, base:loc13, property:3 [ 92] call dst:loc9, callee:loc9, argc:2, argv:18 [ 98] ret value:Undefined(const5) Successors: [ ] but if the comments are flipped we get: foo#CpArJP:[0x103ff4130->0x103f71300, NoneFunctionCall, 113]: 27 instructions (0 16-bit instructions, 0 32-bit instructions, 9 instructions with metadata); 229 bytes (116 metadata bytes); 1 parameter(s); 20 callee register(s); 7 variable(s); scope at loc4 bb#1 Predecessors: [ ] [ 0] enter [ 1] get_scope dst:loc4 [ 3] mov dst:loc5, src:loc4 [ 6] check_traps [ 7] mov dst:loc6, src:callee [ 10] create_lexical_environment dst:loc8, scope:loc4, symbolTable:Cell: 0x104100da8 (0x280004700:[0x4700/18176, SymbolTable, (0/0, 0/0){}, NonArray, Leaf]), StructureID: 18176(const0), initialValue:<JSValue()>(const1) [ 15] mov dst:loc4, src:loc8 [ 18] mov dst:loc7, src:<JSValue()>(const1) [ 21] new_func_exp dst:loc9, scope:loc4, functionDecl:0 [ 25] put_to_scope scope:loc8, var:0, value:loc9, getPutInfo:1049604<DoNotThrowIfNotFound|ResolvedClosureVar|ConstInitialization|NotStrictMode>, symbolTableOrScopeDepth:0, offset:0 [ 33] mov dst:loc9, src:<JSValue()>(const1) [ 36] new_func_exp dst:loc10, scope:loc4, functionDecl:1 [ 40] new_object dst:loc11, inlineCapacity:0 [ 44] define_data_property base:loc11, property:String (atomic),8Bit:(1),length:(11): constructor, StructureID: 16608(const2), value:loc10, attributes:Int32: 89(const3) [ 49] define_data_property base:loc10, property:String (atomic),8Bit:(1),length:(9): prototype, StructureID: 16608(const4), value:loc11, attributes:Int32: 74(const5) [ 54] new_func_exp dst:loc12, scope:loc4, functionDecl:2 [ 58] put_by_id base:loc12, property:1, value:loc11, flags:Strict [ 64] put_by_id base:loc10, property:2, value:loc12, flags:IsDirect|Strict [ 70] mov dst:loc9, src:loc10 [ 73] mov dst:loc7, src:loc10 [ 76] resolve_scope dst:loc12, scope:loc4, var:3, resolveType:GlobalProperty, localScopeDepth:1 [ 83] get_from_scope dst:loc9, scope:loc12, var:3, getPutInfo:2048<ThrowIfNotFound|GlobalProperty|NotInitialization|NotStrictMode>, localScopeDepth:1, offset:0 [ 91] mov dst:loc14, src:loc7 [ 94] construct dst:loc13, callee:loc7, argc:1, argv:20 [ 100] get_by_id dst:loc11, base:loc13, property:4 [ 105] call dst:loc9, callee:loc9, argc:2, argv:18 [ 111] ret value:Undefined(const6) Successors: [ ] Created attachment 455222 [details]
Patch
Comment on attachment 455222 [details]
Patch
r=me
Committed r291577 (248677@main): <https://commits.webkit.org/248677@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 455222 [details]. |
Created attachment 452527 [details] Two reproducible examples Extra params inside class field declarations cause ReferenceErrors. Example 1: ;(() => { const a = (x) => x class B { c = a(('OK')); } // Should write 'OK' document.write(new B().c) })() Throws ReferenceError: Can't find variable: a Example 2: ;(() => { const a = 'OK' class B { static c = { d: a, e: (1), } } // Should write 'OK' document.write(B.c.d) })() Throws ReferenceError: Can't find variable: a Tested on Safari TP 15.4, Safari 15.2, 15.3, iOS 14.5, 15.0