mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-15 06:39:17 +00:00
fix(parser): reject TypeScript class modifiers in JavaScript (#27312)
Reject TypeScript-only class member modifiers in JavaScript with TS8009. Valid JavaScript modifiers and members named `declare`, `override`, or `readonly` remain accepted. Reuse the existing modifier validation and storage, retaining its deduplication and keyword-span behavior. Coverage fixtures and updated conformance snapshots cover ordinary, repeated, and escaped modifiers. fixes #27290 closes #27294
This commit is contained in:
1 parent
335ce792fa
commit
4359a66953
16 files changed
+208
-18
No files matched your search
@@ -1197,6 +1197,11 @@ parser_diagnostics! {
|
||||
ts_error("5087", "A labeled tuple element is declared as rest with a '...' before the name, rather than before the type.").with_label(span)
|
||||
};
|
||||
|
||||
modifier_in_ts(kind: ModifierKind, span: Span) => {
|
||||
ts_error("8009", format!("The '{kind}' modifier can only be used in TypeScript files."))
|
||||
.with_label(span)
|
||||
};
|
||||
|
||||
parameter_modifiers_in_ts(modifier: Modifier, allowed: Option<ModifierKinds>) => {
|
||||
ts_error("8012", "Parameter modifiers can only be used in TypeScript files.")
|
||||
.with_label(modifier.span())
|
||||
|
||||
@@ -267,6 +267,20 @@ impl<'a, C: Config> ParserImpl<'a, C> {
|
||||
false,
|
||||
diagnostics::cannot_appear_on_class_elements,
|
||||
);
|
||||
if !parser.is_ts {
|
||||
parser.verify_modifiers(
|
||||
modifiers,
|
||||
ModifierKinds::new([
|
||||
ModifierKind::Export,
|
||||
ModifierKind::Default,
|
||||
ModifierKind::Static,
|
||||
ModifierKind::Async,
|
||||
ModifierKind::Accessor,
|
||||
]),
|
||||
false,
|
||||
|modifier, _| diagnostics::modifier_in_ts(modifier.kind, modifier.span()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let start = self.cur_start();
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
class A {
|
||||
declare y;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
class A {
|
||||
pr\u0069vate x;
|
||||
publ\u0069c f() {}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
class A {
|
||||
private g() {}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
class A {
|
||||
protected f() {}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
class A {
|
||||
readonly x = 1;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class A {
|
||||
private private x = 1;
|
||||
public public f() {}
|
||||
readonly readonly y = 1;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class A {
|
||||
declare() {}
|
||||
override() {}
|
||||
readonly() {}
|
||||
|
||||
accessor value = 1;
|
||||
static field = 1;
|
||||
async method() {}
|
||||
}
|
||||
|
||||
class B {
|
||||
declare = 1;
|
||||
override = 1;
|
||||
readonly = 1;
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
codegen_misc Summary:
|
||||
AST Parsed : 112/112 (100.00%)
|
||||
Positive Passed: 112/112 (100.00%)
|
||||
AST Parsed : 113/113 (100.00%)
|
||||
Positive Passed: 113/113 (100.00%)
|
||||
@@ -1,3 +1,3 @@
|
||||
formatter_misc Summary:
|
||||
AST Parsed : 112/112 (100.00%)
|
||||
Positive Passed: 112/112 (100.00%)
|
||||
AST Parsed : 113/113 (100.00%)
|
||||
Positive Passed: 113/113 (100.00%)
|
||||
@@ -1,3 +1,3 @@
|
||||
lexer_misc Summary:
|
||||
AST Parsed : 353/353 (100.00%)
|
||||
Positive Passed: 353/353 (100.00%)
|
||||
AST Parsed : 360/360 (100.00%)
|
||||
Positive Passed: 360/360 (100.00%)
|
||||
@@ -1,7 +1,7 @@
|
||||
parser_misc Summary:
|
||||
AST Parsed : 112/112 (100.00%)
|
||||
Positive Passed: 112/112 (100.00%)
|
||||
Negative Passed: 243/243 (100.00%)
|
||||
AST Parsed : 113/113 (100.00%)
|
||||
Positive Passed: 113/113 (100.00%)
|
||||
Negative Passed: 249/249 (100.00%)
|
||||
|
||||
× TS(1275): 'accessor' modifier can only appear on a property declaration.
|
||||
╭─[misc/fail/accessor-modifier-abstract-method.ts:1:29]
|
||||
@@ -4649,6 +4649,121 @@ Negative Passed: 243/243 (100.00%)
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
× TS(8009): The 'declare' modifier can only be used in TypeScript files.
|
||||
╭─[misc/fail/oxc-27290-declare.js:2:3]
|
||||
1 │ class A {
|
||||
2 │ declare y;
|
||||
· ───────
|
||||
3 │ }
|
||||
╰────
|
||||
|
||||
× Keywords cannot contain escape characters
|
||||
╭─[misc/fail/oxc-27290-escaped.js:2:3]
|
||||
1 │ class A {
|
||||
2 │ pr\u0069vate x;
|
||||
· ────────────
|
||||
3 │ publ\u0069c f() {}
|
||||
╰────
|
||||
|
||||
× TS(8009): The 'private' modifier can only be used in TypeScript files.
|
||||
╭─[misc/fail/oxc-27290-escaped.js:2:3]
|
||||
1 │ class A {
|
||||
2 │ pr\u0069vate x;
|
||||
· ───────
|
||||
3 │ publ\u0069c f() {}
|
||||
╰────
|
||||
|
||||
× Keywords cannot contain escape characters
|
||||
╭─[misc/fail/oxc-27290-escaped.js:3:3]
|
||||
2 │ pr\u0069vate x;
|
||||
3 │ publ\u0069c f() {}
|
||||
· ───────────
|
||||
4 │ }
|
||||
╰────
|
||||
|
||||
× TS(8009): The 'public' modifier can only be used in TypeScript files.
|
||||
╭─[misc/fail/oxc-27290-escaped.js:3:3]
|
||||
2 │ pr\u0069vate x;
|
||||
3 │ publ\u0069c f() {}
|
||||
· ──────
|
||||
4 │ }
|
||||
╰────
|
||||
|
||||
× TS(8009): The 'private' modifier can only be used in TypeScript files.
|
||||
╭─[misc/fail/oxc-27290-private.js:2:3]
|
||||
1 │ class A {
|
||||
2 │ private g() {}
|
||||
· ───────
|
||||
3 │ }
|
||||
╰────
|
||||
|
||||
× TS(8009): The 'protected' modifier can only be used in TypeScript files.
|
||||
╭─[misc/fail/oxc-27290-protected.js:2:3]
|
||||
1 │ class A {
|
||||
2 │ protected f() {}
|
||||
· ─────────
|
||||
3 │ }
|
||||
╰────
|
||||
|
||||
× TS(8009): The 'readonly' modifier can only be used in TypeScript files.
|
||||
╭─[misc/fail/oxc-27290-readonly.js:2:3]
|
||||
1 │ class A {
|
||||
2 │ readonly x = 1;
|
||||
· ────────
|
||||
3 │ }
|
||||
╰────
|
||||
|
||||
× TS(1028): Accessibility modifier already seen.
|
||||
╭─[misc/fail/oxc-27290-repeated.js:2:11]
|
||||
1 │ class A {
|
||||
2 │ private private x = 1;
|
||||
· ───────
|
||||
3 │ public public f() {}
|
||||
╰────
|
||||
help: Remove the duplicate modifier.
|
||||
|
||||
× TS(8009): The 'private' modifier can only be used in TypeScript files.
|
||||
╭─[misc/fail/oxc-27290-repeated.js:2:11]
|
||||
1 │ class A {
|
||||
2 │ private private x = 1;
|
||||
· ───────
|
||||
3 │ public public f() {}
|
||||
╰────
|
||||
|
||||
× TS(1028): Accessibility modifier already seen.
|
||||
╭─[misc/fail/oxc-27290-repeated.js:3:10]
|
||||
2 │ private private x = 1;
|
||||
3 │ public public f() {}
|
||||
· ──────
|
||||
4 │ readonly readonly y = 1;
|
||||
╰────
|
||||
help: Remove the duplicate modifier.
|
||||
|
||||
× TS(8009): The 'public' modifier can only be used in TypeScript files.
|
||||
╭─[misc/fail/oxc-27290-repeated.js:3:10]
|
||||
2 │ private private x = 1;
|
||||
3 │ public public f() {}
|
||||
· ──────
|
||||
4 │ readonly readonly y = 1;
|
||||
╰────
|
||||
|
||||
× TS(1030): 'readonly' modifier already seen.
|
||||
╭─[misc/fail/oxc-27290-repeated.js:4:12]
|
||||
3 │ public public f() {}
|
||||
4 │ readonly readonly y = 1;
|
||||
· ────────
|
||||
5 │ }
|
||||
╰────
|
||||
help: Remove the duplicate modifier.
|
||||
|
||||
× TS(8009): The 'readonly' modifier can only be used in TypeScript files.
|
||||
╭─[misc/fail/oxc-27290-repeated.js:4:12]
|
||||
3 │ public public f() {}
|
||||
4 │ readonly readonly y = 1;
|
||||
· ────────
|
||||
5 │ }
|
||||
╰────
|
||||
|
||||
× Expected `:` but found `[`
|
||||
╭─[misc/fail/oxc-3320.tsx:1:8]
|
||||
1 │ m< $<{3[ $<{3[ $<{3[ m< m$<{3[ m< mm< $<{3[ $<{3[ $<{3[ m< m$<{3[ m< m$<{3[ $<{3[ m< m$<{3[
|
||||
|
||||
@@ -3,7 +3,7 @@ commit: f29aeb9f
|
||||
parser_typescript Summary:
|
||||
AST Parsed : 9658/9666 (99.92%)
|
||||
Positive Passed: 9651/9666 (99.84%)
|
||||
Negative Passed: 1689/2759 (61.22%)
|
||||
Negative Passed: 1691/2759 (61.29%)
|
||||
Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/compiler/FunctionDeclaration3.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/compiler/FunctionDeclaration4.ts
|
||||
@@ -570,8 +570,6 @@ Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/compiler
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/compiler/jsFileCompilationOptionalClassElementSyntaxOfClass.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/compiler/jsFileCompilationPublicMethodSyntaxOfClass.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/compiler/jsFunctionWithPrototypeNoErrorTruncationNoCrash.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/compiler/jsTypedefMergedWithModuleExportProperty.ts
|
||||
@@ -1802,8 +1800,6 @@ Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/conforma
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/conformance/node/nodeModulesTopLevelAwait.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/conformance/override/override_js3.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/conformance/parser/ecmascript3/Accessors/parserES3Accessors1.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tsc/testdata/tests/cases/conformance/parser/ecmascript3/Accessors/parserES3Accessors3.ts
|
||||
@@ -2764,6 +2760,14 @@ Expect to Parse: tasks/coverage/typescript/tsc/testdata/tests/cases/conformance/
|
||||
7 │ }
|
||||
╰────
|
||||
|
||||
× TS(8009): The 'declare' modifier can only be used in TypeScript files.
|
||||
╭─[typescript/tsc/testdata/tests/cases/compiler/ambientPropertyDeclarationInJs.ts:6:5]
|
||||
5 │
|
||||
6 │ declare prop: string;
|
||||
· ───────
|
||||
7 │
|
||||
╰────
|
||||
|
||||
× Expected `;` but found `:`
|
||||
╭─[typescript/tsc/testdata/tests/cases/compiler/ambientPropertyDeclarationInJs.ts:6:17]
|
||||
5 │
|
||||
@@ -8933,6 +8937,14 @@ Expect to Parse: tasks/coverage/typescript/tsc/testdata/tests/cases/conformance/
|
||||
· ╰── Opened here
|
||||
╰────
|
||||
|
||||
× TS(8009): The 'public' modifier can only be used in TypeScript files.
|
||||
╭─[typescript/tsc/testdata/tests/cases/compiler/jsFileCompilationPublicMethodSyntaxOfClass.ts:2:5]
|
||||
1 │ class C {
|
||||
2 │ public foo() {
|
||||
· ──────
|
||||
3 │ }
|
||||
╰────
|
||||
|
||||
× TS(8012): Parameter modifiers can only be used in TypeScript files.
|
||||
╭─[typescript/tsc/testdata/tests/cases/compiler/jsFileCompilationPublicParameterModifier.ts:1:23]
|
||||
1 │ class C { constructor(public x) { }}
|
||||
@@ -25981,6 +25993,14 @@ Expect to Parse: tasks/coverage/typescript/tsc/testdata/tests/cases/conformance/
|
||||
╰────
|
||||
help: No modifiers are allowed here.
|
||||
|
||||
× TS(8009): The 'override' modifier can only be used in TypeScript files.
|
||||
╭─[typescript/tsc/testdata/tests/cases/conformance/override/override_js3.ts:7:5]
|
||||
6 │ class D extends B {
|
||||
7 │ override foo (v) {}
|
||||
· ────────
|
||||
8 │ /** @override */
|
||||
╰────
|
||||
|
||||
× Cannot use `await` as an identifier in an async context
|
||||
╭─[typescript/tsc/testdata/tests/cases/conformance/parser/ecmascript2018/asyncGenerators/parser.asyncGenerators.classMethods.es2018.ts:3:15]
|
||||
2 │ class C4 {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
semantic_misc Summary:
|
||||
AST Parsed : 112/112 (100.00%)
|
||||
Positive Passed: 106/112 (94.64%)
|
||||
AST Parsed : 113/113 (100.00%)
|
||||
Positive Passed: 107/113 (94.69%)
|
||||
semantic Error: tasks/coverage/misc/pass/declare-let-private.ts
|
||||
Bindings mismatch:
|
||||
after transform: ScopeId(0): ["private"]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
transformer_misc Summary:
|
||||
AST Parsed : 112/112 (100.00%)
|
||||
Positive Passed: 112/112 (100.00%)
|
||||
AST Parsed : 113/113 (100.00%)
|
||||
Positive Passed: 113/113 (100.00%)
|
||||
Reference in new issue
Block a user