diff --git a/packages/babel-core/src/config/validation/options.js b/packages/babel-core/src/config/validation/options.js index c5e99846b974..6289286e8ed5 100644 --- a/packages/babel-core/src/config/validation/options.js +++ b/packages/babel-core/src/config/validation/options.js @@ -332,8 +332,26 @@ type EnvPath = $ReadOnly<{ export type NestingPath = RootPath | OverridesPath | EnvPath; export const assumptionsNames = new Set([ + "arrayLikeIsIterable", + "constantReexports", + "constantSuper", + "enumerableModuleMeta", + "ignoreFunctionLength", + "ignoreToPrimitiveHint", + "iterableIsArray", "mutableTemplateObject", + "noClassCalls", + "noDocumentAll", + "noNewArrows", + "objectRestNoSymbols", + "privateFieldsAsProperties", + "pureGetters", + "setClassMethods", + "setComputedProperties", "setPublicClassFields", + "setSpreadProperties", + "skipForOfIteratorClosing", + "superIsCallableConstructor", ]); function getSource(loc: NestingPath): OptionsSource { diff --git a/packages/babel-helper-create-class-features-plugin/src/fields.js b/packages/babel-helper-create-class-features-plugin/src/fields.js index 438335e5b9e5..4f1ff24d4b9f 100644 --- a/packages/babel-helper-create-class-features-plugin/src/fields.js +++ b/packages/babel-helper-create-class-features-plugin/src/fields.js @@ -35,11 +35,16 @@ export function buildPrivateNamesMap(props) { return privateNamesMap; } -export function buildPrivateNamesNodes(privateNamesMap, loose, state) { +export function buildPrivateNamesNodes( + privateNamesMap, + privateFieldsAsProperties, + state, +) { const initNodes = []; for (const [name, value] of privateNamesMap) { - // In loose mode, both static and instance fields are transpiled using a + // When the privateFieldsAsProperties assumption is enabled, + // both static and instance fields are transpiled using a // secret non-enumerable property. Hence, we also need to generate that // key (using the classPrivateFieldLooseKey helper). // In spec mode, only instance fields need a "private name" initializer @@ -48,7 +53,7 @@ export function buildPrivateNamesNodes(privateNamesMap, loose, state) { const { static: isStatic, method: isMethod, getId, setId } = value; const isAccessor = getId || setId; const id = t.cloneNode(value.id); - if (loose) { + if (privateFieldsAsProperties) { initNodes.push( template.statement.ast` var ${id} = ${state.addHelper("classPrivateFieldLooseKey")}("${name}") @@ -149,13 +154,13 @@ const privateInVisitor = privateNameVisitorFactory({ if (operator !== "in") return; if (!path.get("left").isPrivateName()) return; - const { loose, privateNamesMap, redeclared } = this; + const { privateFieldsAsProperties, privateNamesMap, redeclared } = this; const { name } = left.id; if (!privateNamesMap.has(name)) return; if (redeclared && redeclared.includes(name)) return; - if (loose) { + if (privateFieldsAsProperties) { const { id } = privateNamesMap.get(name); path.replaceWith(template.expression.ast` Object.prototype.hasOwnProperty.call(${right}, ${t.cloneNode(id)}) @@ -373,13 +378,15 @@ export function transformPrivateNamesUsage( ref, path, privateNamesMap, - loose, + { privateFieldsAsProperties }, state, ) { if (!privateNamesMap.size) return; const body = path.get("body"); - const handler = loose ? privateNameHandlerLoose : privateNameHandlerSpec; + const handler = privateFieldsAsProperties + ? privateNameHandlerLoose + : privateNameHandlerSpec; memberExpressionToFunctions(body, privateNameVisitor, { privateNamesMap, @@ -391,7 +398,7 @@ export function transformPrivateNamesUsage( privateNamesMap, classRef: ref, file: state, - loose, + privateFieldsAsProperties, }); } @@ -573,7 +580,11 @@ function buildPrivateStaticMethodInitLoose(ref, prop, state, privateNamesMap) { `; } -function buildPrivateMethodDeclaration(prop, privateNamesMap, loose = false) { +function buildPrivateMethodDeclaration( + prop, + privateNamesMap, + privateFieldsAsProperties = false, +) { const privateName = privateNamesMap.get(prop.node.key.id.name); const { id, @@ -613,7 +624,7 @@ function buildPrivateMethodDeclaration(prop, privateNamesMap, loose = false) { t.variableDeclarator(setId, methodValue), ]); } - if (isStatic && !loose) { + if (isStatic && !privateFieldsAsProperties) { return t.variableDeclaration("var", [ t.variableDeclarator( t.cloneNode(id), @@ -637,12 +648,12 @@ const thisContextVisitor = traverse.visitors.merge([ environmentVisitor, ]); -function replaceThisContext(path, ref, superRef, file, loose) { +function replaceThisContext(path, ref, superRef, file, constantSuper) { const state = { classRef: ref, needsClassRef: false }; const replacer = new ReplaceSupers({ methodPath: path, - isLoose: loose, + constantSuper, superRef, file, refToPreserve: ref, @@ -666,7 +677,9 @@ export function buildFieldsInitNodes( props, privateNamesMap, state, - loose, + setPublicClassFields, + privateFieldsAsProperties, + constantSuper, ) { const staticNodes = []; const instanceNodes = []; @@ -683,39 +696,45 @@ export function buildFieldsInitNodes( const isMethod = !isField; if (isStatic || (isMethod && isPrivate)) { - const replaced = replaceThisContext(prop, ref, superRef, state, loose); + const replaced = replaceThisContext( + prop, + ref, + superRef, + state, + constantSuper, + ); needsClassRef = needsClassRef || replaced; } switch (true) { - case isStatic && isPrivate && isField && loose: + case isStatic && isPrivate && isField && privateFieldsAsProperties: needsClassRef = true; staticNodes.push( buildPrivateFieldInitLoose(t.cloneNode(ref), prop, privateNamesMap), ); break; - case isStatic && isPrivate && isField && !loose: + case isStatic && isPrivate && isField && !privateFieldsAsProperties: needsClassRef = true; staticNodes.push( buildPrivateStaticFieldInitSpec(prop, privateNamesMap), ); break; - case isStatic && isPublic && isField && loose: + case isStatic && isPublic && isField && setPublicClassFields: needsClassRef = true; staticNodes.push(buildPublicFieldInitLoose(t.cloneNode(ref), prop)); break; - case isStatic && isPublic && isField && !loose: + case isStatic && isPublic && isField && !setPublicClassFields: needsClassRef = true; staticNodes.push( buildPublicFieldInitSpec(t.cloneNode(ref), prop, state), ); break; - case isInstance && isPrivate && isField && loose: + case isInstance && isPrivate && isField && privateFieldsAsProperties: instanceNodes.push( buildPrivateFieldInitLoose(t.thisExpression(), prop, privateNamesMap), ); break; - case isInstance && isPrivate && isField && !loose: + case isInstance && isPrivate && isField && !privateFieldsAsProperties: instanceNodes.push( buildPrivateInstanceFieldInitSpec( t.thisExpression(), @@ -724,7 +743,7 @@ export function buildFieldsInitNodes( ), ); break; - case isInstance && isPrivate && isMethod && loose: + case isInstance && isPrivate && isMethod && privateFieldsAsProperties: instanceNodes.unshift( buildPrivateMethodInitLoose( t.thisExpression(), @@ -733,10 +752,14 @@ export function buildFieldsInitNodes( ), ); staticNodes.push( - buildPrivateMethodDeclaration(prop, privateNamesMap, loose), + buildPrivateMethodDeclaration( + prop, + privateNamesMap, + privateFieldsAsProperties, + ), ); break; - case isInstance && isPrivate && isMethod && !loose: + case isInstance && isPrivate && isMethod && !privateFieldsAsProperties: instanceNodes.unshift( buildPrivateInstanceMethodInitSpec( t.thisExpression(), @@ -745,19 +768,27 @@ export function buildFieldsInitNodes( ), ); staticNodes.push( - buildPrivateMethodDeclaration(prop, privateNamesMap, loose), + buildPrivateMethodDeclaration( + prop, + privateNamesMap, + privateFieldsAsProperties, + ), ); break; - case isStatic && isPrivate && isMethod && !loose: + case isStatic && isPrivate && isMethod && !privateFieldsAsProperties: needsClassRef = true; staticNodes.push( buildPrivateStaticFieldInitSpec(prop, privateNamesMap), ); staticNodes.unshift( - buildPrivateMethodDeclaration(prop, privateNamesMap, loose), + buildPrivateMethodDeclaration( + prop, + privateNamesMap, + privateFieldsAsProperties, + ), ); break; - case isStatic && isPrivate && isMethod && loose: + case isStatic && isPrivate && isMethod && privateFieldsAsProperties: needsClassRef = true; staticNodes.push( buildPrivateStaticMethodInitLoose( @@ -768,13 +799,17 @@ export function buildFieldsInitNodes( ), ); staticNodes.unshift( - buildPrivateMethodDeclaration(prop, privateNamesMap, loose), + buildPrivateMethodDeclaration( + prop, + privateNamesMap, + privateFieldsAsProperties, + ), ); break; - case isInstance && isPublic && isField && loose: + case isInstance && isPublic && isField && setPublicClassFields: instanceNodes.push(buildPublicFieldInitLoose(t.thisExpression(), prop)); break; - case isInstance && isPublic && isField && !loose: + case isInstance && isPublic && isField && !setPublicClassFields: instanceNodes.push( buildPublicFieldInitSpec(t.thisExpression(), prop, state), ); diff --git a/packages/babel-helper-create-class-features-plugin/src/index.js b/packages/babel-helper-create-class-features-plugin/src/index.js index 66cfb83fb082..d5fa310872ca 100644 --- a/packages/babel-helper-create-class-features-plugin/src/index.js +++ b/packages/babel-helper-create-class-features-plugin/src/index.js @@ -36,7 +36,38 @@ export function createClassFeaturePlugin({ feature, loose, manipulateOptions, + // TODO(Babel 8): Remove the default falue + api = { assumption: () => {} }, }) { + const setPublicClassFields = api.assumption("setPublicClassFields"); + const privateFieldsAsProperties = api.assumption("privateFieldsAsProperties"); + const constantSuper = api.assumption("constantSuper"); + + if (loose) { + const explicit = []; + + if (setPublicClassFields !== undefined) { + explicit.push(`"setPublicClassFields"`); + } + if (privateFieldsAsProperties !== undefined) { + explicit.push(`"privateFieldsAsProperties"`); + } + if (explicit.length !== 0) { + console.warn( + `[${name}]: You are using the "loose: true" option and you are` + + ` explicitly setting a value for the ${explicit.join(" and ")}` + + ` assumption${explicit.length > 1 ? "s" : ""}. The "loose" option` + + ` can cause incompatibilities with the other class features` + + ` plugins, so it's recommended that you replace it with the` + + ` following top-level option:\n` + + `\t"assumptions": {\n` + + `\t\t"setPublicClassFields": true,\n` + + `\t\t"privateFieldsAsProperties": true\n` + + `\t}`, + ); + } + } + return { name, manipulateOptions, @@ -151,11 +182,17 @@ export function createClassFeaturePlugin({ const privateNamesMap = buildPrivateNamesMap(props); const privateNamesNodes = buildPrivateNamesNodes( privateNamesMap, - loose, + privateFieldsAsProperties ?? loose, state, ); - transformPrivateNamesUsage(ref, path, privateNamesMap, loose, state); + transformPrivateNamesUsage( + ref, + path, + privateNamesMap, + { privateFieldsAsProperties: privateFieldsAsProperties ?? loose }, + state, + ); let keysNodes, staticNodes, instanceNodes, wrapClass; @@ -175,7 +212,9 @@ export function createClassFeaturePlugin({ props, privateNamesMap, state, - loose, + setPublicClassFields ?? loose, + privateFieldsAsProperties ?? loose, + constantSuper ?? loose, )); } diff --git a/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/input.js b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/input.js new file mode 100644 index 000000000000..eb0eb350654f --- /dev/null +++ b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/input.js @@ -0,0 +1,3 @@ +class A { + foo; +} diff --git a/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/options.json b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/options.json new file mode 100644 index 000000000000..3fae40ed0d43 --- /dev/null +++ b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/options.json @@ -0,0 +1,9 @@ +{ + "validateLogs": true, + "plugins": [ + ["proposal-class-properties", { "loose": true }] + ], + "assumptions": { + "setPublicClassFields": true + } +} diff --git a/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/output.js b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/output.js new file mode 100644 index 000000000000..063a057f52c0 --- /dev/null +++ b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/output.js @@ -0,0 +1,6 @@ +class A { + constructor() { + this.foo = void 0; + } + +} diff --git a/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/stderr.txt b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/stderr.txt new file mode 100644 index 000000000000..2d6c3d02acff --- /dev/null +++ b/packages/babel-helper-create-class-features-plugin/test/fixtures/plugin-proposal-class-properties/warn-loose-and-assumptions/stderr.txt @@ -0,0 +1,5 @@ +[proposal-class-properties]: You are using the "loose: true" option and you are explicitly setting a value for the "setPublicClassFields" assumption. The "loose" option can cause incompatibilities with the other class features plugins, so it's recommended that you replace it with the following top-level option: + "assumptions": { + "setPublicClassFields": true, + "privateFieldsAsProperties": true + } diff --git a/packages/babel-helper-module-transforms/src/index.js b/packages/babel-helper-module-transforms/src/index.js index 164462ee0450..5e244e2ab2f1 100644 --- a/packages/babel-helper-module-transforms/src/index.js +++ b/packages/babel-helper-module-transforms/src/index.js @@ -27,14 +27,19 @@ export { hasExports, isSideEffectImport, isModule, rewriteThis }; export function rewriteModuleStatementsAndPrepareHeader( path: NodePath, { + // TODO(Babel 8): Remove this + loose, + exportName, strict, allowTopLevelThis, strictMode, - loose, noInterop, lazy, esNamespaceOnly, + + constantReexports = loose, + enumerableModuleMeta = loose, }, ) { assert(isModule(path), "Cannot process module statements in a script"); @@ -42,7 +47,7 @@ export function rewriteModuleStatementsAndPrepareHeader( const meta = normalizeAndLoadModuleMetadata(path, exportName, { noInterop, - loose, + initializeReexports: constantReexports, lazy, esNamespaceOnly, }); @@ -67,7 +72,7 @@ export function rewriteModuleStatementsAndPrepareHeader( const headers = []; if (hasExports(meta) && !strict) { - headers.push(buildESModuleHeader(meta, loose /* enumerable */)); + headers.push(buildESModuleHeader(meta, enumerableModuleMeta)); } const nameList = buildExportNameListDeclaration(path, meta); @@ -78,7 +83,9 @@ export function rewriteModuleStatementsAndPrepareHeader( } // Create all of the statically known named exports. - headers.push(...buildExportInitializationStatements(path, meta, loose)); + headers.push( + ...buildExportInitializationStatements(path, meta, constantReexports), + ); return { meta, headers }; } @@ -128,7 +135,7 @@ export function wrapInterop( export function buildNamespaceInitStatements( metadata: ModuleMetadata, sourceMetadata: SourceModuleMetadata, - loose: boolean = false, + constantReexports: boolean = false, ) { const statements = []; @@ -146,8 +153,8 @@ export function buildNamespaceInitStatements( }), ); } - if (loose) { - statements.push(...buildReexportsFromMeta(metadata, sourceMetadata, loose)); + if (constantReexports) { + statements.push(...buildReexportsFromMeta(metadata, sourceMetadata, true)); } for (const exportName of sourceMetadata.reexportNamespace) { // Assign export to namespace object. @@ -172,7 +179,7 @@ export function buildNamespaceInitStatements( const statement = buildNamespaceReexport( metadata, t.cloneNode(srcNamespace), - loose, + constantReexports, ); statement.loc = sourceMetadata.reexportAll.loc; @@ -183,8 +190,8 @@ export function buildNamespaceInitStatements( } const ReexportTemplate = { - loose: template.statement`EXPORTS.EXPORT_NAME = NAMESPACE_IMPORT;`, - looseComputed: template.statement`EXPORTS["EXPORT_NAME"] = NAMESPACE_IMPORT;`, + constant: template.statement`EXPORTS.EXPORT_NAME = NAMESPACE_IMPORT;`, + constantComputed: template.statement`EXPORTS["EXPORT_NAME"] = NAMESPACE_IMPORT;`, spec: template` Object.defineProperty(EXPORTS, "EXPORT_NAME", { enumerable: true, @@ -198,7 +205,7 @@ const ReexportTemplate = { const buildReexportsFromMeta = ( meta: ModuleMetadata, metadata: SourceModuleMetadata, - loose, + constantReexports: boolean, ) => { const namespace = metadata.lazy ? t.callExpression(t.identifier(metadata.name), []) @@ -224,11 +231,11 @@ const buildReexportsFromMeta = ( EXPORT_NAME: exportName, NAMESPACE_IMPORT, }; - if (loose) { + if (constantReexports) { if (stringSpecifiers.has(exportName)) { - return ReexportTemplate.looseComputed(astNodes); + return ReexportTemplate.constantComputed(astNodes); } else { - return ReexportTemplate.loose(astNodes); + return ReexportTemplate.constant(astNodes); } } else { return ReexportTemplate.spec(astNodes); @@ -241,9 +248,9 @@ const buildReexportsFromMeta = ( */ function buildESModuleHeader( metadata: ModuleMetadata, - enumerable: boolean = false, + enumerableModuleMeta: boolean = false, ) { - return (enumerable + return (enumerableModuleMeta ? template.statement` EXPORTS.__esModule = true; ` @@ -257,8 +264,8 @@ function buildESModuleHeader( /** * Create a re-export initialization loop for a specific imported namespace. */ -function buildNamespaceReexport(metadata, namespace, loose) { - return (loose +function buildNamespaceReexport(metadata, namespace, constantReexports) { + return (constantReexports ? template.statement` Object.keys(NAMESPACE).forEach(function(key) { if (key === "default" || key === "__esModule") return; @@ -347,7 +354,7 @@ function buildExportNameListDeclaration( function buildExportInitializationStatements( programPath: NodePath, metadata: ModuleMetadata, - loose: boolean = false, + constantReexports: boolean = false, ) { const initStatements = []; @@ -365,8 +372,8 @@ function buildExportInitializationStatements( } for (const data of metadata.source.values()) { - if (!loose) { - initStatements.push(...buildReexportsFromMeta(metadata, data, loose)); + if (!constantReexports) { + initStatements.push(...buildReexportsFromMeta(metadata, data, false)); } for (const exportName of data.reexportNamespace) { exportNames.push(exportName); diff --git a/packages/babel-helper-module-transforms/src/normalize-and-load-metadata.js b/packages/babel-helper-module-transforms/src/normalize-and-load-metadata.js index c95e0b188cb2..84bac99f3ce0 100644 --- a/packages/babel-helper-module-transforms/src/normalize-and-load-metadata.js +++ b/packages/babel-helper-module-transforms/src/normalize-and-load-metadata.js @@ -86,7 +86,7 @@ export default function normalizeModuleAndLoadMetadata( exportName?: string, { noInterop = false, - loose = false, + initializeReexports = false, lazy = false, esNamespaceOnly = false, } = {}, @@ -100,10 +100,7 @@ export default function normalizeModuleAndLoadMetadata( const { local, source, hasExports } = getModuleMetadata( programPath, - { - loose, - lazy, - }, + { initializeReexports, lazy }, stringSpecifiers, ); @@ -170,12 +167,15 @@ function getExportSpecifierName( */ function getModuleMetadata( programPath: NodePath, - { loose, lazy }: { loose: boolean, lazy: boolean }, + { + lazy, + initializeReexports, + }: { lazy: boolean, initializeReexports: boolean }, stringSpecifiers: Set, ) { const localData = getLocalExportMetadata( programPath, - loose, + initializeReexports, stringSpecifiers, ); @@ -361,7 +361,7 @@ function getModuleMetadata( */ function getLocalExportMetadata( programPath: NodePath, - loose: boolean, + initializeReexports: boolean, stringSpecifiers: Set, ): Map { const bindingKindLookup = new Map(); @@ -376,7 +376,7 @@ function getLocalExportMetadata( if (child.node.declaration) { child = child.get("declaration"); } else if ( - loose && + initializeReexports && child.node.source && child.get("source").isStringLiteral() ) { @@ -429,7 +429,10 @@ function getLocalExportMetadata( }; programPath.get("body").forEach(child => { - if (child.isExportNamedDeclaration() && (loose || !child.node.source)) { + if ( + child.isExportNamedDeclaration() && + (initializeReexports || !child.node.source) + ) { if (child.node.declaration) { const declaration = child.get("declaration"); const ids = declaration.getOuterBindingIdentifierPaths(); diff --git a/packages/babel-helper-remap-async-to-generator/src/index.js b/packages/babel-helper-remap-async-to-generator/src/index.js index ac96c9311218..282d32124b34 100644 --- a/packages/babel-helper-remap-async-to-generator/src/index.js +++ b/packages/babel-helper-remap-async-to-generator/src/index.js @@ -31,6 +31,7 @@ const awaitVisitor = { export default function ( path: NodePath, helpers: { wrapAsync: Object, wrapAwait: Object }, + noNewArrows?: boolean, ) { path.traverse(awaitVisitor, { wrapAwait: helpers.wrapAwait, @@ -41,7 +42,7 @@ export default function ( path.node.async = false; path.node.generator = true; - wrapFunction(path, t.cloneNode(helpers.wrapAsync)); + wrapFunction(path, t.cloneNode(helpers.wrapAsync), noNewArrows); const isProperty = path.isObjectMethod() || diff --git a/packages/babel-helper-replace-supers/src/index.js b/packages/babel-helper-replace-supers/src/index.js index 248d44f9637e..7ae8b2799333 100644 --- a/packages/babel-helper-replace-supers/src/index.js +++ b/packages/babel-helper-replace-supers/src/index.js @@ -255,7 +255,7 @@ const looseHandlers = { type ReplaceSupersOptionsBase = {| methodPath: NodePath, superRef: Object, - isLoose: boolean, + constantSuper: boolean, file: any, // objectRef might have been shadowed in child scopes, // in that case, we need to rename related variables. @@ -284,13 +284,16 @@ export default class ReplaceSupers { this.file = opts.file; this.superRef = opts.superRef; - this.isLoose = opts.isLoose; + this.constantSuper = process.env.BABEL_8_BREAKING + ? opts.constantSuper + : // Fallback to isLoose for backward compatibility + opts.constantSuper ?? (opts: any).isLoose; this.opts = opts; } declare file: HubInterface; declare isDerivedConstructor: boolean; - declare isLoose: boolean; + declare constantSuper: boolean; declare isPrivateMethod: boolean; declare isStatic: boolean; declare methodPath: NodePath; @@ -309,7 +312,7 @@ export default class ReplaceSupers { }); } - const handler = this.isLoose ? looseHandlers : specHandlers; + const handler = this.constantSuper ? looseHandlers : specHandlers; memberExpressionToFunctions(this.methodPath, visitor, { file: this.file, diff --git a/packages/babel-helper-wrap-function/src/index.js b/packages/babel-helper-wrap-function/src/index.js index e1ff0d37ac81..59f47780a972 100644 --- a/packages/babel-helper-wrap-function/src/index.js +++ b/packages/babel-helper-wrap-function/src/index.js @@ -57,7 +57,7 @@ function classOrObjectMethod(path: NodePath, callId: Object) { .unwrapFunctionEnvironment(); } -function plainFunction(path: NodePath, callId: Object) { +function plainFunction(path: NodePath, callId: Object, noNewArrows: boolean) { const node = path.node; const isDeclaration = path.isFunctionDeclaration(); const functionId = node.id; @@ -68,7 +68,7 @@ function plainFunction(path: NodePath, callId: Object) { : buildAnonymousExpressionWrapper; if (path.isArrowFunctionExpression()) { - path.arrowFunctionToExpression(); + path.arrowFunctionToExpression({ noNewArrows }); } node.id = null; @@ -123,10 +123,15 @@ function plainFunction(path: NodePath, callId: Object) { } } -export default function wrapFunction(path: NodePath, callId: Object) { +export default function wrapFunction( + path: NodePath, + callId: Object, + // TODO(Babel 8): Consider defaulting to false for spec compliancy + noNewArrows: boolean = true, +) { if (path.isMethod()) { classOrObjectMethod(path, callId); } else { - plainFunction(path, callId); + plainFunction(path, callId, noNewArrows); } } diff --git a/packages/babel-plugin-proposal-async-generator-functions/src/index.js b/packages/babel-plugin-proposal-async-generator-functions/src/index.js index 82bfa1d32a86..5460a792149e 100644 --- a/packages/babel-plugin-proposal-async-generator-functions/src/index.js +++ b/packages/babel-plugin-proposal-async-generator-functions/src/index.js @@ -70,6 +70,8 @@ export default declare(api => { path.traverse(yieldStarVisitor, state); + // We don't need to pass the noNewArrows assumption, since + // async generators are never arrow functions. remapAsyncToGenerator(path, { wrapAsync: state.addHelper("wrapAsyncGenerator"), wrapAwait: state.addHelper("awaitAsyncGenerator"), diff --git a/packages/babel-plugin-proposal-class-properties/src/index.js b/packages/babel-plugin-proposal-class-properties/src/index.js index 89c016dbca54..f8a6058a181f 100644 --- a/packages/babel-plugin-proposal-class-properties/src/index.js +++ b/packages/babel-plugin-proposal-class-properties/src/index.js @@ -12,6 +12,7 @@ export default declare((api, options) => { return createClassFeaturePlugin({ name: "proposal-class-properties", + api, feature: FEATURES.fields, loose: options.loose, diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/computed-initialization-order/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/computed-initialization-order/exec.js new file mode 100644 index 000000000000..339de138c781 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/computed-initialization-order/exec.js @@ -0,0 +1,38 @@ +const actualOrder = []; + +const track = i => { + actualOrder.push(i); + return i; +}; + +class MyClass { + static [track(1)] = track(10); + [track(2)] = track(13); + get [track(3)]() { + return "foo"; + } + set [track(4)](value) { + this.bar = value; + } + [track(5)] = track(14); + static [track(6)] = track(11); + static [track(7)] = track(12); + [track(8)]() {} + [track(9)] = track(15); +} + +const inst = new MyClass(); + +const expectedOrder = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; +expect(actualOrder).toEqual(expectedOrder); + +expect(MyClass[1]).toBe(10); +expect(inst[2]).toBe(13); +expect(inst[3]).toBe("foo"); +inst[4] = "baz"; +expect(inst.bar).toBe("baz"); +expect(inst[5]).toBe(14); +expect(MyClass[6]).toBe(11); +expect(MyClass[7]).toBe(12); +expect(typeof inst[8]).toBe("function"); +expect(inst[9]).toBe(15); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/computed/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/computed/input.js new file mode 100644 index 000000000000..0e777063a283 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/computed/input.js @@ -0,0 +1,25 @@ +const foo = "foo"; +const bar = () => {}; +const four = 4; + +class MyClass { + static [one()] = "test"; + static [2 * 4 + 7] = "247"; + static [2 * four + 7] = "247"; + static [2 * four + seven] = "247"; + [null] = "null"; + [undefined] = "undefined"; + [void 0] = "void 0"; + get ["whatever"]() {} + set ["whatever"](value) {} + get [computed()]() {} + set [computed()](value) {} + ["test" + one]() {} + static [10]() {} + [/regex/] = "regex"; + [foo] = "foo"; + [bar] = "bar"; + [baz] = "baz"; + [`template`] = "template"; + [`template${expression}`] = "template-with-expression"; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/computed/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/computed/output.js new file mode 100644 index 000000000000..a13d0420c8a7 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/computed/output.js @@ -0,0 +1,48 @@ +let _one, _ref, _undefined, _computed, _computed2, _ref2, _ref3, _baz, _ref4; + +const foo = "foo"; + +const bar = () => {}; + +const four = 4; +_one = one(); +_ref = 2 * four + seven; +_undefined = undefined; +_computed = computed(); +_computed2 = computed(); +_ref2 = "test" + one; +_ref3 = /regex/; +_baz = baz; +_ref4 = `template${expression}`; + +class MyClass { + constructor() { + this[null] = "null"; + this[_undefined] = "undefined"; + this[void 0] = "void 0"; + this[_ref3] = "regex"; + this[foo] = "foo"; + this[bar] = "bar"; + this[_baz] = "baz"; + this[`template`] = "template"; + this[_ref4] = "template-with-expression"; + } + + get ["whatever"]() {} + + set ["whatever"](value) {} + + get [_computed]() {} + + set [_computed2](value) {} + + [_ref2]() {} + + static [10]() {} + +} + +MyClass[_one] = "test"; +MyClass[2 * 4 + 7] = "247"; +MyClass[2 * four + 7] = "247"; +MyClass[_ref] = "247"; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/constructor-collision/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/constructor-collision/input.js new file mode 100644 index 000000000000..3071b5edb87b --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/constructor-collision/input.js @@ -0,0 +1,11 @@ +var foo = "bar"; + +class Foo { + bar = foo; + static bar = baz; + + constructor() { + var foo = "foo"; + var baz = "baz"; + } +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/constructor-collision/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/constructor-collision/output.js new file mode 100644 index 000000000000..58b6d55bfdb6 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/constructor-collision/output.js @@ -0,0 +1,12 @@ +var foo = "bar"; + +class Foo { + constructor() { + this.bar = foo; + var _foo = "foo"; + var baz = "baz"; + } + +} + +Foo.bar = baz; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/derived/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/derived/input.js new file mode 100644 index 000000000000..cd8e3fdd8031 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/derived/input.js @@ -0,0 +1,3 @@ +class Foo extends Bar { + bar = "foo"; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/derived/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/derived/output.js new file mode 100644 index 000000000000..5399e29d2d87 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/derived/output.js @@ -0,0 +1,7 @@ +class Foo extends Bar { + constructor(...args) { + super(...args); + this.bar = "foo"; + } + +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/foobar/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/foobar/input.js new file mode 100644 index 000000000000..60a1c5e823cd --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/foobar/input.js @@ -0,0 +1,9 @@ +class Child extends Parent { + constructor() { + super(); + } + + scopedFunctionWithThis = () => { + this.name = {}; + } +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/foobar/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/foobar/options.json new file mode 100644 index 000000000000..a56954a5e7ea --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/foobar/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "proposal-class-properties" + ], + "presets": ["env"], + "assumptions": { + "setPublicClassFields": true + } +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/foobar/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/foobar/output.js new file mode 100644 index 000000000000..86a6067497dc --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/foobar/output.js @@ -0,0 +1,22 @@ +var Child = /*#__PURE__*/function (_Parent) { + "use strict"; + + babelHelpers.inherits(Child, _Parent); + + var _super = babelHelpers.createSuper(Child); + + function Child() { + var _this; + + babelHelpers.classCallCheck(this, Child); + _this = _super.call(this); + + _this.scopedFunctionWithThis = function () { + _this.name = {}; + }; + + return _this; + } + + return Child; +}(Parent); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-computed/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-computed/exec.js new file mode 100644 index 000000000000..3f619174beb4 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-computed/exec.js @@ -0,0 +1,13 @@ +function test(x) { + class F { + [x] = 1; + constructor() {} + } + + x = 'deadbeef'; + expect(new F().foo).toBe(1); + x = 'wrong'; + expect(new F().foo).toBe(1); +} + +test('foo'); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-computed/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-computed/input.js new file mode 100644 index 000000000000..3f619174beb4 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-computed/input.js @@ -0,0 +1,13 @@ +function test(x) { + class F { + [x] = 1; + constructor() {} + } + + x = 'deadbeef'; + expect(new F().foo).toBe(1); + x = 'wrong'; + expect(new F().foo).toBe(1); +} + +test('foo'); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-computed/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-computed/output.js new file mode 100644 index 000000000000..4216994effe0 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-computed/output.js @@ -0,0 +1,19 @@ +function test(x) { + let _x; + + _x = x; + + class F { + constructor() { + this[_x] = 1; + } + + } + + x = 'deadbeef'; + expect(new F().foo).toBe(1); + x = 'wrong'; + expect(new F().foo).toBe(1); +} + +test('foo'); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-undefined/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-undefined/input.js new file mode 100644 index 000000000000..a36cdd975c82 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-undefined/input.js @@ -0,0 +1,3 @@ +class Foo { + bar; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-undefined/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-undefined/output.js new file mode 100644 index 000000000000..8cd3e63f7fcf --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance-undefined/output.js @@ -0,0 +1,6 @@ +class Foo { + constructor() { + this.bar = void 0; + } + +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance/input.js new file mode 100644 index 000000000000..9cecfe8a3013 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance/input.js @@ -0,0 +1,3 @@ +class Foo { + bar = "foo"; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance/output.js new file mode 100644 index 000000000000..f2bdaefe6a7c --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/instance/output.js @@ -0,0 +1,6 @@ +class Foo { + constructor() { + this.bar = "foo"; + } + +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/non-block-arrow-func/input.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/non-block-arrow-func/input.mjs new file mode 100644 index 000000000000..4b67e0e158f6 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/non-block-arrow-func/input.mjs @@ -0,0 +1,11 @@ +export default param => + class App { + static props = { + prop1: 'prop1', + prop2: 'prop2' + } + + getParam() { + return param; + } + } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/non-block-arrow-func/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/non-block-arrow-func/output.mjs new file mode 100644 index 000000000000..4bacda92aa9c --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/non-block-arrow-func/output.mjs @@ -0,0 +1,13 @@ +export default (param => { + var _class, _temp; + + return _temp = _class = class App { + getParam() { + return param; + } + + }, _class.props = { + prop1: 'prop1', + prop2: 'prop2' + }, _temp; +}); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/options.json new file mode 100644 index 000000000000..018ebbb8d5a8 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "proposal-class-properties", + "syntax-class-properties" + ], + "assumptions": { + "setPublicClassFields": true + } +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T2983/input.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T2983/input.mjs new file mode 100644 index 000000000000..2961c9a40366 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T2983/input.mjs @@ -0,0 +1,7 @@ +call(class { + static test = true +}); + +export default class { + static test = true +}; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T2983/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T2983/output.mjs new file mode 100644 index 000000000000..b962b2bfb723 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T2983/output.mjs @@ -0,0 +1,6 @@ +var _class, _temp; + +call((_temp = _class = class {}, _class.test = true, _temp)); +export default class _class2 {} +_class2.test = true; +; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T6719/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T6719/input.js new file mode 100644 index 000000000000..38b9e80baecc --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T6719/input.js @@ -0,0 +1,14 @@ +function withContext(ComposedComponent) { + return class WithContext extends Component { + + static propTypes = { + context: PropTypes.shape( + { + addCss: PropTypes.func, + setTitle: PropTypes.func, + setMeta: PropTypes.func, + } + ), + }; + }; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T6719/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T6719/output.js new file mode 100644 index 000000000000..7e9c64e86abe --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T6719/output.js @@ -0,0 +1,11 @@ +function withContext(ComposedComponent) { + var _class, _temp; + + return _temp = _class = class WithContext extends Component {}, _class.propTypes = { + context: PropTypes.shape({ + addCss: PropTypes.func, + setTitle: PropTypes.func, + setMeta: PropTypes.func + }) + }, _temp; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T7364/input.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T7364/input.mjs new file mode 100644 index 000000000000..1ddb4a1e7887 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T7364/input.mjs @@ -0,0 +1,17 @@ +class MyClass { + myAsyncMethod = async () => { + console.log(this); + } +} + +(class MyClass2 { + myAsyncMethod = async () => { + console.log(this); + } +}) + +export default class MyClass3 { + myAsyncMethod = async () => { + console.log(this); + } +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T7364/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T7364/options.json new file mode 100644 index 000000000000..7e57d1f03f2b --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T7364/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + "external-helpers", + "transform-async-to-generator", + "proposal-class-properties" + ], + "assumptions": { + "setPublicClassFields": true + } +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T7364/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T7364/output.mjs new file mode 100644 index 000000000000..24c39cad22bd --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/regression-T7364/output.mjs @@ -0,0 +1,32 @@ +class MyClass { + constructor() { + var _this = this; + + this.myAsyncMethod = /*#__PURE__*/babelHelpers.asyncToGenerator(function* () { + console.log(_this); + }); + } + +} + +(class MyClass2 { + constructor() { + var _this2 = this; + + this.myAsyncMethod = /*#__PURE__*/babelHelpers.asyncToGenerator(function* () { + console.log(_this2); + }); + } + +}); + +export default class MyClass3 { + constructor() { + var _this3 = this; + + this.myAsyncMethod = /*#__PURE__*/babelHelpers.asyncToGenerator(function* () { + console.log(_this3); + }); + } + +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-export/input.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-export/input.mjs new file mode 100644 index 000000000000..729475cc52ff --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-export/input.mjs @@ -0,0 +1,7 @@ +export class MyClass { + static property = value; +} + +export default class MyClass2 { + static property = value; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-export/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-export/output.mjs new file mode 100644 index 000000000000..0664f082e29c --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-export/output.mjs @@ -0,0 +1,4 @@ +export class MyClass {} +MyClass.property = value; +export default class MyClass2 {} +MyClass2.property = value; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-infer-name/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-infer-name/exec.js new file mode 100644 index 000000000000..bc62d48d907f --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-infer-name/exec.js @@ -0,0 +1,7 @@ +var Foo = class { + static num = 0; +} + +expect(Foo.num).toBe(0); +expect(Foo.num = 1).toBe(1); +expect(Foo.name).toBe("Foo"); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-infer-name/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-infer-name/input.js new file mode 100644 index 000000000000..96f03df576a0 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-infer-name/input.js @@ -0,0 +1,3 @@ +var Foo = class { + static num = 0; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-infer-name/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-infer-name/output.js new file mode 100644 index 000000000000..812b9613442d --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-infer-name/output.js @@ -0,0 +1,3 @@ +var _class, _temp; + +var Foo = (_temp = _class = class Foo {}, _class.num = 0, _temp); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/input.js new file mode 100644 index 000000000000..9f649ab392bc --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/input.js @@ -0,0 +1,9 @@ +class A { + static prop = 1; +} + +class B extends A { + static prop = 2; + static propA = super.prop; + static getPropA = () => super.prop; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/options.json new file mode 100644 index 000000000000..755819446903 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/options.json @@ -0,0 +1,11 @@ +{ + "validateLogs": true, + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + ["proposal-class-properties", { "loose": true }], + "syntax-class-properties" + ], + "assumptions": { + "setPublicClassFields": true + } +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/output.js new file mode 100644 index 000000000000..269e97147e8a --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/output.js @@ -0,0 +1,10 @@ +class A {} + +A.prop = 1; + +class B extends A {} + +B.prop = 2; +B.propA = A.prop; + +B.getPropA = () => A.prop; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/stderr.txt b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/stderr.txt new file mode 100644 index 000000000000..2d6c3d02acff --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super-loose/stderr.txt @@ -0,0 +1,5 @@ +[proposal-class-properties]: You are using the "loose: true" option and you are explicitly setting a value for the "setPublicClassFields" assumption. The "loose" option can cause incompatibilities with the other class features plugins, so it's recommended that you replace it with the following top-level option: + "assumptions": { + "setPublicClassFields": true, + "privateFieldsAsProperties": true + } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super/exec.js new file mode 100644 index 000000000000..4b4e3fcf1a36 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super/exec.js @@ -0,0 +1,15 @@ +class A { + static prop = 1; +} + +class B extends A { + static prop = 2; + static propA = super.prop; + static getPropA = () => super.prop; +} + +const { prop, propA, getPropA } = B; + +expect(prop).toBe(2); +expect(propA).toBe(1); +expect(getPropA()).toBe(1); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super/input.js new file mode 100644 index 000000000000..9f649ab392bc --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super/input.js @@ -0,0 +1,9 @@ +class A { + static prop = 1; +} + +class B extends A { + static prop = 2; + static propA = super.prop; + static getPropA = () => super.prop; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super/output.js new file mode 100644 index 000000000000..2d4da1550419 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-super/output.js @@ -0,0 +1,10 @@ +class A {} + +A.prop = 1; + +class B extends A {} + +B.prop = 2; +B.propA = babelHelpers.get(babelHelpers.getPrototypeOf(B), "prop", B); + +B.getPropA = () => babelHelpers.get(babelHelpers.getPrototypeOf(B), "prop", B); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-this/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-this/exec.js new file mode 100644 index 000000000000..0dbdf7491878 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-this/exec.js @@ -0,0 +1,9 @@ +class A { + static self = this; + static getA = () => this; +} + +const { self, getA } = A; + +expect(self).toBe(A); +expect(getA()).toBe(A); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-this/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-this/input.js new file mode 100644 index 000000000000..59f5c38c2c3e --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-this/input.js @@ -0,0 +1,4 @@ +class A { + static self = this; + static getA = () => this; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-this/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-this/output.js new file mode 100644 index 000000000000..b51f4e90407e --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-this/output.js @@ -0,0 +1,5 @@ +class A {} + +A.self = A; + +A.getA = () => A; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-undefined/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-undefined/exec.js new file mode 100644 index 000000000000..fa1152511452 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-undefined/exec.js @@ -0,0 +1,6 @@ +class Foo { + static num; +} + +expect("num" in Foo).toBe(true); +expect(Foo.num).toBeUndefined(); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-undefined/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-undefined/input.js new file mode 100644 index 000000000000..4ee31b9c3541 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-undefined/input.js @@ -0,0 +1,3 @@ +class Foo { + static bar; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-undefined/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-undefined/output.js new file mode 100644 index 000000000000..d31c6a0733da --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static-undefined/output.js @@ -0,0 +1,3 @@ +class Foo {} + +Foo.bar = void 0; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static/exec.js new file mode 100644 index 000000000000..c7d613dd53d9 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static/exec.js @@ -0,0 +1,9 @@ +class Foo { + static num = 0; + static str = "foo"; +} + +expect(Foo.num).toBe(0); +expect(Foo.num = 1).toBe(1); +expect(Foo.str).toBe("foo"); +expect(Foo.str = "bar").toBe("bar"); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static/input.js new file mode 100644 index 000000000000..ddc637ec2391 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static/input.js @@ -0,0 +1,3 @@ +class Foo { + static bar = "foo"; +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static/output.js new file mode 100644 index 000000000000..d48d8c76676d --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/static/output.js @@ -0,0 +1,3 @@ +class Foo {} + +Foo.bar = "foo"; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-call/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-call/input.js new file mode 100644 index 000000000000..175fc704e7e0 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-call/input.js @@ -0,0 +1,9 @@ +class A { + foo() { + return "bar"; + } +} + +class B extends A { + foo = super.foo(); +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-call/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-call/output.js new file mode 100644 index 000000000000..7d557cdf90e3 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-call/output.js @@ -0,0 +1,14 @@ +class A { + foo() { + return "bar"; + } + +} + +class B extends A { + constructor(...args) { + super(...args); + this.foo = super.foo(); + } + +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-expression/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-expression/input.js new file mode 100644 index 000000000000..222dec81a60c --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-expression/input.js @@ -0,0 +1,7 @@ +class Foo extends Bar { + bar = "foo"; + + constructor() { + foo(super()); + } +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-expression/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-expression/output.js new file mode 100644 index 000000000000..6896211d2e9d --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-expression/output.js @@ -0,0 +1,8 @@ +class Foo extends Bar { + constructor() { + var _temp; + + foo((_temp = super(), this.bar = "foo", _temp)); + } + +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-statement/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-statement/input.js new file mode 100644 index 000000000000..0af8843375d4 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-statement/input.js @@ -0,0 +1,7 @@ +class Foo extends Bar { + bar = "foo"; + + constructor() { + super(); + } +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-statement/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-statement/output.js new file mode 100644 index 000000000000..73e8f7eb4971 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-statement/output.js @@ -0,0 +1,7 @@ +class Foo extends Bar { + constructor() { + super(); + this.bar = "foo"; + } + +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-with-collision/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-with-collision/input.js new file mode 100644 index 000000000000..a9552f3068e1 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-with-collision/input.js @@ -0,0 +1,6 @@ +class A { + force = force; + foo = super.method(); + + constructor(force) {} +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-with-collision/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-with-collision/output.js new file mode 100644 index 000000000000..19d410990a03 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/assumption-setPublicClassFields/super-with-collision/output.js @@ -0,0 +1,7 @@ +class A { + constructor(_force) { + this.force = force; + this.foo = super.method(); + } + +} diff --git a/packages/babel-plugin-proposal-decorators/src/index.js b/packages/babel-plugin-proposal-decorators/src/index.js index 879de5f04703..a7e142769038 100644 --- a/packages/babel-plugin-proposal-decorators/src/index.js +++ b/packages/babel-plugin-proposal-decorators/src/index.js @@ -50,6 +50,7 @@ export default declare((api, options) => { return createClassFeaturePlugin({ name: "proposal-decorators", + api, feature: FEATURES.decorators, // loose: options.loose, Not supported diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/src/index.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/src/index.js index 12ddbc7cba97..ae948bad9a12 100644 --- a/packages/babel-plugin-proposal-nullish-coalescing-operator/src/index.js +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/src/index.js @@ -4,6 +4,7 @@ import { types as t, template } from "@babel/core"; export default declare((api, { loose = false }) => { api.assertVersion(7); + const noDocumentAll = api.assumption("noDocumentAll") ?? loose; return { name: "proposal-nullish-coalescing-operator", @@ -38,7 +39,7 @@ export default declare((api, { loose = false }) => { t.conditionalExpression( // We cannot use `!= null` in spec mode because // `document.all == null` and `document.all` is not "nullish". - loose + noDocumentAll ? t.binaryExpression("!=", assignment, t.nullLiteral()) : t.logicalExpression( "&&", diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/options.json b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/options.json new file mode 100644 index 000000000000..d0c9dda0ccc3 --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["proposal-nullish-coalescing-operator"], + "assumptions": { + "noDocumentAll": true + } +} diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/runtime-semantics/exec.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/runtime-semantics/exec.js new file mode 100644 index 000000000000..b2b21ccec9ff --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/runtime-semantics/exec.js @@ -0,0 +1,19 @@ +expect(null ?? undefined).toBeUndefined(undefined); +expect(undefined ?? null).toBeNull(); +expect(false ?? true).toBe(false); +expect(0 ?? 1).toBe(0); +expect("" ?? "foo").toBe(""); + +var obj = { exists: true }; +expect(obj.exists ?? false).toBe(true); +expect(obj.doesNotExist ?? "foo").toBe("foo"); + +var counter = 0; +function sideEffect() { return counter++; } +expect(sideEffect() ?? -1).toBe(0); + +var counter2 = 0; +var obj2 = { + get foo() { return counter2++; } +}; +expect(obj2.foo ?? -1).toBe(0); diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-destructuring/input.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-destructuring/input.js new file mode 100644 index 000000000000..876e05c1a625 --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-destructuring/input.js @@ -0,0 +1 @@ +var { qux = foo.bar ?? "qux" } = {}; diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-destructuring/output.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-destructuring/output.js new file mode 100644 index 000000000000..18d9e6f39130 --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-destructuring/output.js @@ -0,0 +1,5 @@ +var _foo$bar; + +var { + qux = (_foo$bar = foo.bar) != null ? _foo$bar : "qux" +} = {}; diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-param/input.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-param/input.js new file mode 100644 index 000000000000..65b7719722bc --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-param/input.js @@ -0,0 +1,3 @@ +function foo(foo, qux = foo.bar ?? "qux") {} + +function bar(bar, qux = bar ?? "qux") {} diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-param/output.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-param/output.js new file mode 100644 index 000000000000..97f53f5aedd3 --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-default-param/output.js @@ -0,0 +1,7 @@ +function foo(foo, qux = (() => { + var _foo$bar; + + return (_foo$bar = foo.bar) != null ? _foo$bar : "qux"; +})()) {} + +function bar(bar, qux = bar != null ? bar : "qux") {} diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-function/input.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-function/input.js new file mode 100644 index 000000000000..63b28b6c23cb --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-function/input.js @@ -0,0 +1,3 @@ +function foo(opts) { + var foo = opts.foo ?? "default"; +} diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-function/output.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-function/output.js new file mode 100644 index 000000000000..ee76d1c950a9 --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-in-function/output.js @@ -0,0 +1,5 @@ +function foo(opts) { + var _opts$foo; + + var foo = (_opts$foo = opts.foo) != null ? _opts$foo : "default"; +} diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-default/input.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-default/input.js new file mode 100644 index 000000000000..7c7dcae88cf4 --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-default/input.js @@ -0,0 +1 @@ +function foo(foo, bar = foo ?? "bar") {} diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-default/output.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-default/output.js new file mode 100644 index 000000000000..d725908ed2a8 --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-default/output.js @@ -0,0 +1 @@ +function foo(foo, bar = foo != null ? foo : "bar") {} diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-function/input.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-function/input.js new file mode 100644 index 000000000000..8e488a306361 --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-function/input.js @@ -0,0 +1,3 @@ +function foo() { + var foo = this ?? {}; +} diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-function/output.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-function/output.js new file mode 100644 index 000000000000..cbf17bc50297 --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform-static-refs-in-function/output.js @@ -0,0 +1,3 @@ +function foo() { + var foo = this != null ? this : {}; +} diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform/input.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform/input.js new file mode 100644 index 000000000000..63b28b6c23cb --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform/input.js @@ -0,0 +1,3 @@ +function foo(opts) { + var foo = opts.foo ?? "default"; +} diff --git a/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform/output.js b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform/output.js new file mode 100644 index 000000000000..ee76d1c950a9 --- /dev/null +++ b/packages/babel-plugin-proposal-nullish-coalescing-operator/test/fixtures/assumption-noDocumentAll/transform/output.js @@ -0,0 +1,5 @@ +function foo(opts) { + var _opts$foo; + + var foo = (_opts$foo = opts.foo) != null ? _opts$foo : "default"; +} diff --git a/packages/babel-plugin-proposal-object-rest-spread/src/index.js b/packages/babel-plugin-proposal-object-rest-spread/src/index.js index e1f9b7d51016..7179c20899ba 100644 --- a/packages/babel-plugin-proposal-object-rest-spread/src/index.js +++ b/packages/babel-plugin-proposal-object-rest-spread/src/index.js @@ -23,6 +23,11 @@ export default declare((api, opts) => { throw new Error(".loose must be a boolean, or undefined"); } + const ignoreFunctionLength = api.assumption("ignoreFunctionLength") ?? loose; + const objectRestNoSymbols = api.assumption("objectRestNoSymbols") ?? loose; + const pureGetters = api.assumption("pureGetters") ?? loose; + const setSpreadProperties = api.assumption("setSpreadProperties") ?? loose; + function getExtendsHelper(file) { return useBuiltIns ? t.memberExpression(t.identifier("Object"), t.identifier("assign")) @@ -133,7 +138,7 @@ export default declare((api, opts) => { } //expects path to an object pattern - function createObjectSpread(path, file, objRef) { + function createObjectRest(path, file, objRef) { const props = path.get("properties"); const last = props[props.length - 1]; t.assertRestElement(last.node); @@ -172,7 +177,9 @@ export default declare((api, opts) => { impureComputedPropertyDeclarators, restElement.argument, t.callExpression( - file.addHelper(`objectWithoutProperties${loose ? "Loose" : ""}`), + file.addHelper( + `objectWithoutProperties${objectRestNoSymbols ? "Loose" : ""}`, + ), [t.cloneNode(objRef), keyExpression], ), ]; @@ -275,7 +282,7 @@ export default declare((api, opts) => { idx >= i - 1 || paramsWithRestElement.has(idx); convertFunctionParams( path, - loose, + ignoreFunctionLength, shouldTransformParam, replaceRestElement, ); @@ -361,9 +368,9 @@ export default declare((api, opts) => { impureComputedPropertyDeclarators, argument, callExpression, - ] = createObjectSpread(objectPatternPath, file, ref); + ] = createObjectRest(objectPatternPath, file, ref); - if (loose) { + if (pureGetters) { removeUnusedExcludedKeys(objectPatternPath); } @@ -444,7 +451,7 @@ export default declare((api, opts) => { impureComputedPropertyDeclarators, argument, callExpression, - ] = createObjectSpread(leftPath, file, t.identifier(refName)); + ] = createObjectRest(leftPath, file, t.identifier(refName)); if (impureComputedPropertyDeclarators.length > 0) { nodes.push( @@ -553,7 +560,7 @@ export default declare((api, opts) => { if (!hasSpread(path.node)) return; let helper; - if (loose) { + if (setSpreadProperties) { helper = getExtendsHelper(file); } else { try { @@ -583,10 +590,9 @@ export default declare((api, opts) => { return; } - // In loose mode, we don't want to make multiple calls. We're assuming - // that the spread objects either don't use getters, or that the - // getters are pure and don't depend on the order of evaluation. - if (loose) { + // When we can assume that getters are pure and don't depend on + // the order of evaluation, we can avoid making multiple calls. + if (pureGetters) { if (hadProps) { exp.arguments.push(obj); } diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-ignoreFunctionLength/options.json b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-ignoreFunctionLength/options.json new file mode 100644 index 000000000000..ec966b0b43ba --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-ignoreFunctionLength/options.json @@ -0,0 +1,8 @@ +{ + "plugins": [ + "proposal-object-rest-spread" + ], + "assumptions": { + "ignoreFunctionLength": true + } +} diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-ignoreFunctionLength/parameters-object-rest-used-in-default/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-ignoreFunctionLength/parameters-object-rest-used-in-default/input.js new file mode 100644 index 000000000000..000e99bcf250 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-ignoreFunctionLength/parameters-object-rest-used-in-default/input.js @@ -0,0 +1,3 @@ +({...R}, a = R) => {} +({...R}, e, c = 2, a = R, f = q) => { let q; } +({...R}, a = f(R)) => {} diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-ignoreFunctionLength/parameters-object-rest-used-in-default/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-ignoreFunctionLength/parameters-object-rest-used-in-default/output.js new file mode 100644 index 000000000000..84e28e863e5b --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-ignoreFunctionLength/parameters-object-rest-used-in-default/output.js @@ -0,0 +1,33 @@ +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +(_ref, a) => { + let R = _extends({}, _ref); + + if (a === void 0) { + a = R; + } +}; + +(_ref2, e, c = 2, a, f) => { + let R = _extends({}, _ref2); + + if (a === void 0) { + a = R; + } + + if (f === void 0) { + f = q; + } + + return function () { + let q; + }(); +}; + +(_ref3, a) => { + let R = _extends({}, _ref3); + + if (a === void 0) { + a = f(R); + } +}; diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/options.json b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/options.json new file mode 100644 index 000000000000..0640a8088af0 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0"}], + "proposal-object-rest-spread" + ], + "assumptions": { + "objectRestNoSymbols": true + } +} diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/input.js new file mode 100644 index 000000000000..f03be37640bc --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/input.js @@ -0,0 +1 @@ +({ a, b, ...c } = obj); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/output.js new file mode 100644 index 000000000000..a1b0485e897b --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/output.js @@ -0,0 +1,7 @@ +var _obj = obj; +({ + a, + b +} = _obj); +c = babelHelpers.objectWithoutPropertiesLoose(_obj, ["a", "b"]); +_obj; diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-computed/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-computed/input.js new file mode 100644 index 000000000000..8ddf55177eac --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-computed/input.js @@ -0,0 +1 @@ +let { [a]: b, ...c } = obj; diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-computed/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-computed/output.js new file mode 100644 index 000000000000..ffc31792901e --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-computed/output.js @@ -0,0 +1,5 @@ +let _a = a, + { + [_a]: b +} = obj, + c = babelHelpers.objectWithoutPropertiesLoose(obj, [_a].map(babelHelpers.toPropertyKey)); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-ignore-symbols/exec.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-ignore-symbols/exec.js new file mode 100644 index 000000000000..2c85a4c5711e --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-ignore-symbols/exec.js @@ -0,0 +1,7 @@ +let sym = Symbol(); + +let { a, ...r } = { a: 1, b: 2, [sym]: 3 }; + +expect(a).toBe(1); +expect(r.b).toBe(2); +expect(sym in r).toBe(false); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-nested/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-nested/input.js new file mode 100644 index 000000000000..e1025ccc4cb9 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-nested/input.js @@ -0,0 +1 @@ +let { a, nested: { b, c, ...d }, e } = obj; diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-nested/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-nested/output.js new file mode 100644 index 000000000000..8a0d9f86b1b7 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-nested/output.js @@ -0,0 +1,9 @@ +let { + a, + nested: { + b, + c + }, + e +} = obj, + d = babelHelpers.objectWithoutPropertiesLoose(obj.nested, ["b", "c"]); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/input.js new file mode 100644 index 000000000000..099aa76e4907 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/input.js @@ -0,0 +1 @@ +var { a, b, ...c } = obj; diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/output.js new file mode 100644 index 000000000000..dbacd1a572a3 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/output.js @@ -0,0 +1,5 @@ +var { + a, + b +} = obj, + c = babelHelpers.objectWithoutPropertiesLoose(obj, ["a", "b"]); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/options.json b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/options.json new file mode 100644 index 000000000000..63724ae13025 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0"}], + "proposal-object-rest-spread" + ], + "assumptions": { + "pureGetters": true + } +} diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/rest-remove-unused-excluded-keys/exec.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/rest-remove-unused-excluded-keys/exec.js new file mode 100644 index 000000000000..d3ad45c50d79 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/rest-remove-unused-excluded-keys/exec.js @@ -0,0 +1,11 @@ +let called = false; +let obj = { + get foo() { called = true } +}; + +let { foo, ...rest } = obj; + +expect("foo" in rest).toBe(false); + +// Without assuming that getters are pure (in this case it isn't), this should be true +expect(called).toBe(false); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/rest-remove-unused-excluded-keys/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/rest-remove-unused-excluded-keys/input.js new file mode 100644 index 000000000000..848847b6d5af --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/rest-remove-unused-excluded-keys/input.js @@ -0,0 +1,20 @@ +// should not remove when destructuring into existing bindings +({ a2, ...b2 } = c2); + +function render() { + const { + excluded, + excluded2: excludedRenamed, + used, + used2: usedRenamed, + ...props + } = this.props; + + console.log(used, usedRenamed); + + return React.createElement("input", props); +} + +function smth({ unused, ...rest }) { + call(rest); +} diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/rest-remove-unused-excluded-keys/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/rest-remove-unused-excluded-keys/output.js new file mode 100644 index 000000000000..cf80c637a3ef --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/rest-remove-unused-excluded-keys/output.js @@ -0,0 +1,23 @@ +// should not remove when destructuring into existing bindings +var _c = c2; +({ + a2 +} = _c); +b2 = babelHelpers.objectWithoutProperties(_c, ["a2"]); +_c; + +function render() { + const _this$props = this.props, + { + used, + used2: usedRenamed + } = _this$props, + props = babelHelpers.objectWithoutProperties(_this$props, ["excluded", "excluded2", "used", "used2"]); + console.log(used, usedRenamed); + return React.createElement("input", props); +} + +function smth(_ref) { + let rest = babelHelpers.objectWithoutProperties(_ref, ["unused"]); + call(rest); +} diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/spread-single-call/exec.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/spread-single-call/exec.js new file mode 100644 index 000000000000..16e821917d0e --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/spread-single-call/exec.js @@ -0,0 +1,10 @@ +let count = 0; + +let withFoo = { get foo() { return count++; } }; +let withBar = { get bar() { return count++; } }; + +let res = { ...withFoo, middle: count, ...withBar }; + +// Without assuming that getters are pure (in this case it isn't), +// the result should be { foo: 0, middle: 1, bar: 1 } +expect(res).toEqual({ foo: 0, middle: 0, bar: 1 }); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/spread-single-call/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/spread-single-call/input.js new file mode 100644 index 000000000000..bfc9f72440df --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/spread-single-call/input.js @@ -0,0 +1 @@ +let obj = { a, ...b, c, ...d, e }; diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/spread-single-call/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/spread-single-call/output.js new file mode 100644 index 000000000000..6aae4df0db26 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-pureGetters/spread-single-call/output.js @@ -0,0 +1,7 @@ +let obj = babelHelpers.objectSpread2({ + a +}, b, { + c +}, d, { + e +}); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/assignment/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/assignment/input.js new file mode 100644 index 000000000000..093a8e9f9351 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/assignment/input.js @@ -0,0 +1,7 @@ +var x; +var y; +var z; + +z = { x, ...y }; + +z = { x, w: { ...y } }; diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/assignment/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/assignment/output.js new file mode 100644 index 000000000000..8e9602898ed6 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/assignment/output.js @@ -0,0 +1,10 @@ +var x; +var y; +var z; +z = Object.assign({ + x +}, y); +z = { + x, + w: Object.assign({}, y) +}; diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/expression/exec.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/expression/exec.js new file mode 100644 index 000000000000..b57d8d3222b9 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/expression/exec.js @@ -0,0 +1,9 @@ +var log = []; + +var a = { + ...{ get foo() { log.push(1); } }, + get bar() { log.push(2); } +}; + +// Loose mode uses regular Get, not GetOwnProperty. +expect(log).toEqual([1, 2]); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/expression/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/expression/input.js new file mode 100644 index 000000000000..da4e7b689505 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/expression/input.js @@ -0,0 +1,16 @@ +var a; +var b; +var c; +var d; +var x; +var y; + +({ x, ...y, a, ...b, c }); + +({ ...Object.prototype }); + +({ ...{ foo: 'bar' } }); + +({ ...{ foo: 'bar' }, ...{ bar: 'baz' } }); + +({ ...{ get foo () { return 'foo' } } }); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/expression/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/expression/output.js new file mode 100644 index 000000000000..cfd3f3b62882 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/expression/output.js @@ -0,0 +1,28 @@ +var a; +var b; +var c; +var d; +var x; +var y; +Object.assign(Object.assign(Object.assign({ + x +}, y), {}, { + a +}, b), {}, { + c +}); +Object.assign({}, Object.prototype); +Object.assign({}, { + foo: 'bar' +}); +Object.assign(Object.assign({}, { + foo: 'bar' +}), { + bar: 'baz' +}); +Object.assign({}, { + get foo() { + return 'foo'; + } + +}); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/no-getOwnPropertyDescriptors/exec.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/no-getOwnPropertyDescriptors/exec.js new file mode 100644 index 000000000000..e4674d812a50 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/no-getOwnPropertyDescriptors/exec.js @@ -0,0 +1,9 @@ +const oldGOPDs = Object.getOwnPropertyDescriptors; +Object.getOwnPropertyDescriptors = null; + +try { + ({ ...{ a: 1 }, b: 1, ...{} }); +} finally { + Object.getOwnPropertyDescriptors = oldGOPDs; +} + diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/no-object-assign-exec/exec.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/no-object-assign-exec/exec.js new file mode 100644 index 000000000000..4d937710e367 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/no-object-assign-exec/exec.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(Object.prototype, 'NOSET', { + get(value) { + // noop + }, +}); + +Object.defineProperty(Object.prototype, 'NOWRITE', { + writable: false, + value: 'abc', +}); + +const obj = { 'NOSET': 123 }; +// this won't work as expected if transformed as Object.assign (or equivalent) +// because those trigger object setters (spread don't) +expect(() => { + const objSpread = { ...obj }; +}).toThrow(); + +const obj2 = { 'NOWRITE': 456 }; +// this throws `TypeError: Cannot assign to read only property 'NOWRITE'` +// if transformed as Object.assign (or equivalent) because those use *assignment* for creating properties +// (spread defines them) +expect(() => { + const obj2Spread = { ...obj2 }; +}).toThrow(); + +const KEY = Symbol('key'); +const obj3Spread = { ...{ get foo () { return 'bar' } }, [KEY]: 'symbol' }; +expect(Object.getOwnPropertyDescriptor(obj3Spread, 'foo').value).toBe('bar'); +expect(Object.getOwnPropertyDescriptor(obj3Spread, KEY).value).toBe('symbol'); + +const obj4Spread = { ...Object.prototype }; +expect(Object.getOwnPropertyDescriptor(obj4Spread, 'hasOwnProperty')).toBeUndefined(); + +expect(() => ({ ...null, ...undefined })).not.toThrow(); + +const o = Object.create(null); +o.a = 'foo'; +o.__proto__ = []; +const o2 = { ...o }; +// Loose will do o2.__proto__ = [] +expect(Array.isArray(Object.getPrototypeOf(o2))).toBe(true); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/options.json b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/options.json new file mode 100644 index 000000000000..d9e80e039563 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties-with-useBuiltIns/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0"}], + ["proposal-object-rest-spread", { "useBuiltIns": true }] + ], + "assumptions": { + "setSpreadProperties": true + } +} diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/assignment/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/assignment/input.js new file mode 100644 index 000000000000..093a8e9f9351 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/assignment/input.js @@ -0,0 +1,7 @@ +var x; +var y; +var z; + +z = { x, ...y }; + +z = { x, w: { ...y } }; diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/assignment/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/assignment/output.js new file mode 100644 index 000000000000..3e34747bd999 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/assignment/output.js @@ -0,0 +1,10 @@ +var x; +var y; +var z; +z = babelHelpers.extends({ + x +}, y); +z = { + x, + w: babelHelpers.extends({}, y) +}; diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/expression/exec.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/expression/exec.js new file mode 100644 index 000000000000..b57d8d3222b9 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/expression/exec.js @@ -0,0 +1,9 @@ +var log = []; + +var a = { + ...{ get foo() { log.push(1); } }, + get bar() { log.push(2); } +}; + +// Loose mode uses regular Get, not GetOwnProperty. +expect(log).toEqual([1, 2]); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/expression/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/expression/input.js new file mode 100644 index 000000000000..da4e7b689505 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/expression/input.js @@ -0,0 +1,16 @@ +var a; +var b; +var c; +var d; +var x; +var y; + +({ x, ...y, a, ...b, c }); + +({ ...Object.prototype }); + +({ ...{ foo: 'bar' } }); + +({ ...{ foo: 'bar' }, ...{ bar: 'baz' } }); + +({ ...{ get foo () { return 'foo' } } }); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/expression/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/expression/output.js new file mode 100644 index 000000000000..a21536eeb3aa --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/expression/output.js @@ -0,0 +1,28 @@ +var a; +var b; +var c; +var d; +var x; +var y; +babelHelpers.extends(babelHelpers.extends(babelHelpers.extends({ + x +}, y), {}, { + a +}, b), {}, { + c +}); +babelHelpers.extends({}, Object.prototype); +babelHelpers.extends({}, { + foo: 'bar' +}); +babelHelpers.extends(babelHelpers.extends({}, { + foo: 'bar' +}), { + bar: 'baz' +}); +babelHelpers.extends({}, { + get foo() { + return 'foo'; + } + +}); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/no-getOwnPropertyDescriptors/exec.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/no-getOwnPropertyDescriptors/exec.js new file mode 100644 index 000000000000..e4674d812a50 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/no-getOwnPropertyDescriptors/exec.js @@ -0,0 +1,9 @@ +const oldGOPDs = Object.getOwnPropertyDescriptors; +Object.getOwnPropertyDescriptors = null; + +try { + ({ ...{ a: 1 }, b: 1, ...{} }); +} finally { + Object.getOwnPropertyDescriptors = oldGOPDs; +} + diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/no-object-assign-exec/exec.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/no-object-assign-exec/exec.js new file mode 100644 index 000000000000..4d937710e367 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/no-object-assign-exec/exec.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(Object.prototype, 'NOSET', { + get(value) { + // noop + }, +}); + +Object.defineProperty(Object.prototype, 'NOWRITE', { + writable: false, + value: 'abc', +}); + +const obj = { 'NOSET': 123 }; +// this won't work as expected if transformed as Object.assign (or equivalent) +// because those trigger object setters (spread don't) +expect(() => { + const objSpread = { ...obj }; +}).toThrow(); + +const obj2 = { 'NOWRITE': 456 }; +// this throws `TypeError: Cannot assign to read only property 'NOWRITE'` +// if transformed as Object.assign (or equivalent) because those use *assignment* for creating properties +// (spread defines them) +expect(() => { + const obj2Spread = { ...obj2 }; +}).toThrow(); + +const KEY = Symbol('key'); +const obj3Spread = { ...{ get foo () { return 'bar' } }, [KEY]: 'symbol' }; +expect(Object.getOwnPropertyDescriptor(obj3Spread, 'foo').value).toBe('bar'); +expect(Object.getOwnPropertyDescriptor(obj3Spread, KEY).value).toBe('symbol'); + +const obj4Spread = { ...Object.prototype }; +expect(Object.getOwnPropertyDescriptor(obj4Spread, 'hasOwnProperty')).toBeUndefined(); + +expect(() => ({ ...null, ...undefined })).not.toThrow(); + +const o = Object.create(null); +o.a = 'foo'; +o.__proto__ = []; +const o2 = { ...o }; +// Loose will do o2.__proto__ = [] +expect(Array.isArray(Object.getPrototypeOf(o2))).toBe(true); diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/options.json b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/options.json new file mode 100644 index 000000000000..2ac8b8a6e836 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/assumption-setSpreadProperties/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0"}], + "proposal-object-rest-spread" + ], + "assumptions": { + "setSpreadProperties": true + } +} diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-rest/parameters-extra/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-rest/parameters-object-rest-used-in-default/input.js similarity index 100% rename from packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-rest/parameters-extra/input.js rename to packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-rest/parameters-object-rest-used-in-default/input.js diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-rest/parameters-extra/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-rest/parameters-object-rest-used-in-default/output.js similarity index 100% rename from packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-rest/parameters-extra/output.js rename to packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-rest/parameters-object-rest-used-in-default/output.js diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-spread-loose/parameters-object-rest-used-in-default/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-spread-loose/parameters-object-rest-used-in-default/input.js new file mode 100644 index 000000000000..000e99bcf250 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-spread-loose/parameters-object-rest-used-in-default/input.js @@ -0,0 +1,3 @@ +({...R}, a = R) => {} +({...R}, e, c = 2, a = R, f = q) => { let q; } +({...R}, a = f(R)) => {} diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-spread-loose/parameters-object-rest-used-in-default/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-spread-loose/parameters-object-rest-used-in-default/output.js new file mode 100644 index 000000000000..84e28e863e5b --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/object-spread-loose/parameters-object-rest-used-in-default/output.js @@ -0,0 +1,33 @@ +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +(_ref, a) => { + let R = _extends({}, _ref); + + if (a === void 0) { + a = R; + } +}; + +(_ref2, e, c = 2, a, f) => { + let R = _extends({}, _ref2); + + if (a === void 0) { + a = R; + } + + if (f === void 0) { + f = q; + } + + return function () { + let q; + }(); +}; + +(_ref3, a) => { + let R = _extends({}, _ref3); + + if (a === void 0) { + a = f(R); + } +}; diff --git a/packages/babel-plugin-proposal-optional-chaining/src/index.js b/packages/babel-plugin-proposal-optional-chaining/src/index.js index 052c71b6f048..d6e72baa0f98 100644 --- a/packages/babel-plugin-proposal-optional-chaining/src/index.js +++ b/packages/babel-plugin-proposal-optional-chaining/src/index.js @@ -13,6 +13,8 @@ export default declare((api, options) => { api.assertVersion(7); const { loose = false } = options; + const noDocumentAll = api.assumption("noDocumentAll") ?? loose; + const pureGetters = api.assumption("pureGetters") ?? loose; function isSimpleMemberExpression(expression) { expression = skipTransparentExprWrappers(expression); @@ -127,8 +129,8 @@ export default declare((api, options) => { check = ref = chain; // `eval?.()` is an indirect eval call transformed to `(0,eval)()` node[replaceKey] = t.sequenceExpression([t.numericLiteral(0), ref]); - } else if (loose && isCall && isSimpleMemberExpression(chain)) { - // If we are using a loose transform (avoiding a Function#call) and we are at the call, + } else if (pureGetters && isCall && isSimpleMemberExpression(chain)) { + // If we assume getters are pure (avoiding a Function#call) and we are at the call, // we can avoid a needless memoize. We only do this if the callee is a simple member // expression, to avoid multiple calls to nested call expressions. check = ref = chainWithTypes; @@ -153,7 +155,7 @@ export default declare((api, options) => { // Ensure call expressions have the proper `this` // `foo.bar()` has context `foo`. if (isCall && t.isMemberExpression(chain)) { - if (loose && isSimpleMemberExpression(chain)) { + if (pureGetters && isSimpleMemberExpression(chain)) { // To avoid a Function#call, we can instead re-grab the property from the context object. // `a.?b.?()` translates roughly to `_a.b != null && _a.b()` node.callee = chainWithTypes; @@ -188,8 +190,9 @@ export default declare((api, options) => { replacementPath.get("object"), ).node; let baseRef; - if (!loose || !isSimpleMemberExpression(object)) { - // memoize the context object in non-loose mode + if (!pureGetters || !isSimpleMemberExpression(object)) { + // memoize the context object when getters are not always pure + // or the object is not a simple member expression // `(a?.b.c)()` to `(a == null ? undefined : (_a$b = a.b).c.bind(_a$b))()` baseRef = scope.maybeGenerateMemoised(object); if (baseRef) { @@ -210,7 +213,7 @@ export default declare((api, options) => { // `if (a?.b) {}` transformed to `if (a != null && a.b) {}` // we don't need to return `void 0` because the returned value will // eveutally cast to boolean. - const nonNullishCheck = loose + const nonNullishCheck = noDocumentAll ? ast`${t.cloneNode(check)} != null` : ast` ${t.cloneNode(check)} !== null && ${t.cloneNode(ref)} !== void 0`; @@ -221,7 +224,7 @@ export default declare((api, options) => { replacementPath.get("right"), ); } else { - const nullishCheck = loose + const nullishCheck = noDocumentAll ? ast`${t.cloneNode(check)} == null` : ast` ${t.cloneNode(check)} === null || ${t.cloneNode(ref)} === void 0`; diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/exec.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/exec.js new file mode 100644 index 000000000000..48bcd49d016e --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/exec.js @@ -0,0 +1,28 @@ +"use strict"; + +const obj = { + a: { + b: { + c: { + d: 2, + }, + }, + }, +}; + +const a = obj?.a; +expect(a).toBe(obj.a); + +const b = obj?.a?.b; +expect(b).toBe(obj.a.b); + +const bad = obj?.b?.b; +expect(bad).toBeUndefined(); + +let val; +val = obj?.a?.b; +expect(val).toBe(obj.a.b); + +expect(() => { + const bad = obj?.b.b; +}).toThrow(); diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/input.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/input.js new file mode 100644 index 000000000000..86e2d6e46d22 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/input.js @@ -0,0 +1,20 @@ +"use strict"; + +const obj = { + a: { + b: { + c: { + d: 2, + }, + }, + }, +}; + +const a = obj?.a; + +const b = obj?.a?.b; + +const bad = obj?.b?.b; + +let val; +val = obj?.a?.b; diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/output.js new file mode 100644 index 000000000000..778b9a11d450 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/output.js @@ -0,0 +1,18 @@ +"use strict"; + +var _obj$a, _obj$b, _obj$a2; + +const obj = { + a: { + b: { + c: { + d: 2 + } + } + } +}; +const a = obj == null ? void 0 : obj.a; +const b = obj == null ? void 0 : (_obj$a = obj.a) == null ? void 0 : _obj$a.b; +const bad = obj == null ? void 0 : (_obj$b = obj.b) == null ? void 0 : _obj$b.b; +let val; +val = obj == null ? void 0 : (_obj$a2 = obj.a) == null ? void 0 : _obj$a2.b; diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/call/exec.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/call/exec.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/exec.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/exec.js new file mode 100644 index 000000000000..77ae4c0a0706 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/exec.js @@ -0,0 +1,120 @@ +class C { + static testIf(o) { + if (o?.a.b.c.d) { + return true; + } + return false; + } + static testConditional(o) { + return o?.a.b?.c.d ? true : false; + } + static testLoop(o) { + while (o?.a.b.c.d) { + for (; o?.a.b.c?.d; ) { + let i = 0; + do { + i++; + if (i === 2) { + return true; + } + } while (o?.a.b?.c.d); + } + } + return false; + } + static testNegate(o) { + return !!o?.a.b?.c.d; + } + static testIfDeep(o) { + if (o.obj?.a.b?.c.d) { + return true; + } + return false; + } + static testConditionalDeep(o) { + return o.obj?.a.b?.c.d ? true : false; + } + static testLoopDeep(o) { + while (o.obj?.a.b.c.d) { + for (; o.obj?.a.b.c?.d; ) { + let i = 0; + do { + i++; + if (i === 2) { + return true; + } + } while (o.obj?.a.b?.c.d); + } + } + return false; + } + static testNegateDeep(o) { + return !!o.obj?.a.b?.c.d; + } + + static testLogicalInIf(o) { + if (o?.a.b?.c.d && o?.a?.b.c.d) { + return true; + } + return false; + } + + static testLogicalInReturn(o) { + return o?.a.b?.c.d && o?.a?.b.c.d; + } + + static testNullishCoalescing(o) { + if (o?.a.b?.c.non_existent ?? o?.a.b?.c.d) { + return o?.a.b?.c.non_existent ?? o?.a.b?.c.d; + } + return o?.a.b?.c.non_existent ?? o; + } + + static test() { + const c = { + a: { + b: { + c: { + d: 2, + }, + }, + }, + }; + expect(C.testIf(c)).toBe(true); + expect(C.testConditional(c)).toBe(true); + expect(C.testLoop(c)).toBe(true); + expect(C.testNegate(c)).toBe(true); + + expect(C.testIfDeep({ obj: c })).toBe(true); + expect(C.testConditionalDeep({ obj: c })).toBe(true); + expect(C.testLoopDeep({ obj: c })).toBe(true); + expect(C.testNegateDeep({ obj: c })).toBe(true); + + expect(C.testLogicalInIf(c)).toBe(true); + expect(C.testLogicalInReturn(c)).toBe(2); + + expect(C.testNullishCoalescing(c)).toBe(2); + } + + static testNullish() { + for (const n of [null, undefined]) { + expect(C.testIf(n)).toBe(false); + expect(C.testConditional(n)).toBe(false); + expect(C.testLoop(n)).toBe(false); + expect(C.testNegate(n)).toBe(false); + + expect(C.testIfDeep({ obj: n })).toBe(false); + expect(C.testConditionalDeep({ obj: n })).toBe(false); + expect(C.testLoopDeep({ obj: n })).toBe(false); + expect(C.testNegateDeep({ obj: n })).toBe(false); + + expect(C.testLogicalInIf(n)).toBe(false); + expect(C.testLogicalInReturn(n)).toBe(undefined); + + expect(C.testNullishCoalescing(n)).toBe(n); + } + } +} + +C.test(); +C.testNullish(); diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/input.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/input.js new file mode 100644 index 000000000000..a9aab8bee395 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/input.js @@ -0,0 +1,75 @@ +class C { + static testIf(o) { + if (o?.a.b.c.d) { + return true; + } + return false; + } + static testConditional(o) { + return o?.a.b?.c.d ? true : false; + } + static testLoop(o) { + while (o?.a.b.c.d) { + for (; o?.a.b.c?.d; ) { + let i = 0; + do { + i++; + if (i === 2) { + return true; + } + } while (o?.a.b?.c.d); + } + } + return false; + } + static testNegate(o) { + return !!o?.a.b?.c.d; + } + static testIfDeep(o) { + if (o.obj?.a.b?.c.d) { + return true; + } + return false; + } + static testConditionalDeep(o) { + return o.obj?.a.b?.c.d ? true : false; + } + static testLoopDeep(o) { + while (o.obj?.a.b.c.d) { + for (; o.obj?.a.b.c?.d; ) { + let i = 0; + do { + i++; + if (i === 2) { + return true; + } + } while (o.obj?.a.b?.c.d); + } + } + return false; + } + static testNegateDeep(o) { + return !!o.obj?.a.b?.c.d; + } + + static testLogicalInIf(o) { + if (o?.a.b?.c.d && o?.a?.b.c.d) { + return true; + } + return false; + } + + static testLogicalInReturn(o) { + return o?.a.b?.c.d && o?.a?.b.c.d; + } + + static testNullishCoalescing(o) { + if (o?.a.b?.c.non_existent ?? o?.a.b?.c.d) { + return o?.a.b?.c.non_existent ?? o?.a.b?.c.d; + } + return o?.a.b?.c.non_existent ?? o; + } +} + +C.test(); +C.testNullish(); diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/options.json b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/options.json new file mode 100644 index 000000000000..f55bb7215867 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["proposal-optional-chaining", "proposal-nullish-coalescing-operator"] +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/output.js new file mode 100644 index 000000000000..4b41cfb287c7 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/output.js @@ -0,0 +1,121 @@ +class C { + static testIf(o) { + if (o != null && o.a.b.c.d) { + return true; + } + + return false; + } + + static testConditional(o) { + var _o$a$b; + + return o != null && (_o$a$b = o.a.b) != null && _o$a$b.c.d ? true : false; + } + + static testLoop(o) { + while (o != null && o.a.b.c.d) { + for (; o != null && (_o$a$b$c = o.a.b.c) != null && _o$a$b$c.d;) { + var _o$a$b$c; + + let i = 0; + + do { + var _o$a$b2; + + i++; + + if (i === 2) { + return true; + } + } while (o != null && (_o$a$b2 = o.a.b) != null && _o$a$b2.c.d); + } + } + + return false; + } + + static testNegate(o) { + var _o$a$b3; + + return !!(o != null && (_o$a$b3 = o.a.b) != null && _o$a$b3.c.d); + } + + static testIfDeep(o) { + var _o$obj, _o$obj$a$b; + + if ((_o$obj = o.obj) != null && (_o$obj$a$b = _o$obj.a.b) != null && _o$obj$a$b.c.d) { + return true; + } + + return false; + } + + static testConditionalDeep(o) { + var _o$obj2, _o$obj2$a$b; + + return (_o$obj2 = o.obj) != null && (_o$obj2$a$b = _o$obj2.a.b) != null && _o$obj2$a$b.c.d ? true : false; + } + + static testLoopDeep(o) { + while ((_o$obj3 = o.obj) != null && _o$obj3.a.b.c.d) { + var _o$obj3; + + for (; (_o$obj4 = o.obj) != null && (_o$obj4$a$b$c = _o$obj4.a.b.c) != null && _o$obj4$a$b$c.d;) { + var _o$obj4, _o$obj4$a$b$c; + + let i = 0; + + do { + var _o$obj5, _o$obj5$a$b; + + i++; + + if (i === 2) { + return true; + } + } while ((_o$obj5 = o.obj) != null && (_o$obj5$a$b = _o$obj5.a.b) != null && _o$obj5$a$b.c.d); + } + } + + return false; + } + + static testNegateDeep(o) { + var _o$obj6, _o$obj6$a$b; + + return !!((_o$obj6 = o.obj) != null && (_o$obj6$a$b = _o$obj6.a.b) != null && _o$obj6$a$b.c.d); + } + + static testLogicalInIf(o) { + var _o$a$b4, _o$a; + + if (o != null && (_o$a$b4 = o.a.b) != null && _o$a$b4.c.d && o != null && (_o$a = o.a) != null && _o$a.b.c.d) { + return true; + } + + return false; + } + + static testLogicalInReturn(o) { + var _o$a$b5, _o$a2; + + return (o == null ? void 0 : (_o$a$b5 = o.a.b) == null ? void 0 : _o$a$b5.c.d) && (o == null ? void 0 : (_o$a2 = o.a) == null ? void 0 : _o$a2.b.c.d); + } + + static testNullishCoalescing(o) { + var _o$a$b$c$non_existent, _o$a$b6, _o$a$b7, _o$a$b$c$non_existent3, _o$a$b10; + + if ((_o$a$b$c$non_existent = o == null ? void 0 : (_o$a$b6 = o.a.b) == null ? void 0 : _o$a$b6.c.non_existent) != null ? _o$a$b$c$non_existent : o == null ? void 0 : (_o$a$b7 = o.a.b) == null ? void 0 : _o$a$b7.c.d) { + var _o$a$b$c$non_existent2, _o$a$b8, _o$a$b9; + + return (_o$a$b$c$non_existent2 = o == null ? void 0 : (_o$a$b8 = o.a.b) == null ? void 0 : _o$a$b8.c.non_existent) != null ? _o$a$b$c$non_existent2 : o == null ? void 0 : (_o$a$b9 = o.a.b) == null ? void 0 : _o$a$b9.c.d; + } + + return (_o$a$b$c$non_existent3 = o == null ? void 0 : (_o$a$b10 = o.a.b) == null ? void 0 : _o$a$b10.c.non_existent) != null ? _o$a$b$c$non_existent3 : o; + } + +} + +C.test(); +C.testNullish(); diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/in-function-params/input.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/in-function-params/input.js new file mode 100644 index 000000000000..882511b447f8 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/in-function-params/input.js @@ -0,0 +1,9 @@ +function f(a = x?.y) {} + +function g({ a, b = a?.c }) {} + +function h(a, { b = a.b?.c?.d.e }) {} + +function i(a, { b = (a.b?.c?.d).e }) {} + +function j(a, { b = a?.b?.c().d.e }) {} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/in-function-params/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/in-function-params/output.js new file mode 100644 index 000000000000..f5cda260cbfe --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/in-function-params/output.js @@ -0,0 +1,34 @@ +function f(a = (() => { + var _x; + + return (_x = x) == null ? void 0 : _x.y; +})()) {} + +function g({ + a, + b = a == null ? void 0 : a.c +}) {} + +function h(a, { + b = (() => { + var _a$b, _a$b$c; + + return (_a$b = a.b) == null ? void 0 : (_a$b$c = _a$b.c) == null ? void 0 : _a$b$c.d.e; + })() +}) {} + +function i(a, { + b = (() => { + var _a$b2, _a$b2$c; + + return (_a$b2 = a.b) == null ? void 0 : (_a$b2$c = _a$b2.c) == null ? void 0 : _a$b2$c.d; + })().e +}) {} + +function j(a, { + b = (() => { + var _a$b3; + + return a == null ? void 0 : (_a$b3 = a.b) == null ? void 0 : _a$b3.c().d.e; + })() +}) {} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/input.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/input.js new file mode 100644 index 000000000000..bbb26771f34e --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/input.js @@ -0,0 +1,29 @@ +function test(foo) { + foo?.bar; + + foo?.bar?.baz; + + foo?.(foo); + + foo?.bar() + + foo.get(bar)?.() + + foo.bar()?.() + foo[bar]()?.() + + foo.bar().baz?.() + foo[bar]().baz?.() + + foo.bar?.(foo.bar, false) + + foo?.bar?.(foo.bar, true) + + foo.bar?.baz(foo.bar, false) + + foo?.bar?.baz(foo.bar, true) + + foo.bar?.baz?.(foo.bar, false) + + foo?.bar?.baz?.(foo.bar, true) +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/output.js new file mode 100644 index 000000000000..3d48a529d4cf --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/output.js @@ -0,0 +1,19 @@ +function test(foo) { + var _foo$bar, _foo$get, _foo$bar2, _foo$bar3, _foo$bar$baz, _foo$bar4, _foo$bar$baz2, _foo$bar5, _foo$bar6, _foo$bar7, _foo$bar8, _foo$bar9, _foo$bar10, _foo$bar10$baz, _foo$bar11, _foo$bar11$baz; + + foo == null ? void 0 : foo.bar; + foo == null ? void 0 : (_foo$bar = foo.bar) == null ? void 0 : _foo$bar.baz; + foo == null ? void 0 : foo(foo); + foo == null ? void 0 : foo.bar(); + (_foo$get = foo.get(bar)) == null ? void 0 : _foo$get(); + (_foo$bar2 = foo.bar()) == null ? void 0 : _foo$bar2(); + (_foo$bar3 = foo[bar]()) == null ? void 0 : _foo$bar3(); + (_foo$bar$baz = (_foo$bar4 = foo.bar()).baz) == null ? void 0 : _foo$bar$baz.call(_foo$bar4); + (_foo$bar$baz2 = (_foo$bar5 = foo[bar]()).baz) == null ? void 0 : _foo$bar$baz2.call(_foo$bar5); + (_foo$bar6 = foo.bar) == null ? void 0 : _foo$bar6.call(foo, foo.bar, false); + foo == null ? void 0 : (_foo$bar7 = foo.bar) == null ? void 0 : _foo$bar7.call(foo, foo.bar, true); + (_foo$bar8 = foo.bar) == null ? void 0 : _foo$bar8.baz(foo.bar, false); + foo == null ? void 0 : (_foo$bar9 = foo.bar) == null ? void 0 : _foo$bar9.baz(foo.bar, true); + (_foo$bar10 = foo.bar) == null ? void 0 : (_foo$bar10$baz = _foo$bar10.baz) == null ? void 0 : _foo$bar10$baz.call(_foo$bar10, foo.bar, false); + foo == null ? void 0 : (_foo$bar11 = foo.bar) == null ? void 0 : (_foo$bar11$baz = _foo$bar11.baz) == null ? void 0 : _foo$bar11$baz.call(_foo$bar11, foo.bar, true); +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/optional-eval-call/input.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/optional-eval-call/input.js new file mode 100644 index 000000000000..731610528ac4 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/optional-eval-call/input.js @@ -0,0 +1,22 @@ +var foo; + +/* indirect eval calls */ +eval?.(foo); + +(eval)?.(foo); + +eval?.()(); + +eval?.().foo; + +/* direct eval calls */ + +eval()?.(); + +eval()?.foo; + +/* plain function calls */ + +foo.eval?.(foo); + +eval.foo?.(foo); diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/optional-eval-call/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/optional-eval-call/output.js new file mode 100644 index 000000000000..a6fd734cae72 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/optional-eval-call/output.js @@ -0,0 +1,17 @@ +var _eval, _eval2, _foo$eval, _eval$foo; + +var foo; +/* indirect eval calls */ + +eval == null ? void 0 : (0, eval)(foo); +eval == null ? void 0 : (0, eval)(foo); +eval == null ? void 0 : (0, eval)()(); +eval == null ? void 0 : (0, eval)().foo; +/* direct eval calls */ + +(_eval = eval()) == null ? void 0 : _eval(); +(_eval2 = eval()) == null ? void 0 : _eval2.foo; +/* plain function calls */ + +(_foo$eval = foo.eval) == null ? void 0 : _foo$eval.call(foo, foo); +(_eval$foo = eval.foo) == null ? void 0 : _eval$foo.call(eval, foo); diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/options.json b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/options.json new file mode 100644 index 000000000000..6f85efc683b3 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["proposal-optional-chaining"], + "assumptions": { + "noDocumentAll": true + } +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/parenthesized-expression-member-call/exec.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/parenthesized-expression-member-call/exec.js new file mode 100644 index 000000000000..2af236e11a8b --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/parenthesized-expression-member-call/exec.js @@ -0,0 +1,51 @@ +class Foo { + constructor() { + this.x = 1; + this.self = this; + } + m() { return this.x; }; + getSelf() { return this } + + test() { + const Foo = this; + const o = { Foo: Foo }; + const fn = function () { + return o; + }; + + expect((Foo?.["m"])()).toEqual(1); + expect((Foo?.["m"])().toString).toEqual(1..toString); + expect((Foo?.["m"])().toString()).toEqual('1'); + + expect(((Foo?.["m"]))()).toEqual(1); + expect(((Foo?.["m"]))().toString).toEqual(1..toString); + expect(((Foo?.["m"]))().toString()).toEqual('1'); + + expect((o?.Foo.m)()).toEqual(1); + expect((o?.Foo.m)().toString).toEqual(1..toString); + expect((o?.Foo.m)().toString()).toEqual('1'); + + expect((((o.Foo?.self.getSelf)())?.m)()).toEqual(1); + expect((((o.Foo.self?.getSelf)())?.m)()).toEqual(1); + + expect((((fn()?.Foo?.self.getSelf)())?.m)()).toEqual(1); + expect((((fn?.().Foo.self?.getSelf)())?.m)()).toEqual(1); + } + + testNull() { + const o = null; + + expect(() => { (o?.Foo.m)() }).toThrow(); + expect(() => { (o?.Foo.m)().toString }).toThrow(); + expect(() => { (o?.Foo.m)().toString() }).toThrow(); + + expect(() => { (((o.Foo?.self.getSelf)())?.m)() }).toThrow(); + expect(() => { (((o.Foo.self?.getSelf)())?.m)() }).toThrow(); + + expect(() => (((fn()?.Foo?.self.getSelf)())?.m)()).toThrow(); + expect(() => (((fn?.().Foo.self?.getSelf)())?.m)()).toThrow(); + } +} + +(new Foo).test(); +(new Foo).testNull(); diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/parenthesized-expression-member-call/options.json b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/parenthesized-expression-member-call/options.json new file mode 100644 index 000000000000..2931a52b5b3f --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/parenthesized-expression-member-call/options.json @@ -0,0 +1,5 @@ +{ + "parserOpts": { + "createParenthesizedExpressions": true + } +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/super-method-call/input.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/super-method-call/input.js new file mode 100644 index 000000000000..445c06ab259e --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/super-method-call/input.js @@ -0,0 +1,12 @@ +"use strict"; +class Base { + method() { + return 'Hello!'; + } +} + +class Derived extends Base { + method() { + return super.method?.() + } +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/super-method-call/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/super-method-call/output.js new file mode 100644 index 000000000000..a274b60b9e65 --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-noDocumentAll/super-method-call/output.js @@ -0,0 +1,17 @@ +"use strict"; + +class Base { + method() { + return 'Hello!'; + } + +} + +class Derived extends Base { + method() { + var _super$method; + + return (_super$method = super.method) == null ? void 0 : _super$method.call(this); + } + +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/function-call/input.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/function-call/input.js new file mode 100644 index 000000000000..51882eacf65d --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/function-call/input.js @@ -0,0 +1,19 @@ +foo?.(foo); + +foo?.bar() + +foo.bar?.(foo.bar, false) + +foo?.bar?.(foo.bar, true) + +foo?.().bar + +foo?.()?.bar + +foo.bar?.().baz + +foo.bar?.()?.baz + +foo?.bar?.().baz + +foo?.bar?.()?.baz diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/function-call/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/function-call/output.js new file mode 100644 index 000000000000..5b41f4a9fd6e --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/function-call/output.js @@ -0,0 +1,12 @@ +var _foo, _foo2, _foo3, _foo$bar, _foo4, _foo5, _foo5$bar; + +foo === null || foo === void 0 ? void 0 : foo(foo); +(_foo = foo) === null || _foo === void 0 ? void 0 : _foo.bar(); +foo.bar === null || foo.bar === void 0 ? void 0 : foo.bar(foo.bar, false); +(_foo2 = foo) === null || _foo2 === void 0 ? void 0 : _foo2.bar === null || _foo2.bar === void 0 ? void 0 : _foo2.bar(foo.bar, true); +foo === null || foo === void 0 ? void 0 : foo().bar; +foo === null || foo === void 0 ? void 0 : (_foo3 = foo()) === null || _foo3 === void 0 ? void 0 : _foo3.bar; +foo.bar === null || foo.bar === void 0 ? void 0 : foo.bar().baz; +foo.bar === null || foo.bar === void 0 ? void 0 : (_foo$bar = foo.bar()) === null || _foo$bar === void 0 ? void 0 : _foo$bar.baz; +(_foo4 = foo) === null || _foo4 === void 0 ? void 0 : _foo4.bar === null || _foo4.bar === void 0 ? void 0 : _foo4.bar().baz; +(_foo5 = foo) === null || _foo5 === void 0 ? void 0 : _foo5.bar === null || _foo5.bar === void 0 ? void 0 : (_foo5$bar = _foo5.bar()) === null || _foo5$bar === void 0 ? void 0 : _foo5$bar.baz; diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/memoize/input.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/memoize/input.js new file mode 100644 index 000000000000..bbb26771f34e --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/memoize/input.js @@ -0,0 +1,29 @@ +function test(foo) { + foo?.bar; + + foo?.bar?.baz; + + foo?.(foo); + + foo?.bar() + + foo.get(bar)?.() + + foo.bar()?.() + foo[bar]()?.() + + foo.bar().baz?.() + foo[bar]().baz?.() + + foo.bar?.(foo.bar, false) + + foo?.bar?.(foo.bar, true) + + foo.bar?.baz(foo.bar, false) + + foo?.bar?.baz(foo.bar, true) + + foo.bar?.baz?.(foo.bar, false) + + foo?.bar?.baz?.(foo.bar, true) +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/memoize/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/memoize/output.js new file mode 100644 index 000000000000..4ac4eb12be8c --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/memoize/output.js @@ -0,0 +1,19 @@ +function test(foo) { + var _foo$bar, _foo$get, _foo$bar2, _foo$bar3, _foo$bar$baz, _foo$bar4, _foo$bar$baz2, _foo$bar5, _foo$bar6, _foo$bar7, _foo$bar8, _foo$bar9; + + foo === null || foo === void 0 ? void 0 : foo.bar; + foo === null || foo === void 0 ? void 0 : (_foo$bar = foo.bar) === null || _foo$bar === void 0 ? void 0 : _foo$bar.baz; + foo === null || foo === void 0 ? void 0 : foo(foo); + foo === null || foo === void 0 ? void 0 : foo.bar(); + (_foo$get = foo.get(bar)) === null || _foo$get === void 0 ? void 0 : _foo$get(); + (_foo$bar2 = foo.bar()) === null || _foo$bar2 === void 0 ? void 0 : _foo$bar2(); + (_foo$bar3 = foo[bar]()) === null || _foo$bar3 === void 0 ? void 0 : _foo$bar3(); + (_foo$bar$baz = (_foo$bar4 = foo.bar()).baz) === null || _foo$bar$baz === void 0 ? void 0 : _foo$bar$baz.call(_foo$bar4); + (_foo$bar$baz2 = (_foo$bar5 = foo[bar]()).baz) === null || _foo$bar$baz2 === void 0 ? void 0 : _foo$bar$baz2.call(_foo$bar5); + foo.bar === null || foo.bar === void 0 ? void 0 : foo.bar(foo.bar, false); + foo === null || foo === void 0 ? void 0 : foo.bar === null || foo.bar === void 0 ? void 0 : foo.bar(foo.bar, true); + (_foo$bar6 = foo.bar) === null || _foo$bar6 === void 0 ? void 0 : _foo$bar6.baz(foo.bar, false); + foo === null || foo === void 0 ? void 0 : (_foo$bar7 = foo.bar) === null || _foo$bar7 === void 0 ? void 0 : _foo$bar7.baz(foo.bar, true); + (_foo$bar8 = foo.bar) === null || _foo$bar8 === void 0 ? void 0 : _foo$bar8.baz === null || _foo$bar8.baz === void 0 ? void 0 : _foo$bar8.baz(foo.bar, false); + foo === null || foo === void 0 ? void 0 : (_foo$bar9 = foo.bar) === null || _foo$bar9 === void 0 ? void 0 : _foo$bar9.baz === null || _foo$bar9.baz === void 0 ? void 0 : _foo$bar9.baz(foo.bar, true); +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/options.json b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/options.json new file mode 100644 index 000000000000..05b80d0efb8f --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["proposal-optional-chaining"], + "assumptions": { + "pureGetters": true + } +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/super-method-call/input.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/super-method-call/input.js new file mode 100644 index 000000000000..445c06ab259e --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/super-method-call/input.js @@ -0,0 +1,12 @@ +"use strict"; +class Base { + method() { + return 'Hello!'; + } +} + +class Derived extends Base { + method() { + return super.method?.() + } +} diff --git a/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/super-method-call/output.js b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/super-method-call/output.js new file mode 100644 index 000000000000..e51be18dde9a --- /dev/null +++ b/packages/babel-plugin-proposal-optional-chaining/test/fixtures/assumption-pureGetters/super-method-call/output.js @@ -0,0 +1,15 @@ +"use strict"; + +class Base { + method() { + return 'Hello!'; + } + +} + +class Derived extends Base { + method() { + return super.method === null || super.method === void 0 ? void 0 : super.method(); + } + +} diff --git a/packages/babel-plugin-proposal-private-methods/src/index.js b/packages/babel-plugin-proposal-private-methods/src/index.js index 0efbf93682a6..31652dfcfacb 100644 --- a/packages/babel-plugin-proposal-private-methods/src/index.js +++ b/packages/babel-plugin-proposal-private-methods/src/index.js @@ -12,6 +12,7 @@ export default declare((api, options) => { return createClassFeaturePlugin({ name: "proposal-private-methods", + api, feature: FEATURES.privateMethods, loose: options.loose, diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/basic/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/basic/exec.js new file mode 100644 index 000000000000..3cdb24863398 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/basic/exec.js @@ -0,0 +1,31 @@ +class Cl { + #privateField = "top secret string"; + + constructor() { + this.publicField = "not secret string"; + } + + get #privateFieldValue() { + return this.#privateField; + } + + set #privateFieldValue(newValue) { + this.#privateField = newValue; + } + + publicGetPrivateField() { + return this.#privateFieldValue; + } + + publicSetPrivateField(newValue) { + this.#privateFieldValue = newValue; + } +} + +const cl = new Cl(); + +expect(cl.publicGetPrivateField()).toEqual("top secret string"); + +cl.publicSetPrivateField("new secret string"); +expect(cl.publicGetPrivateField()).toEqual("new secret string"); + diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/basic/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/basic/input.js new file mode 100644 index 000000000000..53e77128c0bd --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/basic/input.js @@ -0,0 +1,23 @@ +class Cl { + #privateField = "top secret string"; + + constructor() { + this.publicField = "not secret string"; + } + + get #privateFieldValue() { + return this.#privateField; + } + + set #privateFieldValue(newValue) { + this.#privateField = newValue; + } + + publicGetPrivateField() { + return this.#privateFieldValue; + } + + publicSetPrivateField(newValue) { + this.#privateFieldValue = newValue; + } +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/basic/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/basic/output.js new file mode 100644 index 000000000000..e450d62cb5e8 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/basic/output.js @@ -0,0 +1,34 @@ +var _privateField = babelHelpers.classPrivateFieldLooseKey("privateField"); + +var _privateFieldValue = babelHelpers.classPrivateFieldLooseKey("privateFieldValue"); + +class Cl { + constructor() { + Object.defineProperty(this, _privateFieldValue, { + get: _get_privateFieldValue, + set: _set_privateFieldValue + }); + Object.defineProperty(this, _privateField, { + writable: true, + value: "top secret string" + }); + this.publicField = "not secret string"; + } + + publicGetPrivateField() { + return babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue]; + } + + publicSetPrivateField(newValue) { + babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue] = newValue; + } + +} + +var _get_privateFieldValue = function () { + return babelHelpers.classPrivateFieldLooseBase(this, _privateField)[_privateField]; +}; + +var _set_privateFieldValue = function (newValue) { + babelHelpers.classPrivateFieldLooseBase(this, _privateField)[_privateField] = newValue; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/get-only-setter/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/get-only-setter/exec.js new file mode 100644 index 000000000000..92e8197700c0 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/get-only-setter/exec.js @@ -0,0 +1,13 @@ +class Cl { + #privateField = 0; + + set #privateFieldValue(newValue) { + this.#privateField = newValue; + } + + constructor() { + expect(this.#privateFieldValue).toBeUndefined(); + } +} + +const cl = new Cl(); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/get-only-setter/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/get-only-setter/input.js new file mode 100644 index 000000000000..d676919b85eb --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/get-only-setter/input.js @@ -0,0 +1,11 @@ +class Cl { + #privateField = 0; + + set #privateFieldValue(newValue) { + this.#privateField = newValue; + } + + constructor() { + this.publicField = this.#privateFieldValue; + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/get-only-setter/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/get-only-setter/output.js new file mode 100644 index 000000000000..b68476be9665 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/get-only-setter/output.js @@ -0,0 +1,22 @@ +var _privateField = babelHelpers.classPrivateFieldLooseKey("privateField"); + +var _privateFieldValue = babelHelpers.classPrivateFieldLooseKey("privateFieldValue"); + +class Cl { + constructor() { + Object.defineProperty(this, _privateFieldValue, { + get: void 0, + set: _set_privateFieldValue + }); + Object.defineProperty(this, _privateField, { + writable: true, + value: 0 + }); + this.publicField = babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue]; + } + +} + +var _set_privateFieldValue = function (newValue) { + babelHelpers.classPrivateFieldLooseBase(this, _privateField)[_privateField] = newValue; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/helper/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/helper/exec.js new file mode 100644 index 000000000000..59d4b47896ae --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/helper/exec.js @@ -0,0 +1,11 @@ +let foo; +class Cl { + set #foo(v) { return 1 } + test() { + foo = this.#foo = 2; + } +} + +new Cl().test(); + +expect(foo).toBe(2); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/options.json b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/options.json new file mode 100644 index 000000000000..8db8526496b9 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + ["external-helpers",{ "helperVersion": "7.1000.0" }], + "proposal-private-methods", + "proposal-class-properties" + ], + "assumptions": { + "privateFieldsAsProperties": true + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/set-only-getter/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/set-only-getter/exec.js new file mode 100644 index 000000000000..64dd9738fd4f --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/set-only-getter/exec.js @@ -0,0 +1,13 @@ +class Cl { + #privateField = 0; + + get #privateFieldValue() { + return this.#privateField; + } + + constructor() { + expect(() => this.#privateFieldValue = 1).toThrow(TypeError); + } +} + +const cl = new Cl(); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/set-only-getter/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/set-only-getter/input.js new file mode 100644 index 000000000000..a3385ef16034 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/set-only-getter/input.js @@ -0,0 +1,11 @@ +class Cl { + #privateField = 0; + + get #privateFieldValue() { + return this.#privateField; + } + + constructor() { + this.#privateFieldValue = 1; + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/set-only-getter/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/set-only-getter/output.js new file mode 100644 index 000000000000..3ae50780168c --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/set-only-getter/output.js @@ -0,0 +1,22 @@ +var _privateField = babelHelpers.classPrivateFieldLooseKey("privateField"); + +var _privateFieldValue = babelHelpers.classPrivateFieldLooseKey("privateFieldValue"); + +class Cl { + constructor() { + Object.defineProperty(this, _privateFieldValue, { + get: _get_privateFieldValue, + set: void 0 + }); + Object.defineProperty(this, _privateField, { + writable: true, + value: 0 + }); + babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue] = 1; + } + +} + +var _get_privateFieldValue = function () { + return babelHelpers.classPrivateFieldLooseBase(this, _privateField)[_privateField]; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/updates/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/updates/exec.js new file mode 100644 index 000000000000..2e0c58ef2785 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/updates/exec.js @@ -0,0 +1,50 @@ +class Cl { + #privateField = "top secret string"; + + constructor() { + this.publicField = "not secret string"; + } + + get #privateFieldValue() { + return this.#privateField; + } + + set #privateFieldValue(newValue) { + this.#privateField = newValue; + } + + publicGetPrivateField() { + return this.#privateFieldValue; + } + + publicSetPrivateField(newValue) { + this.#privateFieldValue = newValue; + } + + get publicFieldValue() { + return this.publicField; + } + + set publicFieldValue(newValue) { + this.publicField = newValue; + } + + testUpdates() { + this.#privateField = 0; + this.publicField = 0; + this.#privateFieldValue = this.#privateFieldValue++; + this.publicFieldValue = this.publicFieldValue++; + expect(this.#privateField).toEqual(this.publicField); + + ++this.#privateFieldValue; + ++this.publicFieldValue; + expect(this.#privateField).toEqual(this.publicField); + + this.#privateFieldValue += 1; + this.publicFieldValue += 1; + expect(this.#privateField).toEqual(this.publicField); + } +} + +const cl = new Cl(); +cl.testUpdates(); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/updates/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/updates/input.js new file mode 100644 index 000000000000..587f09e0aa93 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/updates/input.js @@ -0,0 +1,47 @@ +class Cl { + #privateField = "top secret string"; + + constructor() { + this.publicField = "not secret string"; + } + + get #privateFieldValue() { + return this.#privateField; + } + + set #privateFieldValue(newValue) { + this.#privateField = newValue; + } + + publicGetPrivateField() { + return this.#privateFieldValue; + } + + publicSetPrivateField(newValue) { + this.#privateFieldValue = newValue; + } + + get publicFieldValue() { + return this.publicField; + } + + set publicFieldValue(newValue) { + this.publicField = newValue; + } + + testUpdates() { + this.#privateField = 0; + this.publicField = 0; + this.#privateFieldValue = this.#privateFieldValue++; + this.publicFieldValue = this.publicFieldValue++; + + ++this.#privateFieldValue; + ++this.publicFieldValue; + + this.#privateFieldValue += 1; + this.publicFieldValue += 1; + + this.#privateFieldValue = -(this.#privateFieldValue ** this.#privateFieldValue); + this.publicFieldValue = -(this.publicFieldValue ** this.publicFieldValue); + } +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/updates/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/updates/output.js new file mode 100644 index 000000000000..b9fb372f9ba5 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-privateFieldsAsProperties/updates/output.js @@ -0,0 +1,55 @@ +var _privateField = babelHelpers.classPrivateFieldLooseKey("privateField"); + +var _privateFieldValue = babelHelpers.classPrivateFieldLooseKey("privateFieldValue"); + +class Cl { + constructor() { + Object.defineProperty(this, _privateFieldValue, { + get: _get_privateFieldValue, + set: _set_privateFieldValue + }); + Object.defineProperty(this, _privateField, { + writable: true, + value: "top secret string" + }); + this.publicField = "not secret string"; + } + + publicGetPrivateField() { + return babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue]; + } + + publicSetPrivateField(newValue) { + babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue] = newValue; + } + + get publicFieldValue() { + return this.publicField; + } + + set publicFieldValue(newValue) { + this.publicField = newValue; + } + + testUpdates() { + babelHelpers.classPrivateFieldLooseBase(this, _privateField)[_privateField] = 0; + this.publicField = 0; + babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue] = babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue]++; + this.publicFieldValue = this.publicFieldValue++; + ++babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue]; + ++this.publicFieldValue; + babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue] += 1; + this.publicFieldValue += 1; + babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue] = -(babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue] ** babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue]); + this.publicFieldValue = -(this.publicFieldValue ** this.publicFieldValue); + } + +} + +var _get_privateFieldValue = function () { + return babelHelpers.classPrivateFieldLooseBase(this, _privateField)[_privateField]; +}; + +var _set_privateFieldValue = function (newValue) { + babelHelpers.classPrivateFieldLooseBase(this, _privateField)[_privateField] = newValue; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/assumption-constantSuper/options.json b/packages/babel-plugin-proposal-private-methods/test/fixtures/assumption-constantSuper/options.json new file mode 100644 index 000000000000..4ada272a1b6b --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/assumption-constantSuper/options.json @@ -0,0 +1,17 @@ +{ + "plugins": [ + [ + "external-helpers", + { + "helperVersion": "7.1000.0" + } + ], + "proposal-private-methods", + "proposal-class-properties", + "transform-block-scoping", + "syntax-class-properties" + ], + "assumptions": { + "constantSuper": true + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/assumption-constantSuper/private-method-super/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/assumption-constantSuper/private-method-super/input.js new file mode 100644 index 000000000000..d85e01133ac1 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/assumption-constantSuper/private-method-super/input.js @@ -0,0 +1,19 @@ +class Base { + superMethod() { + return 'good'; + } +} + +class Sub extends Base { + superMethod() { + return 'bad'; + } + + #privateMethod() { + return super.superMethod(); + } + + publicMethod() { + return this.#privateMethod(); + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/assumption-constantSuper/private-method-super/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/assumption-constantSuper/private-method-super/output.js new file mode 100644 index 000000000000..6c26d54af7c3 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/assumption-constantSuper/private-method-super/output.js @@ -0,0 +1,29 @@ +class Base { + superMethod() { + return 'good'; + } + +} + +var _privateMethod = new WeakSet(); + +class Sub extends Base { + constructor(...args) { + super(...args); + + _privateMethod.add(this); + } + + superMethod() { + return 'bad'; + } + + publicMethod() { + return babelHelpers.classPrivateMethodGet(this, _privateMethod, _privateMethod2).call(this); + } + +} + +var _privateMethod2 = function _privateMethod2() { + return Base.prototype.superMethod.call(this); +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/assignment/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/assignment/exec.js new file mode 100644 index 000000000000..4c1324aeeb62 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/assignment/exec.js @@ -0,0 +1,11 @@ +class Foo { + constructor() { + this.publicField = this.#privateMethod(); + } + + #privateMethod() { + return 42; + } + } + + expect((new Foo).publicField).toEqual(42); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/assignment/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/assignment/input.js new file mode 100644 index 000000000000..e55a8afdd3ad --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/assignment/input.js @@ -0,0 +1,9 @@ +class Foo { + constructor() { + this.publicField = this.#privateMethod(); + } + + #privateMethod() { + return 42; + } +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/assignment/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/assignment/output.js new file mode 100644 index 000000000000..e85cf49ca0e1 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/assignment/output.js @@ -0,0 +1,15 @@ +var _privateMethod = babelHelpers.classPrivateFieldLooseKey("privateMethod"); + +class Foo { + constructor() { + Object.defineProperty(this, _privateMethod, { + value: _privateMethod2 + }); + this.publicField = babelHelpers.classPrivateFieldLooseBase(this, _privateMethod)[_privateMethod](); + } + +} + +var _privateMethod2 = function _privateMethod2() { + return 42; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/exec.js new file mode 100644 index 000000000000..168eb945dd14 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/exec.js @@ -0,0 +1,13 @@ +class Cl { + async #foo() { + return 2; + } + + test() { + return this.#foo(); + } +} + +return new Cl().test().then(val => { + expect(val).toBe(2); +}); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/input.js new file mode 100644 index 000000000000..aed36e25613f --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/input.js @@ -0,0 +1,9 @@ +class Cl { + async #foo() { + return 2; + } + + test() { + return this.#foo(); + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/options.json b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/options.json new file mode 100644 index 000000000000..95ab365853e8 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/options.json @@ -0,0 +1,14 @@ +{ + "minNodeVersion": "8.0.0", + "plugins": [ + ["external-helpers",{ "helperVersion": "7.1000.0" }], + "proposal-private-methods", + "proposal-class-properties" + ], + "assumptions": { + "privateFieldsAsProperties": true + }, + "parserOpts": { + "allowReturnOutsideFunction": true + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/output.js new file mode 100644 index 000000000000..2b437a303f1a --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/async/output.js @@ -0,0 +1,18 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +class Cl { + constructor() { + Object.defineProperty(this, _foo, { + value: _foo2 + }); + } + + test() { + return babelHelpers.classPrivateFieldLooseBase(this, _foo)[_foo](); + } + +} + +var _foo2 = async function _foo2() { + return 2; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/before-fields/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/before-fields/exec.js new file mode 100644 index 000000000000..26caf2d02c1f --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/before-fields/exec.js @@ -0,0 +1,16 @@ +class Cl { + prop = this.#method(1); + + #priv = this.#method(2); + + #method(x) { + return x; + } + + getPriv() { + return this.#priv; + } +} + +expect(new Cl().prop).toBe(1); +expect(new Cl().getPriv()).toBe(2); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/before-fields/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/before-fields/input.js new file mode 100644 index 000000000000..2fcb7857468f --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/before-fields/input.js @@ -0,0 +1,13 @@ +class Cl { + prop = this.#method(1); + + #priv = this.#method(2); + + #method(x) { + return x; + } + + getPriv() { + return this.#priv; + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/before-fields/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/before-fields/output.js new file mode 100644 index 000000000000..2618032e6669 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/before-fields/output.js @@ -0,0 +1,25 @@ +var _priv = babelHelpers.classPrivateFieldLooseKey("priv"); + +var _method = babelHelpers.classPrivateFieldLooseKey("method"); + +class Cl { + constructor() { + Object.defineProperty(this, _method, { + value: _method2 + }); + babelHelpers.defineProperty(this, "prop", babelHelpers.classPrivateFieldLooseBase(this, _method)[_method](1)); + Object.defineProperty(this, _priv, { + writable: true, + value: babelHelpers.classPrivateFieldLooseBase(this, _method)[_method](2) + }); + } + + getPriv() { + return babelHelpers.classPrivateFieldLooseBase(this, _priv)[_priv]; + } + +} + +var _method2 = function _method2(x) { + return x; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/context/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/context/exec.js new file mode 100644 index 000000000000..6c18bf53c193 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/context/exec.js @@ -0,0 +1,41 @@ +class Foo { + constructor(status) { + this.status = status; + expect(() => this.#getStatus = null).toThrow(TypeError); + } + + #getStatus() { + return this.status; + } + + getCurrentStatus() { + return this.#getStatus(); + } + + setCurrentStatus(newStatus) { + this.status = newStatus; + } + + getFakeStatus(fakeStatus) { + const getStatus = this.#getStatus; + return function () { + return getStatus.call({ status: fakeStatus }); + }; + } + + getFakeStatusFunc() { + return { + status: 'fake-status', + getFakeStatus: this.#getStatus, + }; + } + } + + const f = new Foo('inactive'); + expect(f.getCurrentStatus()).toBe('inactive'); + + f.setCurrentStatus('new-status'); + expect(f.getCurrentStatus()).toBe('new-status'); + + expect(f.getFakeStatus('fake')()).toBe('fake'); + expect(f.getFakeStatusFunc().getFakeStatus()).toBe('fake-status'); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/context/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/context/input.js new file mode 100644 index 000000000000..67a8ab68a682 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/context/input.js @@ -0,0 +1,31 @@ +class Foo { + constructor(status) { + this.status = status; + } + + #getStatus() { + return this.status; + } + + getCurrentStatus() { + return this.#getStatus(); + } + + setCurrentStatus(newStatus) { + this.status = newStatus; + } + + getFakeStatus(fakeStatus) { + const fakeGetStatus = this.#getStatus; + return function() { + return fakeGetStatus.call({ status: fakeStatus }); + }; + } + + getFakeStatusFunc() { + return { + status: 'fake-status', + getFakeStatus: this.#getStatus, + }; + } +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/context/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/context/output.js new file mode 100644 index 000000000000..b1c396755f7e --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/context/output.js @@ -0,0 +1,40 @@ +var _getStatus = babelHelpers.classPrivateFieldLooseKey("getStatus"); + +class Foo { + constructor(status) { + Object.defineProperty(this, _getStatus, { + value: _getStatus2 + }); + this.status = status; + } + + getCurrentStatus() { + return babelHelpers.classPrivateFieldLooseBase(this, _getStatus)[_getStatus](); + } + + setCurrentStatus(newStatus) { + this.status = newStatus; + } + + getFakeStatus(fakeStatus) { + const fakeGetStatus = babelHelpers.classPrivateFieldLooseBase(this, _getStatus)[_getStatus]; + + return function () { + return fakeGetStatus.call({ + status: fakeStatus + }); + }; + } + + getFakeStatusFunc() { + return { + status: 'fake-status', + getFakeStatus: babelHelpers.classPrivateFieldLooseBase(this, _getStatus)[_getStatus] + }; + } + +} + +var _getStatus2 = function _getStatus2() { + return this.status; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/exfiltrated/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/exfiltrated/exec.js new file mode 100644 index 000000000000..659a3e891085 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/exfiltrated/exec.js @@ -0,0 +1,15 @@ +let exfiltrated; +class Foo { + #privateMethod() {} + + constructor() { + if (exfiltrated === undefined) { + exfiltrated = this.#privateMethod; + } + expect(exfiltrated).toStrictEqual(this.#privateMethod); + } +} + +new Foo(); +// check for private method function object equality +new Foo(); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/exfiltrated/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/exfiltrated/input.js new file mode 100644 index 000000000000..91bf8510d814 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/exfiltrated/input.js @@ -0,0 +1,10 @@ +let exfiltrated; +class Foo { + #privateMethod() {} + + constructor() { + if (exfiltrated === undefined) { + exfiltrated = this.#privateMethod; + } + } +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/exfiltrated/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/exfiltrated/output.js new file mode 100644 index 000000000000..100562baf534 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/exfiltrated/output.js @@ -0,0 +1,18 @@ +let exfiltrated; + +var _privateMethod = babelHelpers.classPrivateFieldLooseKey("privateMethod"); + +class Foo { + constructor() { + Object.defineProperty(this, _privateMethod, { + value: _privateMethod2 + }); + + if (exfiltrated === undefined) { + exfiltrated = babelHelpers.classPrivateFieldLooseBase(this, _privateMethod)[_privateMethod]; + } + } + +} + +var _privateMethod2 = function _privateMethod2() {}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/generator/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/generator/exec.js new file mode 100644 index 000000000000..472eadeabff6 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/generator/exec.js @@ -0,0 +1,14 @@ +class Cl { + *#foo() { + yield 2; + return 3; + } + + test() { + return this.#foo(); + } +} + +const val = new Cl().test(); +expect(val.next()).toEqual({ value: 2, done: false }); +expect(val.next()).toEqual({ value: 3, done: true }); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/generator/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/generator/input.js new file mode 100644 index 000000000000..39aace6dc402 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/generator/input.js @@ -0,0 +1,10 @@ +class Cl { + *#foo() { + yield 2; + return 3; + } + + test() { + return this.#foo(); + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/generator/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/generator/output.js new file mode 100644 index 000000000000..ead1fffcb593 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/generator/output.js @@ -0,0 +1,19 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +class Cl { + constructor() { + Object.defineProperty(this, _foo, { + value: _foo2 + }); + } + + test() { + return babelHelpers.classPrivateFieldLooseBase(this, _foo)[_foo](); + } + +} + +var _foo2 = function* _foo2() { + yield 2; + return 3; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/options.json b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/options.json new file mode 100644 index 000000000000..8db8526496b9 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + ["external-helpers",{ "helperVersion": "7.1000.0" }], + "proposal-private-methods", + "proposal-class-properties" + ], + "assumptions": { + "privateFieldsAsProperties": true + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/super/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/super/exec.js new file mode 100644 index 000000000000..63d8fe8cdfe3 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/super/exec.js @@ -0,0 +1,21 @@ +class Base { + superMethod() { + return 'good'; + } +} + +class Sub extends Base { + superMethod() { + return 'bad'; + } + + #privateMethod() { + return super.superMethod(); + } + + publicMethod() { + return this.#privateMethod(); + } +} + +expect((new Sub()).publicMethod()).toEqual('good'); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/super/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/super/input.js new file mode 100644 index 000000000000..d85e01133ac1 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/super/input.js @@ -0,0 +1,19 @@ +class Base { + superMethod() { + return 'good'; + } +} + +class Sub extends Base { + superMethod() { + return 'bad'; + } + + #privateMethod() { + return super.superMethod(); + } + + publicMethod() { + return this.#privateMethod(); + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/super/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/super/output.js new file mode 100644 index 000000000000..1a0d87d98e0c --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-privateFieldsAsProperties/super/output.js @@ -0,0 +1,30 @@ +class Base { + superMethod() { + return 'good'; + } + +} + +var _privateMethod = babelHelpers.classPrivateFieldLooseKey("privateMethod"); + +class Sub extends Base { + constructor(...args) { + super(...args); + Object.defineProperty(this, _privateMethod, { + value: _privateMethod2 + }); + } + + superMethod() { + return 'bad'; + } + + publicMethod() { + return babelHelpers.classPrivateFieldLooseBase(this, _privateMethod)[_privateMethod](); + } + +} + +var _privateMethod2 = function _privateMethod2() { + return babelHelpers.get(babelHelpers.getPrototypeOf(Sub.prototype), "superMethod", this).call(this); +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/async/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/async/input.js new file mode 100644 index 000000000000..99125b6f24c4 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/async/input.js @@ -0,0 +1,13 @@ +class Cl { + static async #privateStaticMethod() { + return 2; + } + + test() { + return Cl.#privateStaticMethod(); + } +} + +return new Cl().test().then(val => { + expect(val).toBe(2); +}); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/async/options.json b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/async/options.json new file mode 100644 index 000000000000..95ab365853e8 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/async/options.json @@ -0,0 +1,14 @@ +{ + "minNodeVersion": "8.0.0", + "plugins": [ + ["external-helpers",{ "helperVersion": "7.1000.0" }], + "proposal-private-methods", + "proposal-class-properties" + ], + "assumptions": { + "privateFieldsAsProperties": true + }, + "parserOpts": { + "allowReturnOutsideFunction": true + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/async/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/async/output.js new file mode 100644 index 000000000000..9d5595eaafa9 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/async/output.js @@ -0,0 +1,19 @@ +var _privateStaticMethod = babelHelpers.classPrivateFieldLooseKey("privateStaticMethod"); + +class Cl { + test() { + return babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticMethod)[_privateStaticMethod](); + } + +} + +var _privateStaticMethod2 = async function _privateStaticMethod2() { + return 2; +}; + +Object.defineProperty(Cl, _privateStaticMethod, { + value: _privateStaticMethod2 +}); +return new Cl().test().then(val => { + expect(val).toBe(2); +}); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/basic/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/basic/exec.js new file mode 100644 index 000000000000..d5577057caa9 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/basic/exec.js @@ -0,0 +1,33 @@ +const privateStaticValue = 1017; + +class Cl { + static staticMethod2() { + return Cl.#privateStaticMethod(); + } + + static #privateStaticMethod() { + return privateStaticValue; + } + + static staticMethod() { + return Cl.#privateStaticMethod(); + } + + static privateStaticMethod() { + return Cl.#privateStaticMethod(); + } + + publicMethod() { + return Cl.#privateStaticMethod(); + } + + constructor() { + this.instanceField = Cl.#privateStaticMethod(); + } +} + +expect((new Cl).publicMethod()).toEqual(privateStaticValue); +// expect((new Cl).instanceField).toEqual(privateStaticValue); +// expect(Cl.privateStaticMethod()).toEqual(privateStaticValue); +// expect(Cl.staticMethod()).toEqual(privateStaticValue); +// expect(Cl.staticMethod2()).toEqual(privateStaticValue); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/basic/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/basic/input.js new file mode 100644 index 000000000000..ad0ee3d44814 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/basic/input.js @@ -0,0 +1,25 @@ +class Cl { + static staticMethod2() { + return Cl.#privateStaticMethod(); + } + + static #privateStaticMethod() { + return 1017; + } + + static staticMethod() { + return Cl.#privateStaticMethod(); + } + + static privateStaticMethod() { + return Cl.#privateStaticMethod(); + } + + publicMethod() { + return Cl.#privateStaticMethod(); + } + + constructor() { + this.instanceField = Cl.#privateStaticMethod(); + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/basic/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/basic/output.js new file mode 100644 index 000000000000..c62177365e9a --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/basic/output.js @@ -0,0 +1,32 @@ +var _privateStaticMethod = babelHelpers.classPrivateFieldLooseKey("privateStaticMethod"); + +class Cl { + static staticMethod2() { + return babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticMethod)[_privateStaticMethod](); + } + + static staticMethod() { + return babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticMethod)[_privateStaticMethod](); + } + + static privateStaticMethod() { + return babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticMethod)[_privateStaticMethod](); + } + + publicMethod() { + return babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticMethod)[_privateStaticMethod](); + } + + constructor() { + this.instanceField = babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticMethod)[_privateStaticMethod](); + } + +} + +var _privateStaticMethod2 = function _privateStaticMethod2() { + return 1017; +}; + +Object.defineProperty(Cl, _privateStaticMethod, { + value: _privateStaticMethod2 +}); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/class-check/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/class-check/exec.js new file mode 100644 index 000000000000..940b62801e26 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/class-check/exec.js @@ -0,0 +1,12 @@ +class Cl { + static #privateStaticMethod() { + return 1017; + } + + publicMethod(checked) { + return checked.#privateStaticMethod(); + } +} + +const cl = new Cl(); +expect(cl.publicMethod(Cl)).toBe(1017); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/class-check/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/class-check/input.js new file mode 100644 index 000000000000..fd8c6c331e4e --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/class-check/input.js @@ -0,0 +1,7 @@ +class Cl { + static #privateStaticMethod() { } + + publicMethod(checked) { + return checked.#privateStaticMethod(); + } +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/class-check/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/class-check/output.js new file mode 100644 index 000000000000..353da8ad4fac --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/class-check/output.js @@ -0,0 +1,14 @@ +var _privateStaticMethod = babelHelpers.classPrivateFieldLooseKey("privateStaticMethod"); + +class Cl { + publicMethod(checked) { + return babelHelpers.classPrivateFieldLooseBase(checked, _privateStaticMethod)[_privateStaticMethod](); + } + +} + +var _privateStaticMethod2 = function _privateStaticMethod2() {}; + +Object.defineProperty(Cl, _privateStaticMethod, { + value: _privateStaticMethod2 +}); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/exfiltrated/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/exfiltrated/exec.js new file mode 100644 index 000000000000..14a7b5edd830 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/exfiltrated/exec.js @@ -0,0 +1,20 @@ +let exfiltrated; + +class Cl { + static #privateStaticMethod() { + return 1017; + } + + constructor() { + if (exfiltrated === undefined) { + exfiltrated = Cl.#privateStaticMethod; + } + expect(exfiltrated).toStrictEqual(Cl.#privateStaticMethod); + } +} + +new Cl(); +// check for private method function object equality +new Cl(); + +expect(exfiltrated()).toEqual(1017); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/exfiltrated/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/exfiltrated/input.js new file mode 100644 index 000000000000..fdc78e57981a --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/exfiltrated/input.js @@ -0,0 +1,13 @@ +let exfiltrated; + +class Cl { + static #privateStaticMethod() { + return 1017; + } + + constructor() { + if (exfiltrated === undefined) { + exfiltrated = Cl.#privateStaticMethod; + } + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/exfiltrated/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/exfiltrated/output.js new file mode 100644 index 000000000000..c6a5a2dc8000 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/exfiltrated/output.js @@ -0,0 +1,20 @@ +let exfiltrated; + +var _privateStaticMethod = babelHelpers.classPrivateFieldLooseKey("privateStaticMethod"); + +class Cl { + constructor() { + if (exfiltrated === undefined) { + exfiltrated = babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticMethod)[_privateStaticMethod]; + } + } + +} + +var _privateStaticMethod2 = function _privateStaticMethod2() { + return 1017; +}; + +Object.defineProperty(Cl, _privateStaticMethod, { + value: _privateStaticMethod2 +}); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/generator/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/generator/exec.js new file mode 100644 index 000000000000..97a6a708fc63 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/generator/exec.js @@ -0,0 +1,14 @@ +class Cl { + static *#foo() { + yield 2; + return 3; + } + + test() { + return Cl.#foo(); + } +} + +const val = new Cl().test(); +expect(val.next()).toEqual({ value: 2, done: false }); +expect(val.next()).toEqual({ value: 3, done: true }); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/generator/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/generator/input.js new file mode 100644 index 000000000000..2b8727d64cfa --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/generator/input.js @@ -0,0 +1,10 @@ +class Cl { + static *#foo() { + yield 2; + return 3; + } + + test() { + return Cl.#foo(); + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/generator/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/generator/output.js new file mode 100644 index 000000000000..464971ea7944 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/generator/output.js @@ -0,0 +1,17 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +class Cl { + test() { + return babelHelpers.classPrivateFieldLooseBase(Cl, _foo)[_foo](); + } + +} + +var _foo2 = function* _foo2() { + yield 2; + return 3; +}; + +Object.defineProperty(Cl, _foo, { + value: _foo2 +}); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/options.json b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/options.json new file mode 100644 index 000000000000..8db8526496b9 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + ["external-helpers",{ "helperVersion": "7.1000.0" }], + "proposal-private-methods", + "proposal-class-properties" + ], + "assumptions": { + "privateFieldsAsProperties": true + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/reassignment/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/reassignment/exec.js new file mode 100644 index 000000000000..d55af8ba71d7 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/reassignment/exec.js @@ -0,0 +1,9 @@ +class Cl { + static #privateStaticMethod() { } + + constructor() { + expect(() => Cl.#privateStaticMethod = null).toThrow(TypeError); + } +} + +new Cl(); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/reassignment/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/reassignment/input.js new file mode 100644 index 000000000000..865ddea4ccf1 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/reassignment/input.js @@ -0,0 +1,9 @@ +class Cl { + static #privateStaticMethod() { } + + constructor() { + Cl.#privateStaticMethod = null; + } +} + +new Cl(); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/reassignment/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/reassignment/output.js new file mode 100644 index 000000000000..5b3fae07d026 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/reassignment/output.js @@ -0,0 +1,15 @@ +var _privateStaticMethod = babelHelpers.classPrivateFieldLooseKey("privateStaticMethod"); + +class Cl { + constructor() { + babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticMethod)[_privateStaticMethod] = null; + } + +} + +var _privateStaticMethod2 = function _privateStaticMethod2() {}; + +Object.defineProperty(Cl, _privateStaticMethod, { + value: _privateStaticMethod2 +}); +new Cl(); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/scopable/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/scopable/exec.js new file mode 100644 index 000000000000..f94e5c495f9a --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/scopable/exec.js @@ -0,0 +1,17 @@ +class Cl { + static #privateMethodA() { + const i = 40; + return i; + } + + static #privateMethodB() { + const i = 2; + return i; + } + + publicMethod() { + return Cl.#privateMethodA() + Cl.#privateMethodB(); + } +} + +expect((new Cl).publicMethod()).toEqual(42); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/super/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/super/exec.js new file mode 100644 index 000000000000..1d6f0c63559a --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/super/exec.js @@ -0,0 +1,21 @@ +class Base { + static basePublicStaticMethod() { + return 'good'; + } +} + +class Sub extends Base { + static basePublicStaticMethod() { + return 'bad'; + } + + static #subStaticPrivateMethod() { + return super.basePublicStaticMethod(); + } + + static check() { + return Sub.#subStaticPrivateMethod(); + } +} + +expect(Sub.check()).toEqual('good'); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/super/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/super/input.js new file mode 100644 index 000000000000..e5fb0ecd5eec --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/super/input.js @@ -0,0 +1,19 @@ +class Base { + static basePublicStaticMethod() { + return 'good'; + } +} + +class Sub extends Base { + static basePublicStaticMethod() { + return 'bad'; + } + + static #subStaticPrivateMethod() { + return super.basePublicStaticMethod(); + } + + static check() { + Sub.#subStaticPrivateMethod(); + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/super/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/super/output.js new file mode 100644 index 000000000000..ae589469caf6 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/super/output.js @@ -0,0 +1,27 @@ +class Base { + static basePublicStaticMethod() { + return 'good'; + } + +} + +var _subStaticPrivateMethod = babelHelpers.classPrivateFieldLooseKey("subStaticPrivateMethod"); + +class Sub extends Base { + static basePublicStaticMethod() { + return 'bad'; + } + + static check() { + babelHelpers.classPrivateFieldLooseBase(Sub, _subStaticPrivateMethod)[_subStaticPrivateMethod](); + } + +} + +var _subStaticPrivateMethod2 = function _subStaticPrivateMethod2() { + return babelHelpers.get(babelHelpers.getPrototypeOf(Sub), "basePublicStaticMethod", this).call(this); +}; + +Object.defineProperty(Sub, _subStaticPrivateMethod, { + value: _subStaticPrivateMethod2 +}); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/this/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/this/exec.js new file mode 100644 index 000000000000..3262c36845be --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/this/exec.js @@ -0,0 +1,18 @@ +class A { + static get a() { return 1 } +} + +class B extends A { + static get b() { return 2 } + + static #getA() { return super.a } + static #getB() { return this.b } + + static extract() { + return [this.#getA, this.#getB]; + } +} + +const [getA, getB] = B.extract(); +expect(getA.call({ a: 3 })).toBe(1); +expect(getB.call({ b: 4 })).toBe(4); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/this/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/this/input.js new file mode 100644 index 000000000000..3c8639776d62 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/this/input.js @@ -0,0 +1,16 @@ +class A { + static get a() { return 1 } +} + +class B extends A { + static get b() { return 2 } + + static #getA() { return super.a } + static #getB() { return this.b } + + static extract() { + return [this.#getA, this.#getB]; + } +} + +const [getA, getB] = B.extract(); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/this/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/this/output.js new file mode 100644 index 000000000000..0d39c5bf1282 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-static-method-privateFieldsAsProperties/this/output.js @@ -0,0 +1,37 @@ +class A { + static get a() { + return 1; + } + +} + +var _getA = babelHelpers.classPrivateFieldLooseKey("getA"); + +var _getB = babelHelpers.classPrivateFieldLooseKey("getB"); + +class B extends A { + static get b() { + return 2; + } + + static extract() { + return [babelHelpers.classPrivateFieldLooseBase(this, _getA)[_getA], babelHelpers.classPrivateFieldLooseBase(this, _getB)[_getB]]; + } + +} + +var _getB2 = function _getB2() { + return this.b; +}; + +var _getA2 = function _getA2() { + return babelHelpers.get(babelHelpers.getPrototypeOf(B), "a", this); +}; + +Object.defineProperty(B, _getA, { + value: _getA2 +}); +Object.defineProperty(B, _getB, { + value: _getB2 +}); +const [getA, getB] = B.extract(); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/basic/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/basic/exec.js new file mode 100644 index 000000000000..791a59034af9 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/basic/exec.js @@ -0,0 +1,23 @@ +class Cl { + static #PRIVATE_STATIC_FIELD = "top secret string"; + + static get #privateStaticFieldValue() { + return Cl.#PRIVATE_STATIC_FIELD; + } + + static set #privateStaticFieldValue(newValue) { + Cl.#PRIVATE_STATIC_FIELD = `Updated: ${newValue}`; + } + + static getValue() { + return Cl.#privateStaticFieldValue; + } + + static setValue() { + Cl.#privateStaticFieldValue = "dank"; + } +} + +expect(Cl.getValue()).toEqual("top secret string"); +Cl.setValue(); +expect(Cl.getValue()).toEqual("Updated: dank"); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/basic/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/basic/input.js new file mode 100644 index 000000000000..c79cdbe5ff0e --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/basic/input.js @@ -0,0 +1,19 @@ +class Cl { + static #PRIVATE_STATIC_FIELD = "top secret string"; + + static get #privateStaticFieldValue() { + return Cl.#PRIVATE_STATIC_FIELD; + } + + static set #privateStaticFieldValue(newValue) { + Cl.#PRIVATE_STATIC_FIELD = `Updated: ${newValue}`; + } + + static getValue() { + return Cl.#privateStaticFieldValue; + } + + static setValue() { + Cl.#privateStaticFieldValue = "dank"; + } +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/basic/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/basic/output.js new file mode 100644 index 000000000000..f9b15a52fad0 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/basic/output.js @@ -0,0 +1,31 @@ +var _PRIVATE_STATIC_FIELD = babelHelpers.classPrivateFieldLooseKey("PRIVATE_STATIC_FIELD"); + +var _privateStaticFieldValue = babelHelpers.classPrivateFieldLooseKey("privateStaticFieldValue"); + +class Cl { + static getValue() { + return babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticFieldValue)[_privateStaticFieldValue]; + } + + static setValue() { + babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticFieldValue)[_privateStaticFieldValue] = "dank"; + } + +} + +var _set_privateStaticFieldValue = function (newValue) { + babelHelpers.classPrivateFieldLooseBase(Cl, _PRIVATE_STATIC_FIELD)[_PRIVATE_STATIC_FIELD] = `Updated: ${newValue}`; +}; + +var _get_privateStaticFieldValue = function () { + return babelHelpers.classPrivateFieldLooseBase(Cl, _PRIVATE_STATIC_FIELD)[_PRIVATE_STATIC_FIELD]; +}; + +Object.defineProperty(Cl, _PRIVATE_STATIC_FIELD, { + writable: true, + value: "top secret string" +}); +Object.defineProperty(Cl, _privateStaticFieldValue, { + get: _get_privateStaticFieldValue, + set: _set_privateStaticFieldValue +}); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/get-only-setter/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/get-only-setter/exec.js new file mode 100644 index 000000000000..0c14f25c0938 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/get-only-setter/exec.js @@ -0,0 +1,13 @@ +class Cl { + static #PRIVATE_STATIC_FIELD = 0; + + static set #privateStaticFieldValue(newValue) { + Cl.#PRIVATE_STATIC_FIELD = newValue; + } + + static getPrivateStaticFieldValue() { + return Cl.#privateStaticFieldValue; + } +} + +expect(Cl.getPrivateStaticFieldValue()).toBeUndefined(); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/get-only-setter/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/get-only-setter/input.js new file mode 100644 index 000000000000..ab8771074ec7 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/get-only-setter/input.js @@ -0,0 +1,11 @@ +class Cl { + static #PRIVATE_STATIC_FIELD = 0; + + static set #privateStaticFieldValue(newValue) { + Cl.#PRIVATE_STATIC_FIELD = newValue; + } + + static getPrivateStaticFieldValue() { + return Cl.#privateStaticFieldValue; + } +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/get-only-setter/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/get-only-setter/output.js new file mode 100644 index 000000000000..9fc34593fd65 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/get-only-setter/output.js @@ -0,0 +1,23 @@ +var _PRIVATE_STATIC_FIELD = babelHelpers.classPrivateFieldLooseKey("PRIVATE_STATIC_FIELD"); + +var _privateStaticFieldValue = babelHelpers.classPrivateFieldLooseKey("privateStaticFieldValue"); + +class Cl { + static getPrivateStaticFieldValue() { + return babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticFieldValue)[_privateStaticFieldValue]; + } + +} + +var _set_privateStaticFieldValue = function (newValue) { + babelHelpers.classPrivateFieldLooseBase(Cl, _PRIVATE_STATIC_FIELD)[_PRIVATE_STATIC_FIELD] = newValue; +}; + +Object.defineProperty(Cl, _PRIVATE_STATIC_FIELD, { + writable: true, + value: 0 +}); +Object.defineProperty(Cl, _privateStaticFieldValue, { + get: void 0, + set: _set_privateStaticFieldValue +}); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/options.json b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/options.json new file mode 100644 index 000000000000..8db8526496b9 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + ["external-helpers",{ "helperVersion": "7.1000.0" }], + "proposal-private-methods", + "proposal-class-properties" + ], + "assumptions": { + "privateFieldsAsProperties": true + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/set-only-getter/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/set-only-getter/exec.js new file mode 100644 index 000000000000..7069abfadc9d --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/set-only-getter/exec.js @@ -0,0 +1,13 @@ +class Cl { + static #PRIVATE_STATIC_FIELD = 0; + + static get #privateStaticFieldValue() { + return Cl.#PRIVATE_STATIC_FIELD; + } + + static setPrivateStaticFieldValue() { + Cl.#privateStaticFieldValue = 1; + } +} + +expect(() => Cl.setPrivateStaticFieldValue()).toThrow(TypeError); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/set-only-getter/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/set-only-getter/input.js new file mode 100644 index 000000000000..d54ce4e2c2d0 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/set-only-getter/input.js @@ -0,0 +1,11 @@ +class Cl { + static #PRIVATE_STATIC_FIELD = 0; + + static get #privateStaticFieldValue() { + return Cl.#PRIVATE_STATIC_FIELD; + } + + static setPrivateStaticFieldValue() { + Cl.#privateStaticFieldValue = 1; + } +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/set-only-getter/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/set-only-getter/output.js new file mode 100644 index 000000000000..2dfa44c30302 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/set-only-getter/output.js @@ -0,0 +1,23 @@ +var _PRIVATE_STATIC_FIELD = babelHelpers.classPrivateFieldLooseKey("PRIVATE_STATIC_FIELD"); + +var _privateStaticFieldValue = babelHelpers.classPrivateFieldLooseKey("privateStaticFieldValue"); + +class Cl { + static setPrivateStaticFieldValue() { + babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticFieldValue)[_privateStaticFieldValue] = 1; + } + +} + +var _get_privateStaticFieldValue = function () { + return babelHelpers.classPrivateFieldLooseBase(Cl, _PRIVATE_STATIC_FIELD)[_PRIVATE_STATIC_FIELD]; +}; + +Object.defineProperty(Cl, _PRIVATE_STATIC_FIELD, { + writable: true, + value: 0 +}); +Object.defineProperty(Cl, _privateStaticFieldValue, { + get: _get_privateStaticFieldValue, + set: void 0 +}); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/updates/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/updates/exec.js new file mode 100644 index 000000000000..05f70aecceec --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/updates/exec.js @@ -0,0 +1,46 @@ +class Cl { + static #privateField = "top secret string"; + static publicField = "not secret string"; + + static get #privateFieldValue() { + return Cl.#privateField; + } + + static set #privateFieldValue(newValue) { + Cl.#privateField = newValue; + } + + static publicGetPrivateField() { + return Cl.#privateFieldValue; + } + + static publicSetPrivateField(newValue) { + Cl.#privateFieldValue = newValue; + } + + static get publicFieldValue() { + return Cl.publicField; + } + + static set publicFieldValue(newValue) { + Cl.publicField = newValue; + } + + static testUpdates() { + Cl.#privateField = 0; + Cl.publicField = 0; + Cl.#privateFieldValue = Cl.#privateFieldValue++; + Cl.publicFieldValue = Cl.publicFieldValue++; + expect(Cl.#privateField).toEqual(Cl.publicField); + + ++Cl.#privateFieldValue; + ++Cl.publicFieldValue; + expect(Cl.#privateField).toEqual(Cl.publicField); + + Cl.#privateFieldValue += 1; + Cl.publicFieldValue += 1; + expect(Cl.#privateField).toEqual(Cl.publicField); + } +} + +Cl.testUpdates(); \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/updates/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/updates/input.js new file mode 100644 index 000000000000..33c7b39d9cb4 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/updates/input.js @@ -0,0 +1,44 @@ +class Cl { + static #privateField = "top secret string"; + static publicField = "not secret string"; + + static get #privateFieldValue() { + return Cl.#privateField; + } + + static set #privateFieldValue(newValue) { + Cl.#privateField = newValue; + } + + static publicGetPrivateField() { + return Cl.#privateFieldValue; + } + + static publicSetPrivateField(newValue) { + Cl.#privateFieldValue = newValue; + } + + static get publicFieldValue() { + return Cl.publicField; + } + + static set publicFieldValue(newValue) { + Cl.publicField = newValue; + } + + static testUpdates() { + Cl.#privateField = 0; + Cl.publicField = 0; + Cl.#privateFieldValue = Cl.#privateFieldValue++; + Cl.publicFieldValue = Cl.publicFieldValue++; + + ++Cl.#privateFieldValue; + ++Cl.publicFieldValue; + + Cl.#privateFieldValue += 1; + Cl.publicFieldValue += 1; + + Cl.#privateFieldValue = -(Cl.#privateFieldValue ** Cl.#privateFieldValue); + Cl.publicFieldValue = -(Cl.publicFieldValue ** Cl.publicFieldValue); + } +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/updates/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/updates/output.js new file mode 100644 index 000000000000..d9d601bd2297 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors-privateFieldsAsProperties/updates/output.js @@ -0,0 +1,53 @@ +var _privateField = babelHelpers.classPrivateFieldLooseKey("privateField"); + +var _privateFieldValue = babelHelpers.classPrivateFieldLooseKey("privateFieldValue"); + +class Cl { + static publicGetPrivateField() { + return babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue]; + } + + static publicSetPrivateField(newValue) { + babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue] = newValue; + } + + static get publicFieldValue() { + return Cl.publicField; + } + + static set publicFieldValue(newValue) { + Cl.publicField = newValue; + } + + static testUpdates() { + babelHelpers.classPrivateFieldLooseBase(Cl, _privateField)[_privateField] = 0; + Cl.publicField = 0; + babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue] = babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue]++; + Cl.publicFieldValue = Cl.publicFieldValue++; + ++babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue]; + ++Cl.publicFieldValue; + babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue] += 1; + Cl.publicFieldValue += 1; + babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue] = -(babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue] ** babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue]); + Cl.publicFieldValue = -(Cl.publicFieldValue ** Cl.publicFieldValue); + } + +} + +var _set_privateFieldValue = function (newValue) { + babelHelpers.classPrivateFieldLooseBase(Cl, _privateField)[_privateField] = newValue; +}; + +var _get_privateFieldValue = function () { + return babelHelpers.classPrivateFieldLooseBase(Cl, _privateField)[_privateField]; +}; + +Object.defineProperty(Cl, _privateField, { + writable: true, + value: "top secret string" +}); +babelHelpers.defineProperty(Cl, "publicField", "not secret string"); +Object.defineProperty(Cl, _privateFieldValue, { + get: _get_privateFieldValue, + set: _set_privateFieldValue +}); diff --git a/packages/babel-plugin-proposal-private-property-in-object/src/index.js b/packages/babel-plugin-proposal-private-property-in-object/src/index.js index 70dbf3e4c737..c8c5c7bddcc0 100644 --- a/packages/babel-plugin-proposal-private-property-in-object/src/index.js +++ b/packages/babel-plugin-proposal-private-property-in-object/src/index.js @@ -12,6 +12,7 @@ export default declare((api, options) => { return createClassFeaturePlugin({ name: "proposal-class-properties", + api, feature: FEATURES.privateIn, loose: options.loose, diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/accessor/input.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/accessor/input.js new file mode 100644 index 000000000000..c0e9000615fd --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/accessor/input.js @@ -0,0 +1,7 @@ +class Foo { + get #foo() {} + + test(other) { + return #foo in other; + } +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/accessor/output.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/accessor/output.js new file mode 100644 index 000000000000..9d2a42925dfe --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/accessor/output.js @@ -0,0 +1,17 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +class Foo { + constructor() { + Object.defineProperty(this, _foo, { + get: _get_foo, + set: void 0 + }); + } + + test(other) { + return Object.prototype.hasOwnProperty.call(other, _foo); + } + +} + +var _get_foo = function () {}; diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/compiled-classes/input.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/compiled-classes/input.js new file mode 100644 index 000000000000..23c266018025 --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/compiled-classes/input.js @@ -0,0 +1,12 @@ +class Foo { + static #foo = "foo"; + #bar = "bar"; + + static test() { + return #foo in Foo; + } + + test() { + return #bar in this; + } +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/compiled-classes/options.json b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/compiled-classes/options.json new file mode 100644 index 000000000000..9d27af601e04 --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/compiled-classes/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "proposal-private-property-in-object", + "proposal-class-properties", + "proposal-private-methods", + "transform-classes" + ] +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/compiled-classes/output.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/compiled-classes/output.js new file mode 100644 index 000000000000..1889def268b8 --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/compiled-classes/output.js @@ -0,0 +1,33 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +var _bar = babelHelpers.classPrivateFieldLooseKey("bar"); + +let Foo = /*#__PURE__*/function () { + "use strict"; + + function Foo() { + babelHelpers.classCallCheck(this, Foo); + Object.defineProperty(this, _bar, { + writable: true, + value: "bar" + }); + } + + babelHelpers.createClass(Foo, [{ + key: "test", + value: function test() { + return Object.prototype.hasOwnProperty.call(this, _bar); + } + }], [{ + key: "test", + value: function test() { + return Object.prototype.hasOwnProperty.call(Foo, _foo); + } + }]); + return Foo; +}(); + +Object.defineProperty(Foo, _foo, { + writable: true, + value: "foo" +}); diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/field/input.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/field/input.js new file mode 100644 index 000000000000..a682a1a15c5b --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/field/input.js @@ -0,0 +1,7 @@ +class Foo { + #foo = 1; + + test(other) { + return #foo in other; + } +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/field/output.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/field/output.js new file mode 100644 index 000000000000..df6a89c95c78 --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/field/output.js @@ -0,0 +1,15 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +class Foo { + constructor() { + Object.defineProperty(this, _foo, { + writable: true, + value: 1 + }); + } + + test(other) { + return Object.prototype.hasOwnProperty.call(other, _foo); + } + +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/method/input.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/method/input.js new file mode 100644 index 000000000000..365843c59708 --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/method/input.js @@ -0,0 +1,7 @@ +class Foo { + #foo() {} + + test(other) { + return #foo in other; + } +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/method/output.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/method/output.js new file mode 100644 index 000000000000..aebc5e5ffad0 --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/method/output.js @@ -0,0 +1,16 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +class Foo { + constructor() { + Object.defineProperty(this, _foo, { + value: _foo2 + }); + } + + test(other) { + return Object.prototype.hasOwnProperty.call(other, _foo); + } + +} + +var _foo2 = function _foo2() {}; diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-other-redeclared/input.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-other-redeclared/input.js new file mode 100644 index 000000000000..a084dd06afd6 --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-other-redeclared/input.js @@ -0,0 +1,18 @@ +class Foo { + #foo = 1; + #bar = 1; + + test() { + class Nested { + #bar = 2; + + test() { + #foo in this; + #bar in this; + } + } + + #foo in this; + #bar in this; + } +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-other-redeclared/output.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-other-redeclared/output.js new file mode 100644 index 000000000000..42541d45123f --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-other-redeclared/output.js @@ -0,0 +1,39 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +var _bar = babelHelpers.classPrivateFieldLooseKey("bar"); + +class Foo { + constructor() { + Object.defineProperty(this, _foo, { + writable: true, + value: 1 + }); + Object.defineProperty(this, _bar, { + writable: true, + value: 1 + }); + } + + test() { + var _bar2 = babelHelpers.classPrivateFieldLooseKey("bar"); + + class Nested { + constructor() { + Object.defineProperty(this, _bar2, { + writable: true, + value: 2 + }); + } + + test() { + Object.prototype.hasOwnProperty.call(this, _foo); + Object.prototype.hasOwnProperty.call(this, _bar2); + } + + } + + Object.prototype.hasOwnProperty.call(this, _foo); + Object.prototype.hasOwnProperty.call(this, _bar); + } + +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-redeclared/input.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-redeclared/input.js new file mode 100644 index 000000000000..2258be35c5fd --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-redeclared/input.js @@ -0,0 +1,15 @@ +class Foo { + #foo = 1; + + test() { + class Nested { + #foo = 2; + + test() { + #foo in this; + } + } + + #foo in this; + } +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-redeclared/output.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-redeclared/output.js new file mode 100644 index 000000000000..e20e475ad96f --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class-redeclared/output.js @@ -0,0 +1,31 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +class Foo { + constructor() { + Object.defineProperty(this, _foo, { + writable: true, + value: 1 + }); + } + + test() { + var _foo2 = babelHelpers.classPrivateFieldLooseKey("foo"); + + class Nested { + constructor() { + Object.defineProperty(this, _foo2, { + writable: true, + value: 2 + }); + } + + test() { + Object.prototype.hasOwnProperty.call(this, _foo2); + } + + } + + Object.prototype.hasOwnProperty.call(this, _foo); + } + +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class/input.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class/input.js new file mode 100644 index 000000000000..e17e438b314d --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class/input.js @@ -0,0 +1,13 @@ +class Foo { + #foo = 1; + + test() { + class Nested { + test() { + #foo in this; + } + } + + #foo in this; + } +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class/output.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class/output.js new file mode 100644 index 000000000000..b87aa8205365 --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/nested-class/output.js @@ -0,0 +1,22 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +class Foo { + constructor() { + Object.defineProperty(this, _foo, { + writable: true, + value: 1 + }); + } + + test() { + class Nested { + test() { + Object.prototype.hasOwnProperty.call(this, _foo); + } + + } + + Object.prototype.hasOwnProperty.call(this, _foo); + } + +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/options.json b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/options.json new file mode 100644 index 000000000000..27edc061ba5a --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + ["external-helpers",{ "helperVersion": "7.1000.0" }], + "proposal-private-property-in-object", + "proposal-private-methods", + "proposal-class-properties" + ], + "assumptions": { + "privateFieldsAsProperties": true + } +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-accessor/input.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-accessor/input.js new file mode 100644 index 000000000000..e74333f2055f --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-accessor/input.js @@ -0,0 +1,7 @@ +class Foo { + static get #foo() {} + + test(other) { + return #foo in other; + } +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-accessor/output.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-accessor/output.js new file mode 100644 index 000000000000..3f5bbb4c847f --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-accessor/output.js @@ -0,0 +1,15 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +class Foo { + test(other) { + return Object.prototype.hasOwnProperty.call(other, _foo); + } + +} + +var _get_foo = function () {}; + +Object.defineProperty(Foo, _foo, { + get: _get_foo, + set: void 0 +}); diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-field/input.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-field/input.js new file mode 100644 index 000000000000..a4f771844fe9 --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-field/input.js @@ -0,0 +1,7 @@ +class Foo { + static #foo = 1; + + test(other) { + return #foo in other; + } +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-field/output.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-field/output.js new file mode 100644 index 000000000000..b69ce320b78f --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-field/output.js @@ -0,0 +1,13 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +class Foo { + test(other) { + return Object.prototype.hasOwnProperty.call(other, _foo); + } + +} + +Object.defineProperty(Foo, _foo, { + writable: true, + value: 1 +}); diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-method/input.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-method/input.js new file mode 100644 index 000000000000..9fffe7a01622 --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-method/input.js @@ -0,0 +1,7 @@ +class Foo { + static #foo() {} + + test(other) { + return #foo in other; + } +} diff --git a/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-method/output.js b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-method/output.js new file mode 100644 index 000000000000..e6af49be3aff --- /dev/null +++ b/packages/babel-plugin-proposal-private-property-in-object/test/fixtures/assumption-privateFieldsAsProperties/static-method/output.js @@ -0,0 +1,14 @@ +var _foo = babelHelpers.classPrivateFieldLooseKey("foo"); + +class Foo { + test(other) { + return Object.prototype.hasOwnProperty.call(other, _foo); + } + +} + +var _foo2 = function _foo2() {}; + +Object.defineProperty(Foo, _foo, { + value: _foo2 +}); diff --git a/packages/babel-plugin-transform-arrow-functions/src/index.js b/packages/babel-plugin-transform-arrow-functions/src/index.js index 3e323707a887..98ac9f4d626e 100644 --- a/packages/babel-plugin-transform-arrow-functions/src/index.js +++ b/packages/babel-plugin-transform-arrow-functions/src/index.js @@ -4,7 +4,8 @@ import type NodePath from "@babel/traverse"; export default declare((api, options) => { api.assertVersion(7); - const { spec } = options; + const noNewArrows = api.assumption("noNewArrows") ?? !options.spec; + return { name: "transform-arrow-functions", @@ -20,7 +21,10 @@ export default declare((api, options) => { // While other utils may be fine inserting other arrows to make more transforms possible, // the arrow transform itself absolutely cannot insert new arrow functions. allowInsertArrow: false, - specCompliant: !!spec, + noNewArrows, + + // TODO(Babel 8): This is only needed for backward compat with @babel/traverse <7.13.0 + specCompliant: !noNewArrows, }); }, }, diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/options.json b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/options.json deleted file mode 100644 index edcdc8224cda..000000000000 --- a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/options.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "plugins": [ - "external-helpers", - ["transform-arrow-functions", { "spec": true }], - "transform-function-name" - ] -} diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/basic/input.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/basic/input.js new file mode 100644 index 000000000000..f84ea4ed3876 --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/basic/input.js @@ -0,0 +1,10 @@ +function foo() { + arr.map(x => x * x); + var f = (x, y) => x * y; + (function () { + return () => this; + })(); + return { + g: () => this + } +} diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/basic/output.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/basic/output.js new file mode 100644 index 000000000000..6b0103c02f66 --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/basic/output.js @@ -0,0 +1,29 @@ +function foo() { + var _this = this; + + arr.map(function (x) { + babelHelpers.newArrowCheck(this, _this); + return x * x; + }.bind(this)); + + var f = function f(x, y) { + babelHelpers.newArrowCheck(this, _this); + return x * y; + }.bind(this); + + (function () { + var _this2 = this; + + return function () { + babelHelpers.newArrowCheck(this, _this2); + return this; + }.bind(this); + })(); + + return { + g: function g() { + babelHelpers.newArrowCheck(this, _this); + return this; + }.bind(this) + }; +} diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-naming/input.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/naming/input.js similarity index 100% rename from packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-naming/input.js rename to packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/naming/input.js diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-naming/output.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/naming/output.js similarity index 100% rename from packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-naming/output.js rename to packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/naming/output.js diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/options.json b/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/options.json new file mode 100644 index 000000000000..0f1579e8b4f4 --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["external-helpers", "transform-arrow-functions"], + "assumptions": { + "noNewArrows": false + } +} diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/exec.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/self-referential/exec.js similarity index 100% rename from packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/exec.js rename to packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/self-referential/exec.js diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/input.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/self-referential/input.js similarity index 100% rename from packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/input.js rename to packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/self-referential/input.js diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/output.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/self-referential/output.js similarity index 100% rename from packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/output.js rename to packages/babel-plugin-transform-arrow-functions/test/fixtures/assumption-newableArrowFunctions-false/self-referential/output.js diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-default/input.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-default/input.js new file mode 100644 index 000000000000..0f3dac36a7ce --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-default/input.js @@ -0,0 +1 @@ +let a = () => 1; diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-naming/options.json b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-default/options.json similarity index 100% rename from packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-naming/options.json rename to packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-default/options.json diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-default/output.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-default/output.js new file mode 100644 index 000000000000..cee824c23a0b --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-default/output.js @@ -0,0 +1,6 @@ +var _this = this; + +let a = function a() { + babelHelpers.newArrowCheck(this, _this); + return 1; +}.bind(this); diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-false/input.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-false/input.js new file mode 100644 index 000000000000..0f3dac36a7ce --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-false/input.js @@ -0,0 +1 @@ +let a = () => 1; diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-false/options.json b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-false/options.json new file mode 100644 index 000000000000..54a09372627d --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-false/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + "external-helpers", + ["transform-arrow-functions", { "spec": false }] + ], + "assumptions": { + "noNewArrows": false + } +} diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-false/output.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-false/output.js new file mode 100644 index 000000000000..cee824c23a0b --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-false/output.js @@ -0,0 +1,6 @@ +var _this = this; + +let a = function a() { + babelHelpers.newArrowCheck(this, _this); + return 1; +}.bind(this); diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-true/input.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-true/input.js new file mode 100644 index 000000000000..0f3dac36a7ce --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-true/input.js @@ -0,0 +1 @@ +let a = () => 1; diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-true/options.json b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-true/options.json new file mode 100644 index 000000000000..fe79242117b9 --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-true/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + "external-helpers", + ["transform-arrow-functions", { "spec": true }] + ], + "assumptions": { + "noNewArrows": true + } +} diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-true/output.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-true/output.js new file mode 100644 index 000000000000..ccc9512d820a --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/spec/newableArrowFunction-vs-spec-true/output.js @@ -0,0 +1,3 @@ +let a = function () { + return 1; +}; diff --git a/packages/babel-plugin-transform-async-to-generator/src/index.js b/packages/babel-plugin-transform-async-to-generator/src/index.js index 55669063f13b..da21acedbf12 100644 --- a/packages/babel-plugin-transform-async-to-generator/src/index.js +++ b/packages/babel-plugin-transform-async-to-generator/src/index.js @@ -7,6 +7,7 @@ export default declare((api, options) => { api.assertVersion(7); const { method, module } = options; + const noNewArrows = api.assumption("noNewArrows"); if (method && module) { return { @@ -23,7 +24,7 @@ export default declare((api, options) => { wrapAsync = state.methodWrapper = addNamed(path, method, module); } - remapAsyncToGenerator(path, { wrapAsync }); + remapAsyncToGenerator(path, { wrapAsync }, noNewArrows); }, }, }; @@ -36,9 +37,11 @@ export default declare((api, options) => { Function(path, state) { if (!path.node.async || path.node.generator) return; - remapAsyncToGenerator(path, { - wrapAsync: state.addHelper("asyncToGenerator"), - }); + remapAsyncToGenerator( + path, + { wrapAsync: state.addHelper("asyncToGenerator") }, + noNewArrows, + ); }, }, }; diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/basic/exec.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/basic/exec.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/basic/input.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/basic/input.js new file mode 100644 index 000000000000..eb65515a95bd --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/basic/input.js @@ -0,0 +1 @@ +async () => 2; diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/basic/options.json b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/basic/options.json new file mode 100644 index 000000000000..0aed78e05b38 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/basic/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["external-helpers", "transform-async-to-generator"], + "assumptions": { + "noNewArrows": false + } +} diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/basic/output.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/basic/output.js new file mode 100644 index 000000000000..c0d2e6069da5 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/basic/output.js @@ -0,0 +1,7 @@ +var _this = this; + +/*#__PURE__*/ +babelHelpers.asyncToGenerator(function* () { + babelHelpers.newArrowCheck(this, _this); + return 2; +}); diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/bluebird/input.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/bluebird/input.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/bluebird/options.json b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/bluebird/options.json new file mode 100644 index 000000000000..bcd09c73c443 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/assumption-newableArrowFunctions-false/bluebird/options.json @@ -0,0 +1,12 @@ +{ + "plugins": [ + "external-helpers", + [ + "transform-async-to-generator", + { "module": "bluebird", "method": "coroutine" } + ] + ], + "assumptions": { + "noNewArrows": true + } +} diff --git a/packages/babel-plugin-transform-classes/src/index.js b/packages/babel-plugin-transform-classes/src/index.js index 8f0ecfc202ca..cceccf155e49 100644 --- a/packages/babel-plugin-transform-classes/src/index.js +++ b/packages/babel-plugin-transform-classes/src/index.js @@ -21,6 +21,12 @@ export default declare((api, options) => { const { loose } = options; + const setClassMethods = api.assumption("setClassMethods") ?? options.loose; + const constantSuper = api.assumption("constantSuper") ?? options.loose; + const superIsCallableConstructor = + api.assumption("superIsCallableConstructor") ?? options.loose; + const noClassCalls = api.assumption("noClassCalls") ?? options.loose; + // todo: investigate traversal requeueing const VISITED = Symbol(); @@ -58,12 +64,18 @@ export default declare((api, options) => { node[VISITED] = true; path.replaceWith( - transformClass(path, state.file, builtinClasses, loose), + transformClass(path, state.file, builtinClasses, loose, { + setClassMethods, + constantSuper, + superIsCallableConstructor, + noClassCalls, + }), ); if (path.isCallExpression()) { annotateAsPure(path); if (path.get("callee").isArrowFunctionExpression()) { + // This is an IIFE, so we don't need to worry about the noNewArrows assumption path.get("callee").arrowFunctionToExpression(); } } diff --git a/packages/babel-plugin-transform-classes/src/transformClass.js b/packages/babel-plugin-transform-classes/src/transformClass.js index 0d3fa37600d8..5244e6b64022 100644 --- a/packages/babel-plugin-transform-classes/src/transformClass.js +++ b/packages/babel-plugin-transform-classes/src/transformClass.js @@ -11,6 +11,13 @@ import addCreateSuperHelper from "./inline-createSuper-helpers"; type ReadonlySet = Set | { has(val: T): boolean }; +type ClassAssumptions = { + setClassMethods: boolean, + constantSuper: boolean, + superIsCallableConstructor: boolean, + noClassCalls: boolean, +}; + function buildConstructor(classRef, constructorBody, node) { const func = t.functionDeclaration( t.cloneNode(classRef), @@ -26,6 +33,7 @@ export default function transformClass( file: any, builtinClasses: ReadonlySet, isLoose: boolean, + assumptions: ClassAssumptions, ) { const classState = { parent: undefined, @@ -161,7 +169,7 @@ export default function transformClass( methodPath: path, objectRef: classState.classRef, superRef: classState.superName, - isLoose: classState.isLoose, + constantSuper: assumptions.constantSuper, file: classState.file, refToPreserve: classState.classRef, }); @@ -246,7 +254,7 @@ export default function transformClass( const bareSuperNode = bareSuper.node; let call; - if (classState.isLoose) { + if (assumptions.superIsCallableConstructor) { bareSuperNode.arguments.unshift(t.thisExpression()); if ( bareSuperNode.arguments.length === 2 && @@ -452,7 +460,7 @@ export default function transformClass( } function processMethod(node, scope) { - if (classState.isLoose && !node.decorators) { + if (assumptions.setClassMethods && !node.decorators) { // use assignments instead of define properties for loose classes let { classRef } = classState; if (!node.static) { @@ -563,7 +571,7 @@ export default function transformClass( // Unshift to ensure that the constructor inheritance is set up before // any properties can be assigned to the prototype. - if (!classState.isLoose) { + if (!assumptions.superIsCallableConstructor) { classState.body.unshift( t.variableDeclaration("var", [ t.variableDeclarator( @@ -663,7 +671,7 @@ export default function transformClass( buildBody(); // make sure this class isn't directly called (with A() instead new A()) - if (!classState.isLoose) { + if (!assumptions.noClassCalls) { constructorBody.body.unshift( t.expressionStatement( t.callExpression(classState.file.addHelper("classCallCheck"), [ diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-class/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-class/input.js new file mode 100644 index 000000000000..83f054a6e911 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-class/input.js @@ -0,0 +1,13 @@ +class Test extends Foo { + constructor() { + woops.super.test(); + super(); + super.test(); + + super(...arguments); + super("test", ...arguments); + + super.test(...arguments); + super.test("test", ...arguments); + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-class/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-class/output.js new file mode 100644 index 000000000000..929c2c08fe95 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-class/output.js @@ -0,0 +1,30 @@ +var Test = /*#__PURE__*/function (_Foo) { + "use strict"; + + babelHelpers.inherits(Test, _Foo); + + var _super = babelHelpers.createSuper(Test); + + function Test() { + var _Foo$prototype$test; + + var _this; + + babelHelpers.classCallCheck(this, Test); + woops.super.test(); + _this = _super.call(this); + + _Foo.prototype.test.call(babelHelpers.assertThisInitialized(_this)); + + _this = _super.apply(this, arguments); + _this = _super.call.apply(_super, [this, "test"].concat(Array.prototype.slice.call(arguments))); + + _Foo.prototype.test.apply(babelHelpers.assertThisInitialized(_this), arguments); + + (_Foo$prototype$test = _Foo.prototype.test).call.apply(_Foo$prototype$test, [babelHelpers.assertThisInitialized(_this), "test"].concat(Array.prototype.slice.call(arguments))); + + return _this; + } + + return Test; +}(Foo); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-properties/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-properties/input.js new file mode 100644 index 000000000000..fad2b31584ef --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-properties/input.js @@ -0,0 +1,7 @@ +class Test extends Foo { + constructor() { + super(); + super.test; + super.test.whatever; + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-properties/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-properties/output.js new file mode 100644 index 000000000000..57ce4e416d44 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-properties/output.js @@ -0,0 +1,19 @@ +var Test = /*#__PURE__*/function (_Foo) { + "use strict"; + + babelHelpers.inherits(Test, _Foo); + + var _super = babelHelpers.createSuper(Test); + + function Test() { + var _this; + + babelHelpers.classCallCheck(this, Test); + _this = _super.call(this); + _Foo.prototype.test; + _Foo.prototype.test.whatever; + return _this; + } + + return Test; +}(Foo); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-property-optional-chain/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-property-optional-chain/input.js new file mode 100644 index 000000000000..e0788b60b37f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-property-optional-chain/input.js @@ -0,0 +1,6 @@ +class Test extends Foo { + constructor() { + super.foo?.bar; + super.foo?.(); + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-property-optional-chain/options.json b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-property-optional-chain/options.json new file mode 100644 index 000000000000..d969db5fb34d --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-property-optional-chain/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + ["proposal-optional-chaining", { "loose": true }], + "transform-function-name", + ["transform-classes", { "loose": true }], + ["transform-spread", { "loose": true }], + "transform-block-scoping" + ] +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-property-optional-chain/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-property-optional-chain/output.js new file mode 100644 index 000000000000..d076ccfc9cce --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/accessing-super-property-optional-chain/output.js @@ -0,0 +1,17 @@ +var Test = /*#__PURE__*/function (_Foo) { + "use strict"; + + babelHelpers.inheritsLoose(Test, _Foo); + + function Test() { + var _Foo$prototype$foo, _Foo$prototype$foo2; + + var _this; + + (_Foo$prototype$foo = _Foo.prototype.foo) == null ? void 0 : _Foo$prototype$foo.bar; + (_Foo$prototype$foo2 = _Foo.prototype.foo) == null ? void 0 : _Foo$prototype$foo2.call(babelHelpers.assertThisInitialized(_this)); + return babelHelpers.assertThisInitialized(_this); + } + + return Test; +}(Foo); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/calling-super-properties/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/calling-super-properties/input.js new file mode 100644 index 000000000000..0b392d3eb252 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/calling-super-properties/input.js @@ -0,0 +1,11 @@ +class Test extends Foo { + constructor() { + super(); + super.test.whatever(); + super.test(); + } + + static test() { + return super.wow(); + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/calling-super-properties/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/calling-super-properties/output.js new file mode 100644 index 000000000000..d071019228d2 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/calling-super-properties/output.js @@ -0,0 +1,28 @@ +var Test = /*#__PURE__*/function (_Foo) { + "use strict"; + + babelHelpers.inherits(Test, _Foo); + + var _super = babelHelpers.createSuper(Test); + + function Test() { + var _this; + + babelHelpers.classCallCheck(this, Test); + _this = _super.call(this); + + _Foo.prototype.test.whatever(); + + _Foo.prototype.test.call(babelHelpers.assertThisInitialized(_this)); + + return _this; + } + + babelHelpers.createClass(Test, null, [{ + key: "test", + value: function test() { + return _Foo.wow.call(this); + } + }]); + return Test; +}(Foo); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/default-super/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/default-super/input.js new file mode 100644 index 000000000000..eaba10ab2bbd --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/default-super/input.js @@ -0,0 +1,17 @@ +class Test { + constructor() { + return super.constructor; + } + + static test() { + return super.constructor; + } +} + +// Instances +expect(Object.getPrototypeOf(Test.prototype)).toBe(Object.prototype); +expect(new Test()).toBe(Object); + +// Static +expect(Object.getPrototypeOf(Test)).toBe(Function.prototype); +expect(Test.test()).toBe(Function); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/default-super/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/default-super/output.js new file mode 100644 index 000000000000..56f85c05785c --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/default-super/output.js @@ -0,0 +1,23 @@ +var Test = /*#__PURE__*/function () { + "use strict"; + + function Test() { + babelHelpers.classCallCheck(this, Test); + return Object.prototype.constructor; + } + + babelHelpers.createClass(Test, null, [{ + key: "test", + value: function test() { + return Function.prototype.constructor; + } + }]); + return Test; +}(); // Instances + + +expect(Object.getPrototypeOf(Test.prototype)).toBe(Object.prototype); +expect(new Test()).toBe(Object); // Static + +expect(Object.getPrototypeOf(Test)).toBe(Function.prototype); +expect(Test.test()).toBe(Function); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/options.json b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/options.json new file mode 100644 index 000000000000..39e1d1bab810 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/options.json @@ -0,0 +1,12 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "transform-function-name", + "transform-classes", + ["transform-spread", { "loose": true }], + "transform-block-scoping" + ], + "assumptions": { + "constantSuper": true + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/super-function-fallback/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/super-function-fallback/input.js new file mode 100644 index 000000000000..18ebeb8f3085 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/super-function-fallback/input.js @@ -0,0 +1,5 @@ +class Test { + constructor() { + super.hasOwnProperty("test"); + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/super-function-fallback/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/super-function-fallback/output.js new file mode 100644 index 000000000000..f57c0d549409 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-constantSuper/super-function-fallback/output.js @@ -0,0 +1,6 @@ +var Test = function Test() { + "use strict"; + + babelHelpers.classCallCheck(this, Test); + Object.prototype.hasOwnProperty.call(this, "test"); +}; diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/class/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/class/input.js new file mode 100644 index 000000000000..a869c2849526 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/class/input.js @@ -0,0 +1 @@ +class A {} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/class/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/class/output.js new file mode 100644 index 000000000000..60718092a600 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/class/output.js @@ -0,0 +1,3 @@ +var A = function A() { + "use strict"; +}; diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/options.json b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/options.json new file mode 100644 index 000000000000..fe4fa1e68bec --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/options.json @@ -0,0 +1,12 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "transform-function-name", + "transform-classes", + ["transform-spread", { "loose": true }], + "transform-block-scoping" + ], + "assumptions": { + "noClassCalls": true + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-constructor/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-constructor/input.js new file mode 100644 index 000000000000..9da66478b288 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-constructor/input.js @@ -0,0 +1,11 @@ +class A { + constructor() { + console.log('a'); + } +} + +class B { + b() { + console.log('b'); + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-constructor/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-constructor/output.js new file mode 100644 index 000000000000..a9666614fef8 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-constructor/output.js @@ -0,0 +1,19 @@ +var A = function A() { + "use strict"; + + console.log('a'); +}; + +var B = /*#__PURE__*/function () { + "use strict"; + + function B() {} + + babelHelpers.createClass(B, [{ + key: "b", + value: function b() { + console.log('b'); + } + }]); + return B; +}(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-superClass/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-superClass/input.js new file mode 100644 index 000000000000..76bb1ebddfbf --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-superClass/input.js @@ -0,0 +1,8 @@ +class B {} + +class A extends B { + constructor(track) { + if (track !== undefined) super(track); + else super(); + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-superClass/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-superClass/output.js new file mode 100644 index 000000000000..1d09fd08d8e6 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-noCallClass/with-superClass/output.js @@ -0,0 +1,20 @@ +var B = function B() { + "use strict"; +}; + +var A = /*#__PURE__*/function (_B) { + "use strict"; + + babelHelpers.inherits(A, _B); + + var _super = babelHelpers.createSuper(A); + + function A(track) { + var _this; + + if (track !== undefined) _this = _super.call(this, track);else _this = _super.call(this); + return babelHelpers.possibleConstructorReturn(_this); + } + + return A; +}(B); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/input.js new file mode 100644 index 000000000000..e3ad20145b86 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/input.js @@ -0,0 +1,5 @@ +class Foo { + "bar"() { + + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/output.js new file mode 100644 index 000000000000..610fbb5a157e --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/literal-key/output.js @@ -0,0 +1,13 @@ +var Foo = /*#__PURE__*/function () { + "use strict"; + + function Foo() { + babelHelpers.classCallCheck(this, Foo); + } + + var _proto = Foo.prototype; + + _proto["bar"] = function bar() {}; + + return Foo; +}(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/input.js new file mode 100644 index 000000000000..918e7469b6c7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/input.js @@ -0,0 +1,6 @@ +// @flow +class C { + m(x: number): string { + return 'a'; + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/options.json b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/options.json new file mode 100644 index 000000000000..1f9617ec390b --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + "external-helpers", + "transform-function-name", + ["transform-classes", { "loose": true }], + "transform-spread", + "transform-block-scoping", + "syntax-flow" + ] +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/output.js new file mode 100644 index 000000000000..45403829143d --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-return-type-annotation/output.js @@ -0,0 +1,14 @@ +// @flow +var C = /*#__PURE__*/function () { + "use strict"; + + function C() {} + + var _proto = C.prototype; + + _proto.m = function m(x: number): string { + return 'a'; + }; + + return C; +}(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/input.js new file mode 100644 index 000000000000..1c08a3644980 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/input.js @@ -0,0 +1,5 @@ +class Test { + a() {} + static b() {} + c() {} +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/output.js new file mode 100644 index 000000000000..844b0d7655e7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/method-reuse-prototype/output.js @@ -0,0 +1,17 @@ +var Test = /*#__PURE__*/function () { + "use strict"; + + function Test() { + babelHelpers.classCallCheck(this, Test); + } + + var _proto = Test.prototype; + + _proto.a = function a() {}; + + Test.b = function b() {}; + + _proto.c = function c() {}; + + return Test; +}(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/options.json b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/options.json new file mode 100644 index 000000000000..62562eb645d7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/options.json @@ -0,0 +1,12 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "transform-function-name", + "transform-classes", + ["transform-spread", { "loose": true }], + "transform-block-scoping" + ], + "assumptions": { + "setClassMethods": true + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/input.js new file mode 100644 index 000000000000..4bbf0638b3be --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/input.js @@ -0,0 +1,7 @@ +"use strict"; + +class Foo { + method() { + + } +} \ No newline at end of file diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/output.js new file mode 100644 index 000000000000..96acb356c59a --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-setClassMethods/program-with-use-strict-directive/output.js @@ -0,0 +1,13 @@ +"use strict"; + +var Foo = /*#__PURE__*/function () { + function Foo() { + babelHelpers.classCallCheck(this, Foo); + } + + var _proto = Foo.prototype; + + _proto.method = function method() {}; + + return Foo; +}(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/options.json b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/options.json new file mode 100644 index 000000000000..7002b66f731e --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/options.json @@ -0,0 +1,12 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "transform-function-name", + "transform-classes", + ["transform-spread", { "loose": true }], + "transform-block-scoping" + ], + "assumptions": { + "superIsCallableConstructor": true + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-id-member-expression/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-id-member-expression/input.js new file mode 100644 index 000000000000..e245d3a69baa --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-id-member-expression/input.js @@ -0,0 +1,7 @@ +class BaseController extends Chaplin.Controller { + +} + +class BaseController2 extends Chaplin.Controller.Another { + +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-id-member-expression/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-id-member-expression/output.js new file mode 100644 index 000000000000..1b4b3a994b0d --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-id-member-expression/output.js @@ -0,0 +1,25 @@ +var BaseController = /*#__PURE__*/function (_Chaplin$Controller) { + "use strict"; + + babelHelpers.inherits(BaseController, _Chaplin$Controller); + + function BaseController() { + babelHelpers.classCallCheck(this, BaseController); + return _Chaplin$Controller.apply(this, arguments) || this; + } + + return BaseController; +}(Chaplin.Controller); + +var BaseController2 = /*#__PURE__*/function (_Chaplin$Controller$A) { + "use strict"; + + babelHelpers.inherits(BaseController2, _Chaplin$Controller$A); + + function BaseController2() { + babelHelpers.classCallCheck(this, BaseController2); + return _Chaplin$Controller$A.apply(this, arguments) || this; + } + + return BaseController2; +}(Chaplin.Controller.Another); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-this-usage/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-this-usage/input.js new file mode 100644 index 000000000000..f27cd5b8b449 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-this-usage/input.js @@ -0,0 +1,9 @@ +class Test extends Foo { + constructor() { + super(); + + this; + + this.prop = 1; + } +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-this-usage/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-this-usage/output.js new file mode 100644 index 000000000000..f516eaf62a1f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class-this-usage/output.js @@ -0,0 +1,17 @@ +var Test = /*#__PURE__*/function (_Foo) { + "use strict"; + + babelHelpers.inherits(Test, _Foo); + + function Test() { + var _this; + + babelHelpers.classCallCheck(this, Test); + _this = _Foo.call(this) || this; + babelHelpers.assertThisInitialized(_this); + _this.prop = 1; + return _this; + } + + return Test; +}(Foo); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class/input.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class/input.js new file mode 100644 index 000000000000..13a98b37be8b --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class/input.js @@ -0,0 +1 @@ +class Test extends Foo { } diff --git a/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class/output.js b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class/output.js new file mode 100644 index 000000000000..01c3014c0112 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/assumption-superIsCallableConstructor/super-class/output.js @@ -0,0 +1,12 @@ +var Test = /*#__PURE__*/function (_Foo) { + "use strict"; + + babelHelpers.inherits(Test, _Foo); + + function Test() { + babelHelpers.classCallCheck(this, Test); + return _Foo.apply(this, arguments) || this; + } + + return Test; +}(Foo); diff --git a/packages/babel-plugin-transform-computed-properties/src/index.js b/packages/babel-plugin-transform-computed-properties/src/index.js index eabb277b3e42..9fa5c5c96482 100644 --- a/packages/babel-plugin-transform-computed-properties/src/index.js +++ b/packages/babel-plugin-transform-computed-properties/src/index.js @@ -4,8 +4,10 @@ import { template, types as t } from "@babel/core"; export default declare((api, options) => { api.assertVersion(7); - const { loose } = options; - const pushComputedProps = loose + const setComputedProperties = + api.assumption("setComputedProperties") ?? options.loose; + + const pushComputedProps = setComputedProperties ? pushComputedPropsLoose : pushComputedPropsSpec; diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/accessors/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/accessors/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/accessors/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/accessors/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/accessors/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/accessors/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/accessors/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/accessors/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/argument/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/argument/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/argument/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/argument/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/argument/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/argument/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/argument/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/argument/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/assignment/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/assignment/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/assignment/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/assignment/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/assignment/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/assignment/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/assignment/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/assignment/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/coerce/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/coerce/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/coerce/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/coerce/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/coerce/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/coerce/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/coerce/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/coerce/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/method/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/method/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/method/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/method/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/method/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/method/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/method/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/method/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/mixed/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/mixed/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/mixed/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/mixed/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/mixed/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/mixed/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/mixed/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/mixed/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/multiple/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/multiple/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/multiple/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/multiple/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/multiple/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/multiple/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/multiple/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/multiple/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/options.json b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/options.json new file mode 100644 index 000000000000..2a2f114c2a9e --- /dev/null +++ b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + "external-helpers", + "transform-computed-properties" + ], + "assumptions": { + "setComputedProperties": true + } +} diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/single/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/single/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/single/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/single/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/single/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/single/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/single/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/single/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/symbol/exec.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/symbol/exec.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/symbol/exec.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/symbol/exec.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/symbol/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/symbol/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/symbol/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/symbol/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/symbol/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/symbol/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/symbol/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/symbol/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/this/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/this/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/this/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/this/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/this/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/this/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/this/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/this/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/two/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/two/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/two/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/two/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/two/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/two/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/two/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/two/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/variable/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/variable/input.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/variable/input.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/variable/input.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/variable/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/variable/output.js similarity index 100% rename from packages/babel-plugin-transform-computed-properties/test/fixtures/loose/variable/output.js rename to packages/babel-plugin-transform-computed-properties/test/fixtures/assumption-setComputedProperties/variable/output.js diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/setComputedProperties/input.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/setComputedProperties/input.js new file mode 100644 index 000000000000..02d4195fa78d --- /dev/null +++ b/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/setComputedProperties/input.js @@ -0,0 +1,4 @@ +var obj = { + ["x" + foo]: "heh", + ["y" + bar]: "noo" +}; diff --git a/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/setComputedProperties/output.js b/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/setComputedProperties/output.js new file mode 100644 index 000000000000..13145e4a26f8 --- /dev/null +++ b/packages/babel-plugin-transform-computed-properties/test/fixtures/loose/setComputedProperties/output.js @@ -0,0 +1,3 @@ +var _obj; + +var obj = (_obj = {}, _obj["x" + foo] = "heh", _obj["y" + bar] = "noo", _obj); diff --git a/packages/babel-plugin-transform-destructuring/src/index.js b/packages/babel-plugin-transform-destructuring/src/index.js index cca55d21be77..d42c2bfc7a5d 100644 --- a/packages/babel-plugin-transform-destructuring/src/index.js +++ b/packages/babel-plugin-transform-destructuring/src/index.js @@ -4,17 +4,13 @@ import { types as t } from "@babel/core"; export default declare((api, options) => { api.assertVersion(7); - const { - loose = false, - useBuiltIns = false, - allowArrayLike = false, - } = options; - - if (typeof loose !== "boolean") { - throw new Error(`.loose must be a boolean or undefined`); - } + const { useBuiltIns = false } = options; - const arrayOnlySpread = loose; + const iterableIsArray = api.assumption("iterableIsArray") ?? options.loose; + const arrayLikeIsIterable = + options.allowArrayLike ?? api.assumption("arrayLikeIsIterable"); + const objectRestNoSymbols = + api.assumption("objectRestNoSymbols") ?? options.loose; function getExtendsHelper(file) { return useBuiltIns @@ -88,8 +84,8 @@ export default declare((api, options) => { this.nodes = opts.nodes || []; this.scope = opts.scope; this.kind = opts.kind; - this.arrayOnlySpread = opts.arrayOnlySpread; - this.allowArrayLike = opts.allowArrayLike; + this.iterableIsArray = opts.iterableIsArray; + this.arrayLikeIsIterable = opts.arrayLikeIsIterable; this.addHelper = opts.addHelper; } @@ -141,12 +137,12 @@ export default declare((api, options) => { toArray(node, count) { if ( - this.arrayOnlySpread || + this.iterableIsArray || (t.isIdentifier(node) && this.arrays[node.name]) ) { return node; } else { - return this.scope.toArray(node, count, this.allowArrayLike); + return this.scope.toArray(node, count, this.arrayLikeIsIterable); } } @@ -235,7 +231,9 @@ export default declare((api, options) => { } value = t.callExpression( - this.addHelper(`objectWithoutProperties${loose ? "Loose" : ""}`), + this.addHelper( + `objectWithoutProperties${objectRestNoSymbols ? "Loose" : ""}`, + ), [t.cloneNode(objRef), keyExpression], ); } @@ -527,8 +525,8 @@ export default declare((api, options) => { kind: left.kind, scope: scope, nodes: nodes, - arrayOnlySpread, - allowArrayLike, + iterableIsArray, + arrayLikeIsIterable, addHelper: name => this.addHelper(name), }); @@ -553,8 +551,8 @@ export default declare((api, options) => { kind: "let", scope: scope, nodes: nodes, - arrayOnlySpread, - allowArrayLike, + iterableIsArray, + arrayLikeIsIterable, addHelper: name => this.addHelper(name), }); destructuring.init(pattern, ref); @@ -572,8 +570,8 @@ export default declare((api, options) => { operator: node.operator, scope: scope, nodes: nodes, - arrayOnlySpread, - allowArrayLike, + iterableIsArray, + arrayLikeIsIterable, addHelper: name => this.addHelper(name), }); @@ -631,8 +629,8 @@ export default declare((api, options) => { nodes: nodes, scope: scope, kind: node.kind, - arrayOnlySpread, - allowArrayLike, + iterableIsArray, + arrayLikeIsIterable, addHelper: name => this.addHelper(name), }); diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/holes/exec.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/holes/exec.js new file mode 100644 index 000000000000..108b033a0cc7 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/holes/exec.js @@ -0,0 +1,6 @@ +var o = { 0: "a", 2: "c", length: 3 }; + +var [...rest] = o; + +expect(rest).toEqual(["a", undefined, "c"]); +expect(1 in rest).toBe(true); // Not holey diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/length-cropped/exec.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/length-cropped/exec.js new file mode 100644 index 000000000000..ec1b3fc7dfc3 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/length-cropped/exec.js @@ -0,0 +1,6 @@ +var o = { 0: "a", 1: "b", 2: "c", length: 2 }; + +var [first, ...rest] = o; + +expect(first).toBe("a"); +expect(rest).toEqual(["b"]); diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/options.json b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/options.json new file mode 100644 index 000000000000..c2eb7c339ded --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "transform-destructuring" + ], + "assumptions": { + "arrayLikeIsIterable": true + } +} diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/simple/exec.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/simple/exec.js new file mode 100644 index 000000000000..8e71b1e45cfa --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/simple/exec.js @@ -0,0 +1,6 @@ +var o = { 0: "a", 1: "b", 2: "c", length: 3 }; + +var [first, ...rest] = o; + +expect(first).toBe("a"); +expect(rest).toEqual(["b", "c"]); diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/simple/input.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/simple/input.js new file mode 100644 index 000000000000..7d37e9622d78 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/simple/input.js @@ -0,0 +1 @@ +var [first, ...rest] = o; diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/simple/output.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/simple/output.js new file mode 100644 index 000000000000..50615d4e3e13 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-arrayLikeIsIterable/simple/output.js @@ -0,0 +1,4 @@ +var _o = o, + _o2 = babelHelpers.maybeArrayLike(babelHelpers.toArray, _o), + first = _o2[0], + rest = _o2.slice(1); diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/basic/input.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/basic/input.js new file mode 100644 index 000000000000..bc86d03f6d6b --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/basic/input.js @@ -0,0 +1 @@ +let [foo, bar] = baz; diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/basic/output.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/basic/output.js new file mode 100644 index 000000000000..c5b4279cf5fc --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/basic/output.js @@ -0,0 +1,3 @@ +let _baz = baz, + foo = _baz[0], + bar = _baz[1]; diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/for-in/input.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/for-in/input.js new file mode 100644 index 000000000000..f7a87fe3f876 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/for-in/input.js @@ -0,0 +1,7 @@ +for (var [name, value] in obj) { + print("Name: " + name + ", Value: " + value); +} + +for ([name, value] in obj) { + print("Name: " + name + ", Value: " + value); +} diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/for-in/output.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/for-in/output.js new file mode 100644 index 000000000000..de8d1198b549 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/for-in/output.js @@ -0,0 +1,11 @@ +for (var _ref in obj) { + var name = _ref[0]; + var value = _ref[1]; + print("Name: " + name + ", Value: " + value); +} + +for (var _ref2 in obj) { + name = _ref2[0]; + value = _ref2[1]; + print("Name: " + name + ", Value: " + value); +} diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/options.json b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/options.json new file mode 100644 index 000000000000..e08ab5b1c8f4 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-iterableIsArray/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "transform-destructuring" + ], + "assumptions": { + "iterableIsArray": true + } +} diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/options.json b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/options.json new file mode 100644 index 000000000000..d48381a6db92 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0"}], + "transform-destructuring" + ], + "assumptions": { + "objectRestNoSymbols": true + } +} diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/input.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/input.js new file mode 100644 index 000000000000..f03be37640bc --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/input.js @@ -0,0 +1 @@ +({ a, b, ...c } = obj); diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/output.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/output.js new file mode 100644 index 000000000000..462fb0f56a31 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-assignment-expression/output.js @@ -0,0 +1,5 @@ +var _obj = obj; +a = _obj.a; +b = _obj.b; +c = babelHelpers.objectWithoutPropertiesLoose(_obj, ["a", "b"]); +_obj; diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-computed/input.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-computed/input.js new file mode 100644 index 000000000000..8ddf55177eac --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-computed/input.js @@ -0,0 +1 @@ +let { [a]: b, ...c } = obj; diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-computed/output.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-computed/output.js new file mode 100644 index 000000000000..3e00dda0fa08 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-computed/output.js @@ -0,0 +1,4 @@ +let _obj = obj, + _a = a, + b = _obj[_a], + c = babelHelpers.objectWithoutPropertiesLoose(_obj, [_a].map(babelHelpers.toPropertyKey)); diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-ignore-symbols/exec.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-ignore-symbols/exec.js new file mode 100644 index 000000000000..2c85a4c5711e --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-ignore-symbols/exec.js @@ -0,0 +1,7 @@ +let sym = Symbol(); + +let { a, ...r } = { a: 1, b: 2, [sym]: 3 }; + +expect(a).toBe(1); +expect(r.b).toBe(2); +expect(sym in r).toBe(false); diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-nested/input.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-nested/input.js new file mode 100644 index 000000000000..e1025ccc4cb9 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-nested/input.js @@ -0,0 +1 @@ +let { a, nested: { b, c, ...d }, e } = obj; diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-nested/output.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-nested/output.js new file mode 100644 index 000000000000..db6b37a3420f --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-nested/output.js @@ -0,0 +1,7 @@ +let _obj = obj, + a = _obj.a, + _obj$nested = _obj.nested, + b = _obj$nested.b, + c = _obj$nested.c, + d = babelHelpers.objectWithoutPropertiesLoose(_obj$nested, ["b", "c"]), + e = _obj.e; diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/input.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/input.js new file mode 100644 index 000000000000..099aa76e4907 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/input.js @@ -0,0 +1 @@ +var { a, b, ...c } = obj; diff --git a/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/output.js b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/output.js new file mode 100644 index 000000000000..96c7228e6297 --- /dev/null +++ b/packages/babel-plugin-transform-destructuring/test/fixtures/assumption-objectRestNoSymbols/rest-var-declaration/output.js @@ -0,0 +1,4 @@ +var _obj = obj, + a = _obj.a, + b = _obj.b, + c = babelHelpers.objectWithoutPropertiesLoose(_obj, ["a", "b"]); diff --git a/packages/babel-plugin-transform-for-of/src/index.js b/packages/babel-plugin-transform-for-of/src/index.js index 42b238aef076..882ff9b82baa 100644 --- a/packages/babel-plugin-transform-for-of/src/index.js +++ b/packages/babel-plugin-transform-for-of/src/index.js @@ -6,28 +6,48 @@ import transformWithoutHelper from "./no-helper-implementation"; export default declare((api, options) => { api.assertVersion(7); - const { loose, assumeArray, allowArrayLike } = options; + { + const { assumeArray, allowArrayLike, loose } = options; - if (loose === true && assumeArray === true) { - throw new Error( - `The loose and assumeArray options cannot be used together in @babel/plugin-transform-for-of`, - ); - } + if (loose === true && assumeArray === true) { + throw new Error( + `The loose and assumeArray options cannot be used together in @babel/plugin-transform-for-of`, + ); + } - if (assumeArray === true && allowArrayLike === true) { - throw new Error( - `The assumeArray and allowArrayLike options cannot be used together in @babel/plugin-transform-for-of`, - ); + if (assumeArray === true && allowArrayLike === true) { + throw new Error( + `The assumeArray and allowArrayLike options cannot be used together in @babel/plugin-transform-for-of`, + ); + } + + // TODO: Remove in Babel 8 + if (allowArrayLike && /^7\.\d\./.test(api.version)) { + throw new Error( + `The allowArrayLike is only supported when using @babel/core@^7.10.0`, + ); + } } - // TODO: Remove in Babel 8 - if (allowArrayLike && /^7\.\d\./.test(api.version)) { + const iterableIsArray = + options.assumeArray ?? + // Loose mode is not compatible with 'assumeArray', so we shouldn't read + // 'iterableIsArray' if 'loose' is true. + (!options.loose && api.assumption("iterableIsArray")); + + const arrayLikeIsIterable = + options.allowArrayLike ?? api.assumption("arrayLikeIsIterable"); + + const skipteratorClosing = + api.assumption("skipForOfIteratorClosing") ?? options.loose; + + if (iterableIsArray && arrayLikeIsIterable) { throw new Error( - `The allowArrayLike is only supported when using @babel/core@^7.10.0`, + `The "iterableIsArray" and "arrayLikeIsIterable" assumptions are not compatible.`, ); } - if (assumeArray) { + if (iterableIsArray) { return { name: "transform-for-of", @@ -94,17 +114,17 @@ export default declare((api, options) => { }; } - const buildForOfArray = template(` + const buildForOfArray = template` for (var KEY = 0, NAME = ARR; KEY < NAME.length; KEY++) BODY; - `); + `; - const buildForOfLoose = template.statements(` - for (var ITERATOR_HELPER = CREATE_ITERATOR_HELPER(OBJECT, ALLOW_ARRAY_LIKE), STEP_KEY; + const buildForOfNoIteratorClosing = template.statements` + for (var ITERATOR_HELPER = CREATE_ITERATOR_HELPER(OBJECT, ARRAY_LIKE_IS_ITERABLE), STEP_KEY; !(STEP_KEY = ITERATOR_HELPER()).done;) BODY; - `); + `; - const buildForOf = template.statements(` - var ITERATOR_HELPER = CREATE_ITERATOR_HELPER(OBJECT, ALLOW_ARRAY_LIKE), STEP_KEY; + const buildForOf = template.statements` + var ITERATOR_HELPER = CREATE_ITERATOR_HELPER(OBJECT, ARRAY_LIKE_IS_ITERABLE), STEP_KEY; try { for (ITERATOR_HELPER.s(); !(STEP_KEY = ITERATOR_HELPER.n()).done;) BODY; } catch (err) { @@ -112,11 +132,11 @@ export default declare((api, options) => { } finally { ITERATOR_HELPER.f(); } - `); + `; - const builder = loose + const builder = skipteratorClosing ? { - build: buildForOfLoose, + build: buildForOfNoIteratorClosing, helper: "createForOfIteratorHelperLoose", getContainer: nodes => nodes, } @@ -179,7 +199,7 @@ export default declare((api, options) => { if (!state.availableHelper(builder.helper)) { // Babel <7.9.0 doesn't support this helper - transformWithoutHelper(loose, path, state); + transformWithoutHelper(skipteratorClosing, path, state); return; } @@ -213,7 +233,9 @@ export default declare((api, options) => { const nodes = builder.build({ CREATE_ITERATOR_HELPER: state.addHelper(builder.helper), ITERATOR_HELPER: scope.generateUidIdentifier("iterator"), - ALLOW_ARRAY_LIKE: allowArrayLike ? t.booleanLiteral(true) : null, + ARRAY_LIKE_IS_ITERABLE: arrayLikeIsIterable + ? t.booleanLiteral(true) + : null, STEP_KEY: t.identifier(stepKey), OBJECT: node.right, BODY: node.body, diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/holes/exec.js b/packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/holes/exec.js similarity index 100% rename from packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/holes/exec.js rename to packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/holes/exec.js diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/holes/options.json b/packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/holes/options.json similarity index 100% rename from packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/holes/options.json rename to packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/holes/options.json diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/length-cropped/exec.js b/packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/length-cropped/exec.js similarity index 100% rename from packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/length-cropped/exec.js rename to packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/length-cropped/exec.js diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/length-cropped/options.json b/packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/length-cropped/options.json similarity index 100% rename from packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/length-cropped/options.json rename to packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/length-cropped/options.json diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/simple/exec.js b/packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/simple/exec.js similarity index 100% rename from packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/simple/exec.js rename to packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/simple/exec.js diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/simple/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/simple/input.js similarity index 100% rename from packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/simple/input.js rename to packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/simple/input.js diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/simple/options.json b/packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/simple/options.json similarity index 100% rename from packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/simple/options.json rename to packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/simple/options.json diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/simple/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/simple/output.js similarity index 100% rename from packages/babel-plugin-transform-for-of/test/fixtures/spec-allowArrayLike/simple/output.js rename to packages/babel-plugin-transform-for-of/test/fixtures/allowArrayLike/simple/output.js diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/holes/exec.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/holes/exec.js new file mode 100644 index 000000000000..4bd0a5df0097 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/holes/exec.js @@ -0,0 +1,7 @@ +var p2 = { 0: "a", 2: "c", length: 3 }; + +var arr = []; +for (var x of p2) arr.push(x); + +expect(arr).toEqual(["a", undefined, "c"]); +expect(1 in arr).toBe(true); // Not holey diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/length-cropped/exec.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/length-cropped/exec.js new file mode 100644 index 000000000000..16d81476a95e --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/length-cropped/exec.js @@ -0,0 +1,6 @@ +var p2 = { 0: "b", 1: "c", 2: "d", length: 2 }; + +var arr = []; +for (var x of p2) arr.push(x); + +expect(arr).toEqual(["b", "c"]); diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/options.json b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/options.json new file mode 100644 index 000000000000..34fc8ef005b1 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "transform-for-of" + ], + "assumptions": { + "arrayLikeIsIterable": true + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/simple/exec.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/simple/exec.js new file mode 100644 index 000000000000..d016662a6048 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/simple/exec.js @@ -0,0 +1,6 @@ +var p2 = { 0: "b", 1: "c", 2: "d", length: 3 }; + +var arr = []; +for (var x of p2) arr.push(x); + +expect(arr).toEqual(["b", "c", "d"]); diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/simple/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/simple/input.js new file mode 100644 index 000000000000..9bcb06d816be --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/simple/input.js @@ -0,0 +1 @@ +for (var x of p2) arr.push(x); diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/simple/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/simple/output.js new file mode 100644 index 000000000000..9dbae0e22992 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-arrayLikeIsIterable/simple/output.js @@ -0,0 +1,13 @@ +var _iterator = babelHelpers.createForOfIteratorHelper(p2, true), + _step; + +try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var x = _step.value; + arr.push(x); + } +} catch (err) { + _iterator.e(err); +} finally { + _iterator.f(); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-await-of/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-await-of/input.js new file mode 100644 index 000000000000..623d204b34cb --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-await-of/input.js @@ -0,0 +1 @@ +async () => { for await (let foo of []); }; diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-await-of/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-await-of/output.js new file mode 100644 index 000000000000..03379d55586f --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-await-of/output.js @@ -0,0 +1,3 @@ +async () => { + for await (let foo of []); +}; diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-array-pattern/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-array-pattern/input.js new file mode 100644 index 000000000000..8ffcd7ff809f --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-array-pattern/input.js @@ -0,0 +1,4 @@ +let elm; +for ([elm] of array) { + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-array-pattern/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-array-pattern/output.js new file mode 100644 index 000000000000..f405987d23e2 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-array-pattern/output.js @@ -0,0 +1,6 @@ +let elm; + +for (let _i = 0, _array = array; _i < _array.length; _i++) { + [elm] = _array[_i]; + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration-array-pattern/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration-array-pattern/input.js new file mode 100644 index 000000000000..2de13b3e47dd --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration-array-pattern/input.js @@ -0,0 +1,3 @@ +for (const [elm] of array) { + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration-array-pattern/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration-array-pattern/output.js new file mode 100644 index 000000000000..97fa884dc981 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration-array-pattern/output.js @@ -0,0 +1,4 @@ +for (let _i = 0, _array = array; _i < _array.length; _i++) { + const [elm] = _array[_i]; + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration/input.js new file mode 100644 index 000000000000..9f773dd63361 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration/input.js @@ -0,0 +1,3 @@ +for (const elm of array) { + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration/output.js new file mode 100644 index 000000000000..3794b43c998e --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-declaration/output.js @@ -0,0 +1,4 @@ +for (let _i = 0, _array = array; _i < _array.length; _i++) { + const elm = _array[_i]; + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression-declaration/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression-declaration/input.js new file mode 100644 index 000000000000..f47de4cad51b --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression-declaration/input.js @@ -0,0 +1 @@ +for (const i of items) i; diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression-declaration/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression-declaration/output.js new file mode 100644 index 000000000000..935f3004f555 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression-declaration/output.js @@ -0,0 +1,4 @@ +for (let _i = 0, _items = items; _i < _items.length; _i++) { + const i = _items[_i]; + i; +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression/input.js new file mode 100644 index 000000000000..794f63b28034 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression/input.js @@ -0,0 +1,2 @@ +let i; +for (i of items) i; diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression/output.js new file mode 100644 index 000000000000..eef987e35c90 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-expression/output.js @@ -0,0 +1,6 @@ +let i; + +for (let _i = 0, _items = items; _i < _items.length; _i++) { + i = _items[_i]; + i; +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-amd/input.mjs b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-amd/input.mjs new file mode 100644 index 000000000000..bd895e71c71f --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-amd/input.mjs @@ -0,0 +1,5 @@ +import { array } from "foo"; + +for (const elm of array) { + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-amd/options.json b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-amd/options.json new file mode 100644 index 000000000000..89a0601dc948 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-amd/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "transform-for-of", + { + "assumeArray": true + } + ], + ["transform-modules-amd"] + ] +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-amd/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-amd/output.js new file mode 100644 index 000000000000..0e9d9e0152cb --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-amd/output.js @@ -0,0 +1,8 @@ +define(["foo"], function (_foo) { + "use strict"; + + for (let _i = 0; _i < _foo.array.length; _i++) { + const elm = _foo.array[_i]; + console.log(elm); + } +}); diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-commonjs/input.mjs b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-commonjs/input.mjs new file mode 100644 index 000000000000..bd895e71c71f --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-commonjs/input.mjs @@ -0,0 +1,5 @@ +import { array } from "foo"; + +for (const elm of array) { + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-commonjs/options.json b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-commonjs/options.json new file mode 100644 index 000000000000..855454080e78 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-commonjs/options.json @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "transform-for-of", + { + "assumeArray": true + } + ], + ["transform-modules-commonjs"] + ] +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-commonjs/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-commonjs/output.js new file mode 100644 index 000000000000..9cf9ad09b782 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-commonjs/output.js @@ -0,0 +1,8 @@ +"use strict"; + +var _foo = require("foo"); + +for (let _i = 0; _i < _foo.array.length; _i++) { + const elm = _foo.array[_i]; + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-es2015/input.mjs b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-es2015/input.mjs new file mode 100644 index 000000000000..bd895e71c71f --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-es2015/input.mjs @@ -0,0 +1,5 @@ +import { array } from "foo"; + +for (const elm of array) { + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-es2015/output.mjs b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-es2015/output.mjs new file mode 100644 index 000000000000..62a2980913e6 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-import-es2015/output.mjs @@ -0,0 +1,6 @@ +import { array } from "foo"; + +for (let _i = 0; _i < array.length; _i++) { + const elm = array[_i]; + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-array-pattern/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-array-pattern/input.js new file mode 100644 index 000000000000..9c42dd07cf92 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-array-pattern/input.js @@ -0,0 +1,5 @@ +for (const [head, ...tail] of array) { + const head = 1; + console.log(tail); + console.log(head); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-array-pattern/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-array-pattern/output.js new file mode 100644 index 000000000000..d10f3cea1988 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-array-pattern/output.js @@ -0,0 +1,8 @@ +for (let _i = 0, _array = array; _i < _array.length; _i++) { + const [head, ...tail] = _array[_i]; + { + const head = 1; + console.log(tail); + console.log(head); + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-object-pattern/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-object-pattern/input.js new file mode 100644 index 000000000000..5d9d07cdff54 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-object-pattern/input.js @@ -0,0 +1,5 @@ +for (const [type, ...rest] of array) { + const type = 1; + console.log(rest); + console.log(type); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-object-pattern/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-object-pattern/output.js new file mode 100644 index 000000000000..bca1a961708b --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-partial-redeclaration-in-body-object-pattern/output.js @@ -0,0 +1,8 @@ +for (let _i = 0, _array = array; _i < _array.length; _i++) { + const [type, ...rest] = _array[_i]; + { + const type = 1; + console.log(rest); + console.log(type); + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-array-pattern/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-array-pattern/input.js new file mode 100644 index 000000000000..150e02bcd775 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-array-pattern/input.js @@ -0,0 +1,6 @@ +for (const [head, ...tail] of array) { + const head = 1; + let tail; + console.log(tail); + console.log(head); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-array-pattern/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-array-pattern/output.js new file mode 100644 index 000000000000..bb103233d714 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-array-pattern/output.js @@ -0,0 +1,9 @@ +for (let _i = 0, _array = array; _i < _array.length; _i++) { + const [head, ...tail] = _array[_i]; + { + const head = 1; + let tail; + console.log(tail); + console.log(head); + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-object-pattern/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-object-pattern/input.js new file mode 100644 index 000000000000..756ecda0da25 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-object-pattern/input.js @@ -0,0 +1,6 @@ +for (const {type, ...rest} of array) { + const type = 1; + let rest; + console.log(rest); + console.log(type); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-object-pattern/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-object-pattern/output.js new file mode 100644 index 000000000000..03a45647d69f --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body-object-pattern/output.js @@ -0,0 +1,12 @@ +for (let _i = 0, _array = array; _i < _array.length; _i++) { + const { + type, + ...rest + } = _array[_i]; + { + const type = 1; + let rest; + console.log(rest); + console.log(type); + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body/input.js new file mode 100644 index 000000000000..ded052290862 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body/input.js @@ -0,0 +1,3 @@ +for (const elm of array) { + const elm = 2; +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body/output.js new file mode 100644 index 000000000000..f05d069d547d --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclaration-in-body/output.js @@ -0,0 +1,6 @@ +for (let _i = 0, _array = array; _i < _array.length; _i++) { + const elm = _array[_i]; + { + const elm = 2; + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclare-iterable/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclare-iterable/input.js new file mode 100644 index 000000000000..3abfab88f65b --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclare-iterable/input.js @@ -0,0 +1,3 @@ +for (let o of arr) { + const arr = o; +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclare-iterable/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclare-iterable/output.js new file mode 100644 index 000000000000..81a8e0ef45fb --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-redeclare-iterable/output.js @@ -0,0 +1,4 @@ +for (let _i = 0, _arr = arr; _i < _arr.length; _i++) { + let o = _arr[_i]; + const arr = o; +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static-declaration/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static-declaration/input.js new file mode 100644 index 000000000000..b84065c48dcf --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static-declaration/input.js @@ -0,0 +1,5 @@ +const array = []; + +for (const elm of array) { + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static-declaration/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static-declaration/output.js new file mode 100644 index 000000000000..072dd5498da1 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static-declaration/output.js @@ -0,0 +1,6 @@ +const array = []; + +for (let _i = 0; _i < array.length; _i++) { + const elm = array[_i]; + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static/input.js new file mode 100644 index 000000000000..d4de87d351dd --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static/input.js @@ -0,0 +1,6 @@ +const array = []; +let elm; + +for (elm of array) { + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static/output.js new file mode 100644 index 000000000000..fc47bc82edf3 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of-static/output.js @@ -0,0 +1,7 @@ +const array = []; +let elm; + +for (let _i = 0; _i < array.length; _i++) { + elm = array[_i]; + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of/input.js new file mode 100644 index 000000000000..4b77690e9e86 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of/input.js @@ -0,0 +1,5 @@ +let elm; + +for (elm of array) { + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of/output.js new file mode 100644 index 000000000000..1024f7a72773 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/for-of/output.js @@ -0,0 +1,6 @@ +let elm; + +for (let _i = 0, _array = array; _i < _array.length; _i++) { + elm = _array[_i]; + console.log(elm); +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/options.json b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/options.json new file mode 100644 index 000000000000..d1e759f09a9d --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-iterableIsArray/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["transform-for-of"], + "assumptions": { + "iterableIsArray": true + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/identifier/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/identifier/input.js new file mode 100644 index 000000000000..ddd15051ba40 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/identifier/input.js @@ -0,0 +1,3 @@ +for (i of arr) { + +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/identifier/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/identifier/output.js new file mode 100644 index 000000000000..09cfa4b62184 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/identifier/output.js @@ -0,0 +1,3 @@ +for (var _iterator = babelHelpers.createForOfIteratorHelperLoose(arr), _step; !(_step = _iterator()).done;) { + i = _step.value; +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/ignore-cases/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/ignore-cases/input.js new file mode 100644 index 000000000000..e79141052993 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/ignore-cases/input.js @@ -0,0 +1,6 @@ +for (var i of foo) { + switch (i) { + case 1: + break; + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/ignore-cases/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/ignore-cases/output.js new file mode 100644 index 000000000000..346e9bed2735 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/ignore-cases/output.js @@ -0,0 +1,8 @@ +for (var _iterator = babelHelpers.createForOfIteratorHelperLoose(foo), _step; !(_step = _iterator()).done;) { + var i = _step.value; + + switch (i) { + case 1: + break; + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/let/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/let/input.js new file mode 100644 index 000000000000..f1e32392def1 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/let/input.js @@ -0,0 +1,3 @@ +for (let i of arr) { + +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/let/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/let/output.js new file mode 100644 index 000000000000..5181b1253590 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/let/output.js @@ -0,0 +1,3 @@ +for (var _iterator = babelHelpers.createForOfIteratorHelperLoose(arr), _step; !(_step = _iterator()).done;) { + let i = _step.value; +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/member-expression/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/member-expression/input.js new file mode 100644 index 000000000000..d67e03308150 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/member-expression/input.js @@ -0,0 +1,3 @@ +for (obj.prop of arr) { + +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/member-expression/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/member-expression/output.js new file mode 100644 index 000000000000..670a8f952d51 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/member-expression/output.js @@ -0,0 +1,3 @@ +for (var _iterator = babelHelpers.createForOfIteratorHelperLoose(arr), _step; !(_step = _iterator()).done;) { + obj.prop = _step.value; +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/multiple/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/multiple/input.js new file mode 100644 index 000000000000..d9c969b80951 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/multiple/input.js @@ -0,0 +1,7 @@ +for (var i of arr) { + +} + +for (var i of numbers) { + +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/multiple/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/multiple/output.js new file mode 100644 index 000000000000..adc55422e337 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/multiple/output.js @@ -0,0 +1,7 @@ +for (var _iterator = babelHelpers.createForOfIteratorHelperLoose(arr), _step; !(_step = _iterator()).done;) { + var i = _step.value; +} + +for (var _iterator2 = babelHelpers.createForOfIteratorHelperLoose(numbers), _step2; !(_step2 = _iterator2()).done;) { + var i = _step2.value; +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/nested-label-for-of/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/nested-label-for-of/input.js new file mode 100644 index 000000000000..73c8203449d4 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/nested-label-for-of/input.js @@ -0,0 +1,5 @@ +b: for (let c of d()) { + for (let e of f()) { + continue b; + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/nested-label-for-of/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/nested-label-for-of/output.js new file mode 100644 index 000000000000..87e1ddec80f7 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/nested-label-for-of/output.js @@ -0,0 +1,8 @@ +b: for (var _iterator = babelHelpers.createForOfIteratorHelperLoose(d()), _step; !(_step = _iterator()).done;) { + let c = _step.value; + + for (var _iterator2 = babelHelpers.createForOfIteratorHelperLoose(f()), _step2; !(_step2 = _iterator2()).done;) { + let e = _step2.value; + continue b; + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/options.json b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/options.json new file mode 100644 index 000000000000..77ffac99ff48 --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "transform-for-of" + ], + "assumptions": { + "skipForOfIteratorClosing": true + } +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/var/input.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/var/input.js new file mode 100644 index 000000000000..48e5f59b2c6b --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/var/input.js @@ -0,0 +1,3 @@ +for (var i of arr) { + +} diff --git a/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/var/output.js b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/var/output.js new file mode 100644 index 000000000000..c9f297e237ab --- /dev/null +++ b/packages/babel-plugin-transform-for-of/test/fixtures/assumption-skipForOfIteratorClosing/var/output.js @@ -0,0 +1,3 @@ +for (var _iterator = babelHelpers.createForOfIteratorHelperLoose(arr), _step; !(_step = _iterator()).done;) { + var i = _step.value; +} diff --git a/packages/babel-plugin-transform-modules-amd/src/index.js b/packages/babel-plugin-transform-modules-amd/src/index.js index 7ea2b150f04b..9d916292d8df 100644 --- a/packages/babel-plugin-transform-modules-amd/src/index.js +++ b/packages/babel-plugin-transform-modules-amd/src/index.js @@ -38,7 +38,13 @@ function injectWrapper(path, wrapper) { export default declare((api, options) => { api.assertVersion(7); - const { loose, allowTopLevelThis, strict, strictMode, noInterop } = options; + const { allowTopLevelThis, strict, strictMode, noInterop } = options; + + const constantReexports = + api.assumption("constantReexports") ?? options.loose; + const enumerableModuleMeta = + api.assumption("enumerableModuleMeta") ?? options.loose; + return { name: "transform-modules-amd", @@ -103,7 +109,8 @@ export default declare((api, options) => { const { meta, headers } = rewriteModuleStatementsAndPrepareHeader( path, { - loose, + enumerableModuleMeta, + constantReexports, strict, strictMode, allowTopLevelThis, @@ -141,7 +148,11 @@ export default declare((api, options) => { } headers.push( - ...buildNamespaceInitStatements(meta, metadata, loose), + ...buildNamespaceInitStatements( + meta, + metadata, + constantReexports, + ), ); } diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-2/input.mjs b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-2/input.mjs new file mode 100644 index 000000000000..5be9a685aabd --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-2/input.mjs @@ -0,0 +1 @@ +export {foo as default} from "foo"; diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-2/output.js b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-2/output.js new file mode 100644 index 000000000000..c4d089259801 --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-2/output.js @@ -0,0 +1,9 @@ +define(["exports", "foo"], function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + _exports.default = _foo.foo; +}); diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-3/input.mjs b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-3/input.mjs new file mode 100644 index 000000000000..4461d79e3bf3 --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-3/input.mjs @@ -0,0 +1 @@ +export {foo as default, bar} from "foo"; diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-3/output.js b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-3/output.js new file mode 100644 index 000000000000..0497fcd36acb --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-3/output.js @@ -0,0 +1,10 @@ +define(["exports", "foo"], function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.bar = _exports.default = void 0; + _exports.default = _foo.foo; + _exports.bar = _foo.bar; +}); diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-4/input.mjs b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-4/input.mjs new file mode 100644 index 000000000000..9fff903bd969 --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-4/input.mjs @@ -0,0 +1 @@ +export {foo as bar} from "foo"; diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-4/output.js b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-4/output.js new file mode 100644 index 000000000000..ee86c9ebeb3a --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-4/output.js @@ -0,0 +1,9 @@ +define(["exports", "foo"], function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.bar = void 0; + _exports.bar = _foo.foo; +}); diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-5/input.mjs b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-5/input.mjs new file mode 100644 index 000000000000..35c2762a2954 --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-5/input.mjs @@ -0,0 +1 @@ +export {foo, bar} from "foo"; diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-5/output.js b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-5/output.js new file mode 100644 index 000000000000..64d68cdbf862 --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-5/output.js @@ -0,0 +1,10 @@ +define(["exports", "foo"], function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.bar = _exports.foo = void 0; + _exports.foo = _foo.foo; + _exports.bar = _foo.bar; +}); diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-6/input.mjs b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-6/input.mjs new file mode 100644 index 000000000000..9ec8f63ab2fd --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-6/input.mjs @@ -0,0 +1 @@ +export * from "foo"; diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-6/output.js b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-6/output.js new file mode 100644 index 000000000000..e7988a807f00 --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from-6/output.js @@ -0,0 +1,12 @@ +define(["exports", "foo"], function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + Object.keys(_foo).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (key in _exports && _exports[key] === _foo[key]) return; + _exports[key] = _foo[key]; + }); +}); diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from/input.mjs b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from/input.mjs new file mode 100644 index 000000000000..83b7b67c51ce --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from/input.mjs @@ -0,0 +1 @@ +export {foo} from "foo"; diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from/output.js b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from/output.js new file mode 100644 index 000000000000..6fb67b7327a9 --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/export-from/output.js @@ -0,0 +1,9 @@ +define(["exports", "foo"], function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.foo = void 0; + _exports.foo = _foo.foo; +}); diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/import-export/input.mjs b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/import-export/input.mjs new file mode 100644 index 000000000000..b9e4c92265a4 --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/import-export/input.mjs @@ -0,0 +1,3 @@ +import { foo } from "./foo"; + +export { foo }; diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/import-export/output.js b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/import-export/output.js new file mode 100644 index 000000000000..4b3c1b13a220 --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/import-export/output.js @@ -0,0 +1,8 @@ +define(["exports", "./foo"], function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.foo = _foo.foo; +}); diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/options.json b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/options.json new file mode 100644 index 000000000000..6687fc23f80a --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-constantReexports/options.json @@ -0,0 +1,6 @@ +{ + "assumptions": { + "constantReexports": true + }, + "plugins": ["external-helpers", "transform-modules-amd"] +} diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-enumerableModuleMeta/export/input.mjs b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-enumerableModuleMeta/export/input.mjs new file mode 100644 index 000000000000..2263b5a27c28 --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-enumerableModuleMeta/export/input.mjs @@ -0,0 +1 @@ +export var foo = 2; diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-enumerableModuleMeta/export/output.js b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-enumerableModuleMeta/export/output.js new file mode 100644 index 000000000000..06ac96c4985d --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-enumerableModuleMeta/export/output.js @@ -0,0 +1,8 @@ +define(["exports"], function (_exports) { + "use strict"; + + _exports.__esModule = true; + _exports.foo = void 0; + var foo = 2; + _exports.foo = foo; +}); diff --git a/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-enumerableModuleMeta/options.json b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-enumerableModuleMeta/options.json new file mode 100644 index 000000000000..7f92d5a3c9ea --- /dev/null +++ b/packages/babel-plugin-transform-modules-amd/test/fixtures/assumption-enumerableModuleMeta/options.json @@ -0,0 +1,6 @@ +{ + "assumptions": { + "enumerableModuleMeta": true + }, + "plugins": ["external-helpers", "transform-modules-amd"] +} diff --git a/packages/babel-plugin-transform-modules-commonjs/src/index.js b/packages/babel-plugin-transform-modules-commonjs/src/index.js index de9274d890f7..0004c3c773bc 100644 --- a/packages/babel-plugin-transform-modules-commonjs/src/index.js +++ b/packages/babel-plugin-transform-modules-commonjs/src/index.js @@ -19,8 +19,6 @@ export default declare((api, options) => { const transformImportCall = createDynamicImportTransform(api); const { - loose, - // 'true' for non-mjs files to strictly have .default, instead of having // destructuring-like behavior for their properties. strictNamespace = false, @@ -37,6 +35,11 @@ export default declare((api, options) => { allowCommonJSExports = true, } = options; + const constantReexports = + api.assumption("constantReexports") ?? options.loose; + const enumerableModuleMeta = + api.assumption("enumerableModuleMeta") ?? options.loose; + if ( typeof lazy !== "boolean" && typeof lazy !== "function" && @@ -169,7 +172,8 @@ export default declare((api, options) => { path, { exportName: "exports", - loose, + constantReexports, + enumerableModuleMeta, strict, strictMode, allowTopLevelThis, @@ -215,7 +219,11 @@ export default declare((api, options) => { headers.push(header); headers.push( - ...buildNamespaceInitStatements(meta, metadata, loose), + ...buildNamespaceInitStatements( + meta, + metadata, + constantReexports, + ), ); } diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-2/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-2/input.mjs new file mode 100644 index 000000000000..5be9a685aabd --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-2/input.mjs @@ -0,0 +1 @@ +export {foo as default} from "foo"; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-2/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-2/output.js new file mode 100644 index 000000000000..efa99139e82e --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-2/output.js @@ -0,0 +1,10 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _foo = require("foo"); + +exports.default = _foo.foo; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-3/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-3/input.mjs new file mode 100644 index 000000000000..4461d79e3bf3 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-3/input.mjs @@ -0,0 +1 @@ +export {foo as default, bar} from "foo"; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-3/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-3/output.js new file mode 100644 index 000000000000..aef9e075e34e --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-3/output.js @@ -0,0 +1,11 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.bar = exports.default = void 0; + +var _foo = require("foo"); + +exports.default = _foo.foo; +exports.bar = _foo.bar; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-4/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-4/input.mjs new file mode 100644 index 000000000000..9fff903bd969 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-4/input.mjs @@ -0,0 +1 @@ +export {foo as bar} from "foo"; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-4/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-4/output.js new file mode 100644 index 000000000000..7c4b8590b769 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-4/output.js @@ -0,0 +1,10 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.bar = void 0; + +var _foo = require("foo"); + +exports.bar = _foo.foo; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-5/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-5/input.mjs new file mode 100644 index 000000000000..35c2762a2954 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-5/input.mjs @@ -0,0 +1 @@ +export {foo, bar} from "foo"; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-5/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-5/output.js new file mode 100644 index 000000000000..f9446e04700f --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-5/output.js @@ -0,0 +1,11 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.bar = exports.foo = void 0; + +var _foo = require("foo"); + +exports.foo = _foo.foo; +exports.bar = _foo.bar; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-6/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-6/input.mjs new file mode 100644 index 000000000000..9ec8f63ab2fd --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-6/input.mjs @@ -0,0 +1 @@ +export * from "foo"; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-6/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-6/output.js new file mode 100644 index 000000000000..8eba9a5ceeca --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from-6/output.js @@ -0,0 +1,13 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _foo = require("foo"); + +Object.keys(_foo).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (key in exports && exports[key] === _foo[key]) return; + exports[key] = _foo[key]; +}); diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from/input.mjs new file mode 100644 index 000000000000..83b7b67c51ce --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from/input.mjs @@ -0,0 +1 @@ +export {foo} from "foo"; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from/output.js new file mode 100644 index 000000000000..9902d90fc95f --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/export-from/output.js @@ -0,0 +1,10 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.foo = void 0; + +var _foo = require("foo"); + +exports.foo = _foo.foo; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/import-export/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/import-export/input.mjs new file mode 100644 index 000000000000..b9e4c92265a4 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/import-export/input.mjs @@ -0,0 +1,3 @@ +import { foo } from "./foo"; + +export { foo }; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/import-export/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/import-export/output.js new file mode 100644 index 000000000000..8e12703582dc --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/import-export/output.js @@ -0,0 +1,9 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _foo = require("./foo"); + +exports.foo = _foo.foo; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/options.json b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/options.json new file mode 100644 index 000000000000..d795b6de6c28 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-constantReexports/options.json @@ -0,0 +1,6 @@ +{ + "assumptions": { + "constantReexports": true + }, + "plugins": ["external-helpers", "transform-modules-commonjs"] +} diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-enumerableModuleMeta/export/input.mjs b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-enumerableModuleMeta/export/input.mjs new file mode 100644 index 000000000000..2263b5a27c28 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-enumerableModuleMeta/export/input.mjs @@ -0,0 +1 @@ +export var foo = 2; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-enumerableModuleMeta/export/output.js b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-enumerableModuleMeta/export/output.js new file mode 100644 index 000000000000..5429b31f4ce8 --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-enumerableModuleMeta/export/output.js @@ -0,0 +1,6 @@ +"use strict"; + +exports.__esModule = true; +exports.foo = void 0; +var foo = 2; +exports.foo = foo; diff --git a/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-enumerableModuleMeta/options.json b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-enumerableModuleMeta/options.json new file mode 100644 index 000000000000..7b20177727bd --- /dev/null +++ b/packages/babel-plugin-transform-modules-commonjs/test/fixtures/assumption-enumerableModuleMeta/options.json @@ -0,0 +1,6 @@ +{ + "assumptions": { + "enumerableModuleMeta": true + }, + "plugins": ["external-helpers", "transform-modules-commonjs"] +} diff --git a/packages/babel-plugin-transform-modules-umd/src/index.js b/packages/babel-plugin-transform-modules-umd/src/index.js index 0f85d5f9a324..4b1d69b63bdd 100644 --- a/packages/babel-plugin-transform-modules-umd/src/index.js +++ b/packages/babel-plugin-transform-modules-umd/src/index.js @@ -44,13 +44,17 @@ export default declare((api, options) => { const { globals, exactGlobals, - loose, allowTopLevelThis, strict, strictMode, noInterop, } = options; + const constantReexports = + api.assumption("constantReexports") ?? options.loose; + const enumerableModuleMeta = + api.assumption("enumerableModuleMeta") ?? options.loose; + /** * Build the assignment statements that initialize the UMD global. */ @@ -147,7 +151,8 @@ export default declare((api, options) => { const { meta, headers } = rewriteModuleStatementsAndPrepareHeader( path, { - loose, + constantReexports, + enumerableModuleMeta, strict, strictMode, allowTopLevelThis, @@ -201,7 +206,11 @@ export default declare((api, options) => { } headers.push( - ...buildNamespaceInitStatements(meta, metadata, loose), + ...buildNamespaceInitStatements( + meta, + metadata, + constantReexports, + ), ); } diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-2/input.mjs b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-2/input.mjs new file mode 100644 index 000000000000..5be9a685aabd --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-2/input.mjs @@ -0,0 +1 @@ +export {foo as default} from "foo"; diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-2/output.js b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-2/output.js new file mode 100644 index 000000000000..88d339f99e7c --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-2/output.js @@ -0,0 +1,21 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo")); + } else { + var mod = { + exports: {} + }; + factory(mod.exports, global.foo); + global.input = mod.exports; + } +})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + _exports.default = _foo.foo; +}); diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-3/input.mjs b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-3/input.mjs new file mode 100644 index 000000000000..4461d79e3bf3 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-3/input.mjs @@ -0,0 +1 @@ +export {foo as default, bar} from "foo"; diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-3/output.js b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-3/output.js new file mode 100644 index 000000000000..6a46f9585f99 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-3/output.js @@ -0,0 +1,22 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo")); + } else { + var mod = { + exports: {} + }; + factory(mod.exports, global.foo); + global.input = mod.exports; + } +})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.bar = _exports.default = void 0; + _exports.default = _foo.foo; + _exports.bar = _foo.bar; +}); diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-4/input.mjs b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-4/input.mjs new file mode 100644 index 000000000000..9fff903bd969 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-4/input.mjs @@ -0,0 +1 @@ +export {foo as bar} from "foo"; diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-4/output.js b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-4/output.js new file mode 100644 index 000000000000..de25f98ea8a6 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-4/output.js @@ -0,0 +1,21 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo")); + } else { + var mod = { + exports: {} + }; + factory(mod.exports, global.foo); + global.input = mod.exports; + } +})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.bar = void 0; + _exports.bar = _foo.foo; +}); diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-5/input.mjs b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-5/input.mjs new file mode 100644 index 000000000000..35c2762a2954 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-5/input.mjs @@ -0,0 +1 @@ +export {foo, bar} from "foo"; diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-5/output.js b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-5/output.js new file mode 100644 index 000000000000..ebcd9bd3ef61 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-5/output.js @@ -0,0 +1,22 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo")); + } else { + var mod = { + exports: {} + }; + factory(mod.exports, global.foo); + global.input = mod.exports; + } +})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.bar = _exports.foo = void 0; + _exports.foo = _foo.foo; + _exports.bar = _foo.bar; +}); diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-6/input.mjs b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-6/input.mjs new file mode 100644 index 000000000000..9ec8f63ab2fd --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-6/input.mjs @@ -0,0 +1 @@ +export * from "foo"; diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-6/output.js b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-6/output.js new file mode 100644 index 000000000000..2ce869023290 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from-6/output.js @@ -0,0 +1,24 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo")); + } else { + var mod = { + exports: {} + }; + factory(mod.exports, global.foo); + global.input = mod.exports; + } +})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + Object.keys(_foo).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (key in _exports && _exports[key] === _foo[key]) return; + _exports[key] = _foo[key]; + }); +}); diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from/input.mjs b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from/input.mjs new file mode 100644 index 000000000000..83b7b67c51ce --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from/input.mjs @@ -0,0 +1 @@ +export {foo} from "foo"; diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from/output.js b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from/output.js new file mode 100644 index 000000000000..4e921805b159 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/export-from/output.js @@ -0,0 +1,21 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("foo")); + } else { + var mod = { + exports: {} + }; + factory(mod.exports, global.foo); + global.input = mod.exports; + } +})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.foo = void 0; + _exports.foo = _foo.foo; +}); diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/import-export/input.mjs b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/import-export/input.mjs new file mode 100644 index 000000000000..b9e4c92265a4 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/import-export/input.mjs @@ -0,0 +1,3 @@ +import { foo } from "./foo"; + +export { foo }; diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/import-export/output.js b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/import-export/output.js new file mode 100644 index 000000000000..b1b0636d9e00 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/import-export/output.js @@ -0,0 +1,20 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["exports", "./foo"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("./foo")); + } else { + var mod = { + exports: {} + }; + factory(mod.exports, global.foo); + global.input = mod.exports; + } +})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _foo) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.foo = _foo.foo; +}); diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/options.json b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/options.json new file mode 100644 index 000000000000..1a3f6d1a0d60 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-constantReexports/options.json @@ -0,0 +1,6 @@ +{ + "assumptions": { + "constantReexports": true + }, + "plugins": ["external-helpers", "transform-modules-umd"] +} diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-enumerableModuleMeta/export/input.mjs b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-enumerableModuleMeta/export/input.mjs new file mode 100644 index 000000000000..2263b5a27c28 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-enumerableModuleMeta/export/input.mjs @@ -0,0 +1 @@ +export var foo = 2; diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-enumerableModuleMeta/export/output.js b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-enumerableModuleMeta/export/output.js new file mode 100644 index 000000000000..e80e1fe59ee3 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-enumerableModuleMeta/export/output.js @@ -0,0 +1,20 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["exports"], factory); + } else if (typeof exports !== "undefined") { + factory(exports); + } else { + var mod = { + exports: {} + }; + factory(mod.exports); + global.input = mod.exports; + } +})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports) { + "use strict"; + + _exports.__esModule = true; + _exports.foo = void 0; + var foo = 2; + _exports.foo = foo; +}); diff --git a/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-enumerableModuleMeta/options.json b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-enumerableModuleMeta/options.json new file mode 100644 index 000000000000..56bfa8f269a6 --- /dev/null +++ b/packages/babel-plugin-transform-modules-umd/test/fixtures/assumption-enumerableModuleMeta/options.json @@ -0,0 +1,6 @@ +{ + "assumptions": { + "enumerableModuleMeta": true + }, + "plugins": ["external-helpers", "transform-modules-umd"] +} diff --git a/packages/babel-plugin-transform-parameters/src/index.js b/packages/babel-plugin-transform-parameters/src/index.js index 1f5cb7184b04..69d2ce512f15 100644 --- a/packages/babel-plugin-transform-parameters/src/index.js +++ b/packages/babel-plugin-transform-parameters/src/index.js @@ -6,7 +6,10 @@ export { convertFunctionParams }; export default declare((api, options) => { api.assertVersion(7); - const { loose } = options; + const ignoreFunctionLength = + api.assumption("ignoreFunctionLength") ?? options.loose; + const noNewArrows = api.assumption("noNewArrows"); + return { name: "transform-parameters", @@ -19,11 +22,14 @@ export default declare((api, options) => { .some(param => param.isRestElement() || param.isAssignmentPattern()) ) { // default/rest visitors require access to `arguments`, so it cannot be an arrow - path.arrowFunctionToExpression(); + path.arrowFunctionToExpression({ noNewArrows }); } const convertedRest = convertFunctionRest(path); - const convertedParams = convertFunctionParams(path, loose); + const convertedParams = convertFunctionParams( + path, + ignoreFunctionLength, + ); if (convertedRest || convertedParams) { // Manually reprocess this scope to ensure that the moved params are updated. diff --git a/packages/babel-plugin-transform-parameters/src/params.js b/packages/babel-plugin-transform-parameters/src/params.js index 4608a225af45..335a8e884241 100644 --- a/packages/babel-plugin-transform-parameters/src/params.js +++ b/packages/babel-plugin-transform-parameters/src/params.js @@ -44,7 +44,7 @@ const iifeVisitor = { // last 2 parameters are optional -- they are used by proposal-object-rest-spread/src/index.js export default function convertFunctionParams( path, - loose, + ignoreFunctionLength, shouldTransformParam, replaceRestElement, ) { @@ -123,7 +123,10 @@ export default function convertFunctionParams( } const paramIsAssignmentPattern = param.isAssignmentPattern(); - if (paramIsAssignmentPattern && (loose || node.kind === "set")) { + if ( + paramIsAssignmentPattern && + (ignoreFunctionLength || node.kind === "set") + ) { const left = param.get("left"); const right = param.get("right"); @@ -203,6 +206,8 @@ export default function convertFunctionParams( // sure that we correctly handle this and arguments. const bodyPath = path.get("body.body"); const arrowPath = bodyPath[bodyPath.length - 1].get("argument.callee"); + + // This is an IIFE, so we don't need to worry about the noNewArrows assumption arrowPath.arrowFunctionToExpression(); arrowPath.node.generator = path.node.generator; diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/complex-assignment/input.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/complex-assignment/input.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/complex-assignment/input.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/complex-assignment/input.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/complex-assignment/output.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/complex-assignment/output.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/complex-assignment/output.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/complex-assignment/output.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-array-destructuring/exec.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-array-destructuring/exec.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-array-destructuring/exec.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-array-destructuring/exec.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-array-destructuring/input.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-array-destructuring/input.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-array-destructuring/input.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-array-destructuring/input.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-array-destructuring/output.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-array-destructuring/output.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-array-destructuring/output.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-array-destructuring/output.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-assignment-with-types/input.mjs b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-assignment-with-types/input.mjs similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-assignment-with-types/input.mjs rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-assignment-with-types/input.mjs diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-assignment-with-types/options.json b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-assignment-with-types/options.json similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-assignment-with-types/options.json rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-assignment-with-types/options.json diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-assignment-with-types/output.mjs b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-assignment-with-types/output.mjs similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-assignment-with-types/output.mjs rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-assignment-with-types/output.mjs diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-earlier-params/exec.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-earlier-params/exec.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-earlier-params/exec.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-earlier-params/exec.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-iife-1128/exec.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-iife-1128/exec.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-iife-1128/exec.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-iife-1128/exec.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-iife-4253/exec.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-iife-4253/exec.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-iife-4253/exec.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-iife-4253/exec.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-iife-self/exec.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-iife-self/exec.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-iife-self/exec.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-iife-self/exec.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-multiple/input.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-multiple/input.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-multiple/input.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-multiple/input.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-multiple/output.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-multiple/output.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-multiple/output.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-multiple/output.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-object-destructuring/exec.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-object-destructuring/exec.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-object-destructuring/exec.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-object-destructuring/exec.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-rest-mix/input.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-rest-mix/input.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-rest-mix/input.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-rest-mix/input.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-rest-mix/output.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-rest-mix/output.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-rest-mix/output.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-rest-mix/output.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-rest/exec.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-rest/exec.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-rest/exec.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-rest/exec.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-single/input.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-single/input.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-single/input.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-single/input.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-single/output.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-single/output.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/default-single/output.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/default-single/output.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/destructuring-rest/input.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/destructuring-rest/input.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/destructuring-rest/input.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/destructuring-rest/input.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/destructuring-rest/output.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/destructuring-rest/output.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/destructuring-rest/output.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/destructuring-rest/output.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/options.json b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/options.json similarity index 62% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/options.json rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/options.json index aa8f6cf317dd..f8c2c7a9fafe 100644 --- a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/options.json +++ b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/options.json @@ -3,12 +3,14 @@ "proposal-class-properties", "external-helpers", "syntax-flow", - ["transform-parameters", { "loose": true }], + "transform-parameters", "transform-block-scoping", "transform-spread", "transform-classes", "transform-destructuring", - "transform-arrow-functions", - "transform-for-of" - ] + "transform-arrow-functions" + ], + "assumptions": { + "ignoreFunctionLength": true + } } diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/overwrite-undefined/exec.js b/packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/overwrite-undefined/exec.js similarity index 100% rename from packages/babel-plugin-transform-parameters/test/fixtures/use-loose-option/overwrite-undefined/exec.js rename to packages/babel-plugin-transform-parameters/test/fixtures/assumption-ignoreFunctionLength/overwrite-undefined/exec.js diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/loose/ignoreFunctionLength/input.js b/packages/babel-plugin-transform-parameters/test/fixtures/loose/ignoreFunctionLength/input.js new file mode 100644 index 000000000000..b91cfb244914 --- /dev/null +++ b/packages/babel-plugin-transform-parameters/test/fixtures/loose/ignoreFunctionLength/input.js @@ -0,0 +1,3 @@ +function fn(a, b = c()) { + return b; +} diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/loose/ignoreFunctionLength/output.js b/packages/babel-plugin-transform-parameters/test/fixtures/loose/ignoreFunctionLength/output.js new file mode 100644 index 000000000000..6c1471d59a4f --- /dev/null +++ b/packages/babel-plugin-transform-parameters/test/fixtures/loose/ignoreFunctionLength/output.js @@ -0,0 +1,7 @@ +function fn(a, b) { + if (b === void 0) { + b = c(); + } + + return b; +} diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/loose/options.json b/packages/babel-plugin-transform-parameters/test/fixtures/loose/options.json new file mode 100644 index 000000000000..0d49296cfac0 --- /dev/null +++ b/packages/babel-plugin-transform-parameters/test/fixtures/loose/options.json @@ -0,0 +1,5 @@ +{ + "plugins": [ + ["transform-parameters", { "loose": true }] + ] +} diff --git a/packages/babel-plugin-transform-spread/src/index.js b/packages/babel-plugin-transform-spread/src/index.js index 3bacc1f677fc..f6559cfccd8c 100644 --- a/packages/babel-plugin-transform-spread/src/index.js +++ b/packages/babel-plugin-transform-spread/src/index.js @@ -5,13 +5,18 @@ import { types as t } from "@babel/core"; export default declare((api, options) => { api.assertVersion(7); - const { loose, allowArrayLike } = options; + const iterableIsArray = api.assumption("iterableIsArray") ?? options.loose; + const arrayLikeIsIterable = + options.allowArrayLike ?? api.assumption("arrayLikeIsIterable"); function getSpreadLiteral(spread, scope) { - if (loose && !t.isIdentifier(spread.argument, { name: "arguments" })) { + if ( + iterableIsArray && + !t.isIdentifier(spread.argument, { name: "arguments" }) + ) { return spread.argument; } else { - return scope.toArray(spread.argument, true, allowArrayLike); + return scope.toArray(spread.argument, true, arrayLikeIsIterable); } } diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/holes/exec.js b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/holes/exec.js new file mode 100644 index 000000000000..c5f809fae86f --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/holes/exec.js @@ -0,0 +1,6 @@ +var p2 = { 0: "a", 2: "c", length: 3 }; + +var arr = [...p2, "d"]; + +expect(arr).toEqual(["a", undefined, "c", "d"]); +expect(1 in arr).toBe(true); // Not holey diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/length-cropped/exec.js b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/length-cropped/exec.js new file mode 100644 index 000000000000..dbb1602da453 --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/length-cropped/exec.js @@ -0,0 +1,5 @@ +var p2 = { 0: "b", 1: "c", 2: "d", length: 2 }; + +var arr = ["a", ...p2, "e"]; + +expect(arr).toEqual(["a", "b", "c", "e"]); diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/options.json b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/options.json new file mode 100644 index 000000000000..966d179d1685 --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/options.json @@ -0,0 +1,9 @@ +{ + "plugins": [ + ["external-helpers", { "helperVersion": "7.100.0" }], + "transform-spread" + ], + "assumptions": { + "arrayLikeIsIterable": true + } +} diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/simple/exec.js b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/simple/exec.js new file mode 100644 index 000000000000..786324084b00 --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/simple/exec.js @@ -0,0 +1,5 @@ +var p2 = { 0: "b", 1: "c", 2: "d", length: 3 }; + +var arr = ["a", ...p2, "e"]; + +expect(arr).toEqual(["a", "b", "c", "d", "e"]); diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/simple/input.js b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/simple/input.js new file mode 100644 index 000000000000..266012c540ec --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/simple/input.js @@ -0,0 +1 @@ +var arr = ["a", ...p2, "e"]; diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/simple/output.js b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/simple/output.js new file mode 100644 index 000000000000..caa46f72da3c --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-arrayLikeIsIterable/simple/output.js @@ -0,0 +1 @@ +var arr = ["a"].concat(babelHelpers.maybeArrayLike(babelHelpers.toConsumableArray, p2), ["e"]); diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/arguments/input.js b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/arguments/input.js new file mode 100644 index 000000000000..55bba0661b94 --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/arguments/input.js @@ -0,0 +1,5 @@ +function foo() { + // We know for sure that 'arguments' is _not_ an array, so we + // can ignore the assumption in this case. + return [...arguments]; +} diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/arguments/output.js b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/arguments/output.js new file mode 100644 index 000000000000..8261a6054ace --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/arguments/output.js @@ -0,0 +1,5 @@ +function foo() { + // We know for sure that 'arguments' is _not_ an array, so we + // can ignore the assumption in this case. + return Array.prototype.slice.call(arguments); +} diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/array-literals/input.js b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/array-literals/input.js new file mode 100644 index 000000000000..5ebb80da6607 --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/array-literals/input.js @@ -0,0 +1 @@ +var lyrics = ["head", "and", "toes", ...parts]; diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/array-literals/output.js b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/array-literals/output.js new file mode 100644 index 000000000000..ff599f4229aa --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/array-literals/output.js @@ -0,0 +1 @@ +var lyrics = ["head", "and", "toes"].concat(parts); diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/function-call/input.js b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/function-call/input.js new file mode 100644 index 000000000000..01f9b028cc5e --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/function-call/input.js @@ -0,0 +1 @@ +lyrics(["head", "and", "toes", ...parts]); diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/function-call/output.js b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/function-call/output.js new file mode 100644 index 000000000000..f069f8d6db57 --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/function-call/output.js @@ -0,0 +1 @@ +lyrics(["head", "and", "toes"].concat(parts)); diff --git a/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/options.json b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/options.json new file mode 100644 index 000000000000..992778aa569d --- /dev/null +++ b/packages/babel-plugin-transform-spread/test/fixtures/assumption-iterableIsArray/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["external-helpers", "transform-spread"], + "assumptions": { + "iterableIsArray": true + } +} diff --git a/packages/babel-plugin-transform-template-literals/src/index.js b/packages/babel-plugin-transform-template-literals/src/index.js index d1f1689103df..5b588900d33e 100644 --- a/packages/babel-plugin-transform-template-literals/src/index.js +++ b/packages/babel-plugin-transform-template-literals/src/index.js @@ -3,10 +3,14 @@ import { template, types as t } from "@babel/core"; export default declare((api, options) => { api.assertVersion(7); - const { loose } = options; + + const ignoreToPrimitiveHint = + api.assumption("ignoreToPrimitiveHint") ?? options.loose; + const mutableTemplateObject = + api.assumption("mutableTemplateObject") ?? options.loose; let helperName = "taggedTemplateLiteral"; - if (loose) helperName += "Loose"; + if (mutableTemplateObject) helperName += "Loose"; /** * This function groups the objects into multiple calls to `.concat()` in @@ -115,13 +119,15 @@ export default declare((api, options) => { // since `+` is left-to-right associative // ensure the first node is a string if first/second isn't - const considerSecondNode = !loose || !t.isStringLiteral(nodes[1]); - if (!t.isStringLiteral(nodes[0]) && considerSecondNode) { + if ( + !t.isStringLiteral(nodes[0]) && + !(ignoreToPrimitiveHint && t.isStringLiteral(nodes[1])) + ) { nodes.unshift(t.stringLiteral("")); } let root = nodes[0]; - if (loose) { + if (ignoreToPrimitiveHint) { for (let i = 1; i < nodes.length; i++) { root = t.binaryExpression("+", root, nodes[i]); } diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/escape-quotes/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/escape-quotes/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/escape-quotes/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/escape-quotes/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/escape-quotes/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/escape-quotes/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/escape-quotes/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/escape-quotes/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/expression-first/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/expression-first/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/expression-first/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/expression-first/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/expression-first/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/expression-first/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/expression-first/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/expression-first/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/functions/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/functions/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/functions/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/functions/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/functions/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/functions/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/functions/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/functions/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/literals/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/literals/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/literals/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/literals/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/literals/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/literals/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/literals/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/literals/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/multiline/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/multiline/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/multiline/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/multiline/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/multiline/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/multiline/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/multiline/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/multiline/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/multiple/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/multiple/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/multiple/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/multiple/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/multiple/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/multiple/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/multiple/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/multiple/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/none/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/none/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/none/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/none/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/none/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/none/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/none/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/none/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/only/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/only/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/only/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/only/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/only/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/only/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/only/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/only/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/options.json b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/options.json new file mode 100644 index 000000000000..e9058d39d544 --- /dev/null +++ b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["transform-template-literals"], + "assumptions": { + "ignoreToPrimitiveHint": true + } +} diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/order/exec.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/order/exec.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/order/exec.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/order/exec.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/order/options.json b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/order/options.json similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/order/options.json rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/order/options.json diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/order2/exec.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/order2/exec.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/order2/exec.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/order2/exec.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/order2/options.json b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/order2/options.json similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/order2/options.json rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/order2/options.json diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/single/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/single/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/single/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/single/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/single/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/single/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/single/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/single/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/statement/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/statement/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/statement/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/statement/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/statement/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/statement/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/statement/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/statement/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/symbol/exec.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/symbol/exec.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/symbol/exec.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/symbol/exec.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/tag/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/tag/input.js new file mode 100644 index 000000000000..79f996661e4b --- /dev/null +++ b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/tag/input.js @@ -0,0 +1 @@ +tag`foo ${bar} baz`; diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/tag/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/tag/output.js new file mode 100644 index 000000000000..d2bd91618a71 --- /dev/null +++ b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-ignoreToPrimitiveHint/tag/output.js @@ -0,0 +1,5 @@ +var _templateObject; + +function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } + +tag(_templateObject || (_templateObject = _taggedTemplateLiteral(["foo ", " baz"])), bar); diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/no-tag/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/no-tag/input.js new file mode 100644 index 000000000000..05ead3e65df5 --- /dev/null +++ b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/no-tag/input.js @@ -0,0 +1 @@ +`foo ${bar} baz`; diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/no-tag/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/no-tag/output.js new file mode 100644 index 000000000000..2328f9dfa655 --- /dev/null +++ b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/no-tag/output.js @@ -0,0 +1 @@ +"foo ".concat(bar, " baz"); diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/options.json b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/options.json new file mode 100644 index 000000000000..29cf2ac88867 --- /dev/null +++ b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/options.json @@ -0,0 +1,6 @@ +{ + "plugins": ["transform-template-literals"], + "assumptions": { + "mutableTemplateObject": true + } +} diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/tag/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/tag/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/tag/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/tag/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/tag/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/tag/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/tag/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/tag/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/template-revision/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/template-revision/input.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/template-revision/input.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/template-revision/input.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/template-revision/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/template-revision/output.js similarity index 100% rename from packages/babel-plugin-transform-template-literals/test/fixtures/loose/template-revision/output.js rename to packages/babel-plugin-transform-template-literals/test/fixtures/assumption-mutableTemplateObject/template-revision/output.js diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/ignoreToPrimitiveHint/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/loose/ignoreToPrimitiveHint/input.js new file mode 100644 index 000000000000..98413bcfcede --- /dev/null +++ b/packages/babel-plugin-transform-template-literals/test/fixtures/loose/ignoreToPrimitiveHint/input.js @@ -0,0 +1 @@ +var o = `foo ${bar} baz`; diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/ignoreToPrimitiveHint/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/loose/ignoreToPrimitiveHint/output.js new file mode 100644 index 000000000000..f0a7277e17f4 --- /dev/null +++ b/packages/babel-plugin-transform-template-literals/test/fixtures/loose/ignoreToPrimitiveHint/output.js @@ -0,0 +1 @@ +var o = "foo " + bar + " baz"; diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/mutableTemplateObject/input.js b/packages/babel-plugin-transform-template-literals/test/fixtures/loose/mutableTemplateObject/input.js new file mode 100644 index 000000000000..8b87c3fe9f4d --- /dev/null +++ b/packages/babel-plugin-transform-template-literals/test/fixtures/loose/mutableTemplateObject/input.js @@ -0,0 +1 @@ +var o = tag`foo ${bar} baz`; diff --git a/packages/babel-plugin-transform-template-literals/test/fixtures/loose/mutableTemplateObject/output.js b/packages/babel-plugin-transform-template-literals/test/fixtures/loose/mutableTemplateObject/output.js new file mode 100644 index 000000000000..195dbdc46430 --- /dev/null +++ b/packages/babel-plugin-transform-template-literals/test/fixtures/loose/mutableTemplateObject/output.js @@ -0,0 +1,5 @@ +var _templateObject; + +function _taggedTemplateLiteralLoose(strings, raw) { if (!raw) { raw = strings.slice(0); } strings.raw = raw; return strings; } + +var o = tag(_templateObject || (_templateObject = _taggedTemplateLiteralLoose(["foo ", " baz"])), bar); diff --git a/packages/babel-traverse/src/path/conversion.ts b/packages/babel-traverse/src/path/conversion.ts index 028695961264..5e401415c14e 100644 --- a/packages/babel-traverse/src/path/conversion.ts +++ b/packages/babel-traverse/src/path/conversion.ts @@ -76,6 +76,7 @@ export function ensureBlock( /** * Keeping this for backward-compatibility. You should use arrowFunctionToExpression() for >=7.x. */ +// TODO(Babel 8): Remove this export function arrowFunctionToShadowed(this: NodePath) { if (!this.isArrowFunctionExpression()) return; @@ -107,7 +108,13 @@ export function unwrapFunctionEnvironment(this: NodePath) { */ export function arrowFunctionToExpression( this: NodePath, - { allowInsertArrow = true, specCompliant = false } = {}, + { + allowInsertArrow = true, + /** @deprecated Use `noNewArrows` instead */ + specCompliant = false, + // TODO(Babel 8): Consider defaulting to `false` for spec compliancy + noNewArrows = !specCompliant, + } = {}, ) { if (!this.isArrowFunctionExpression()) { throw this.buildCodeFrameError( @@ -117,14 +124,14 @@ export function arrowFunctionToExpression( const thisBinding = hoistFunctionEnvironment( this, - specCompliant, + noNewArrows, allowInsertArrow, ); this.ensureBlock(); // @ts-expect-error todo(flow->ts): avoid mutating nodes this.node.type = "FunctionExpression"; - if (specCompliant) { + if (!noNewArrows) { const checkBinding = thisBinding ? null : this.parentPath.scope.generateUidIdentifier("arrowCheckId"); @@ -165,7 +172,8 @@ export function arrowFunctionToExpression( */ function hoistFunctionEnvironment( fnPath, - specCompliant = false, + // TODO(Babel 8): Consider defaulting to `false` for spec compliancy + noNewArrows = true, allowInsertArrow = true, ) { const thisEnvFn = fnPath.findParent(p => { @@ -303,11 +311,11 @@ function hoistFunctionEnvironment( // Convert all "this" references in the arrow to point at the alias. let thisBinding; - if (thisPaths.length > 0 || specCompliant) { + if (thisPaths.length > 0 || !noNewArrows) { thisBinding = getThisBinding(thisEnvFn, inConstructor); if ( - !specCompliant || + noNewArrows || // In subclass constructors, still need to rewrite because "this" can't be bound in spec mode // because it might not have been initialized yet. (inConstructor && hasSuperClass(thisEnvFn)) @@ -321,7 +329,7 @@ function hoistFunctionEnvironment( thisChild.replaceWith(thisRef); }); - if (specCompliant) thisBinding = null; + if (!noNewArrows) thisBinding = null; } } diff --git a/packages/babel-traverse/src/path/replacement.ts b/packages/babel-traverse/src/path/replacement.ts index 3774fa53ffc3..e114740501e8 100644 --- a/packages/babel-traverse/src/path/replacement.ts +++ b/packages/babel-traverse/src/path/replacement.ts @@ -272,6 +272,8 @@ export function replaceExpressionWithStatements( } const callee = this.get("callee") as NodePath; + + // This is an IIFE, so we don't need to worry about the noNewArrows assumption callee.arrowFunctionToExpression(); // (() => await xxx)() -> await (async () => await xxx)(); diff --git a/packages/babel-traverse/src/scope/index.ts b/packages/babel-traverse/src/scope/index.ts index 169f8a585e98..6a9b8b80c5ed 100644 --- a/packages/babel-traverse/src/scope/index.ts +++ b/packages/babel-traverse/src/scope/index.ts @@ -578,7 +578,7 @@ export default class Scope { } // TODO: (Babel 8) Split i in two parameters, and use an object of flags - toArray(node: t.Node, i?: number | boolean, allowArrayLike?: boolean) { + toArray(node: t.Node, i?: number | boolean, arrayLikeIsIterable?: boolean) { if (t.isIdentifier(node)) { const binding = this.getBinding(node.name); if (binding?.constant && binding.path.isGenericType("Array")) { @@ -622,7 +622,7 @@ export default class Scope { helperName = "toArray"; } - if (allowArrayLike) { + if (arrayLikeIsIterable) { args.unshift(this.hub.addHelper(helperName)); helperName = "maybeArrayLike"; }