Support TS 4.3 override syntax in class (#13097)
* support TS 4.3 `override` syntax in class * fix types * fix types * tweak error message * update TypeScript commit * split tests * add more tests * update allowlist * disallow `override` with `declare` * disallow `override` in non-sub class * update TypeScript allowlist * rename error message key * add more tests
This commit is contained in:
parent
f8aa32f767
commit
bf14a106ad
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
|||||||
FLOW_COMMIT = a1f9a4c709dcebb27a5084acf47755fbae699c25
|
FLOW_COMMIT = a1f9a4c709dcebb27a5084acf47755fbae699c25
|
||||||
TEST262_COMMIT = eca69e2c95972a4c5780ef58fe1f1e53e871b9b1
|
TEST262_COMMIT = eca69e2c95972a4c5780ef58fe1f1e53e871b9b1
|
||||||
TYPESCRIPT_COMMIT = 41dc625b0a609eb294b975dd92675e72b2b3fdec
|
TYPESCRIPT_COMMIT = dd1ef88d016dc40a145eafc0a1169e7f0a4a9ebe
|
||||||
|
|
||||||
# Fix color output until TravisCI fixes https://github.com/travis-ci/travis-ci/issues/7967
|
# Fix color output until TravisCI fixes https://github.com/travis-ci/travis-ci/issues/7967
|
||||||
export FORCE_COLOR = true
|
export FORCE_COLOR = true
|
||||||
|
|||||||
@ -644,6 +644,10 @@ export function tsPrintClassMemberModifiers(this: Printer, node: any, isField) {
|
|||||||
this.word("declare");
|
this.word("declare");
|
||||||
this.space();
|
this.space();
|
||||||
}
|
}
|
||||||
|
if (node.override) {
|
||||||
|
this.word("override");
|
||||||
|
this.space();
|
||||||
|
}
|
||||||
if (node.accessibility) {
|
if (node.accessibility) {
|
||||||
this.word(node.accessibility);
|
this.word(node.accessibility);
|
||||||
this.space();
|
this.space();
|
||||||
|
|||||||
8
packages/babel-generator/test/fixtures/typescript/class-modifier-override/input.js
vendored
Normal file
8
packages/babel-generator/test/fixtures/typescript/class-modifier-override/input.js
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
class MyClass extends BaseClass {
|
||||||
|
override show() {}
|
||||||
|
override public show() {}
|
||||||
|
public override show() {}
|
||||||
|
override size = 5;
|
||||||
|
override readonly size = 5;
|
||||||
|
readonly override size = 5;
|
||||||
|
}
|
||||||
4
packages/babel-generator/test/fixtures/typescript/class-modifier-override/options.json
vendored
Normal file
4
packages/babel-generator/test/fixtures/typescript/class-modifier-override/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"sourceType": "module",
|
||||||
|
"plugins": ["typescript", "classProperties"]
|
||||||
|
}
|
||||||
11
packages/babel-generator/test/fixtures/typescript/class-modifier-override/output.js
vendored
Normal file
11
packages/babel-generator/test/fixtures/typescript/class-modifier-override/output.js
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class MyClass extends BaseClass {
|
||||||
|
override show() {}
|
||||||
|
|
||||||
|
override public show() {}
|
||||||
|
|
||||||
|
override public show() {}
|
||||||
|
|
||||||
|
override size = 5;
|
||||||
|
override readonly size = 5;
|
||||||
|
override readonly size = 5;
|
||||||
|
}
|
||||||
@ -128,6 +128,8 @@ export const ErrorMessages = makeErrorTemplates(
|
|||||||
"constructors in/after an Optional Chain are not allowed",
|
"constructors in/after an Optional Chain are not allowed",
|
||||||
OptionalChainingNoTemplate:
|
OptionalChainingNoTemplate:
|
||||||
"Tagged Template Literals are not allowed in optionalChain",
|
"Tagged Template Literals are not allowed in optionalChain",
|
||||||
|
OverrideOnConstructor:
|
||||||
|
"'override' modifier cannot appear on a constructor declaration.",
|
||||||
ParamDupe: "Argument name clash",
|
ParamDupe: "Argument name clash",
|
||||||
PatternHasAccessor: "Object pattern can't contain getter or setter",
|
PatternHasAccessor: "Object pattern can't contain getter or setter",
|
||||||
PatternHasMethod: "Object pattern can't contain methods",
|
PatternHasMethod: "Object pattern can't contain methods",
|
||||||
|
|||||||
@ -1205,15 +1205,12 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://tc39.es/ecma262/#prod-ClassBody
|
// https://tc39.es/ecma262/#prod-ClassBody
|
||||||
parseClassBody(
|
parseClassBody(hadSuperClass: boolean, oldStrict: boolean): N.ClassBody {
|
||||||
constructorAllowsSuper: boolean,
|
|
||||||
oldStrict: boolean,
|
|
||||||
): N.ClassBody {
|
|
||||||
this.classScope.enter();
|
this.classScope.enter();
|
||||||
|
|
||||||
const state: N.ParseClassMemberState = {
|
const state: N.ParseClassMemberState = {
|
||||||
constructorAllowsSuper,
|
|
||||||
hadConstructor: false,
|
hadConstructor: false,
|
||||||
|
hadSuperClass,
|
||||||
};
|
};
|
||||||
let decorators: N.Decorator[] = [];
|
let decorators: N.Decorator[] = [];
|
||||||
const classBody: N.ClassBody = this.startNode();
|
const classBody: N.ClassBody = this.startNode();
|
||||||
@ -1400,8 +1397,11 @@ export default class StatementParser extends ExpressionParser {
|
|||||||
if (state.hadConstructor && !this.hasPlugin("typescript")) {
|
if (state.hadConstructor && !this.hasPlugin("typescript")) {
|
||||||
this.raise(key.start, Errors.DuplicateConstructor);
|
this.raise(key.start, Errors.DuplicateConstructor);
|
||||||
}
|
}
|
||||||
|
if (isConstructor && this.hasPlugin("typescript") && member.override) {
|
||||||
|
this.raise(key.start, Errors.OverrideOnConstructor);
|
||||||
|
}
|
||||||
state.hadConstructor = true;
|
state.hadConstructor = true;
|
||||||
allowsDirectSuper = state.constructorAllowsSuper;
|
allowsDirectSuper = state.hadSuperClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pushClassMethod(
|
this.pushClassMethod(
|
||||||
|
|||||||
@ -41,6 +41,7 @@ type TsModifier =
|
|||||||
| "abstract"
|
| "abstract"
|
||||||
| "declare"
|
| "declare"
|
||||||
| "static"
|
| "static"
|
||||||
|
| "override"
|
||||||
| N.Accessibility;
|
| N.Accessibility;
|
||||||
|
|
||||||
function nonNull<T>(x: ?T): T {
|
function nonNull<T>(x: ?T): T {
|
||||||
@ -86,12 +87,15 @@ const TSErrors = makeErrorTemplates(
|
|||||||
ExpectedAmbientAfterExportDeclare:
|
ExpectedAmbientAfterExportDeclare:
|
||||||
"'export declare' must be followed by an ambient declaration.",
|
"'export declare' must be followed by an ambient declaration.",
|
||||||
ImportAliasHasImportType: "An import alias can not use 'import type'",
|
ImportAliasHasImportType: "An import alias can not use 'import type'",
|
||||||
|
IncompatibleModifiers: "'%0' modifier cannot be used with '%1' modifier.",
|
||||||
IndexSignatureHasAbstract:
|
IndexSignatureHasAbstract:
|
||||||
"Index signatures cannot have the 'abstract' modifier",
|
"Index signatures cannot have the 'abstract' modifier",
|
||||||
IndexSignatureHasAccessibility:
|
IndexSignatureHasAccessibility:
|
||||||
"Index signatures cannot have an accessibility modifier ('%0')",
|
"Index signatures cannot have an accessibility modifier ('%0')",
|
||||||
IndexSignatureHasDeclare:
|
IndexSignatureHasDeclare:
|
||||||
"Index signatures cannot have the 'declare' modifier",
|
"Index signatures cannot have the 'declare' modifier",
|
||||||
|
IndexSignatureHasOverride:
|
||||||
|
"'override' modifier cannot appear on an index signature.",
|
||||||
IndexSignatureHasStatic:
|
IndexSignatureHasStatic:
|
||||||
"Index signatures cannot have the 'static' modifier",
|
"Index signatures cannot have the 'static' modifier",
|
||||||
InvalidModifierOnTypeMember:
|
InvalidModifierOnTypeMember:
|
||||||
@ -107,6 +111,8 @@ const TSErrors = makeErrorTemplates(
|
|||||||
"'abstract' modifier can only appear on a class, method, or property declaration.",
|
"'abstract' modifier can only appear on a class, method, or property declaration.",
|
||||||
OptionalTypeBeforeRequired:
|
OptionalTypeBeforeRequired:
|
||||||
"A required element cannot follow an optional element.",
|
"A required element cannot follow an optional element.",
|
||||||
|
OverrideNotInSubClass:
|
||||||
|
"This member cannot have an 'override' modifier because its containing class does not extend another class.",
|
||||||
PatternIsOptional:
|
PatternIsOptional:
|
||||||
"A binding pattern parameter cannot be optional in an implementation signature.",
|
"A binding pattern parameter cannot be optional in an implementation signature.",
|
||||||
PrivateElementHasAbstract:
|
PrivateElementHasAbstract:
|
||||||
@ -257,6 +263,16 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
"static",
|
"static",
|
||||||
"readonly",
|
"readonly",
|
||||||
);
|
);
|
||||||
|
} else if (
|
||||||
|
(modified.declare && modifier === "override") ||
|
||||||
|
(modified.override && modifier === "declare")
|
||||||
|
) {
|
||||||
|
this.raise(
|
||||||
|
startPos,
|
||||||
|
TSErrors.IncompatibleModifiers,
|
||||||
|
"declare",
|
||||||
|
"override",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
modified[modifier] = true;
|
modified[modifier] = true;
|
||||||
}
|
}
|
||||||
@ -622,7 +638,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
this.tsParseModifiers(
|
this.tsParseModifiers(
|
||||||
node,
|
node,
|
||||||
["readonly"],
|
["readonly"],
|
||||||
["declare", "abstract", "private", "protected", "public", "static"],
|
[
|
||||||
|
"declare",
|
||||||
|
"abstract",
|
||||||
|
"private",
|
||||||
|
"protected",
|
||||||
|
"public",
|
||||||
|
"static",
|
||||||
|
"override",
|
||||||
|
],
|
||||||
TSErrors.InvalidModifierOnTypeMember,
|
TSErrors.InvalidModifierOnTypeMember,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -2223,6 +2247,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
"private",
|
"private",
|
||||||
"public",
|
"public",
|
||||||
"protected",
|
"protected",
|
||||||
|
"override",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const callParseClassMember = () => {
|
const callParseClassMember = () => {
|
||||||
@ -2246,6 +2271,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
"readonly",
|
"readonly",
|
||||||
"declare",
|
"declare",
|
||||||
"static",
|
"static",
|
||||||
|
"override",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (isStatic) {
|
if (isStatic) {
|
||||||
@ -2269,6 +2295,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
if ((member: any).declare) {
|
if ((member: any).declare) {
|
||||||
this.raise(member.start, TSErrors.IndexSignatureHasDeclare);
|
this.raise(member.start, TSErrors.IndexSignatureHasDeclare);
|
||||||
}
|
}
|
||||||
|
if ((member: any).override) {
|
||||||
|
this.raise(member.start, TSErrors.IndexSignatureHasOverride);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2277,6 +2306,19 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
this.raise(member.start, TSErrors.NonAbstractClassHasAbstractMethod);
|
this.raise(member.start, TSErrors.NonAbstractClassHasAbstractMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((member: any).override) {
|
||||||
|
if (isStatic) {
|
||||||
|
this.raise(
|
||||||
|
member.start,
|
||||||
|
TSErrors.IncompatibleModifiers,
|
||||||
|
"static",
|
||||||
|
"override",
|
||||||
|
);
|
||||||
|
} else if (!state.hadSuperClass) {
|
||||||
|
this.raise(member.start, TSErrors.OverrideNotInSubClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*:: invariant(member.type !== "TSIndexSignature") */
|
/*:: invariant(member.type !== "TSIndexSignature") */
|
||||||
|
|
||||||
super.parseClassMemberWithIsStatic(classBody, member, state, isStatic);
|
super.parseClassMemberWithIsStatic(classBody, member, state, isStatic);
|
||||||
|
|||||||
@ -730,6 +730,7 @@ export type ClassMemberBase = NodeBase &
|
|||||||
computed: boolean,
|
computed: boolean,
|
||||||
// TypeScript only:
|
// TypeScript only:
|
||||||
accessibility?: ?Accessibility,
|
accessibility?: ?Accessibility,
|
||||||
|
override?: ?true,
|
||||||
abstract?: ?true,
|
abstract?: ?true,
|
||||||
optional?: ?true,
|
optional?: ?true,
|
||||||
};
|
};
|
||||||
@ -807,6 +808,7 @@ export type ClassPrivateProperty = NodeBase & {
|
|||||||
optional?: true,
|
optional?: true,
|
||||||
definite?: true,
|
definite?: true,
|
||||||
readonly?: true,
|
readonly?: true,
|
||||||
|
override?: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type OptClassDeclaration = ClassBase &
|
export type OptClassDeclaration = ClassBase &
|
||||||
@ -1536,5 +1538,5 @@ export type ParseSubscriptState = {
|
|||||||
|
|
||||||
export type ParseClassMemberState = {|
|
export type ParseClassMemberState = {|
|
||||||
hadConstructor: boolean,
|
hadConstructor: boolean,
|
||||||
constructorAllowsSuper: boolean,
|
hadSuperClass: boolean,
|
||||||
|};
|
|};
|
||||||
|
|||||||
15
packages/babel-parser/test/fixtures/typescript/class/modifiers-override-errors/input.ts
vendored
Normal file
15
packages/babel-parser/test/fixtures/typescript/class/modifiers-override-errors/input.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
class MyClass2 extends BaseClass {
|
||||||
|
override constructor() {}
|
||||||
|
override [x: string]: any;
|
||||||
|
override static size = 5;
|
||||||
|
static override size = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare class MyClass3 extends BaseClass {
|
||||||
|
declare override prop1: any
|
||||||
|
override declare prop2: any
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyClass4 {
|
||||||
|
override prop: any
|
||||||
|
}
|
||||||
237
packages/babel-parser/test/fixtures/typescript/class/modifiers-override-errors/output.json
vendored
Normal file
237
packages/babel-parser/test/fixtures/typescript/class/modifiers-override-errors/output.json
vendored
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start":0,"end":296,"loc":{"start":{"line":1,"column":0},"end":{"line":15,"column":1}},
|
||||||
|
"errors": [
|
||||||
|
"SyntaxError: 'override' modifier cannot appear on a constructor declaration. (2:11)",
|
||||||
|
"SyntaxError: 'override' modifier cannot appear on an index signature. (3:2)",
|
||||||
|
"SyntaxError: 'static' modifier cannot be used with 'override' modifier. (4:2)",
|
||||||
|
"SyntaxError: 'static' modifier cannot be used with 'override' modifier. (5:2)",
|
||||||
|
"SyntaxError: 'declare' modifier cannot be used with 'override' modifier. (9:10)",
|
||||||
|
"SyntaxError: 'declare' modifier cannot be used with 'override' modifier. (10:11)",
|
||||||
|
"SyntaxError: This member cannot have an 'override' modifier because its containing class does not extend another class. (14:2)"
|
||||||
|
],
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start":0,"end":296,"loc":{"start":{"line":1,"column":0},"end":{"line":15,"column":1}},
|
||||||
|
"sourceType": "module",
|
||||||
|
"interpreter": null,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassDeclaration",
|
||||||
|
"start":0,"end":149,"loc":{"start":{"line":1,"column":0},"end":{"line":6,"column":1}},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":6,"end":14,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":14},"identifierName":"MyClass2"},
|
||||||
|
"name": "MyClass2"
|
||||||
|
},
|
||||||
|
"superClass": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":23,"end":32,"loc":{"start":{"line":1,"column":23},"end":{"line":1,"column":32},"identifierName":"BaseClass"},
|
||||||
|
"name": "BaseClass"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "ClassBody",
|
||||||
|
"start":33,"end":149,"loc":{"start":{"line":1,"column":33},"end":{"line":6,"column":1}},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassMethod",
|
||||||
|
"start":37,"end":62,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":27}},
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":46,"end":57,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":22},"identifierName":"constructor"},
|
||||||
|
"name": "constructor"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"kind": "constructor",
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"async": false,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start":60,"end":62,"loc":{"start":{"line":2,"column":25},"end":{"line":2,"column":27}},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TSIndexSignature",
|
||||||
|
"start":65,"end":91,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":28}},
|
||||||
|
"override": true,
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":75,"end":84,"loc":{"start":{"line":3,"column":12},"end":{"line":3,"column":21},"identifierName":"x"},
|
||||||
|
"name": "x",
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSTypeAnnotation",
|
||||||
|
"start":76,"end":84,"loc":{"start":{"line":3,"column":13},"end":{"line":3,"column":21}},
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSStringKeyword",
|
||||||
|
"start":78,"end":84,"loc":{"start":{"line":3,"column":15},"end":{"line":3,"column":21}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSTypeAnnotation",
|
||||||
|
"start":85,"end":90,"loc":{"start":{"line":3,"column":22},"end":{"line":3,"column":27}},
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSAnyKeyword",
|
||||||
|
"start":87,"end":90,"loc":{"start":{"line":3,"column":24},"end":{"line":3,"column":27}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start":94,"end":119,"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":27}},
|
||||||
|
"override": true,
|
||||||
|
"static": true,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":110,"end":114,"loc":{"start":{"line":4,"column":18},"end":{"line":4,"column":22},"identifierName":"size"},
|
||||||
|
"name": "size"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"value": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start":117,"end":118,"loc":{"start":{"line":4,"column":25},"end":{"line":4,"column":26}},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 5,
|
||||||
|
"raw": "5"
|
||||||
|
},
|
||||||
|
"value": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start":122,"end":147,"loc":{"start":{"line":5,"column":2},"end":{"line":5,"column":27}},
|
||||||
|
"override": true,
|
||||||
|
"static": true,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":138,"end":142,"loc":{"start":{"line":5,"column":18},"end":{"line":5,"column":22},"identifierName":"size"},
|
||||||
|
"name": "size"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"value": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start":145,"end":146,"loc":{"start":{"line":5,"column":25},"end":{"line":5,"column":26}},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 5,
|
||||||
|
"raw": "5"
|
||||||
|
},
|
||||||
|
"value": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassDeclaration",
|
||||||
|
"start":151,"end":255,"loc":{"start":{"line":8,"column":0},"end":{"line":11,"column":1}},
|
||||||
|
"declare": true,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":165,"end":173,"loc":{"start":{"line":8,"column":14},"end":{"line":8,"column":22},"identifierName":"MyClass3"},
|
||||||
|
"name": "MyClass3"
|
||||||
|
},
|
||||||
|
"superClass": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":182,"end":191,"loc":{"start":{"line":8,"column":31},"end":{"line":8,"column":40},"identifierName":"BaseClass"},
|
||||||
|
"name": "BaseClass"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "ClassBody",
|
||||||
|
"start":192,"end":255,"loc":{"start":{"line":8,"column":41},"end":{"line":11,"column":1}},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start":196,"end":223,"loc":{"start":{"line":9,"column":2},"end":{"line":9,"column":29}},
|
||||||
|
"declare": true,
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":213,"end":218,"loc":{"start":{"line":9,"column":19},"end":{"line":9,"column":24},"identifierName":"prop1"},
|
||||||
|
"name": "prop1"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSTypeAnnotation",
|
||||||
|
"start":218,"end":223,"loc":{"start":{"line":9,"column":24},"end":{"line":9,"column":29}},
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSAnyKeyword",
|
||||||
|
"start":220,"end":223,"loc":{"start":{"line":9,"column":26},"end":{"line":9,"column":29}}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start":226,"end":253,"loc":{"start":{"line":10,"column":2},"end":{"line":10,"column":29}},
|
||||||
|
"override": true,
|
||||||
|
"declare": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":243,"end":248,"loc":{"start":{"line":10,"column":19},"end":{"line":10,"column":24},"identifierName":"prop2"},
|
||||||
|
"name": "prop2"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSTypeAnnotation",
|
||||||
|
"start":248,"end":253,"loc":{"start":{"line":10,"column":24},"end":{"line":10,"column":29}},
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSAnyKeyword",
|
||||||
|
"start":250,"end":253,"loc":{"start":{"line":10,"column":26},"end":{"line":10,"column":29}}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassDeclaration",
|
||||||
|
"start":257,"end":296,"loc":{"start":{"line":13,"column":0},"end":{"line":15,"column":1}},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":263,"end":271,"loc":{"start":{"line":13,"column":6},"end":{"line":13,"column":14},"identifierName":"MyClass4"},
|
||||||
|
"name": "MyClass4"
|
||||||
|
},
|
||||||
|
"superClass": null,
|
||||||
|
"body": {
|
||||||
|
"type": "ClassBody",
|
||||||
|
"start":272,"end":296,"loc":{"start":{"line":13,"column":15},"end":{"line":15,"column":1}},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start":276,"end":294,"loc":{"start":{"line":14,"column":2},"end":{"line":14,"column":20}},
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":285,"end":289,"loc":{"start":{"line":14,"column":11},"end":{"line":14,"column":15},"identifierName":"prop"},
|
||||||
|
"name": "prop"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSTypeAnnotation",
|
||||||
|
"start":289,"end":294,"loc":{"start":{"line":14,"column":15},"end":{"line":14,"column":20}},
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSAnyKeyword",
|
||||||
|
"start":291,"end":294,"loc":{"start":{"line":14,"column":17},"end":{"line":14,"column":20}}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
20
packages/babel-parser/test/fixtures/typescript/class/modifiers-override/input.ts
vendored
Normal file
20
packages/babel-parser/test/fixtures/typescript/class/modifiers-override/input.ts
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
class MyClass extends BaseClass {
|
||||||
|
override show() {}
|
||||||
|
override public show() {}
|
||||||
|
public override show() {}
|
||||||
|
override size = 5;
|
||||||
|
override readonly size = 5;
|
||||||
|
readonly override size = 5;
|
||||||
|
|
||||||
|
override get text() {}
|
||||||
|
override set text(value) {}
|
||||||
|
|
||||||
|
override async fetch() {}
|
||||||
|
|
||||||
|
override [x] = 2
|
||||||
|
override [x]() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare class DeclaredClass extends BaseClass {
|
||||||
|
override test() {}
|
||||||
|
}
|
||||||
332
packages/babel-parser/test/fixtures/typescript/class/modifiers-override/output.json
vendored
Normal file
332
packages/babel-parser/test/fixtures/typescript/class/modifiers-override/output.json
vendored
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start":0,"end":390,"loc":{"start":{"line":1,"column":0},"end":{"line":20,"column":1}},
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start":0,"end":390,"loc":{"start":{"line":1,"column":0},"end":{"line":20,"column":1}},
|
||||||
|
"sourceType": "module",
|
||||||
|
"interpreter": null,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassDeclaration",
|
||||||
|
"start":0,"end":318,"loc":{"start":{"line":1,"column":0},"end":{"line":16,"column":1}},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":6,"end":13,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":13},"identifierName":"MyClass"},
|
||||||
|
"name": "MyClass"
|
||||||
|
},
|
||||||
|
"superClass": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":22,"end":31,"loc":{"start":{"line":1,"column":22},"end":{"line":1,"column":31},"identifierName":"BaseClass"},
|
||||||
|
"name": "BaseClass"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "ClassBody",
|
||||||
|
"start":32,"end":318,"loc":{"start":{"line":1,"column":32},"end":{"line":16,"column":1}},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassMethod",
|
||||||
|
"start":36,"end":54,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":20}},
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":45,"end":49,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":15},"identifierName":"show"},
|
||||||
|
"name": "show"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"kind": "method",
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"async": false,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start":52,"end":54,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":20}},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassMethod",
|
||||||
|
"start":57,"end":82,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":27}},
|
||||||
|
"override": true,
|
||||||
|
"accessibility": "public",
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":73,"end":77,"loc":{"start":{"line":3,"column":18},"end":{"line":3,"column":22},"identifierName":"show"},
|
||||||
|
"name": "show"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"kind": "method",
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"async": false,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start":80,"end":82,"loc":{"start":{"line":3,"column":25},"end":{"line":3,"column":27}},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassMethod",
|
||||||
|
"start":85,"end":110,"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":27}},
|
||||||
|
"accessibility": "public",
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":101,"end":105,"loc":{"start":{"line":4,"column":18},"end":{"line":4,"column":22},"identifierName":"show"},
|
||||||
|
"name": "show"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"kind": "method",
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"async": false,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start":108,"end":110,"loc":{"start":{"line":4,"column":25},"end":{"line":4,"column":27}},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start":113,"end":131,"loc":{"start":{"line":5,"column":2},"end":{"line":5,"column":20}},
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":122,"end":126,"loc":{"start":{"line":5,"column":11},"end":{"line":5,"column":15},"identifierName":"size"},
|
||||||
|
"name": "size"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"value": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start":129,"end":130,"loc":{"start":{"line":5,"column":18},"end":{"line":5,"column":19}},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 5,
|
||||||
|
"raw": "5"
|
||||||
|
},
|
||||||
|
"value": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start":134,"end":161,"loc":{"start":{"line":6,"column":2},"end":{"line":6,"column":29}},
|
||||||
|
"override": true,
|
||||||
|
"readonly": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":152,"end":156,"loc":{"start":{"line":6,"column":20},"end":{"line":6,"column":24},"identifierName":"size"},
|
||||||
|
"name": "size"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"value": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start":159,"end":160,"loc":{"start":{"line":6,"column":27},"end":{"line":6,"column":28}},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 5,
|
||||||
|
"raw": "5"
|
||||||
|
},
|
||||||
|
"value": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start":164,"end":191,"loc":{"start":{"line":7,"column":2},"end":{"line":7,"column":29}},
|
||||||
|
"readonly": true,
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":182,"end":186,"loc":{"start":{"line":7,"column":20},"end":{"line":7,"column":24},"identifierName":"size"},
|
||||||
|
"name": "size"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"value": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start":189,"end":190,"loc":{"start":{"line":7,"column":27},"end":{"line":7,"column":28}},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 5,
|
||||||
|
"raw": "5"
|
||||||
|
},
|
||||||
|
"value": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassMethod",
|
||||||
|
"start":195,"end":217,"loc":{"start":{"line":9,"column":2},"end":{"line":9,"column":24}},
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":208,"end":212,"loc":{"start":{"line":9,"column":15},"end":{"line":9,"column":19},"identifierName":"text"},
|
||||||
|
"name": "text"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"kind": "get",
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"async": false,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start":215,"end":217,"loc":{"start":{"line":9,"column":22},"end":{"line":9,"column":24}},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassMethod",
|
||||||
|
"start":220,"end":247,"loc":{"start":{"line":10,"column":2},"end":{"line":10,"column":29}},
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":233,"end":237,"loc":{"start":{"line":10,"column":15},"end":{"line":10,"column":19},"identifierName":"text"},
|
||||||
|
"name": "text"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"kind": "set",
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"async": false,
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":238,"end":243,"loc":{"start":{"line":10,"column":20},"end":{"line":10,"column":25},"identifierName":"value"},
|
||||||
|
"name": "value"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start":245,"end":247,"loc":{"start":{"line":10,"column":27},"end":{"line":10,"column":29}},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassMethod",
|
||||||
|
"start":251,"end":276,"loc":{"start":{"line":12,"column":2},"end":{"line":12,"column":27}},
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":266,"end":271,"loc":{"start":{"line":12,"column":17},"end":{"line":12,"column":22},"identifierName":"fetch"},
|
||||||
|
"name": "fetch"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"kind": "method",
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"async": true,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start":274,"end":276,"loc":{"start":{"line":12,"column":25},"end":{"line":12,"column":27}},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start":280,"end":296,"loc":{"start":{"line":14,"column":2},"end":{"line":14,"column":18}},
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"computed": true,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":290,"end":291,"loc":{"start":{"line":14,"column":12},"end":{"line":14,"column":13},"identifierName":"x"},
|
||||||
|
"name": "x"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "NumericLiteral",
|
||||||
|
"start":295,"end":296,"loc":{"start":{"line":14,"column":17},"end":{"line":14,"column":18}},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": 2,
|
||||||
|
"raw": "2"
|
||||||
|
},
|
||||||
|
"value": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassMethod",
|
||||||
|
"start":299,"end":316,"loc":{"start":{"line":15,"column":2},"end":{"line":15,"column":19}},
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"computed": true,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":309,"end":310,"loc":{"start":{"line":15,"column":12},"end":{"line":15,"column":13},"identifierName":"x"},
|
||||||
|
"name": "x"
|
||||||
|
},
|
||||||
|
"kind": "method",
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"async": false,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start":314,"end":316,"loc":{"start":{"line":15,"column":17},"end":{"line":15,"column":19}},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassDeclaration",
|
||||||
|
"start":320,"end":390,"loc":{"start":{"line":18,"column":0},"end":{"line":20,"column":1}},
|
||||||
|
"declare": true,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":334,"end":347,"loc":{"start":{"line":18,"column":14},"end":{"line":18,"column":27},"identifierName":"DeclaredClass"},
|
||||||
|
"name": "DeclaredClass"
|
||||||
|
},
|
||||||
|
"superClass": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":356,"end":365,"loc":{"start":{"line":18,"column":36},"end":{"line":18,"column":45},"identifierName":"BaseClass"},
|
||||||
|
"name": "BaseClass"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "ClassBody",
|
||||||
|
"start":366,"end":390,"loc":{"start":{"line":18,"column":46},"end":{"line":20,"column":1}},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassMethod",
|
||||||
|
"start":370,"end":388,"loc":{"start":{"line":19,"column":2},"end":{"line":19,"column":20}},
|
||||||
|
"override": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":379,"end":383,"loc":{"start":{"line":19,"column":11},"end":{"line":19,"column":15},"identifierName":"test"},
|
||||||
|
"name": "test"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"kind": "method",
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"async": false,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start":386,"end":388,"loc":{"start":{"line":19,"column":18},"end":{"line":19,"column":20}},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -909,6 +909,7 @@ export interface ClassMethod extends BaseNode {
|
|||||||
accessibility?: "public" | "private" | "protected" | null;
|
accessibility?: "public" | "private" | "protected" | null;
|
||||||
decorators?: Array<Decorator> | null;
|
decorators?: Array<Decorator> | null;
|
||||||
optional?: boolean | null;
|
optional?: boolean | null;
|
||||||
|
override?: boolean;
|
||||||
returnType?: TypeAnnotation | TSTypeAnnotation | Noop | null;
|
returnType?: TypeAnnotation | TSTypeAnnotation | Noop | null;
|
||||||
typeParameters?:
|
typeParameters?:
|
||||||
| TypeParameterDeclaration
|
| TypeParameterDeclaration
|
||||||
@ -1535,6 +1536,7 @@ export interface ClassProperty extends BaseNode {
|
|||||||
declare?: boolean | null;
|
declare?: boolean | null;
|
||||||
definite?: boolean | null;
|
definite?: boolean | null;
|
||||||
optional?: boolean | null;
|
optional?: boolean | null;
|
||||||
|
override?: boolean;
|
||||||
readonly?: boolean | null;
|
readonly?: boolean | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1576,6 +1578,7 @@ export interface ClassPrivateMethod extends BaseNode {
|
|||||||
decorators?: Array<Decorator> | null;
|
decorators?: Array<Decorator> | null;
|
||||||
generator?: boolean;
|
generator?: boolean;
|
||||||
optional?: boolean | null;
|
optional?: boolean | null;
|
||||||
|
override?: boolean;
|
||||||
returnType?: TypeAnnotation | TSTypeAnnotation | Noop | null;
|
returnType?: TypeAnnotation | TSTypeAnnotation | Noop | null;
|
||||||
typeParameters?:
|
typeParameters?:
|
||||||
| TypeParameterDeclaration
|
| TypeParameterDeclaration
|
||||||
@ -1668,6 +1671,7 @@ export interface TSDeclareMethod extends BaseNode {
|
|||||||
generator?: boolean;
|
generator?: boolean;
|
||||||
kind?: "get" | "set" | "method" | "constructor";
|
kind?: "get" | "set" | "method" | "constructor";
|
||||||
optional?: boolean | null;
|
optional?: boolean | null;
|
||||||
|
override?: boolean;
|
||||||
static?: boolean;
|
static?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1705,6 +1705,9 @@ export const classMethodOrPropertyCommon = {
|
|||||||
static: {
|
static: {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
override: {
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user