Skip to content

Commit

Permalink
fix(semantic): fix identifying strict mode arrow functions (#7785)
Browse files Browse the repository at this point in the history
Semantic analysis was not marking an arrow function containing a `"use strict"` directive as `ScopeFlags::StrictMode`. Fix that.
  • Loading branch information
overlookmotel committed Dec 10, 2024
1 parent f7900ab commit 4a3bca8
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 53 deletions.
11 changes: 10 additions & 1 deletion crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1680,7 +1680,16 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
// so that the correct cfg_ix is associated with the ast node.
let kind = AstKind::ArrowFunctionExpression(self.alloc(expr));
self.enter_node(kind);
self.enter_scope(ScopeFlags::Function | ScopeFlags::Arrow, &expr.scope_id);
self.enter_scope(
{
let mut flags = ScopeFlags::Function | ScopeFlags::Arrow;
if expr.has_use_strict_directive() {
flags |= ScopeFlags::StrictMode;
}
flags
},
&expr.scope_id,
);

if let Some(parameters) = &expr.type_parameters {
self.visit_ts_type_parameter_declaration(parameters);
Expand Down
79 changes: 73 additions & 6 deletions tasks/coverage/snapshots/parser_babel.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,19 @@ commit: 54a8389f
parser_babel Summary:
AST Parsed : 2205/2218 (99.41%)
Positive Passed: 2190/2218 (98.74%)
Negative Passed: 1511/1634 (92.47%)
Negative Passed: 1516/1634 (92.78%)
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/annex-b/enabled/3.1-sloppy-labeled-functions-if-body/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-if/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-startindex-and-startline-specified-without-startcolumn/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/startline-and-startcolumn-specified/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/startline-specified/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/escape-string/non-octal-eight-and-nine/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/escape-string/non-octal-eight-and-nine-before-use-strict/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/scope/dupl-bind-catch-func/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/scope/dupl-bind-func-var-sloppy/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2015/class-methods/direct-super-in-object-method/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2015/destructuring/error-operator-for-default/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2015/for-of/invalid-let-as-identifier/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2015/object/disallow-duplicate-method-params/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2015/uncategorised/297/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2015/uncategorised/335/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/async-await-as-arrow-binding-identifier/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2017/async-functions/await-binding-inside-arrow-params-inside-async-arrow-params/input.js
Expand All @@ -33,9 +30,7 @@ Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/class-static-block/invalid-decorators/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/private-in/invalid-private-followed-by-in-2/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2022/top-level-await-module/inside-class-property/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/esprima/es2015-arrow-function/invalid-param-strict-mode/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/esprima/es2015-generator/generator-parameter-binding-property-reserved/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0101/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0276/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/flow/expect-plugin/export-interface/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/flow/expect-plugin/export-type/input.js
Expand Down Expand Up @@ -851,6 +846,60 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
╰────
help: for octal literals use the '0o' prefix instead

× Invalid escape sequence
╭─[babel/packages/babel-parser/test/fixtures/core/escape-string/non-octal-eight-and-nine/input.js:4:3]
3 │ "use strict";
4 │ "\8";"\9";
· ────
5 │ }
╰────
help: \8 and \9 are not allowed in strict mode

× Invalid escape sequence
╭─[babel/packages/babel-parser/test/fixtures/core/escape-string/non-octal-eight-and-nine/input.js:4:8]
3 │ "use strict";
4 │ "\8";"\9";
· ────
5 │ }
╰────
help: \8 and \9 are not allowed in strict mode

× Invalid escape sequence
╭─[babel/packages/babel-parser/test/fixtures/core/escape-string/non-octal-eight-and-nine-before-use-strict/input.js:2:3]
1 │ () => {
2 │ "\8";"\9";
· ────
3 │ "use strict";
╰────
help: \8 and \9 are not allowed in strict mode

× Invalid escape sequence
╭─[babel/packages/babel-parser/test/fixtures/core/escape-string/non-octal-eight-and-nine-before-use-strict/input.js:2:8]
1 │ () => {
2 │ "\8";"\9";
· ────
3 │ "use strict";
╰────
help: \8 and \9 are not allowed in strict mode

× Invalid escape sequence
╭─[babel/packages/babel-parser/test/fixtures/core/escape-string/non-octal-eight-and-nine-before-use-strict/input.js:4:3]
3 │ "use strict";
4 │ "\8";"\9";
· ────
5 │ }
╰────
help: \8 and \9 are not allowed in strict mode

× Invalid escape sequence
╭─[babel/packages/babel-parser/test/fixtures/core/escape-string/non-octal-eight-and-nine-before-use-strict/input.js:4:8]
3 │ "use strict";
4 │ "\8";"\9";
· ────
5 │ }
╰────
help: \8 and \9 are not allowed in strict mode

× '0'-prefixed octal literals and octal escape sequences are deprecated
╭─[babel/packages/babel-parser/test/fixtures/core/escape-string/numeric-escape-in-directive/input.js:1:53]
1 │ function hello() { "use strict"; function inner() { "octal directive\1"; } }
Expand Down Expand Up @@ -4216,6 +4265,12 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
· ────
╰────

