[babel 8] Enable allowDeclareFields option by default with TS (#12461)
This commit is contained in:
parent
ff52acee79
commit
50462eb5e4
@ -149,6 +149,14 @@ jobs:
|
|||||||
at: /tmp/verdaccio-workspace
|
at: /tmp/verdaccio-workspace
|
||||||
- run: ./scripts/integration-tests/e2e-babel.sh
|
- run: ./scripts/integration-tests/e2e-babel.sh
|
||||||
|
|
||||||
|
e2e-babel-breaking:
|
||||||
|
executor: node-executor
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- attach_workspace:
|
||||||
|
at: /tmp/verdaccio-workspace
|
||||||
|
- run: BABEL_8_BREAKING=true ./scripts/integration-tests/e2e-babel.sh
|
||||||
|
|
||||||
e2e-babel-old-version:
|
e2e-babel-old-version:
|
||||||
executor: node-executor
|
executor: node-executor
|
||||||
steps:
|
steps:
|
||||||
@ -185,6 +193,14 @@ jobs:
|
|||||||
at: /tmp/verdaccio-workspace
|
at: /tmp/verdaccio-workspace
|
||||||
- run: ./scripts/integration-tests/e2e-jest.sh
|
- run: ./scripts/integration-tests/e2e-jest.sh
|
||||||
|
|
||||||
|
e2e-jest-breaking:
|
||||||
|
executor: node-python-executor
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- attach_workspace:
|
||||||
|
at: /tmp/verdaccio-workspace
|
||||||
|
- run: BABEL_8_BREAKING=true ./scripts/integration-tests/e2e-jest.sh
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
build-standalone:
|
build-standalone:
|
||||||
@ -247,7 +263,7 @@ workflows:
|
|||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only: [main, next-8-dev, next-8-rebased]
|
only: [main, next-8-dev, next-8-rebased]
|
||||||
- e2e-babel:
|
- e2e-babel-breaking:
|
||||||
requires:
|
requires:
|
||||||
- publish-verdaccio-babel-8-breaking
|
- publish-verdaccio-babel-8-breaking
|
||||||
- e2e-create-react-app:
|
- e2e-create-react-app:
|
||||||
@ -256,7 +272,7 @@ workflows:
|
|||||||
- e2e-vue-cli:
|
- e2e-vue-cli:
|
||||||
requires:
|
requires:
|
||||||
- publish-verdaccio-babel-8-breaking
|
- publish-verdaccio-babel-8-breaking
|
||||||
- e2e-jest:
|
- e2e-jest-breaking:
|
||||||
requires:
|
requires:
|
||||||
- publish-verdaccio-babel-8-breaking
|
- publish-verdaccio-babel-8-breaking
|
||||||
|
|
||||||
@ -270,7 +286,7 @@ workflows:
|
|||||||
- publish-verdaccio-babel-8-breaking:
|
- publish-verdaccio-babel-8-breaking:
|
||||||
requires:
|
requires:
|
||||||
- approve-e2e-breaking-run
|
- approve-e2e-breaking-run
|
||||||
- e2e-babel:
|
- e2e-babel-breaking:
|
||||||
requires:
|
requires:
|
||||||
- publish-verdaccio-babel-8-breaking
|
- publish-verdaccio-babel-8-breaking
|
||||||
- e2e-create-react-app:
|
- e2e-create-react-app:
|
||||||
@ -279,7 +295,7 @@ workflows:
|
|||||||
- e2e-vue-cli:
|
- e2e-vue-cli:
|
||||||
requires:
|
requires:
|
||||||
- publish-verdaccio-babel-8-breaking
|
- publish-verdaccio-babel-8-breaking
|
||||||
- e2e-jest:
|
- e2e-jest-breaking:
|
||||||
requires:
|
requires:
|
||||||
- publish-verdaccio-babel-8-breaking
|
- publish-verdaccio-babel-8-breaking
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
class C {
|
||||||
|
// Output should not use `_initialiseProps`
|
||||||
|
x: T;
|
||||||
|
y = 0;
|
||||||
|
constructor(T) {}
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"BABEL_8_BREAKING": false,
|
||||||
|
"plugins": ["transform-typescript", "proposal-class-properties"]
|
||||||
|
}
|
||||||
@ -1,8 +1,9 @@
|
|||||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||||
|
|
||||||
class A {
|
class C {
|
||||||
constructor() {
|
// Output should not use `_initialiseProps`
|
||||||
_defineProperty(this, "y", void 0);
|
constructor(T) {
|
||||||
|
_defineProperty(this, "y", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
class C {
|
||||||
|
// Output should not use `_initialiseProps`
|
||||||
|
x: T;
|
||||||
|
y = 0;
|
||||||
|
constructor(T) {}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"BABEL_8_BREAKING": false,
|
||||||
|
"plugins": [
|
||||||
|
"transform-typescript",
|
||||||
|
["proposal-class-properties", { "loose": true }]
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
class C {
|
||||||
|
// Output should not use `_initialiseProps`
|
||||||
|
constructor(T) {
|
||||||
|
this.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"BABEL_8_BREAKING": true,
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"transform-typescript",
|
"transform-typescript",
|
||||||
["proposal-class-properties", { "loose": true }]
|
["proposal-class-properties", { "loose": true }]
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
class C {
|
class C {
|
||||||
// Output should not use `_initialiseProps`
|
// Output should not use `_initialiseProps`
|
||||||
constructor(T) {
|
constructor(T) {
|
||||||
|
this.x = void 0;
|
||||||
this.y = 0;
|
this.y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
|
"BABEL_8_BREAKING": true,
|
||||||
"plugins": ["transform-typescript", "proposal-class-properties"]
|
"plugins": ["transform-typescript", "proposal-class-properties"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
|||||||
class C {
|
class C {
|
||||||
// Output should not use `_initialiseProps`
|
// Output should not use `_initialiseProps`
|
||||||
constructor(T) {
|
constructor(T) {
|
||||||
|
_defineProperty(this, "x", void 0);
|
||||||
|
|
||||||
_defineProperty(this, "y", 0);
|
_defineProperty(this, "y", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,52 +45,59 @@ function registerGlobalType(programScope, name) {
|
|||||||
GLOBAL_TYPES.get(programScope.path.node).add(name);
|
GLOBAL_TYPES.get(programScope.path.node).add(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default declare(
|
export default declare((api, opts) => {
|
||||||
(
|
api.assertVersion(7);
|
||||||
api,
|
|
||||||
{
|
|
||||||
jsxPragma = "React.createElement",
|
|
||||||
jsxPragmaFrag = "React.Fragment",
|
|
||||||
allowNamespaces = false,
|
|
||||||
allowDeclareFields = false,
|
|
||||||
onlyRemoveTypeImports = false,
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
api.assertVersion(7);
|
|
||||||
|
|
||||||
const JSX_PRAGMA_REGEX = /\*?\s*@jsx((?:Frag)?)\s+([^\s]+)/;
|
const JSX_PRAGMA_REGEX = /\*?\s*@jsx((?:Frag)?)\s+([^\s]+)/;
|
||||||
|
|
||||||
const classMemberVisitors = {
|
const {
|
||||||
field(path) {
|
jsxPragma = "React.createElement",
|
||||||
const { node } = path;
|
jsxPragmaFrag = "React.Fragment",
|
||||||
|
allowNamespaces = false,
|
||||||
|
onlyRemoveTypeImports = false,
|
||||||
|
} = opts;
|
||||||
|
|
||||||
|
if (!process.env.BABEL_8_BREAKING) {
|
||||||
|
// eslint-disable-next-line no-var
|
||||||
|
var { allowDeclareFields = false } = opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
const classMemberVisitors = {
|
||||||
|
field(path) {
|
||||||
|
const { node } = path;
|
||||||
|
|
||||||
|
if (!process.env.BABEL_8_BREAKING) {
|
||||||
if (!allowDeclareFields && node.declare) {
|
if (!allowDeclareFields && node.declare) {
|
||||||
throw path.buildCodeFrameError(
|
throw path.buildCodeFrameError(
|
||||||
`The 'declare' modifier is only allowed when the 'allowDeclareFields' option of ` +
|
`The 'declare' modifier is only allowed when the 'allowDeclareFields' option of ` +
|
||||||
`@babel/plugin-transform-typescript or @babel/preset-typescript is enabled.`,
|
`@babel/plugin-transform-typescript or @babel/preset-typescript is enabled.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (node.declare) {
|
}
|
||||||
if (node.value) {
|
if (node.declare) {
|
||||||
throw path.buildCodeFrameError(
|
if (node.value) {
|
||||||
`Fields with the 'declare' modifier cannot be initialized here, but only in the constructor`,
|
throw path.buildCodeFrameError(
|
||||||
);
|
`Fields with the 'declare' modifier cannot be initialized here, but only in the constructor`,
|
||||||
}
|
);
|
||||||
if (!node.decorators) {
|
}
|
||||||
path.remove();
|
if (!node.decorators) {
|
||||||
}
|
path.remove();
|
||||||
} else if (node.definite) {
|
}
|
||||||
if (node.value) {
|
} else if (node.definite) {
|
||||||
throw path.buildCodeFrameError(
|
if (node.value) {
|
||||||
`Definitely assigned fields cannot be initialized here, but only in the constructor`,
|
throw path.buildCodeFrameError(
|
||||||
);
|
`Definitely assigned fields cannot be initialized here, but only in the constructor`,
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
if (!process.env.BABEL_8_BREAKING) {
|
||||||
// keep the definitely assigned fields only when `allowDeclareFields` (equivalent of
|
// keep the definitely assigned fields only when `allowDeclareFields` (equivalent of
|
||||||
// Typescript's `useDefineForClassFields`) is true
|
// Typescript's `useDefineForClassFields`) is true
|
||||||
if (!allowDeclareFields && !node.decorators) {
|
if (!allowDeclareFields && !node.decorators) {
|
||||||
path.remove();
|
path.remove();
|
||||||
}
|
}
|
||||||
} else if (
|
}
|
||||||
|
} else if (!process.env.BABEL_8_BREAKING) {
|
||||||
|
if (
|
||||||
!allowDeclareFields &&
|
!allowDeclareFields &&
|
||||||
!node.value &&
|
!node.value &&
|
||||||
!node.decorators &&
|
!node.decorators &&
|
||||||
@ -98,405 +105,405 @@ export default declare(
|
|||||||
) {
|
) {
|
||||||
path.remove();
|
path.remove();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (node.accessibility) node.accessibility = null;
|
if (node.accessibility) node.accessibility = null;
|
||||||
if (node.abstract) node.abstract = null;
|
if (node.abstract) node.abstract = null;
|
||||||
if (node.readonly) node.readonly = null;
|
if (node.readonly) node.readonly = null;
|
||||||
if (node.optional) node.optional = null;
|
if (node.optional) node.optional = null;
|
||||||
if (node.typeAnnotation) node.typeAnnotation = null;
|
if (node.typeAnnotation) node.typeAnnotation = null;
|
||||||
if (node.definite) node.definite = null;
|
if (node.definite) node.definite = null;
|
||||||
if (node.declare) node.declare = null;
|
if (node.declare) node.declare = null;
|
||||||
},
|
},
|
||||||
method({ node }) {
|
method({ node }) {
|
||||||
if (node.accessibility) node.accessibility = null;
|
if (node.accessibility) node.accessibility = null;
|
||||||
if (node.abstract) node.abstract = null;
|
if (node.abstract) node.abstract = null;
|
||||||
if (node.optional) node.optional = null;
|
if (node.optional) node.optional = null;
|
||||||
|
|
||||||
// Rest handled by Function visitor
|
// Rest handled by Function visitor
|
||||||
},
|
},
|
||||||
constructor(path, classPath) {
|
constructor(path, classPath) {
|
||||||
if (path.node.accessibility) path.node.accessibility = null;
|
if (path.node.accessibility) path.node.accessibility = null;
|
||||||
// Collects parameter properties so that we can add an assignment
|
// Collects parameter properties so that we can add an assignment
|
||||||
// for each of them in the constructor body
|
// for each of them in the constructor body
|
||||||
//
|
//
|
||||||
// We use a WeakSet to ensure an assignment for a parameter
|
// We use a WeakSet to ensure an assignment for a parameter
|
||||||
// property is only added once. This is necessary for cases like
|
// property is only added once. This is necessary for cases like
|
||||||
// using `transform-classes`, which causes this visitor to run
|
// using `transform-classes`, which causes this visitor to run
|
||||||
// twice.
|
// twice.
|
||||||
const parameterProperties = [];
|
const parameterProperties = [];
|
||||||
for (const param of path.node.params) {
|
for (const param of path.node.params) {
|
||||||
if (
|
if (
|
||||||
param.type === "TSParameterProperty" &&
|
param.type === "TSParameterProperty" &&
|
||||||
!PARSED_PARAMS.has(param.parameter)
|
!PARSED_PARAMS.has(param.parameter)
|
||||||
) {
|
) {
|
||||||
PARSED_PARAMS.add(param.parameter);
|
PARSED_PARAMS.add(param.parameter);
|
||||||
parameterProperties.push(param.parameter);
|
parameterProperties.push(param.parameter);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (parameterProperties.length) {
|
if (parameterProperties.length) {
|
||||||
const assigns = parameterProperties.map(p => {
|
const assigns = parameterProperties.map(p => {
|
||||||
let id;
|
let id;
|
||||||
if (t.isIdentifier(p)) {
|
if (t.isIdentifier(p)) {
|
||||||
id = p;
|
id = p;
|
||||||
} else if (t.isAssignmentPattern(p) && t.isIdentifier(p.left)) {
|
} else if (t.isAssignmentPattern(p) && t.isIdentifier(p.left)) {
|
||||||
id = p.left;
|
id = p.left;
|
||||||
} else {
|
} else {
|
||||||
throw path.buildCodeFrameError(
|
throw path.buildCodeFrameError(
|
||||||
"Parameter properties can not be destructuring patterns.",
|
"Parameter properties can not be destructuring patterns.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return template.statement.ast`
|
return template.statement.ast`
|
||||||
this.${t.cloneNode(id)} = ${t.cloneNode(id)}`;
|
this.${t.cloneNode(id)} = ${t.cloneNode(id)}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
injectInitialization(classPath, path, assigns);
|
injectInitialization(classPath, path, assigns);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: "transform-typescript",
|
||||||
|
inherits: syntaxTypeScript,
|
||||||
|
|
||||||
|
visitor: {
|
||||||
|
//"Pattern" alias doesn't include Identifier or RestElement.
|
||||||
|
Pattern: visitPattern,
|
||||||
|
Identifier: visitPattern,
|
||||||
|
RestElement: visitPattern,
|
||||||
|
|
||||||
|
Program(path, state) {
|
||||||
|
const { file } = state;
|
||||||
|
let fileJsxPragma = null;
|
||||||
|
let fileJsxPragmaFrag = null;
|
||||||
|
|
||||||
|
if (!GLOBAL_TYPES.has(path.node)) {
|
||||||
|
GLOBAL_TYPES.set(path.node, new Set());
|
||||||
}
|
}
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
if (file.ast.comments) {
|
||||||
name: "transform-typescript",
|
for (const comment of (file.ast.comments: Array<Object>)) {
|
||||||
inherits: syntaxTypeScript,
|
const jsxMatches = JSX_PRAGMA_REGEX.exec(comment.value);
|
||||||
|
if (jsxMatches) {
|
||||||
visitor: {
|
if (jsxMatches[1]) {
|
||||||
//"Pattern" alias doesn't include Identifier or RestElement.
|
// isFragment
|
||||||
Pattern: visitPattern,
|
fileJsxPragmaFrag = jsxMatches[2];
|
||||||
Identifier: visitPattern,
|
} else {
|
||||||
RestElement: visitPattern,
|
fileJsxPragma = jsxMatches[2];
|
||||||
|
|
||||||
Program(path, state) {
|
|
||||||
const { file } = state;
|
|
||||||
let fileJsxPragma = null;
|
|
||||||
let fileJsxPragmaFrag = null;
|
|
||||||
|
|
||||||
if (!GLOBAL_TYPES.has(path.node)) {
|
|
||||||
GLOBAL_TYPES.set(path.node, new Set());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file.ast.comments) {
|
|
||||||
for (const comment of (file.ast.comments: Array<Object>)) {
|
|
||||||
const jsxMatches = JSX_PRAGMA_REGEX.exec(comment.value);
|
|
||||||
if (jsxMatches) {
|
|
||||||
if (jsxMatches[1]) {
|
|
||||||
// isFragment
|
|
||||||
fileJsxPragmaFrag = jsxMatches[2];
|
|
||||||
} else {
|
|
||||||
fileJsxPragma = jsxMatches[2];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let pragmaImportName = fileJsxPragma || jsxPragma;
|
let pragmaImportName = fileJsxPragma || jsxPragma;
|
||||||
if (pragmaImportName) {
|
if (pragmaImportName) {
|
||||||
[pragmaImportName] = pragmaImportName.split(".");
|
[pragmaImportName] = pragmaImportName.split(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
let pragmaFragImportName = fileJsxPragmaFrag || jsxPragmaFrag;
|
let pragmaFragImportName = fileJsxPragmaFrag || jsxPragmaFrag;
|
||||||
if (pragmaFragImportName) {
|
if (pragmaFragImportName) {
|
||||||
[pragmaFragImportName] = pragmaFragImportName.split(".");
|
[pragmaFragImportName] = pragmaFragImportName.split(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove type imports
|
|
||||||
for (let stmt of path.get("body")) {
|
|
||||||
if (t.isImportDeclaration(stmt)) {
|
|
||||||
if (stmt.node.importKind === "type") {
|
|
||||||
stmt.remove();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If onlyRemoveTypeImports is `true`, only remove type-only imports
|
|
||||||
// and exports introduced in TypeScript 3.8.
|
|
||||||
if (!onlyRemoveTypeImports) {
|
|
||||||
// Note: this will allow both `import { } from "m"` and `import "m";`.
|
|
||||||
// In TypeScript, the former would be elided.
|
|
||||||
if (stmt.node.specifiers.length === 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let allElided = true;
|
|
||||||
const importsToRemove: Path<Node>[] = [];
|
|
||||||
|
|
||||||
for (const specifier of stmt.node.specifiers) {
|
|
||||||
const binding = stmt.scope.getBinding(specifier.local.name);
|
|
||||||
|
|
||||||
// The binding may not exist if the import node was explicitly
|
|
||||||
// injected by another plugin. Currently core does not do a good job
|
|
||||||
// of keeping scope bindings synchronized with the AST. For now we
|
|
||||||
// just bail if there is no binding, since chances are good that if
|
|
||||||
// the import statement was injected then it wasn't a typescript type
|
|
||||||
// import anyway.
|
|
||||||
if (
|
|
||||||
binding &&
|
|
||||||
isImportTypeOnly({
|
|
||||||
binding,
|
|
||||||
programPath: path,
|
|
||||||
pragmaImportName,
|
|
||||||
pragmaFragImportName,
|
|
||||||
})
|
|
||||||
) {
|
|
||||||
importsToRemove.push(binding.path);
|
|
||||||
} else {
|
|
||||||
allElided = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allElided) {
|
|
||||||
stmt.remove();
|
|
||||||
} else {
|
|
||||||
for (const importPath of importsToRemove) {
|
|
||||||
importPath.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// remove type imports
|
||||||
|
for (let stmt of path.get("body")) {
|
||||||
|
if (t.isImportDeclaration(stmt)) {
|
||||||
|
if (stmt.node.importKind === "type") {
|
||||||
|
stmt.remove();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stmt.isExportDeclaration()) {
|
// If onlyRemoveTypeImports is `true`, only remove type-only imports
|
||||||
stmt = stmt.get("declaration");
|
// and exports introduced in TypeScript 3.8.
|
||||||
}
|
if (!onlyRemoveTypeImports) {
|
||||||
|
// Note: this will allow both `import { } from "m"` and `import "m";`.
|
||||||
if (stmt.isVariableDeclaration({ declare: true })) {
|
// In TypeScript, the former would be elided.
|
||||||
for (const name of Object.keys(stmt.getBindingIdentifiers())) {
|
if (stmt.node.specifiers.length === 0) {
|
||||||
registerGlobalType(path.scope, name);
|
continue;
|
||||||
}
|
}
|
||||||
} else if (
|
|
||||||
stmt.isTSTypeAliasDeclaration() ||
|
|
||||||
stmt.isTSDeclareFunction() ||
|
|
||||||
stmt.isTSInterfaceDeclaration() ||
|
|
||||||
stmt.isClassDeclaration({ declare: true }) ||
|
|
||||||
stmt.isTSEnumDeclaration({ declare: true }) ||
|
|
||||||
(stmt.isTSModuleDeclaration({ declare: true }) &&
|
|
||||||
stmt.get("id").isIdentifier())
|
|
||||||
) {
|
|
||||||
registerGlobalType(path.scope, stmt.node.id.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
ExportNamedDeclaration(path) {
|
let allElided = true;
|
||||||
if (path.node.exportKind === "type") {
|
const importsToRemove: Path<Node>[] = [];
|
||||||
path.remove();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove export declaration if it's exporting only types
|
for (const specifier of stmt.node.specifiers) {
|
||||||
// This logic is needed when exportKind is "value", because
|
const binding = stmt.scope.getBinding(specifier.local.name);
|
||||||
// currently the "type" keyword is optional.
|
|
||||||
// TODO:
|
|
||||||
// Also, currently @babel/parser sets exportKind to "value" for
|
|
||||||
// export interface A {}
|
|
||||||
// etc.
|
|
||||||
if (
|
|
||||||
!path.node.source &&
|
|
||||||
path.node.specifiers.length > 0 &&
|
|
||||||
path.node.specifiers.every(({ local }) =>
|
|
||||||
isGlobalType(path, local.name),
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
path.remove();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
ExportSpecifier(path) {
|
// The binding may not exist if the import node was explicitly
|
||||||
// remove type exports
|
// injected by another plugin. Currently core does not do a good job
|
||||||
if (!path.parent.source && isGlobalType(path, path.node.local.name)) {
|
// of keeping scope bindings synchronized with the AST. For now we
|
||||||
path.remove();
|
// just bail if there is no binding, since chances are good that if
|
||||||
}
|
// the import statement was injected then it wasn't a typescript type
|
||||||
},
|
// import anyway.
|
||||||
|
if (
|
||||||
|
binding &&
|
||||||
|
isImportTypeOnly({
|
||||||
|
binding,
|
||||||
|
programPath: path,
|
||||||
|
pragmaImportName,
|
||||||
|
pragmaFragImportName,
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
importsToRemove.push(binding.path);
|
||||||
|
} else {
|
||||||
|
allElided = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ExportDefaultDeclaration(path) {
|
if (allElided) {
|
||||||
// remove whole declaration if it's exporting a TS type
|
stmt.remove();
|
||||||
if (
|
|
||||||
t.isIdentifier(path.node.declaration) &&
|
|
||||||
isGlobalType(path, path.node.declaration.name)
|
|
||||||
) {
|
|
||||||
path.remove();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
TSDeclareFunction(path) {
|
|
||||||
path.remove();
|
|
||||||
},
|
|
||||||
|
|
||||||
TSDeclareMethod(path) {
|
|
||||||
path.remove();
|
|
||||||
},
|
|
||||||
|
|
||||||
VariableDeclaration(path) {
|
|
||||||
if (path.node.declare) {
|
|
||||||
path.remove();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
VariableDeclarator({ node }) {
|
|
||||||
if (node.definite) node.definite = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
TSIndexSignature(path) {
|
|
||||||
path.remove();
|
|
||||||
},
|
|
||||||
|
|
||||||
ClassDeclaration(path) {
|
|
||||||
const { node } = path;
|
|
||||||
if (node.declare) {
|
|
||||||
path.remove();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Class(path) {
|
|
||||||
const { node } = path;
|
|
||||||
|
|
||||||
if (node.typeParameters) node.typeParameters = null;
|
|
||||||
if (node.superTypeParameters) node.superTypeParameters = null;
|
|
||||||
if (node.implements) node.implements = null;
|
|
||||||
if (node.abstract) node.abstract = null;
|
|
||||||
|
|
||||||
// Similar to the logic in `transform-flow-strip-types`, we need to
|
|
||||||
// handle `TSParameterProperty` and `ClassProperty` here because the
|
|
||||||
// class transform would transform the class, causing more specific
|
|
||||||
// visitors to not run.
|
|
||||||
path.get("body.body").forEach(child => {
|
|
||||||
if (child.isClassMethod() || child.isClassPrivateMethod()) {
|
|
||||||
if (child.node.kind === "constructor") {
|
|
||||||
classMemberVisitors.constructor(child, path);
|
|
||||||
} else {
|
} else {
|
||||||
classMemberVisitors.method(child, path);
|
for (const importPath of importsToRemove) {
|
||||||
|
importPath.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (
|
|
||||||
child.isClassProperty() ||
|
|
||||||
child.isClassPrivateProperty()
|
|
||||||
) {
|
|
||||||
classMemberVisitors.field(child, path);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
Function({ node }) {
|
continue;
|
||||||
if (node.typeParameters) node.typeParameters = null;
|
|
||||||
if (node.returnType) node.returnType = null;
|
|
||||||
|
|
||||||
const p0 = node.params[0];
|
|
||||||
if (p0 && t.isIdentifier(p0) && p0.name === "this") {
|
|
||||||
node.params.shift();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We replace `TSParameterProperty` here so that transforms that
|
if (stmt.isExportDeclaration()) {
|
||||||
// rely on a `Function` visitor to deal with arguments, like
|
stmt = stmt.get("declaration");
|
||||||
// `transform-parameters`, work properly.
|
}
|
||||||
node.params = node.params.map(p => {
|
|
||||||
return p.type === "TSParameterProperty" ? p.parameter : p;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
TSModuleDeclaration(path) {
|
if (stmt.isVariableDeclaration({ declare: true })) {
|
||||||
transpileNamespace(path, t, allowNamespaces);
|
for (const name of Object.keys(stmt.getBindingIdentifiers())) {
|
||||||
},
|
registerGlobalType(path.scope, name);
|
||||||
|
}
|
||||||
TSInterfaceDeclaration(path) {
|
} else if (
|
||||||
path.remove();
|
stmt.isTSTypeAliasDeclaration() ||
|
||||||
},
|
stmt.isTSDeclareFunction() ||
|
||||||
|
stmt.isTSInterfaceDeclaration() ||
|
||||||
TSTypeAliasDeclaration(path) {
|
stmt.isClassDeclaration({ declare: true }) ||
|
||||||
path.remove();
|
stmt.isTSEnumDeclaration({ declare: true }) ||
|
||||||
},
|
(stmt.isTSModuleDeclaration({ declare: true }) &&
|
||||||
|
stmt.get("id").isIdentifier())
|
||||||
TSEnumDeclaration(path) {
|
) {
|
||||||
transpileEnum(path, t);
|
registerGlobalType(path.scope, stmt.node.id.name);
|
||||||
},
|
}
|
||||||
|
|
||||||
TSImportEqualsDeclaration(path) {
|
|
||||||
throw path.buildCodeFrameError(
|
|
||||||
"`import =` is not supported by @babel/plugin-transform-typescript\n" +
|
|
||||||
"Please consider using " +
|
|
||||||
"`import <moduleName> from '<moduleName>';` alongside " +
|
|
||||||
"Typescript's --allowSyntheticDefaultImports option.",
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
TSExportAssignment(path) {
|
|
||||||
throw path.buildCodeFrameError(
|
|
||||||
"`export =` is not supported by @babel/plugin-transform-typescript\n" +
|
|
||||||
"Please consider using `export <value>;`.",
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
TSTypeAssertion(path) {
|
|
||||||
path.replaceWith(path.node.expression);
|
|
||||||
},
|
|
||||||
|
|
||||||
TSAsExpression(path) {
|
|
||||||
let { node } = path;
|
|
||||||
do {
|
|
||||||
node = node.expression;
|
|
||||||
} while (t.isTSAsExpression(node));
|
|
||||||
path.replaceWith(node);
|
|
||||||
},
|
|
||||||
|
|
||||||
TSNonNullExpression(path) {
|
|
||||||
path.replaceWith(path.node.expression);
|
|
||||||
},
|
|
||||||
|
|
||||||
CallExpression(path) {
|
|
||||||
path.node.typeParameters = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
OptionalCallExpression(path) {
|
|
||||||
path.node.typeParameters = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
NewExpression(path) {
|
|
||||||
path.node.typeParameters = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
JSXOpeningElement(path) {
|
|
||||||
path.node.typeParameters = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
TaggedTemplateExpression(path) {
|
|
||||||
path.node.typeParameters = null;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
function visitPattern({ node }) {
|
|
||||||
if (node.typeAnnotation) node.typeAnnotation = null;
|
|
||||||
if (t.isIdentifier(node) && node.optional) node.optional = null;
|
|
||||||
// 'access' and 'readonly' are only for parameter properties, so constructor visitor will handle them.
|
|
||||||
}
|
|
||||||
|
|
||||||
function isImportTypeOnly({
|
|
||||||
binding,
|
|
||||||
programPath,
|
|
||||||
pragmaImportName,
|
|
||||||
pragmaFragImportName,
|
|
||||||
}) {
|
|
||||||
for (const path of binding.referencePaths) {
|
|
||||||
if (!isInType(path)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
if (
|
ExportNamedDeclaration(path) {
|
||||||
binding.identifier.name !== pragmaImportName &&
|
if (path.node.exportKind === "type") {
|
||||||
binding.identifier.name !== pragmaFragImportName
|
path.remove();
|
||||||
) {
|
return;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// "React" or the JSX pragma is referenced as a value if there are any JSX elements/fragments in the code.
|
// remove export declaration if it's exporting only types
|
||||||
let sourceFileHasJsx = false;
|
// This logic is needed when exportKind is "value", because
|
||||||
programPath.traverse({
|
// currently the "type" keyword is optional.
|
||||||
"JSXElement|JSXFragment"(path) {
|
// TODO:
|
||||||
sourceFileHasJsx = true;
|
// Also, currently @babel/parser sets exportKind to "value" for
|
||||||
path.stop();
|
// export interface A {}
|
||||||
},
|
// etc.
|
||||||
});
|
if (
|
||||||
return !sourceFileHasJsx;
|
!path.node.source &&
|
||||||
|
path.node.specifiers.length > 0 &&
|
||||||
|
path.node.specifiers.every(({ local }) =>
|
||||||
|
isGlobalType(path, local.name),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
path.remove();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ExportSpecifier(path) {
|
||||||
|
// remove type exports
|
||||||
|
if (!path.parent.source && isGlobalType(path, path.node.local.name)) {
|
||||||
|
path.remove();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ExportDefaultDeclaration(path) {
|
||||||
|
// remove whole declaration if it's exporting a TS type
|
||||||
|
if (
|
||||||
|
t.isIdentifier(path.node.declaration) &&
|
||||||
|
isGlobalType(path, path.node.declaration.name)
|
||||||
|
) {
|
||||||
|
path.remove();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
TSDeclareFunction(path) {
|
||||||
|
path.remove();
|
||||||
|
},
|
||||||
|
|
||||||
|
TSDeclareMethod(path) {
|
||||||
|
path.remove();
|
||||||
|
},
|
||||||
|
|
||||||
|
VariableDeclaration(path) {
|
||||||
|
if (path.node.declare) {
|
||||||
|
path.remove();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
VariableDeclarator({ node }) {
|
||||||
|
if (node.definite) node.definite = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
TSIndexSignature(path) {
|
||||||
|
path.remove();
|
||||||
|
},
|
||||||
|
|
||||||
|
ClassDeclaration(path) {
|
||||||
|
const { node } = path;
|
||||||
|
if (node.declare) {
|
||||||
|
path.remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Class(path) {
|
||||||
|
const { node } = path;
|
||||||
|
|
||||||
|
if (node.typeParameters) node.typeParameters = null;
|
||||||
|
if (node.superTypeParameters) node.superTypeParameters = null;
|
||||||
|
if (node.implements) node.implements = null;
|
||||||
|
if (node.abstract) node.abstract = null;
|
||||||
|
|
||||||
|
// Similar to the logic in `transform-flow-strip-types`, we need to
|
||||||
|
// handle `TSParameterProperty` and `ClassProperty` here because the
|
||||||
|
// class transform would transform the class, causing more specific
|
||||||
|
// visitors to not run.
|
||||||
|
path.get("body.body").forEach(child => {
|
||||||
|
if (child.isClassMethod() || child.isClassPrivateMethod()) {
|
||||||
|
if (child.node.kind === "constructor") {
|
||||||
|
classMemberVisitors.constructor(child, path);
|
||||||
|
} else {
|
||||||
|
classMemberVisitors.method(child, path);
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
child.isClassProperty() ||
|
||||||
|
child.isClassPrivateProperty()
|
||||||
|
) {
|
||||||
|
classMemberVisitors.field(child, path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
Function({ node }) {
|
||||||
|
if (node.typeParameters) node.typeParameters = null;
|
||||||
|
if (node.returnType) node.returnType = null;
|
||||||
|
|
||||||
|
const p0 = node.params[0];
|
||||||
|
if (p0 && t.isIdentifier(p0) && p0.name === "this") {
|
||||||
|
node.params.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We replace `TSParameterProperty` here so that transforms that
|
||||||
|
// rely on a `Function` visitor to deal with arguments, like
|
||||||
|
// `transform-parameters`, work properly.
|
||||||
|
node.params = node.params.map(p => {
|
||||||
|
return p.type === "TSParameterProperty" ? p.parameter : p;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
TSModuleDeclaration(path) {
|
||||||
|
transpileNamespace(path, t, allowNamespaces);
|
||||||
|
},
|
||||||
|
|
||||||
|
TSInterfaceDeclaration(path) {
|
||||||
|
path.remove();
|
||||||
|
},
|
||||||
|
|
||||||
|
TSTypeAliasDeclaration(path) {
|
||||||
|
path.remove();
|
||||||
|
},
|
||||||
|
|
||||||
|
TSEnumDeclaration(path) {
|
||||||
|
transpileEnum(path, t);
|
||||||
|
},
|
||||||
|
|
||||||
|
TSImportEqualsDeclaration(path) {
|
||||||
|
throw path.buildCodeFrameError(
|
||||||
|
"`import =` is not supported by @babel/plugin-transform-typescript\n" +
|
||||||
|
"Please consider using " +
|
||||||
|
"`import <moduleName> from '<moduleName>';` alongside " +
|
||||||
|
"Typescript's --allowSyntheticDefaultImports option.",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
TSExportAssignment(path) {
|
||||||
|
throw path.buildCodeFrameError(
|
||||||
|
"`export =` is not supported by @babel/plugin-transform-typescript\n" +
|
||||||
|
"Please consider using `export <value>;`.",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
TSTypeAssertion(path) {
|
||||||
|
path.replaceWith(path.node.expression);
|
||||||
|
},
|
||||||
|
|
||||||
|
TSAsExpression(path) {
|
||||||
|
let { node } = path;
|
||||||
|
do {
|
||||||
|
node = node.expression;
|
||||||
|
} while (t.isTSAsExpression(node));
|
||||||
|
path.replaceWith(node);
|
||||||
|
},
|
||||||
|
|
||||||
|
TSNonNullExpression(path) {
|
||||||
|
path.replaceWith(path.node.expression);
|
||||||
|
},
|
||||||
|
|
||||||
|
CallExpression(path) {
|
||||||
|
path.node.typeParameters = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
OptionalCallExpression(path) {
|
||||||
|
path.node.typeParameters = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
NewExpression(path) {
|
||||||
|
path.node.typeParameters = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
JSXOpeningElement(path) {
|
||||||
|
path.node.typeParameters = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
TaggedTemplateExpression(path) {
|
||||||
|
path.node.typeParameters = null;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function visitPattern({ node }) {
|
||||||
|
if (node.typeAnnotation) node.typeAnnotation = null;
|
||||||
|
if (t.isIdentifier(node) && node.optional) node.optional = null;
|
||||||
|
// 'access' and 'readonly' are only for parameter properties, so constructor visitor will handle them.
|
||||||
|
}
|
||||||
|
|
||||||
|
function isImportTypeOnly({
|
||||||
|
binding,
|
||||||
|
programPath,
|
||||||
|
pragmaImportName,
|
||||||
|
pragmaFragImportName,
|
||||||
|
}) {
|
||||||
|
for (const path of binding.referencePaths) {
|
||||||
|
if (!isInType(path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
);
|
if (
|
||||||
|
binding.identifier.name !== pragmaImportName &&
|
||||||
|
binding.identifier.name !== pragmaFragImportName
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "React" or the JSX pragma is referenced as a value if there are any JSX elements/fragments in the code.
|
||||||
|
let sourceFileHasJsx = false;
|
||||||
|
programPath.traverse({
|
||||||
|
"JSXElement|JSXFragment"(path) {
|
||||||
|
sourceFileHasJsx = true;
|
||||||
|
path.stop();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return !sourceFileHasJsx;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
4
packages/babel-plugin-transform-typescript/test/fixtures/class/declare-babel-7/input.ts
vendored
Normal file
4
packages/babel-plugin-transform-typescript/test/fixtures/class/declare-babel-7/input.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
class A {
|
||||||
|
declare x;
|
||||||
|
@foo declare y: string;
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
"BABEL_8_BREAKING": false,
|
||||||
"plugins": [
|
"plugins": [
|
||||||
["transform-typescript", { "allowDeclareFields": true }],
|
["transform-typescript", { "allowDeclareFields": true }],
|
||||||
"proposal-class-properties"
|
["syntax-decorators", { "legacy": true }]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
class A {
|
class A {
|
||||||
declare x;
|
@foo
|
||||||
y;
|
y;
|
||||||
}
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"BABEL_8_BREAKING": false,
|
||||||
"plugins": ["transform-typescript"],
|
"plugins": ["transform-typescript"],
|
||||||
"throws": "The 'declare' modifier is only allowed when the 'allowDeclareFields' option of @babel/plugin-transform-typescript or @babel/preset-typescript is enabled."
|
"throws": "The 'declare' modifier is only allowed when the 'allowDeclareFields' option of @babel/plugin-transform-typescript or @babel/preset-typescript is enabled."
|
||||||
}
|
}
|
||||||
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"plugins": [["transform-typescript", { "allowDeclareFields": true }]]
|
|
||||||
}
|
|
||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
"BABEL_8_BREAKING": true,
|
||||||
"plugins": [
|
"plugins": [
|
||||||
["transform-typescript", { "allowDeclareFields": true }],
|
"transform-typescript",
|
||||||
["syntax-decorators", { "legacy": true }]
|
["syntax-decorators", { "legacy": true }]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"BABEL_8_BREAKING": false,
|
||||||
|
"plugins": ["transform-typescript"]
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
x;
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"BABEL_8_BREAKING": true,
|
||||||
|
"plugins": ["transform-typescript"]
|
||||||
|
}
|
||||||
11
packages/babel-plugin-transform-typescript/test/fixtures/class/properties-babel-7/input.ts
vendored
Normal file
11
packages/babel-plugin-transform-typescript/test/fixtures/class/properties-babel-7/input.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class C {
|
||||||
|
public a?: number;
|
||||||
|
private b: number = 0;
|
||||||
|
readonly c: number = 1;
|
||||||
|
@foo d: number;
|
||||||
|
@foo e: number = 3;
|
||||||
|
f!: number;
|
||||||
|
@foo g!: number;
|
||||||
|
#h: string;
|
||||||
|
#i: number = 10;
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"BABEL_8_BREAKING": false,
|
||||||
|
"plugins": [
|
||||||
|
"transform-typescript",
|
||||||
|
["syntax-decorators", { "legacy": true }],
|
||||||
|
"syntax-class-properties"
|
||||||
|
]
|
||||||
|
}
|
||||||
12
packages/babel-plugin-transform-typescript/test/fixtures/class/properties-babel-7/output.js
vendored
Normal file
12
packages/babel-plugin-transform-typescript/test/fixtures/class/properties-babel-7/output.js
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
class C {
|
||||||
|
b = 0;
|
||||||
|
c = 1;
|
||||||
|
@foo
|
||||||
|
d;
|
||||||
|
@foo
|
||||||
|
e = 3;
|
||||||
|
@foo
|
||||||
|
g;
|
||||||
|
#h;
|
||||||
|
#i = 10;
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"BABEL_8_BREAKING": true,
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"transform-typescript",
|
"transform-typescript",
|
||||||
["syntax-decorators", { "legacy": true }],
|
["syntax-decorators", { "legacy": true }],
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
class C {
|
class C {
|
||||||
|
a;
|
||||||
b = 0;
|
b = 0;
|
||||||
c = 1;
|
c = 1;
|
||||||
@foo
|
@foo
|
||||||
d;
|
d;
|
||||||
@foo
|
@foo
|
||||||
e = 3;
|
e = 3;
|
||||||
|
f;
|
||||||
@foo
|
@foo
|
||||||
g;
|
g;
|
||||||
#h;
|
#h;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"proposal-class-properties",
|
"proposal-class-properties",
|
||||||
["transform-typescript", { "allowDeclareFields": true }]
|
"transform-typescript"
|
||||||
],
|
],
|
||||||
"throws": "TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript.\nIf you have already enabled that plugin (or '@babel/preset-typescript'), make sure that it runs before any plugin related to additional class features:\n - @babel/plugin-proposal-class-properties\n - @babel/plugin-proposal-private-methods\n - @babel/plugin-proposal-decorators"
|
"throws": "TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript.\nIf you have already enabled that plugin (or '@babel/preset-typescript'), make sure that it runs before any plugin related to additional class features:\n - @babel/plugin-proposal-class-properties\n - @babel/plugin-proposal-private-methods\n - @babel/plugin-proposal-decorators"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
|
"BABEL_8_BREAKING": false,
|
||||||
"plugins": [["transform-typescript", { "allowDeclareFields": true }]]
|
"plugins": [["transform-typescript", { "allowDeclareFields": true }]]
|
||||||
}
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
|
"BABEL_8_BREAKING": false,
|
||||||
"plugins": [["transform-typescript", { "allowDeclareFields": false }]]
|
"plugins": [["transform-typescript", { "allowDeclareFields": false }]]
|
||||||
}
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
class A {}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
x!;
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"BABEL_8_BREAKING": true,
|
||||||
|
"plugins": ["transform-typescript"]
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
x;
|
||||||
|
}
|
||||||
@ -1,12 +1,12 @@
|
|||||||
export module src {
|
export module src {
|
||||||
export namespace ns1 {
|
export namespace ns1 {
|
||||||
export class foo {
|
export class foo {
|
||||||
F1: string;
|
F1: string = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export namespace ns2 {
|
export namespace ns2 {
|
||||||
export class foo {
|
export class foo {
|
||||||
F1: string;
|
F1: string = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,9 @@ export let src;
|
|||||||
let ns1;
|
let ns1;
|
||||||
|
|
||||||
(function (_ns) {
|
(function (_ns) {
|
||||||
class foo {}
|
class foo {
|
||||||
|
F1 = "";
|
||||||
|
}
|
||||||
|
|
||||||
_ns.foo = foo;
|
_ns.foo = foo;
|
||||||
})(ns1 || (ns1 = _src.ns1 || (_src.ns1 = {})));
|
})(ns1 || (ns1 = _src.ns1 || (_src.ns1 = {})));
|
||||||
@ -12,7 +14,9 @@ export let src;
|
|||||||
let ns2;
|
let ns2;
|
||||||
|
|
||||||
(function (_ns2) {
|
(function (_ns2) {
|
||||||
class foo {}
|
class foo {
|
||||||
|
F1 = "";
|
||||||
|
}
|
||||||
|
|
||||||
_ns2.foo = foo;
|
_ns2.foo = foo;
|
||||||
})(ns2 || (ns2 = _src.ns2 || (_src.ns2 = {})));
|
})(ns2 || (ns2 = _src.ns2 || (_src.ns2 = {})));
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
module src {
|
module src {
|
||||||
export namespace ns1 {
|
export namespace ns1 {
|
||||||
export class foo {
|
export class foo {
|
||||||
F1: string;
|
F1: string = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export namespace ns2 {
|
export namespace ns2 {
|
||||||
export class foo {
|
export class foo {
|
||||||
F1: string;
|
F1: string = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,9 @@ let src;
|
|||||||
let ns1;
|
let ns1;
|
||||||
|
|
||||||
(function (_ns) {
|
(function (_ns) {
|
||||||
class foo {}
|
class foo {
|
||||||
|
F1 = "";
|
||||||
|
}
|
||||||
|
|
||||||
_ns.foo = foo;
|
_ns.foo = foo;
|
||||||
})(ns1 || (ns1 = _src.ns1 || (_src.ns1 = {})));
|
})(ns1 || (ns1 = _src.ns1 || (_src.ns1 = {})));
|
||||||
@ -12,7 +14,9 @@ let src;
|
|||||||
let ns2;
|
let ns2;
|
||||||
|
|
||||||
(function (_ns2) {
|
(function (_ns2) {
|
||||||
class foo {}
|
class foo {
|
||||||
|
F1 = "";
|
||||||
|
}
|
||||||
|
|
||||||
_ns2.foo = foo;
|
_ns2.foo = foo;
|
||||||
})(ns2 || (ns2 = _src.ns2 || (_src.ns2 = {})));
|
})(ns2 || (ns2 = _src.ns2 || (_src.ns2 = {})));
|
||||||
|
|||||||
@ -7,7 +7,6 @@ export default declare((api, opts) => {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
allExtensions,
|
allExtensions,
|
||||||
allowDeclareFields,
|
|
||||||
allowNamespaces,
|
allowNamespaces,
|
||||||
isTSX,
|
isTSX,
|
||||||
jsxPragma,
|
jsxPragma,
|
||||||
@ -15,14 +14,22 @@ export default declare((api, opts) => {
|
|||||||
onlyRemoveTypeImports,
|
onlyRemoveTypeImports,
|
||||||
} = normalizeOptions(opts);
|
} = normalizeOptions(opts);
|
||||||
|
|
||||||
const pluginOptions = isTSX => ({
|
const pluginOptions = process.env.BABEL_8_BREAKING
|
||||||
allowDeclareFields,
|
? isTSX => ({
|
||||||
allowNamespaces,
|
allowNamespaces,
|
||||||
isTSX,
|
isTSX,
|
||||||
jsxPragma,
|
jsxPragma,
|
||||||
jsxPragmaFrag,
|
jsxPragmaFrag,
|
||||||
onlyRemoveTypeImports,
|
onlyRemoveTypeImports,
|
||||||
});
|
})
|
||||||
|
: isTSX => ({
|
||||||
|
allowDeclareFields: opts.allowDeclareFields,
|
||||||
|
allowNamespaces,
|
||||||
|
isTSX,
|
||||||
|
jsxPragma,
|
||||||
|
jsxPragmaFrag,
|
||||||
|
onlyRemoveTypeImports,
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
overrides: allExtensions
|
overrides: allExtensions
|
||||||
|
|||||||
@ -2,16 +2,10 @@ import { OptionValidator } from "@babel/helper-validator-option";
|
|||||||
const v = new OptionValidator("@babel/preset-typescript");
|
const v = new OptionValidator("@babel/preset-typescript");
|
||||||
|
|
||||||
export default function normalizeOptions(options = {}) {
|
export default function normalizeOptions(options = {}) {
|
||||||
let {
|
let { allowNamespaces, jsxPragma, onlyRemoveTypeImports } = options;
|
||||||
allowDeclareFields,
|
|
||||||
allowNamespaces,
|
|
||||||
jsxPragma,
|
|
||||||
onlyRemoveTypeImports,
|
|
||||||
} = options;
|
|
||||||
|
|
||||||
if (process.env.BABEL_8_BREAKING) {
|
if (process.env.BABEL_8_BREAKING) {
|
||||||
const TopLevelOptions = {
|
const TopLevelOptions = {
|
||||||
allowDeclareFields: "allowDeclareFields",
|
|
||||||
allExtensions: "allExtensions",
|
allExtensions: "allExtensions",
|
||||||
allowNamespaces: "allowNamespaces",
|
allowNamespaces: "allowNamespaces",
|
||||||
isTSX: "isTSX",
|
isTSX: "isTSX",
|
||||||
@ -20,11 +14,6 @@ export default function normalizeOptions(options = {}) {
|
|||||||
onlyRemoveTypeImports: "onlyRemoveTypeImports",
|
onlyRemoveTypeImports: "onlyRemoveTypeImports",
|
||||||
};
|
};
|
||||||
v.validateTopLevelOptions(options, TopLevelOptions);
|
v.validateTopLevelOptions(options, TopLevelOptions);
|
||||||
allowDeclareFields = v.validateBooleanOption(
|
|
||||||
TopLevelOptions.allowDeclareFields,
|
|
||||||
options.allowDeclareFields,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
allowNamespaces = v.validateBooleanOption(
|
allowNamespaces = v.validateBooleanOption(
|
||||||
TopLevelOptions.allowNamespaces,
|
TopLevelOptions.allowNamespaces,
|
||||||
options.allowNamespaces,
|
options.allowNamespaces,
|
||||||
@ -62,7 +51,6 @@ export default function normalizeOptions(options = {}) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
allExtensions,
|
allExtensions,
|
||||||
allowDeclareFields,
|
|
||||||
allowNamespaces,
|
allowNamespaces,
|
||||||
isTSX,
|
isTSX,
|
||||||
jsxPragma,
|
jsxPragma,
|
||||||
|
|||||||
@ -7,7 +7,6 @@ describe("normalize options", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
it.each([
|
it.each([
|
||||||
"allowDeclareFields",
|
|
||||||
"allExtensions",
|
"allExtensions",
|
||||||
"allowNamespaces",
|
"allowNamespaces",
|
||||||
"isTSX",
|
"isTSX",
|
||||||
@ -32,7 +31,6 @@ describe("normalize options", () => {
|
|||||||
expect(normalizeOptions({})).toMatchInlineSnapshot(`
|
expect(normalizeOptions({})).toMatchInlineSnapshot(`
|
||||||
Object {
|
Object {
|
||||||
"allExtensions": false,
|
"allExtensions": false,
|
||||||
"allowDeclareFields": true,
|
|
||||||
"allowNamespaces": true,
|
"allowNamespaces": true,
|
||||||
"isTSX": false,
|
"isTSX": false,
|
||||||
"jsxPragma": "React",
|
"jsxPragma": "React",
|
||||||
@ -80,7 +78,6 @@ describe("normalize options", () => {
|
|||||||
expect(normalizeOptions({})).toMatchInlineSnapshot(`
|
expect(normalizeOptions({})).toMatchInlineSnapshot(`
|
||||||
Object {
|
Object {
|
||||||
"allExtensions": false,
|
"allExtensions": false,
|
||||||
"allowDeclareFields": undefined,
|
|
||||||
"allowNamespaces": undefined,
|
"allowNamespaces": undefined,
|
||||||
"isTSX": false,
|
"isTSX": false,
|
||||||
"jsxPragma": undefined,
|
"jsxPragma": undefined,
|
||||||
|
|||||||
@ -20,6 +20,11 @@ cd ../..
|
|||||||
# TEST #
|
# TEST #
|
||||||
#==============================================================================#
|
#==============================================================================#
|
||||||
|
|
||||||
|
if [ "$BABEL_8_BREAKING" = true ] ; then
|
||||||
|
# This option is removed in Babel 8
|
||||||
|
sed -i 's/allowDeclareFields: true,\?/\/* allowDeclareFields: true *\//g' babel.config.js
|
||||||
|
fi
|
||||||
|
|
||||||
startLocalRegistry "$PWD"/scripts/integration-tests/verdaccio-config.yml
|
startLocalRegistry "$PWD"/scripts/integration-tests/verdaccio-config.yml
|
||||||
# We only bump dependencies in the top-level package.json, because workspaces
|
# We only bump dependencies in the top-level package.json, because workspaces
|
||||||
# already use the workspace: protocol so will get the version in the monorepo
|
# already use the workspace: protocol so will get the version in the monorepo
|
||||||
|
|||||||
@ -37,11 +37,6 @@ python --version
|
|||||||
# TEST #
|
# TEST #
|
||||||
#==============================================================================#
|
#==============================================================================#
|
||||||
|
|
||||||
startLocalRegistry "$root"/verdaccio-config.yml
|
|
||||||
yarn install
|
|
||||||
yarn dedupe '@babel/*'
|
|
||||||
yarn build
|
|
||||||
|
|
||||||
# Workaround for https://github.com/babel/babel/pull/12567
|
# Workaround for https://github.com/babel/babel/pull/12567
|
||||||
node -e '
|
node -e '
|
||||||
let snapshots = fs.readFileSync("packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap", "utf8");
|
let snapshots = fs.readFileSync("packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap", "utf8");
|
||||||
@ -49,6 +44,16 @@ node -e '
|
|||||||
fs.writeFileSync("packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap", snapshots);
|
fs.writeFileSync("packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap", snapshots);
|
||||||
'
|
'
|
||||||
|
|
||||||
|
if [ "$BABEL_8_BREAKING" = true ] ; then
|
||||||
|
# This option is removed in Babel 8
|
||||||
|
sed -i 's/allowDeclareFields: true,\?/\/* allowDeclareFields: true *\//g' babel.config.js
|
||||||
|
fi
|
||||||
|
|
||||||
|
startLocalRegistry "$root"/verdaccio-config.yml
|
||||||
|
yarn install
|
||||||
|
yarn dedupe '@babel/*'
|
||||||
|
yarn build
|
||||||
|
|
||||||
# The full test suite takes about 20mins on CircleCI. We run only a few of them
|
# The full test suite takes about 20mins on CircleCI. We run only a few of them
|
||||||
# to speed it up.
|
# to speed it up.
|
||||||
# The goals of this e2e test are:
|
# The goals of this e2e test are:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user