Implement assumptions defined in the babel/rfcs#5 RFC
- `mutableTemplateObject` and `ignoreToPrimitiveHint` (#12408) - `setClassMethods` (#12407) - `setComputedProperties` (#12490) - `ignoreFunctionLength` (#12491) - `noDocumentAll` (#12481) - `iterableIsArray` and `arrayLikeIsIterable` (#12489) - `pureGetters` (#12504) - `skipForOfIteratorClosing` (#12496) - `objectRestNoSymbols`, `setSpreadProperties` and `pureGetters` (#12505) - `noNewArrows` (#12613, #12793) - `setPublicClassFields` and `privateFieldsAsProperties` (#12497) - `constantReexports` and `enumerableModuleMeta` (#12618) - `constantSuper`, `superIsCallableConstructor` and `noClassCalls` (#12726) Co-authored-by: Justin Ridgewell <justin@ridgewell.name> Co-authored-by: Huáng Jùnliàng <JLHwung@users.noreply.github.com>
This commit is contained in:
parent
7965c15557
commit
6ef7b51a11
@ -332,8 +332,26 @@ type EnvPath = $ReadOnly<{
|
|||||||
export type NestingPath = RootPath | OverridesPath | EnvPath;
|
export type NestingPath = RootPath | OverridesPath | EnvPath;
|
||||||
|
|
||||||
export const assumptionsNames = new Set<string>([
|
export const assumptionsNames = new Set<string>([
|
||||||
|
"arrayLikeIsIterable",
|
||||||
|
"constantReexports",
|
||||||
|
"constantSuper",
|
||||||
|
"enumerableModuleMeta",
|
||||||
|
"ignoreFunctionLength",
|
||||||
|
"ignoreToPrimitiveHint",
|
||||||
|
"iterableIsArray",
|
||||||
"mutableTemplateObject",
|
"mutableTemplateObject",
|
||||||
|
"noClassCalls",
|
||||||
|
"noDocumentAll",
|
||||||
|
"noNewArrows",
|
||||||
|
"objectRestNoSymbols",
|
||||||
|
"privateFieldsAsProperties",
|
||||||
|
"pureGetters",
|
||||||
|
"setClassMethods",
|
||||||
|
"setComputedProperties",
|
||||||
"setPublicClassFields",
|
"setPublicClassFields",
|
||||||
|
"setSpreadProperties",
|
||||||
|
"skipForOfIteratorClosing",
|
||||||
|
"superIsCallableConstructor",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function getSource(loc: NestingPath): OptionsSource {
|
function getSource(loc: NestingPath): OptionsSource {
|
||||||
|
|||||||
@ -35,11 +35,16 @@ export function buildPrivateNamesMap(props) {
|
|||||||
return privateNamesMap;
|
return privateNamesMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildPrivateNamesNodes(privateNamesMap, loose, state) {
|
export function buildPrivateNamesNodes(
|
||||||
|
privateNamesMap,
|
||||||
|
privateFieldsAsProperties,
|
||||||
|
state,
|
||||||
|
) {
|
||||||
const initNodes = [];
|
const initNodes = [];
|
||||||
|
|
||||||
for (const [name, value] of privateNamesMap) {
|
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
|
// secret non-enumerable property. Hence, we also need to generate that
|
||||||
// key (using the classPrivateFieldLooseKey helper).
|
// key (using the classPrivateFieldLooseKey helper).
|
||||||
// In spec mode, only instance fields need a "private name" initializer
|
// 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 { static: isStatic, method: isMethod, getId, setId } = value;
|
||||||
const isAccessor = getId || setId;
|
const isAccessor = getId || setId;
|
||||||
const id = t.cloneNode(value.id);
|
const id = t.cloneNode(value.id);
|
||||||
if (loose) {
|
if (privateFieldsAsProperties) {
|
||||||
initNodes.push(
|
initNodes.push(
|
||||||
template.statement.ast`
|
template.statement.ast`
|
||||||
var ${id} = ${state.addHelper("classPrivateFieldLooseKey")}("${name}")
|
var ${id} = ${state.addHelper("classPrivateFieldLooseKey")}("${name}")
|
||||||
@ -149,13 +154,13 @@ const privateInVisitor = privateNameVisitorFactory({
|
|||||||
if (operator !== "in") return;
|
if (operator !== "in") return;
|
||||||
if (!path.get("left").isPrivateName()) return;
|
if (!path.get("left").isPrivateName()) return;
|
||||||
|
|
||||||
const { loose, privateNamesMap, redeclared } = this;
|
const { privateFieldsAsProperties, privateNamesMap, redeclared } = this;
|
||||||
const { name } = left.id;
|
const { name } = left.id;
|
||||||
|
|
||||||
if (!privateNamesMap.has(name)) return;
|
if (!privateNamesMap.has(name)) return;
|
||||||
if (redeclared && redeclared.includes(name)) return;
|
if (redeclared && redeclared.includes(name)) return;
|
||||||
|
|
||||||
if (loose) {
|
if (privateFieldsAsProperties) {
|
||||||
const { id } = privateNamesMap.get(name);
|
const { id } = privateNamesMap.get(name);
|
||||||
path.replaceWith(template.expression.ast`
|
path.replaceWith(template.expression.ast`
|
||||||
Object.prototype.hasOwnProperty.call(${right}, ${t.cloneNode(id)})
|
Object.prototype.hasOwnProperty.call(${right}, ${t.cloneNode(id)})
|
||||||
@ -373,13 +378,15 @@ export function transformPrivateNamesUsage(
|
|||||||
ref,
|
ref,
|
||||||
path,
|
path,
|
||||||
privateNamesMap,
|
privateNamesMap,
|
||||||
loose,
|
{ privateFieldsAsProperties },
|
||||||
state,
|
state,
|
||||||
) {
|
) {
|
||||||
if (!privateNamesMap.size) return;
|
if (!privateNamesMap.size) return;
|
||||||
|
|
||||||
const body = path.get("body");
|
const body = path.get("body");
|
||||||
const handler = loose ? privateNameHandlerLoose : privateNameHandlerSpec;
|
const handler = privateFieldsAsProperties
|
||||||
|
? privateNameHandlerLoose
|
||||||
|
: privateNameHandlerSpec;
|
||||||
|
|
||||||
memberExpressionToFunctions(body, privateNameVisitor, {
|
memberExpressionToFunctions(body, privateNameVisitor, {
|
||||||
privateNamesMap,
|
privateNamesMap,
|
||||||
@ -391,7 +398,7 @@ export function transformPrivateNamesUsage(
|
|||||||
privateNamesMap,
|
privateNamesMap,
|
||||||
classRef: ref,
|
classRef: ref,
|
||||||
file: state,
|
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 privateName = privateNamesMap.get(prop.node.key.id.name);
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
@ -613,7 +624,7 @@ function buildPrivateMethodDeclaration(prop, privateNamesMap, loose = false) {
|
|||||||
t.variableDeclarator(setId, methodValue),
|
t.variableDeclarator(setId, methodValue),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if (isStatic && !loose) {
|
if (isStatic && !privateFieldsAsProperties) {
|
||||||
return t.variableDeclaration("var", [
|
return t.variableDeclaration("var", [
|
||||||
t.variableDeclarator(
|
t.variableDeclarator(
|
||||||
t.cloneNode(id),
|
t.cloneNode(id),
|
||||||
@ -637,12 +648,12 @@ const thisContextVisitor = traverse.visitors.merge([
|
|||||||
environmentVisitor,
|
environmentVisitor,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function replaceThisContext(path, ref, superRef, file, loose) {
|
function replaceThisContext(path, ref, superRef, file, constantSuper) {
|
||||||
const state = { classRef: ref, needsClassRef: false };
|
const state = { classRef: ref, needsClassRef: false };
|
||||||
|
|
||||||
const replacer = new ReplaceSupers({
|
const replacer = new ReplaceSupers({
|
||||||
methodPath: path,
|
methodPath: path,
|
||||||
isLoose: loose,
|
constantSuper,
|
||||||
superRef,
|
superRef,
|
||||||
file,
|
file,
|
||||||
refToPreserve: ref,
|
refToPreserve: ref,
|
||||||
@ -666,7 +677,9 @@ export function buildFieldsInitNodes(
|
|||||||
props,
|
props,
|
||||||
privateNamesMap,
|
privateNamesMap,
|
||||||
state,
|
state,
|
||||||
loose,
|
setPublicClassFields,
|
||||||
|
privateFieldsAsProperties,
|
||||||
|
constantSuper,
|
||||||
) {
|
) {
|
||||||
const staticNodes = [];
|
const staticNodes = [];
|
||||||
const instanceNodes = [];
|
const instanceNodes = [];
|
||||||
@ -683,39 +696,45 @@ export function buildFieldsInitNodes(
|
|||||||
const isMethod = !isField;
|
const isMethod = !isField;
|
||||||
|
|
||||||
if (isStatic || (isMethod && isPrivate)) {
|
if (isStatic || (isMethod && isPrivate)) {
|
||||||
const replaced = replaceThisContext(prop, ref, superRef, state, loose);
|
const replaced = replaceThisContext(
|
||||||
|
prop,
|
||||||
|
ref,
|
||||||
|
superRef,
|
||||||
|
state,
|
||||||
|
constantSuper,
|
||||||
|
);
|
||||||
needsClassRef = needsClassRef || replaced;
|
needsClassRef = needsClassRef || replaced;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case isStatic && isPrivate && isField && loose:
|
case isStatic && isPrivate && isField && privateFieldsAsProperties:
|
||||||
needsClassRef = true;
|
needsClassRef = true;
|
||||||
staticNodes.push(
|
staticNodes.push(
|
||||||
buildPrivateFieldInitLoose(t.cloneNode(ref), prop, privateNamesMap),
|
buildPrivateFieldInitLoose(t.cloneNode(ref), prop, privateNamesMap),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case isStatic && isPrivate && isField && !loose:
|
case isStatic && isPrivate && isField && !privateFieldsAsProperties:
|
||||||
needsClassRef = true;
|
needsClassRef = true;
|
||||||
staticNodes.push(
|
staticNodes.push(
|
||||||
buildPrivateStaticFieldInitSpec(prop, privateNamesMap),
|
buildPrivateStaticFieldInitSpec(prop, privateNamesMap),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case isStatic && isPublic && isField && loose:
|
case isStatic && isPublic && isField && setPublicClassFields:
|
||||||
needsClassRef = true;
|
needsClassRef = true;
|
||||||
staticNodes.push(buildPublicFieldInitLoose(t.cloneNode(ref), prop));
|
staticNodes.push(buildPublicFieldInitLoose(t.cloneNode(ref), prop));
|
||||||
break;
|
break;
|
||||||
case isStatic && isPublic && isField && !loose:
|
case isStatic && isPublic && isField && !setPublicClassFields:
|
||||||
needsClassRef = true;
|
needsClassRef = true;
|
||||||
staticNodes.push(
|
staticNodes.push(
|
||||||
buildPublicFieldInitSpec(t.cloneNode(ref), prop, state),
|
buildPublicFieldInitSpec(t.cloneNode(ref), prop, state),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case isInstance && isPrivate && isField && loose:
|
case isInstance && isPrivate && isField && privateFieldsAsProperties:
|
||||||
instanceNodes.push(
|
instanceNodes.push(
|
||||||
buildPrivateFieldInitLoose(t.thisExpression(), prop, privateNamesMap),
|
buildPrivateFieldInitLoose(t.thisExpression(), prop, privateNamesMap),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case isInstance && isPrivate && isField && !loose:
|
case isInstance && isPrivate && isField && !privateFieldsAsProperties:
|
||||||
instanceNodes.push(
|
instanceNodes.push(
|
||||||
buildPrivateInstanceFieldInitSpec(
|
buildPrivateInstanceFieldInitSpec(
|
||||||
t.thisExpression(),
|
t.thisExpression(),
|
||||||
@ -724,7 +743,7 @@ export function buildFieldsInitNodes(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case isInstance && isPrivate && isMethod && loose:
|
case isInstance && isPrivate && isMethod && privateFieldsAsProperties:
|
||||||
instanceNodes.unshift(
|
instanceNodes.unshift(
|
||||||
buildPrivateMethodInitLoose(
|
buildPrivateMethodInitLoose(
|
||||||
t.thisExpression(),
|
t.thisExpression(),
|
||||||
@ -733,10 +752,14 @@ export function buildFieldsInitNodes(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
staticNodes.push(
|
staticNodes.push(
|
||||||
buildPrivateMethodDeclaration(prop, privateNamesMap, loose),
|
buildPrivateMethodDeclaration(
|
||||||
|
prop,
|
||||||
|
privateNamesMap,
|
||||||
|
privateFieldsAsProperties,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case isInstance && isPrivate && isMethod && !loose:
|
case isInstance && isPrivate && isMethod && !privateFieldsAsProperties:
|
||||||
instanceNodes.unshift(
|
instanceNodes.unshift(
|
||||||
buildPrivateInstanceMethodInitSpec(
|
buildPrivateInstanceMethodInitSpec(
|
||||||
t.thisExpression(),
|
t.thisExpression(),
|
||||||
@ -745,19 +768,27 @@ export function buildFieldsInitNodes(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
staticNodes.push(
|
staticNodes.push(
|
||||||
buildPrivateMethodDeclaration(prop, privateNamesMap, loose),
|
buildPrivateMethodDeclaration(
|
||||||
|
prop,
|
||||||
|
privateNamesMap,
|
||||||
|
privateFieldsAsProperties,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case isStatic && isPrivate && isMethod && !loose:
|
case isStatic && isPrivate && isMethod && !privateFieldsAsProperties:
|
||||||
needsClassRef = true;
|
needsClassRef = true;
|
||||||
staticNodes.push(
|
staticNodes.push(
|
||||||
buildPrivateStaticFieldInitSpec(prop, privateNamesMap),
|
buildPrivateStaticFieldInitSpec(prop, privateNamesMap),
|
||||||
);
|
);
|
||||||
staticNodes.unshift(
|
staticNodes.unshift(
|
||||||
buildPrivateMethodDeclaration(prop, privateNamesMap, loose),
|
buildPrivateMethodDeclaration(
|
||||||
|
prop,
|
||||||
|
privateNamesMap,
|
||||||
|
privateFieldsAsProperties,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case isStatic && isPrivate && isMethod && loose:
|
case isStatic && isPrivate && isMethod && privateFieldsAsProperties:
|
||||||
needsClassRef = true;
|
needsClassRef = true;
|
||||||
staticNodes.push(
|
staticNodes.push(
|
||||||
buildPrivateStaticMethodInitLoose(
|
buildPrivateStaticMethodInitLoose(
|
||||||
@ -768,13 +799,17 @@ export function buildFieldsInitNodes(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
staticNodes.unshift(
|
staticNodes.unshift(
|
||||||
buildPrivateMethodDeclaration(prop, privateNamesMap, loose),
|
buildPrivateMethodDeclaration(
|
||||||
|
prop,
|
||||||
|
privateNamesMap,
|
||||||
|
privateFieldsAsProperties,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case isInstance && isPublic && isField && loose:
|
case isInstance && isPublic && isField && setPublicClassFields:
|
||||||
instanceNodes.push(buildPublicFieldInitLoose(t.thisExpression(), prop));
|
instanceNodes.push(buildPublicFieldInitLoose(t.thisExpression(), prop));
|
||||||
break;
|
break;
|
||||||
case isInstance && isPublic && isField && !loose:
|
case isInstance && isPublic && isField && !setPublicClassFields:
|
||||||
instanceNodes.push(
|
instanceNodes.push(
|
||||||
buildPublicFieldInitSpec(t.thisExpression(), prop, state),
|
buildPublicFieldInitSpec(t.thisExpression(), prop, state),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -36,7 +36,38 @@ export function createClassFeaturePlugin({
|
|||||||
feature,
|
feature,
|
||||||
loose,
|
loose,
|
||||||
manipulateOptions,
|
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 {
|
return {
|
||||||
name,
|
name,
|
||||||
manipulateOptions,
|
manipulateOptions,
|
||||||
@ -151,11 +182,17 @@ export function createClassFeaturePlugin({
|
|||||||
const privateNamesMap = buildPrivateNamesMap(props);
|
const privateNamesMap = buildPrivateNamesMap(props);
|
||||||
const privateNamesNodes = buildPrivateNamesNodes(
|
const privateNamesNodes = buildPrivateNamesNodes(
|
||||||
privateNamesMap,
|
privateNamesMap,
|
||||||
loose,
|
privateFieldsAsProperties ?? loose,
|
||||||
state,
|
state,
|
||||||
);
|
);
|
||||||
|
|
||||||
transformPrivateNamesUsage(ref, path, privateNamesMap, loose, state);
|
transformPrivateNamesUsage(
|
||||||
|
ref,
|
||||||
|
path,
|
||||||
|
privateNamesMap,
|
||||||
|
{ privateFieldsAsProperties: privateFieldsAsProperties ?? loose },
|
||||||
|
state,
|
||||||
|
);
|
||||||
|
|
||||||
let keysNodes, staticNodes, instanceNodes, wrapClass;
|
let keysNodes, staticNodes, instanceNodes, wrapClass;
|
||||||
|
|
||||||
@ -175,7 +212,9 @@ export function createClassFeaturePlugin({
|
|||||||
props,
|
props,
|
||||||
privateNamesMap,
|
privateNamesMap,
|
||||||
state,
|
state,
|
||||||
loose,
|
setPublicClassFields ?? loose,
|
||||||
|
privateFieldsAsProperties ?? loose,
|
||||||
|
constantSuper ?? loose,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
foo;
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"validateLogs": true,
|
||||||
|
"plugins": [
|
||||||
|
["proposal-class-properties", { "loose": true }]
|
||||||
|
],
|
||||||
|
"assumptions": {
|
||||||
|
"setPublicClassFields": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
class A {
|
||||||
|
constructor() {
|
||||||
|
this.foo = void 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
}
|
||||||
@ -27,14 +27,19 @@ export { hasExports, isSideEffectImport, isModule, rewriteThis };
|
|||||||
export function rewriteModuleStatementsAndPrepareHeader(
|
export function rewriteModuleStatementsAndPrepareHeader(
|
||||||
path: NodePath,
|
path: NodePath,
|
||||||
{
|
{
|
||||||
|
// TODO(Babel 8): Remove this
|
||||||
|
loose,
|
||||||
|
|
||||||
exportName,
|
exportName,
|
||||||
strict,
|
strict,
|
||||||
allowTopLevelThis,
|
allowTopLevelThis,
|
||||||
strictMode,
|
strictMode,
|
||||||
loose,
|
|
||||||
noInterop,
|
noInterop,
|
||||||
lazy,
|
lazy,
|
||||||
esNamespaceOnly,
|
esNamespaceOnly,
|
||||||
|
|
||||||
|
constantReexports = loose,
|
||||||
|
enumerableModuleMeta = loose,
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
assert(isModule(path), "Cannot process module statements in a script");
|
assert(isModule(path), "Cannot process module statements in a script");
|
||||||
@ -42,7 +47,7 @@ export function rewriteModuleStatementsAndPrepareHeader(
|
|||||||
|
|
||||||
const meta = normalizeAndLoadModuleMetadata(path, exportName, {
|
const meta = normalizeAndLoadModuleMetadata(path, exportName, {
|
||||||
noInterop,
|
noInterop,
|
||||||
loose,
|
initializeReexports: constantReexports,
|
||||||
lazy,
|
lazy,
|
||||||
esNamespaceOnly,
|
esNamespaceOnly,
|
||||||
});
|
});
|
||||||
@ -67,7 +72,7 @@ export function rewriteModuleStatementsAndPrepareHeader(
|
|||||||
|
|
||||||
const headers = [];
|
const headers = [];
|
||||||
if (hasExports(meta) && !strict) {
|
if (hasExports(meta) && !strict) {
|
||||||
headers.push(buildESModuleHeader(meta, loose /* enumerable */));
|
headers.push(buildESModuleHeader(meta, enumerableModuleMeta));
|
||||||
}
|
}
|
||||||
|
|
||||||
const nameList = buildExportNameListDeclaration(path, meta);
|
const nameList = buildExportNameListDeclaration(path, meta);
|
||||||
@ -78,7 +83,9 @@ export function rewriteModuleStatementsAndPrepareHeader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create all of the statically known named exports.
|
// Create all of the statically known named exports.
|
||||||
headers.push(...buildExportInitializationStatements(path, meta, loose));
|
headers.push(
|
||||||
|
...buildExportInitializationStatements(path, meta, constantReexports),
|
||||||
|
);
|
||||||
|
|
||||||
return { meta, headers };
|
return { meta, headers };
|
||||||
}
|
}
|
||||||
@ -128,7 +135,7 @@ export function wrapInterop(
|
|||||||
export function buildNamespaceInitStatements(
|
export function buildNamespaceInitStatements(
|
||||||
metadata: ModuleMetadata,
|
metadata: ModuleMetadata,
|
||||||
sourceMetadata: SourceModuleMetadata,
|
sourceMetadata: SourceModuleMetadata,
|
||||||
loose: boolean = false,
|
constantReexports: boolean = false,
|
||||||
) {
|
) {
|
||||||
const statements = [];
|
const statements = [];
|
||||||
|
|
||||||
@ -146,8 +153,8 @@ export function buildNamespaceInitStatements(
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (loose) {
|
if (constantReexports) {
|
||||||
statements.push(...buildReexportsFromMeta(metadata, sourceMetadata, loose));
|
statements.push(...buildReexportsFromMeta(metadata, sourceMetadata, true));
|
||||||
}
|
}
|
||||||
for (const exportName of sourceMetadata.reexportNamespace) {
|
for (const exportName of sourceMetadata.reexportNamespace) {
|
||||||
// Assign export to namespace object.
|
// Assign export to namespace object.
|
||||||
@ -172,7 +179,7 @@ export function buildNamespaceInitStatements(
|
|||||||
const statement = buildNamespaceReexport(
|
const statement = buildNamespaceReexport(
|
||||||
metadata,
|
metadata,
|
||||||
t.cloneNode(srcNamespace),
|
t.cloneNode(srcNamespace),
|
||||||
loose,
|
constantReexports,
|
||||||
);
|
);
|
||||||
statement.loc = sourceMetadata.reexportAll.loc;
|
statement.loc = sourceMetadata.reexportAll.loc;
|
||||||
|
|
||||||
@ -183,8 +190,8 @@ export function buildNamespaceInitStatements(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ReexportTemplate = {
|
const ReexportTemplate = {
|
||||||
loose: template.statement`EXPORTS.EXPORT_NAME = NAMESPACE_IMPORT;`,
|
constant: template.statement`EXPORTS.EXPORT_NAME = NAMESPACE_IMPORT;`,
|
||||||
looseComputed: template.statement`EXPORTS["EXPORT_NAME"] = NAMESPACE_IMPORT;`,
|
constantComputed: template.statement`EXPORTS["EXPORT_NAME"] = NAMESPACE_IMPORT;`,
|
||||||
spec: template`
|
spec: template`
|
||||||
Object.defineProperty(EXPORTS, "EXPORT_NAME", {
|
Object.defineProperty(EXPORTS, "EXPORT_NAME", {
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
@ -198,7 +205,7 @@ const ReexportTemplate = {
|
|||||||
const buildReexportsFromMeta = (
|
const buildReexportsFromMeta = (
|
||||||
meta: ModuleMetadata,
|
meta: ModuleMetadata,
|
||||||
metadata: SourceModuleMetadata,
|
metadata: SourceModuleMetadata,
|
||||||
loose,
|
constantReexports: boolean,
|
||||||
) => {
|
) => {
|
||||||
const namespace = metadata.lazy
|
const namespace = metadata.lazy
|
||||||
? t.callExpression(t.identifier(metadata.name), [])
|
? t.callExpression(t.identifier(metadata.name), [])
|
||||||
@ -224,11 +231,11 @@ const buildReexportsFromMeta = (
|
|||||||
EXPORT_NAME: exportName,
|
EXPORT_NAME: exportName,
|
||||||
NAMESPACE_IMPORT,
|
NAMESPACE_IMPORT,
|
||||||
};
|
};
|
||||||
if (loose) {
|
if (constantReexports) {
|
||||||
if (stringSpecifiers.has(exportName)) {
|
if (stringSpecifiers.has(exportName)) {
|
||||||
return ReexportTemplate.looseComputed(astNodes);
|
return ReexportTemplate.constantComputed(astNodes);
|
||||||
} else {
|
} else {
|
||||||
return ReexportTemplate.loose(astNodes);
|
return ReexportTemplate.constant(astNodes);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return ReexportTemplate.spec(astNodes);
|
return ReexportTemplate.spec(astNodes);
|
||||||
@ -241,9 +248,9 @@ const buildReexportsFromMeta = (
|
|||||||
*/
|
*/
|
||||||
function buildESModuleHeader(
|
function buildESModuleHeader(
|
||||||
metadata: ModuleMetadata,
|
metadata: ModuleMetadata,
|
||||||
enumerable: boolean = false,
|
enumerableModuleMeta: boolean = false,
|
||||||
) {
|
) {
|
||||||
return (enumerable
|
return (enumerableModuleMeta
|
||||||
? template.statement`
|
? template.statement`
|
||||||
EXPORTS.__esModule = true;
|
EXPORTS.__esModule = true;
|
||||||
`
|
`
|
||||||
@ -257,8 +264,8 @@ function buildESModuleHeader(
|
|||||||
/**
|
/**
|
||||||
* Create a re-export initialization loop for a specific imported namespace.
|
* Create a re-export initialization loop for a specific imported namespace.
|
||||||
*/
|
*/
|
||||||
function buildNamespaceReexport(metadata, namespace, loose) {
|
function buildNamespaceReexport(metadata, namespace, constantReexports) {
|
||||||
return (loose
|
return (constantReexports
|
||||||
? template.statement`
|
? template.statement`
|
||||||
Object.keys(NAMESPACE).forEach(function(key) {
|
Object.keys(NAMESPACE).forEach(function(key) {
|
||||||
if (key === "default" || key === "__esModule") return;
|
if (key === "default" || key === "__esModule") return;
|
||||||
@ -347,7 +354,7 @@ function buildExportNameListDeclaration(
|
|||||||
function buildExportInitializationStatements(
|
function buildExportInitializationStatements(
|
||||||
programPath: NodePath,
|
programPath: NodePath,
|
||||||
metadata: ModuleMetadata,
|
metadata: ModuleMetadata,
|
||||||
loose: boolean = false,
|
constantReexports: boolean = false,
|
||||||
) {
|
) {
|
||||||
const initStatements = [];
|
const initStatements = [];
|
||||||
|
|
||||||
@ -365,8 +372,8 @@ function buildExportInitializationStatements(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const data of metadata.source.values()) {
|
for (const data of metadata.source.values()) {
|
||||||
if (!loose) {
|
if (!constantReexports) {
|
||||||
initStatements.push(...buildReexportsFromMeta(metadata, data, loose));
|
initStatements.push(...buildReexportsFromMeta(metadata, data, false));
|
||||||
}
|
}
|
||||||
for (const exportName of data.reexportNamespace) {
|
for (const exportName of data.reexportNamespace) {
|
||||||
exportNames.push(exportName);
|
exportNames.push(exportName);
|
||||||
|
|||||||
@ -86,7 +86,7 @@ export default function normalizeModuleAndLoadMetadata(
|
|||||||
exportName?: string,
|
exportName?: string,
|
||||||
{
|
{
|
||||||
noInterop = false,
|
noInterop = false,
|
||||||
loose = false,
|
initializeReexports = false,
|
||||||
lazy = false,
|
lazy = false,
|
||||||
esNamespaceOnly = false,
|
esNamespaceOnly = false,
|
||||||
} = {},
|
} = {},
|
||||||
@ -100,10 +100,7 @@ export default function normalizeModuleAndLoadMetadata(
|
|||||||
|
|
||||||
const { local, source, hasExports } = getModuleMetadata(
|
const { local, source, hasExports } = getModuleMetadata(
|
||||||
programPath,
|
programPath,
|
||||||
{
|
{ initializeReexports, lazy },
|
||||||
loose,
|
|
||||||
lazy,
|
|
||||||
},
|
|
||||||
stringSpecifiers,
|
stringSpecifiers,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -170,12 +167,15 @@ function getExportSpecifierName(
|
|||||||
*/
|
*/
|
||||||
function getModuleMetadata(
|
function getModuleMetadata(
|
||||||
programPath: NodePath,
|
programPath: NodePath,
|
||||||
{ loose, lazy }: { loose: boolean, lazy: boolean },
|
{
|
||||||
|
lazy,
|
||||||
|
initializeReexports,
|
||||||
|
}: { lazy: boolean, initializeReexports: boolean },
|
||||||
stringSpecifiers: Set<string>,
|
stringSpecifiers: Set<string>,
|
||||||
) {
|
) {
|
||||||
const localData = getLocalExportMetadata(
|
const localData = getLocalExportMetadata(
|
||||||
programPath,
|
programPath,
|
||||||
loose,
|
initializeReexports,
|
||||||
stringSpecifiers,
|
stringSpecifiers,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -361,7 +361,7 @@ function getModuleMetadata(
|
|||||||
*/
|
*/
|
||||||
function getLocalExportMetadata(
|
function getLocalExportMetadata(
|
||||||
programPath: NodePath,
|
programPath: NodePath,
|
||||||
loose: boolean,
|
initializeReexports: boolean,
|
||||||
stringSpecifiers: Set<string>,
|
stringSpecifiers: Set<string>,
|
||||||
): Map<string, LocalExportMetadata> {
|
): Map<string, LocalExportMetadata> {
|
||||||
const bindingKindLookup = new Map();
|
const bindingKindLookup = new Map();
|
||||||
@ -376,7 +376,7 @@ function getLocalExportMetadata(
|
|||||||
if (child.node.declaration) {
|
if (child.node.declaration) {
|
||||||
child = child.get("declaration");
|
child = child.get("declaration");
|
||||||
} else if (
|
} else if (
|
||||||
loose &&
|
initializeReexports &&
|
||||||
child.node.source &&
|
child.node.source &&
|
||||||
child.get("source").isStringLiteral()
|
child.get("source").isStringLiteral()
|
||||||
) {
|
) {
|
||||||
@ -429,7 +429,10 @@ function getLocalExportMetadata(
|
|||||||
};
|
};
|
||||||
|
|
||||||
programPath.get("body").forEach(child => {
|
programPath.get("body").forEach(child => {
|
||||||
if (child.isExportNamedDeclaration() && (loose || !child.node.source)) {
|
if (
|
||||||
|
child.isExportNamedDeclaration() &&
|
||||||
|
(initializeReexports || !child.node.source)
|
||||||
|
) {
|
||||||
if (child.node.declaration) {
|
if (child.node.declaration) {
|
||||||
const declaration = child.get("declaration");
|
const declaration = child.get("declaration");
|
||||||
const ids = declaration.getOuterBindingIdentifierPaths();
|
const ids = declaration.getOuterBindingIdentifierPaths();
|
||||||
|
|||||||
@ -31,6 +31,7 @@ const awaitVisitor = {
|
|||||||
export default function (
|
export default function (
|
||||||
path: NodePath,
|
path: NodePath,
|
||||||
helpers: { wrapAsync: Object, wrapAwait: Object },
|
helpers: { wrapAsync: Object, wrapAwait: Object },
|
||||||
|
noNewArrows?: boolean,
|
||||||
) {
|
) {
|
||||||
path.traverse(awaitVisitor, {
|
path.traverse(awaitVisitor, {
|
||||||
wrapAwait: helpers.wrapAwait,
|
wrapAwait: helpers.wrapAwait,
|
||||||
@ -41,7 +42,7 @@ export default function (
|
|||||||
path.node.async = false;
|
path.node.async = false;
|
||||||
path.node.generator = true;
|
path.node.generator = true;
|
||||||
|
|
||||||
wrapFunction(path, t.cloneNode(helpers.wrapAsync));
|
wrapFunction(path, t.cloneNode(helpers.wrapAsync), noNewArrows);
|
||||||
|
|
||||||
const isProperty =
|
const isProperty =
|
||||||
path.isObjectMethod() ||
|
path.isObjectMethod() ||
|
||||||
|
|||||||
@ -255,7 +255,7 @@ const looseHandlers = {
|
|||||||
type ReplaceSupersOptionsBase = {|
|
type ReplaceSupersOptionsBase = {|
|
||||||
methodPath: NodePath,
|
methodPath: NodePath,
|
||||||
superRef: Object,
|
superRef: Object,
|
||||||
isLoose: boolean,
|
constantSuper: boolean,
|
||||||
file: any,
|
file: any,
|
||||||
// objectRef might have been shadowed in child scopes,
|
// objectRef might have been shadowed in child scopes,
|
||||||
// in that case, we need to rename related variables.
|
// in that case, we need to rename related variables.
|
||||||
@ -284,13 +284,16 @@ export default class ReplaceSupers {
|
|||||||
|
|
||||||
this.file = opts.file;
|
this.file = opts.file;
|
||||||
this.superRef = opts.superRef;
|
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;
|
this.opts = opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare file: HubInterface;
|
declare file: HubInterface;
|
||||||
declare isDerivedConstructor: boolean;
|
declare isDerivedConstructor: boolean;
|
||||||
declare isLoose: boolean;
|
declare constantSuper: boolean;
|
||||||
declare isPrivateMethod: boolean;
|
declare isPrivateMethod: boolean;
|
||||||
declare isStatic: boolean;
|
declare isStatic: boolean;
|
||||||
declare methodPath: NodePath;
|
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, {
|
memberExpressionToFunctions(this.methodPath, visitor, {
|
||||||
file: this.file,
|
file: this.file,
|
||||||
|
|||||||
@ -57,7 +57,7 @@ function classOrObjectMethod(path: NodePath, callId: Object) {
|
|||||||
.unwrapFunctionEnvironment();
|
.unwrapFunctionEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
function plainFunction(path: NodePath, callId: Object) {
|
function plainFunction(path: NodePath, callId: Object, noNewArrows: boolean) {
|
||||||
const node = path.node;
|
const node = path.node;
|
||||||
const isDeclaration = path.isFunctionDeclaration();
|
const isDeclaration = path.isFunctionDeclaration();
|
||||||
const functionId = node.id;
|
const functionId = node.id;
|
||||||
@ -68,7 +68,7 @@ function plainFunction(path: NodePath, callId: Object) {
|
|||||||
: buildAnonymousExpressionWrapper;
|
: buildAnonymousExpressionWrapper;
|
||||||
|
|
||||||
if (path.isArrowFunctionExpression()) {
|
if (path.isArrowFunctionExpression()) {
|
||||||
path.arrowFunctionToExpression();
|
path.arrowFunctionToExpression({ noNewArrows });
|
||||||
}
|
}
|
||||||
|
|
||||||
node.id = null;
|
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()) {
|
if (path.isMethod()) {
|
||||||
classOrObjectMethod(path, callId);
|
classOrObjectMethod(path, callId);
|
||||||
} else {
|
} else {
|
||||||
plainFunction(path, callId);
|
plainFunction(path, callId, noNewArrows);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,8 @@ export default declare(api => {
|
|||||||
|
|
||||||
path.traverse(yieldStarVisitor, state);
|
path.traverse(yieldStarVisitor, state);
|
||||||
|
|
||||||
|
// We don't need to pass the noNewArrows assumption, since
|
||||||
|
// async generators are never arrow functions.
|
||||||
remapAsyncToGenerator(path, {
|
remapAsyncToGenerator(path, {
|
||||||
wrapAsync: state.addHelper("wrapAsyncGenerator"),
|
wrapAsync: state.addHelper("wrapAsyncGenerator"),
|
||||||
wrapAwait: state.addHelper("awaitAsyncGenerator"),
|
wrapAwait: state.addHelper("awaitAsyncGenerator"),
|
||||||
|
|||||||
@ -12,6 +12,7 @@ export default declare((api, options) => {
|
|||||||
return createClassFeaturePlugin({
|
return createClassFeaturePlugin({
|
||||||
name: "proposal-class-properties",
|
name: "proposal-class-properties",
|
||||||
|
|
||||||
|
api,
|
||||||
feature: FEATURES.fields,
|
feature: FEATURES.fields,
|
||||||
loose: options.loose,
|
loose: options.loose,
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
@ -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";
|
||||||
|
}
|
||||||
@ -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";
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
var foo = "bar";
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
bar = foo;
|
||||||
|
static bar = baz;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
var foo = "foo";
|
||||||
|
var baz = "baz";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
var foo = "bar";
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
constructor() {
|
||||||
|
this.bar = foo;
|
||||||
|
var _foo = "foo";
|
||||||
|
var baz = "baz";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Foo.bar = baz;
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class Foo extends Bar {
|
||||||
|
bar = "foo";
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
class Foo extends Bar {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
this.bar = "foo";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
class Child extends Parent {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
scopedFunctionWithThis = () => {
|
||||||
|
this.name = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
["external-helpers", { "helperVersion": "7.100.0" }],
|
||||||
|
"proposal-class-properties"
|
||||||
|
],
|
||||||
|
"presets": ["env"],
|
||||||
|
"assumptions": {
|
||||||
|
"setPublicClassFields": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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);
|
||||||
@ -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');
|
||||||
@ -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');
|
||||||
@ -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');
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class Foo {
|
||||||
|
bar;
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
class Foo {
|
||||||
|
constructor() {
|
||||||
|
this.bar = void 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class Foo {
|
||||||
|
bar = "foo";
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
class Foo {
|
||||||
|
constructor() {
|
||||||
|
this.bar = "foo";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
export default param =>
|
||||||
|
class App {
|
||||||
|
static props = {
|
||||||
|
prop1: 'prop1',
|
||||||
|
prop2: 'prop2'
|
||||||
|
}
|
||||||
|
|
||||||
|
getParam() {
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
});
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
["external-helpers", { "helperVersion": "7.100.0" }],
|
||||||
|
"proposal-class-properties",
|
||||||
|
"syntax-class-properties"
|
||||||
|
],
|
||||||
|
"assumptions": {
|
||||||
|
"setPublicClassFields": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
call(class {
|
||||||
|
static test = true
|
||||||
|
});
|
||||||
|
|
||||||
|
export default class {
|
||||||
|
static test = true
|
||||||
|
};
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
var _class, _temp;
|
||||||
|
|
||||||
|
call((_temp = _class = class {}, _class.test = true, _temp));
|
||||||
|
export default class _class2 {}
|
||||||
|
_class2.test = true;
|
||||||
|
;
|
||||||
@ -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,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"external-helpers",
|
||||||
|
"transform-async-to-generator",
|
||||||
|
"proposal-class-properties"
|
||||||
|
],
|
||||||
|
"assumptions": {
|
||||||
|
"setPublicClassFields": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
export class MyClass {
|
||||||
|
static property = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class MyClass2 {
|
||||||
|
static property = value;
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
export class MyClass {}
|
||||||
|
MyClass.property = value;
|
||||||
|
export default class MyClass2 {}
|
||||||
|
MyClass2.property = value;
|
||||||
@ -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");
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
var Foo = class {
|
||||||
|
static num = 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
var _class, _temp;
|
||||||
|
|
||||||
|
var Foo = (_temp = _class = class Foo {}, _class.num = 0, _temp);
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
class A {
|
||||||
|
static prop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {
|
||||||
|
static prop = 2;
|
||||||
|
static propA = super.prop;
|
||||||
|
static getPropA = () => super.prop;
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"validateLogs": true,
|
||||||
|
"plugins": [
|
||||||
|
["external-helpers", { "helperVersion": "7.100.0" }],
|
||||||
|
["proposal-class-properties", { "loose": true }],
|
||||||
|
"syntax-class-properties"
|
||||||
|
],
|
||||||
|
"assumptions": {
|
||||||
|
"setPublicClassFields": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
class A {}
|
||||||
|
|
||||||
|
A.prop = 1;
|
||||||
|
|
||||||
|
class B extends A {}
|
||||||
|
|
||||||
|
B.prop = 2;
|
||||||
|
B.propA = A.prop;
|
||||||
|
|
||||||
|
B.getPropA = () => A.prop;
|
||||||
@ -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
|
||||||
|
}
|
||||||
@ -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);
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
class A {
|
||||||
|
static prop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {
|
||||||
|
static prop = 2;
|
||||||
|
static propA = super.prop;
|
||||||
|
static getPropA = () => super.prop;
|
||||||
|
}
|
||||||
@ -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);
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
class A {
|
||||||
|
static self = this;
|
||||||
|
static getA = () => this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { self, getA } = A;
|
||||||
|
|
||||||
|
expect(self).toBe(A);
|
||||||
|
expect(getA()).toBe(A);
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
class A {
|
||||||
|
static self = this;
|
||||||
|
static getA = () => this;
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
class A {}
|
||||||
|
|
||||||
|
A.self = A;
|
||||||
|
|
||||||
|
A.getA = () => A;
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
class Foo {
|
||||||
|
static num;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect("num" in Foo).toBe(true);
|
||||||
|
expect(Foo.num).toBeUndefined();
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class Foo {
|
||||||
|
static bar;
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class Foo {}
|
||||||
|
|
||||||
|
Foo.bar = void 0;
|
||||||
@ -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");
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class Foo {
|
||||||
|
static bar = "foo";
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class Foo {}
|
||||||
|
|
||||||
|
Foo.bar = "foo";
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
class A {
|
||||||
|
foo() {
|
||||||
|
return "bar";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {
|
||||||
|
foo = super.foo();
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
class A {
|
||||||
|
foo() {
|
||||||
|
return "bar";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
this.foo = super.foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
class Foo extends Bar {
|
||||||
|
bar = "foo";
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
foo(super());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
class Foo extends Bar {
|
||||||
|
constructor() {
|
||||||
|
var _temp;
|
||||||
|
|
||||||
|
foo((_temp = super(), this.bar = "foo", _temp));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
class Foo extends Bar {
|
||||||
|
bar = "foo";
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
class Foo extends Bar {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.bar = "foo";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
class A {
|
||||||
|
force = force;
|
||||||
|
foo = super.method();
|
||||||
|
|
||||||
|
constructor(force) {}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
class A {
|
||||||
|
constructor(_force) {
|
||||||
|
this.force = force;
|
||||||
|
this.foo = super.method();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -50,6 +50,7 @@ export default declare((api, options) => {
|
|||||||
return createClassFeaturePlugin({
|
return createClassFeaturePlugin({
|
||||||
name: "proposal-decorators",
|
name: "proposal-decorators",
|
||||||
|
|
||||||
|
api,
|
||||||
feature: FEATURES.decorators,
|
feature: FEATURES.decorators,
|
||||||
// loose: options.loose, Not supported
|
// loose: options.loose, Not supported
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { types as t, template } from "@babel/core";
|
|||||||
|
|
||||||
export default declare((api, { loose = false }) => {
|
export default declare((api, { loose = false }) => {
|
||||||
api.assertVersion(7);
|
api.assertVersion(7);
|
||||||
|
const noDocumentAll = api.assumption("noDocumentAll") ?? loose;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: "proposal-nullish-coalescing-operator",
|
name: "proposal-nullish-coalescing-operator",
|
||||||
@ -38,7 +39,7 @@ export default declare((api, { loose = false }) => {
|
|||||||
t.conditionalExpression(
|
t.conditionalExpression(
|
||||||
// We cannot use `!= null` in spec mode because
|
// We cannot use `!= null` in spec mode because
|
||||||
// `document.all == null` and `document.all` is not "nullish".
|
// `document.all == null` and `document.all` is not "nullish".
|
||||||
loose
|
noDocumentAll
|
||||||
? t.binaryExpression("!=", assignment, t.nullLiteral())
|
? t.binaryExpression("!=", assignment, t.nullLiteral())
|
||||||
: t.logicalExpression(
|
: t.logicalExpression(
|
||||||
"&&",
|
"&&",
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["proposal-nullish-coalescing-operator"],
|
||||||
|
"assumptions": {
|
||||||
|
"noDocumentAll": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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);
|
||||||
@ -0,0 +1 @@
|
|||||||
|
var { qux = foo.bar ?? "qux" } = {};
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
var _foo$bar;
|
||||||
|
|
||||||
|
var {
|
||||||
|
qux = (_foo$bar = foo.bar) != null ? _foo$bar : "qux"
|
||||||
|
} = {};
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
function foo(foo, qux = foo.bar ?? "qux") {}
|
||||||
|
|
||||||
|
function bar(bar, qux = bar ?? "qux") {}
|
||||||
@ -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") {}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
function foo(opts) {
|
||||||
|
var foo = opts.foo ?? "default";
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
function foo(opts) {
|
||||||
|
var _opts$foo;
|
||||||
|
|
||||||
|
var foo = (_opts$foo = opts.foo) != null ? _opts$foo : "default";
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
function foo(foo, bar = foo ?? "bar") {}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
function foo(foo, bar = foo != null ? foo : "bar") {}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
function foo() {
|
||||||
|
var foo = this ?? {};
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
function foo() {
|
||||||
|
var foo = this != null ? this : {};
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
function foo(opts) {
|
||||||
|
var foo = opts.foo ?? "default";
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
function foo(opts) {
|
||||||
|
var _opts$foo;
|
||||||
|
|
||||||
|
var foo = (_opts$foo = opts.foo) != null ? _opts$foo : "default";
|
||||||
|
}
|
||||||
@ -23,6 +23,11 @@ export default declare((api, opts) => {
|
|||||||
throw new Error(".loose must be a boolean, or undefined");
|
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) {
|
function getExtendsHelper(file) {
|
||||||
return useBuiltIns
|
return useBuiltIns
|
||||||
? t.memberExpression(t.identifier("Object"), t.identifier("assign"))
|
? t.memberExpression(t.identifier("Object"), t.identifier("assign"))
|
||||||
@ -133,7 +138,7 @@ export default declare((api, opts) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//expects path to an object pattern
|
//expects path to an object pattern
|
||||||
function createObjectSpread(path, file, objRef) {
|
function createObjectRest(path, file, objRef) {
|
||||||
const props = path.get("properties");
|
const props = path.get("properties");
|
||||||
const last = props[props.length - 1];
|
const last = props[props.length - 1];
|
||||||
t.assertRestElement(last.node);
|
t.assertRestElement(last.node);
|
||||||
@ -172,7 +177,9 @@ export default declare((api, opts) => {
|
|||||||
impureComputedPropertyDeclarators,
|
impureComputedPropertyDeclarators,
|
||||||
restElement.argument,
|
restElement.argument,
|
||||||
t.callExpression(
|
t.callExpression(
|
||||||
file.addHelper(`objectWithoutProperties${loose ? "Loose" : ""}`),
|
file.addHelper(
|
||||||
|
`objectWithoutProperties${objectRestNoSymbols ? "Loose" : ""}`,
|
||||||
|
),
|
||||||
[t.cloneNode(objRef), keyExpression],
|
[t.cloneNode(objRef), keyExpression],
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@ -275,7 +282,7 @@ export default declare((api, opts) => {
|
|||||||
idx >= i - 1 || paramsWithRestElement.has(idx);
|
idx >= i - 1 || paramsWithRestElement.has(idx);
|
||||||
convertFunctionParams(
|
convertFunctionParams(
|
||||||
path,
|
path,
|
||||||
loose,
|
ignoreFunctionLength,
|
||||||
shouldTransformParam,
|
shouldTransformParam,
|
||||||
replaceRestElement,
|
replaceRestElement,
|
||||||
);
|
);
|
||||||
@ -361,9 +368,9 @@ export default declare((api, opts) => {
|
|||||||
impureComputedPropertyDeclarators,
|
impureComputedPropertyDeclarators,
|
||||||
argument,
|
argument,
|
||||||
callExpression,
|
callExpression,
|
||||||
] = createObjectSpread(objectPatternPath, file, ref);
|
] = createObjectRest(objectPatternPath, file, ref);
|
||||||
|
|
||||||
if (loose) {
|
if (pureGetters) {
|
||||||
removeUnusedExcludedKeys(objectPatternPath);
|
removeUnusedExcludedKeys(objectPatternPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,7 +451,7 @@ export default declare((api, opts) => {
|
|||||||
impureComputedPropertyDeclarators,
|
impureComputedPropertyDeclarators,
|
||||||
argument,
|
argument,
|
||||||
callExpression,
|
callExpression,
|
||||||
] = createObjectSpread(leftPath, file, t.identifier(refName));
|
] = createObjectRest(leftPath, file, t.identifier(refName));
|
||||||
|
|
||||||
if (impureComputedPropertyDeclarators.length > 0) {
|
if (impureComputedPropertyDeclarators.length > 0) {
|
||||||
nodes.push(
|
nodes.push(
|
||||||
@ -553,7 +560,7 @@ export default declare((api, opts) => {
|
|||||||
if (!hasSpread(path.node)) return;
|
if (!hasSpread(path.node)) return;
|
||||||
|
|
||||||
let helper;
|
let helper;
|
||||||
if (loose) {
|
if (setSpreadProperties) {
|
||||||
helper = getExtendsHelper(file);
|
helper = getExtendsHelper(file);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -583,10 +590,9 @@ export default declare((api, opts) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In loose mode, we don't want to make multiple calls. We're assuming
|
// When we can assume that getters are pure and don't depend on
|
||||||
// that the spread objects either don't use getters, or that the
|
// the order of evaluation, we can avoid making multiple calls.
|
||||||
// getters are pure and don't depend on the order of evaluation.
|
if (pureGetters) {
|
||||||
if (loose) {
|
|
||||||
if (hadProps) {
|
if (hadProps) {
|
||||||
exp.arguments.push(obj);
|
exp.arguments.push(obj);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"proposal-object-rest-spread"
|
||||||
|
],
|
||||||
|
"assumptions": {
|
||||||
|
"ignoreFunctionLength": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
({...R}, a = R) => {}
|
||||||
|
({...R}, e, c = 2, a = R, f = q) => { let q; }
|
||||||
|
({...R}, a = f(R)) => {}
|
||||||
@ -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);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
["external-helpers", { "helperVersion": "7.100.0"}],
|
||||||
|
"proposal-object-rest-spread"
|
||||||
|
],
|
||||||
|
"assumptions": {
|
||||||
|
"objectRestNoSymbols": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
({ a, b, ...c } = obj);
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
var _obj = obj;
|
||||||
|
({
|
||||||
|
a,
|
||||||
|
b
|
||||||
|
} = _obj);
|
||||||
|
c = babelHelpers.objectWithoutPropertiesLoose(_obj, ["a", "b"]);
|
||||||
|
_obj;
|
||||||
@ -0,0 +1 @@
|
|||||||
|
let { [a]: b, ...c } = obj;
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
let _a = a,
|
||||||
|
{
|
||||||
|
[_a]: b
|
||||||
|
} = obj,
|
||||||
|
c = babelHelpers.objectWithoutPropertiesLoose(obj, [_a].map(babelHelpers.toPropertyKey));
|
||||||
@ -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);
|
||||||
@ -0,0 +1 @@
|
|||||||
|
let { a, nested: { b, c, ...d }, e } = obj;
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
let {
|
||||||
|
a,
|
||||||
|
nested: {
|
||||||
|
b,
|
||||||
|
c
|
||||||
|
},
|
||||||
|
e
|
||||||
|
} = obj,
|
||||||
|
d = babelHelpers.objectWithoutPropertiesLoose(obj.nested, ["b", "c"]);
|
||||||
@ -0,0 +1 @@
|
|||||||
|
var { a, b, ...c } = obj;
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
var {
|
||||||
|
a,
|
||||||
|
b
|
||||||
|
} = obj,
|
||||||
|
c = babelHelpers.objectWithoutPropertiesLoose(obj, ["a", "b"]);
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user