× Cannot assign to 'eval' in strict mode
╭─[babel/packages/babel-parser/test/fixtures/es2015/uncategorised/297/input.js:1:2]
1 │ (eval) => { "use strict"; 42 }
· ────
╰────

× Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[babel/packages/babel-parser/test/fixtures/es2015/uncategorised/298/input.js:1:21]
1 │ ({ get test() { } }) => 42
Expand Down Expand Up @@ -8455,6 +8510,12 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
· ──
╰────

× Cannot assign to 'eval' in strict mode
╭─[babel/packages/babel-parser/test/fixtures/esprima/es2015-arrow-function/invalid-param-strict-mode/input.js:1:1]
1 │ eval => {"use strict"};
· ────
╰────

× Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[babel/packages/babel-parser/test/fixtures/esprima/es2015-arrow-function/non-arrow-param-followed-by-arrow/input.js:1:6]
1 │ ((a)) => 0
Expand Down Expand Up @@ -10038,6 +10099,12 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
· ────
╰────

× Cannot assign to 'eval' in strict mode
╭─[babel/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0101/input.js:1:2]
1 │ (eval) => { "use strict"; 42 }
· ────
╰────

× Expected `,` but found `/`
╭─[babel/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0102/input.js:1:8]
1 │ p = { q/ }
Expand Down
47 changes: 1 addition & 46 deletions tasks/coverage/snapshots/semantic_test262.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ commit: eefc5cf3

semantic_test262 Summary:
AST Parsed : 44169/44169 (100.00%)
Positive Passed: 43637/44169 (98.80%)
Positive Passed: 43640/44169 (98.80%)
tasks/coverage/test262/test/annexB/language/function-code/if-decl-else-decl-a-func-block-scoping.js
semantic error: Symbol scope ID mismatch for "f":
after transform: SymbolId(3): ScopeId(4294967294)
Expand Down Expand Up @@ -1165,51 +1165,6 @@ Symbol scope ID mismatch for "_step":
after transform: SymbolId(5): ScopeId(5)
rebuilt : SymbolId(9): ScopeId(4)

tasks/coverage/test262/test/language/expressions/async-arrow-function/forbidden-ext/b2/async-arrow-function-forbidden-ext-indirect-access-own-prop-caller-get.js
semantic error: Scope flags mismatch:
after transform: ScopeId(2): ScopeFlags(Function)
rebuilt : ScopeId(2): ScopeFlags(StrictMode | Function)
Scope flags mismatch:
after transform: ScopeId(3): ScopeFlags(0x0)
rebuilt : ScopeId(3): ScopeFlags(StrictMode)
Scope flags mismatch:
after transform: ScopeId(4): ScopeFlags(Function)
rebuilt : ScopeId(4): ScopeFlags(StrictMode | Function)
Scope flags mismatch:
after transform: ScopeId(5): ScopeFlags(0x0)
rebuilt : ScopeId(5): ScopeFlags(StrictMode)
Scope flags mismatch:
after transform: ScopeId(6): ScopeFlags(0x0)
rebuilt : ScopeId(6): ScopeFlags(StrictMode)

tasks/coverage/test262/test/language/expressions/async-arrow-function/forbidden-ext/b2/async-arrow-function-forbidden-ext-indirect-access-own-prop-caller-value.js
semantic error: Scope flags mismatch:
after transform: ScopeId(2): ScopeFlags(Function)
rebuilt : ScopeId(2): ScopeFlags(StrictMode | Function)
Scope flags mismatch:
after transform: ScopeId(3): ScopeFlags(0x0)
rebuilt : ScopeId(3): ScopeFlags(StrictMode)
Scope flags mismatch:
after transform: ScopeId(4): ScopeFlags(0x0)
rebuilt : ScopeId(4): ScopeFlags(StrictMode)
Scope flags mismatch:
after transform: ScopeId(5): ScopeFlags(0x0)
rebuilt : ScopeId(5): ScopeFlags(StrictMode)

tasks/coverage/test262/test/language/expressions/async-arrow-function/forbidden-ext/b2/async-arrow-function-forbidden-ext-indirect-access-prop-caller.js
semantic error: Scope flags mismatch:
after transform: ScopeId(2): ScopeFlags(Function)
rebuilt : ScopeId(2): ScopeFlags(StrictMode | Function)
Scope flags mismatch:
after transform: ScopeId(3): ScopeFlags(0x0)
rebuilt : ScopeId(3): ScopeFlags(StrictMode)
Scope flags mismatch:
after transform: ScopeId(4): ScopeFlags(0x0)
rebuilt : ScopeId(4): ScopeFlags(StrictMode)
Scope flags mismatch:
after transform: ScopeId(5): ScopeFlags(0x0)
rebuilt : ScopeId(5): ScopeFlags(StrictMode)

tasks/coverage/test262/test/language/expressions/class/async-gen-method/dflt-params-abrupt.js
semantic error: Scope children mismatch:
after transform: ScopeId(5): [ScopeId(2)]
Expand Down

0 comments on commit 4a3bca8

Please sign in to comment.