WIP - add extractor, generate snippet_data

This commit is contained in:
Stefan Fejes
2019-08-20 15:52:05 +02:00
parent 88084d3d30
commit cc8f1d8a7a
37396 changed files with 4588842 additions and 133 deletions

View File

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,19 @@
# @babel/helper-create-class-features-plugin
> Compile class public and private fields, private methods and decorators to ES6
See our website [@babel/helper-create-class-features-plugin](https://babeljs.io/docs/en/next/babel-helper-create-class-features-plugin.html) for more information.
## Install
Using npm:
```sh
npm install --save-dev @babel/helper-create-class-features-plugin
```
or using yarn:
```sh
yarn add @babel/helper-create-class-features-plugin --dev
```

View File

@ -0,0 +1,188 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.hasOwnDecorators = hasOwnDecorators;
exports.hasDecorators = hasDecorators;
exports.buildDecoratedClass = buildDecoratedClass;
function _core() {
const data = require("@babel/core");
_core = function () {
return data;
};
return data;
}
function _helperReplaceSupers() {
const data = _interopRequireDefault(require("@babel/helper-replace-supers"));
_helperReplaceSupers = function () {
return data;
};
return data;
}
function _helperFunctionName() {
const data = _interopRequireDefault(require("@babel/helper-function-name"));
_helperFunctionName = function () {
return data;
};
return data;
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function hasOwnDecorators(node) {
return !!(node.decorators && node.decorators.length);
}
function hasDecorators(node) {
return hasOwnDecorators(node) || node.body.body.some(hasOwnDecorators);
}
function prop(key, value) {
if (!value) return null;
return _core().types.objectProperty(_core().types.identifier(key), value);
}
function method(key, body) {
return _core().types.objectMethod("method", _core().types.identifier(key), [], _core().types.blockStatement(body));
}
function takeDecorators(node) {
let result;
if (node.decorators && node.decorators.length > 0) {
result = _core().types.arrayExpression(node.decorators.map(decorator => decorator.expression));
}
node.decorators = undefined;
return result;
}
function getKey(node) {
if (node.computed) {
return node.key;
} else if (_core().types.isIdentifier(node.key)) {
return _core().types.stringLiteral(node.key.name);
} else {
return _core().types.stringLiteral(String(node.key.value));
}
}
function extractElementDescriptor(classRef, superRef, path) {
const {
node,
scope
} = path;
const isMethod = path.isClassMethod();
if (path.isPrivate()) {
throw path.buildCodeFrameError(`Private ${isMethod ? "methods" : "fields"} in decorated classes are not supported yet.`);
}
new (_helperReplaceSupers().default)({
methodPath: path,
methodNode: node,
objectRef: classRef,
isStatic: node.static,
superRef,
scope,
file: this
}, true).replace();
const properties = [prop("kind", _core().types.stringLiteral(isMethod ? node.kind : "field")), prop("decorators", takeDecorators(node)), prop("static", node.static && _core().types.booleanLiteral(true)), prop("key", getKey(node))].filter(Boolean);
if (isMethod) {
const id = node.computed ? null : node.key;
_core().types.toExpression(node);
properties.push(prop("value", (0, _helperFunctionName().default)({
node,
id,
scope
}) || node));
} else if (node.value) {
properties.push(method("value", _core().template.statements.ast`return ${node.value}`));
} else {
properties.push(prop("value", scope.buildUndefinedNode()));
}
path.remove();
return _core().types.objectExpression(properties);
}
function addDecorateHelper(file) {
try {
return file.addHelper("decorate");
} catch (err) {
if (err.code === "BABEL_HELPER_UNKNOWN") {
err.message += "\n '@babel/plugin-transform-decorators' in non-legacy mode" + " requires '@babel/core' version ^7.0.2 and you appear to be using" + " an older version.";
}
throw err;
}
}
function buildDecoratedClass(ref, path, elements, file) {
const {
node,
scope
} = path;
const initializeId = scope.generateUidIdentifier("initialize");
const isDeclaration = node.id && path.isDeclaration();
const isStrict = path.isInStrictMode();
const {
superClass
} = node;
node.type = "ClassDeclaration";
if (!node.id) node.id = _core().types.cloneNode(ref);
let superId;
if (superClass) {
superId = scope.generateUidIdentifierBasedOnNode(node.superClass, "super");
node.superClass = superId;
}
const classDecorators = takeDecorators(node);
const definitions = _core().types.arrayExpression(elements.map(extractElementDescriptor.bind(file, node.id, superId)));
let replacement = _core().template.expression.ast`
${addDecorateHelper(file)}(
${classDecorators || _core().types.nullLiteral()},
function (${initializeId}, ${superClass ? superId : null}) {
${node}
return { F: ${_core().types.cloneNode(node.id)}, d: ${definitions} };
},
${superClass}
)
`;
let classPathDesc = "arguments.1.body.body.0";
if (!isStrict) {
replacement.arguments[1].body.directives.push(_core().types.directive(_core().types.directiveLiteral("use strict")));
}
if (isDeclaration) {
replacement = _core().template.ast`let ${ref} = ${replacement}`;
classPathDesc = "declarations.0.init." + classPathDesc;
}
return {
instanceNodes: [_core().template.statement.ast`${initializeId}(this)`],
wrapClass(path) {
path.replaceWith(replacement);
return path.get(classPathDesc);
}
};
}

View File

@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.enableFeature = enableFeature;
exports.isLoose = isLoose;
exports.verifyUsedFeatures = verifyUsedFeatures;
exports.FEATURES = void 0;
var _decorators = require("./decorators");
const FEATURES = Object.freeze({
fields: 1 << 1,
privateMethods: 1 << 2,
decorators: 1 << 3
});
exports.FEATURES = FEATURES;
const featuresKey = "@babel/plugin-class-features/featuresKey";
const looseKey = "@babel/plugin-class-features/looseKey";
function enableFeature(file, feature, loose) {
if (!hasFeature(file, feature)) {
file.set(featuresKey, file.get(featuresKey) | feature);
if (loose) file.set(looseKey, file.get(looseKey) | feature);
}
}
function hasFeature(file, feature) {
return !!(file.get(featuresKey) & feature);
}
function isLoose(file, feature) {
return !!(file.get(looseKey) & feature);
}
function verifyUsedFeatures(path, file) {
if ((0, _decorators.hasOwnDecorators)(path.node)) {
if (!hasFeature(file, FEATURES.decorators)) {
throw path.buildCodeFrameError("Decorators are not enabled." + "\nIf you are using " + '["@babel/plugin-proposal-decorators", { "legacy": true }], ' + 'make sure it comes *before* "@babel/plugin-proposal-class-properties" ' + "and enable loose mode, like so:\n" + '\t["@babel/plugin-proposal-decorators", { "legacy": true }]\n' + '\t["@babel/plugin-proposal-class-properties", { "loose": true }]');
}
if (path.isPrivate()) {
throw path.buildCodeFrameError(`Private ${path.isClassMethod() ? "methods" : "fields"} in decorated classes are not supported yet.`);
}
}
if (path.isPrivate() && path.isMethod()) {
if (!hasFeature(file, FEATURES.privateMethods)) {
throw path.buildCodeFrameError("Class private methods are not enabled.");
}
if (path.node.static && path.node.kind !== "method") {
throw path.buildCodeFrameError("@babel/plugin-class-features doesn't support class static private accessors yet.");
}
}
if (hasFeature(file, FEATURES.privateMethods) && hasFeature(file, FEATURES.fields) && isLoose(file, FEATURES.privateMethods) !== isLoose(file, FEATURES.fields)) {
throw path.buildCodeFrameError("'loose' mode configuration must be the same for both @babel/plugin-proposal-class-properties " + "and @babel/plugin-proposal-private-methods");
}
if (path.isProperty()) {
if (!hasFeature(file, FEATURES.fields)) {
throw path.buildCodeFrameError("Class fields are not enabled.");
}
}
}

View File

@ -0,0 +1,669 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.buildPrivateNamesMap = buildPrivateNamesMap;
exports.buildPrivateNamesNodes = buildPrivateNamesNodes;
exports.transformPrivateNamesUsage = transformPrivateNamesUsage;
exports.buildFieldsInitNodes = buildFieldsInitNodes;
function _core() {
const data = require("@babel/core");
_core = function () {
return data;
};
return data;
}
function _helperReplaceSupers() {
const data = _interopRequireWildcard(require("@babel/helper-replace-supers"));
_helperReplaceSupers = function () {
return data;
};
return data;
}
function _helperMemberExpressionToFunctions() {
const data = _interopRequireDefault(require("@babel/helper-member-expression-to-functions"));
_helperMemberExpressionToFunctions = function () {
return data;
};
return data;
}
function _helperOptimiseCallExpression() {
const data = _interopRequireDefault(require("@babel/helper-optimise-call-expression"));
_helperOptimiseCallExpression = function () {
return data;
};
return data;
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
function buildPrivateNamesMap(props) {
const privateNamesMap = new Map();
for (const prop of props) {
const isPrivate = prop.isPrivate();
const isMethod = !prop.isProperty();
const isInstance = !prop.node.static;
if (isPrivate) {
const {
name
} = prop.node.key.id;
const update = privateNamesMap.has(name) ? privateNamesMap.get(name) : {
id: prop.scope.generateUidIdentifier(name),
static: !isInstance,
method: isMethod
};
if (prop.node.kind === "get") {
update.getId = prop.scope.generateUidIdentifier(`get_${name}`);
} else if (prop.node.kind === "set") {
update.setId = prop.scope.generateUidIdentifier(`set_${name}`);
} else if (prop.node.kind === "method") {
update.methodId = prop.scope.generateUidIdentifier(name);
}
privateNamesMap.set(name, update);
}
}
return privateNamesMap;
}
function buildPrivateNamesNodes(privateNamesMap, loose, state) {
const initNodes = [];
for (const [name, value] of privateNamesMap) {
const {
id,
static: isStatic,
method: isMethod,
getId,
setId
} = value;
if (loose) {
initNodes.push(_core().template.statement.ast`
var ${id} = ${state.addHelper("classPrivateFieldLooseKey")}("${name}")
`);
} else if (isMethod && !isStatic) {
if (getId || setId) {
initNodes.push(_core().template.statement.ast`var ${id} = new WeakMap();`);
} else {
initNodes.push(_core().template.statement.ast`var ${id} = new WeakSet();`);
}
} else if (!isStatic) {
initNodes.push(_core().template.statement.ast`var ${id} = new WeakMap();`);
}
}
return initNodes;
}
const privateNameVisitor = {
PrivateName(path) {
const {
privateNamesMap
} = this;
const {
node,
parentPath
} = path;
if (!parentPath.isMemberExpression({
property: node
})) return;
if (!privateNamesMap.has(node.id.name)) return;
this.handle(parentPath);
},
Class(path) {
const {
privateNamesMap
} = this;
const body = path.get("body.body");
for (const prop of body) {
if (!prop.isPrivate()) {
continue;
}
if (!privateNamesMap.has(prop.node.key.id.name)) continue;
path.traverse(privateNameInnerVisitor, this);
path.skip();
break;
}
}
};
const privateNameInnerVisitor = _core().traverse.visitors.merge([{
PrivateName: privateNameVisitor.PrivateName
}, _helperReplaceSupers().environmentVisitor]);
const privateNameHandlerSpec = {
memoise(member, count) {
const {
scope
} = member;
const {
object
} = member.node;
const memo = scope.maybeGenerateMemoised(object);
if (!memo) {
return;
}
this.memoiser.set(object, memo, count);
},
receiver(member) {
const {
object
} = member.node;
if (this.memoiser.has(object)) {
return _core().types.cloneNode(this.memoiser.get(object));
}
return _core().types.cloneNode(object);
},
get(member) {
const {
classRef,
privateNamesMap,
file
} = this;
const {
name
} = member.node.property.id;
const {
id,
static: isStatic,
method: isMethod,
methodId,
getId,
setId
} = privateNamesMap.get(name);
if (isStatic) {
const helperName = isMethod ? "classStaticPrivateMethodGet" : "classStaticPrivateFieldSpecGet";
return _core().types.callExpression(file.addHelper(helperName), [this.receiver(member), _core().types.cloneNode(classRef), _core().types.cloneNode(id)]);
}
if (isMethod) {
if (getId || setId) {
return _core().types.callExpression(file.addHelper("classPrivateFieldGet"), [this.receiver(member), _core().types.cloneNode(id)]);
}
return _core().types.callExpression(file.addHelper("classPrivateMethodGet"), [this.receiver(member), _core().types.cloneNode(id), _core().types.cloneNode(methodId)]);
}
return _core().types.callExpression(file.addHelper("classPrivateFieldGet"), [this.receiver(member), _core().types.cloneNode(id)]);
},
set(member, value) {
const {
classRef,
privateNamesMap,
file
} = this;
const {
name
} = member.node.property.id;
const {
id,
static: isStatic,
method: isMethod,
setId
} = privateNamesMap.get(name);
if (isStatic) {
const helperName = isMethod ? "classStaticPrivateMethodSet" : "classStaticPrivateFieldSpecSet";
return _core().types.callExpression(file.addHelper(helperName), [this.receiver(member), _core().types.cloneNode(classRef), _core().types.cloneNode(id), value]);
}
if (isMethod) {
if (setId) {
return _core().types.callExpression(file.addHelper("classPrivateFieldSet"), [this.receiver(member), _core().types.cloneNode(id), value]);
}
return _core().types.callExpression(file.addHelper("classPrivateMethodSet"), []);
}
return _core().types.callExpression(file.addHelper("classPrivateFieldSet"), [this.receiver(member), _core().types.cloneNode(id), value]);
},
destructureSet(member) {
const {
privateNamesMap,
file
} = this;
const {
name
} = member.node.property.id;
const {
id
} = privateNamesMap.get(name);
return _core().types.memberExpression(_core().types.callExpression(file.addHelper("classPrivateFieldDestructureSet"), [this.receiver(member), _core().types.cloneNode(id)]), _core().types.identifier("value"));
},
call(member, args) {
this.memoise(member, 1);
return (0, _helperOptimiseCallExpression().default)(this.get(member), this.receiver(member), args);
}
};
const privateNameHandlerLoose = {
handle(member) {
const {
privateNamesMap,
file
} = this;
const {
object
} = member.node;
const {
name
} = member.node.property.id;
member.replaceWith(_core().template.expression`BASE(REF, PROP)[PROP]`({
BASE: file.addHelper("classPrivateFieldLooseBase"),
REF: object,
PROP: privateNamesMap.get(name).id
}));
}
};
function transformPrivateNamesUsage(ref, path, privateNamesMap, loose, state) {
const body = path.get("body");
if (loose) {
body.traverse(privateNameVisitor, Object.assign({
privateNamesMap,
file: state
}, privateNameHandlerLoose));
} else {
(0, _helperMemberExpressionToFunctions().default)(body, privateNameVisitor, Object.assign({
privateNamesMap,
classRef: ref,
file: state
}, privateNameHandlerSpec));
}
}
function buildPrivateFieldInitLoose(ref, prop, privateNamesMap) {
const {
id
} = privateNamesMap.get(prop.node.key.id.name);
const value = prop.node.value || prop.scope.buildUndefinedNode();
return _core().template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
writable: true,
value: ${value}
});
`;
}
function buildPrivateInstanceFieldInitSpec(ref, prop, privateNamesMap) {
const {
id
} = privateNamesMap.get(prop.node.key.id.name);
const value = prop.node.value || prop.scope.buildUndefinedNode();
return _core().template.statement.ast`${id}.set(${ref}, {
// configurable is always false for private elements
// enumerable is always false for private elements
writable: true,
value: ${value},
})`;
}
function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) {
const {
id
} = privateNamesMap.get(prop.node.key.id.name);
const value = prop.node.value || prop.scope.buildUndefinedNode();
return _core().template.statement.ast`
var ${id} = {
// configurable is false by default
// enumerable is false by default
writable: true,
value: ${value}
};
`;
}
function buildPrivateMethodInitLoose(ref, prop, privateNamesMap) {
const privateName = privateNamesMap.get(prop.node.key.id.name);
const {
methodId,
id,
getId,
setId,
initAdded
} = privateName;
if (initAdded) return;
if (methodId) {
return _core().template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
value: ${methodId.name}
});
`;
}
if (getId || setId) {
privateNamesMap.set(prop.node.key.id.name, Object.assign({}, privateName, {
initAdded: true
}));
if (getId && setId) {
return _core().template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
get: ${getId.name},
set: ${setId.name}
});
`;
} else if (getId && !setId) {
return _core().template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
get: ${getId.name}
});
`;
} else if (!getId && setId) {
return _core().template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
set: ${setId.name}
});
`;
}
}
}
function buildPrivateInstanceMethodInitSpec(ref, prop, privateNamesMap) {
const privateName = privateNamesMap.get(prop.node.key.id.name);
const {
id,
getId,
setId,
initAdded
} = privateName;
if (initAdded) return;
if (getId || setId) {
privateNamesMap.set(prop.node.key.id.name, Object.assign({}, privateName, {
initAdded: true
}));
if (getId && setId) {
return _core().template.statement.ast`
${id}.set(${ref}, {
get: ${getId.name},
set: ${setId.name}
});
`;
} else if (getId && !setId) {
return _core().template.statement.ast`
${id}.set(${ref}, {
get: ${getId.name}
});
`;
} else if (!getId && setId) {
return _core().template.statement.ast`
${id}.set(${ref}, {
set: ${setId.name}
});
`;
}
}
return _core().template.statement.ast`${id}.add(${ref})`;
}
function buildPublicFieldInitLoose(ref, prop) {
const {
key,
computed
} = prop.node;
const value = prop.node.value || prop.scope.buildUndefinedNode();
return _core().types.expressionStatement(_core().types.assignmentExpression("=", _core().types.memberExpression(ref, key, computed || _core().types.isLiteral(key)), value));
}
function buildPublicFieldInitSpec(ref, prop, state) {
const {
key,
computed
} = prop.node;
const value = prop.node.value || prop.scope.buildUndefinedNode();
return _core().types.expressionStatement(_core().types.callExpression(state.addHelper("defineProperty"), [ref, computed || _core().types.isLiteral(key) ? key : _core().types.stringLiteral(key.name), value]));
}
function buildPrivateStaticMethodInitLoose(ref, prop, state, privateNamesMap) {
const {
id,
methodId
} = privateNamesMap.get(prop.node.key.id.name);
return _core().template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
value: ${methodId.name}
});
`;
}
function buildPrivateMethodDeclaration(prop, privateNamesMap, loose = false) {
const privateName = privateNamesMap.get(prop.node.key.id.name);
const {
id,
methodId,
getId,
setId,
getterDeclared,
setterDeclared,
static: isStatic
} = privateName;
const {
params,
body,
generator,
async
} = prop.node;
const methodValue = _core().types.functionExpression(methodId, params, body, generator, async);
const isGetter = getId && !getterDeclared && params.length === 0;
const isSetter = setId && !setterDeclared && params.length > 0;
if (isGetter) {
privateNamesMap.set(prop.node.key.id.name, Object.assign({}, privateName, {
getterDeclared: true
}));
return _core().types.variableDeclaration("var", [_core().types.variableDeclarator(getId, methodValue)]);
}
if (isSetter) {
privateNamesMap.set(prop.node.key.id.name, Object.assign({}, privateName, {
setterDeclared: true
}));
return _core().types.variableDeclaration("var", [_core().types.variableDeclarator(setId, methodValue)]);
}
if (isStatic && !loose) {
return _core().types.variableDeclaration("var", [_core().types.variableDeclarator(id, _core().types.functionExpression(id, params, body, generator, async))]);
}
return _core().types.variableDeclaration("var", [_core().types.variableDeclarator(methodId, methodValue)]);
}
const thisContextVisitor = _core().traverse.visitors.merge([{
ThisExpression(path, state) {
state.needsClassRef = true;
path.replaceWith(_core().types.cloneNode(state.classRef));
}
}, _helperReplaceSupers().environmentVisitor]);
function replaceThisContext(path, ref, superRef, file, loose) {
const state = {
classRef: ref,
needsClassRef: false
};
const replacer = new (_helperReplaceSupers().default)({
methodPath: path,
isLoose: loose,
superRef,
file,
getObjectRef() {
state.needsClassRef = true;
return path.node.static ? ref : _core().types.memberExpression(ref, _core().types.identifier("prototype"));
}
});
replacer.replace();
if (path.isProperty()) {
path.traverse(thisContextVisitor, state);
}
return state.needsClassRef;
}
function buildFieldsInitNodes(ref, superRef, props, privateNamesMap, state, loose) {
const staticNodes = [];
const instanceNodes = [];
let needsClassRef = false;
for (const prop of props) {
const isStatic = prop.node.static;
const isInstance = !isStatic;
const isPrivate = prop.isPrivate();
const isPublic = !isPrivate;
const isField = prop.isProperty();
const isMethod = !isField;
if (isStatic || isMethod && isPrivate) {
const replaced = replaceThisContext(prop, ref, superRef, state, loose);
needsClassRef = needsClassRef || replaced;
}
switch (true) {
case isStatic && isPrivate && isField && loose:
needsClassRef = true;
staticNodes.push(buildPrivateFieldInitLoose(_core().types.cloneNode(ref), prop, privateNamesMap));
break;
case isStatic && isPrivate && isField && !loose:
needsClassRef = true;
staticNodes.push(buildPrivateStaticFieldInitSpec(prop, privateNamesMap));
break;
case isStatic && isPublic && isField && loose:
needsClassRef = true;
staticNodes.push(buildPublicFieldInitLoose(_core().types.cloneNode(ref), prop));
break;
case isStatic && isPublic && isField && !loose:
needsClassRef = true;
staticNodes.push(buildPublicFieldInitSpec(_core().types.cloneNode(ref), prop, state));
break;
case isInstance && isPrivate && isField && loose:
instanceNodes.push(buildPrivateFieldInitLoose(_core().types.thisExpression(), prop, privateNamesMap));
break;
case isInstance && isPrivate && isField && !loose:
instanceNodes.push(buildPrivateInstanceFieldInitSpec(_core().types.thisExpression(), prop, privateNamesMap));
break;
case isInstance && isPrivate && isMethod && loose:
instanceNodes.unshift(buildPrivateMethodInitLoose(_core().types.thisExpression(), prop, privateNamesMap));
staticNodes.push(buildPrivateMethodDeclaration(prop, privateNamesMap, loose));
break;
case isInstance && isPrivate && isMethod && !loose:
instanceNodes.unshift(buildPrivateInstanceMethodInitSpec(_core().types.thisExpression(), prop, privateNamesMap));
staticNodes.push(buildPrivateMethodDeclaration(prop, privateNamesMap, loose));
break;
case isStatic && isPrivate && isMethod && !loose:
needsClassRef = true;
staticNodes.push(buildPrivateMethodDeclaration(prop, privateNamesMap, loose));
break;
case isStatic && isPrivate && isMethod && loose:
needsClassRef = true;
staticNodes.push(buildPrivateMethodDeclaration(prop, privateNamesMap, loose));
staticNodes.push(buildPrivateStaticMethodInitLoose(_core().types.cloneNode(ref), prop, state, privateNamesMap));
break;
case isInstance && isPublic && isField && loose:
instanceNodes.push(buildPublicFieldInitLoose(_core().types.thisExpression(), prop));
break;
case isInstance && isPublic && isField && !loose:
instanceNodes.push(buildPublicFieldInitSpec(_core().types.thisExpression(), prop, state));
break;
default:
throw new Error("Unreachable.");
}
}
return {
staticNodes,
instanceNodes: instanceNodes.filter(Boolean),
wrapClass(path) {
for (const prop of props) {
prop.remove();
}
if (!needsClassRef) return path;
if (path.isClassExpression()) {
path.scope.push({
id: ref
});
path.replaceWith(_core().types.assignmentExpression("=", _core().types.cloneNode(ref), path.node));
} else if (!path.node.id) {
path.node.id = ref;
}
return path;
}
};
}

View File

@ -0,0 +1,203 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createClassFeaturePlugin = createClassFeaturePlugin;
Object.defineProperty(exports, "injectInitialization", {
enumerable: true,
get: function () {
return _misc.injectInitialization;
}
});
Object.defineProperty(exports, "FEATURES", {
enumerable: true,
get: function () {
return _features.FEATURES;
}
});
function _helperFunctionName() {
const data = _interopRequireDefault(require("@babel/helper-function-name"));
_helperFunctionName = function () {
return data;
};
return data;
}
function _helperSplitExportDeclaration() {
const data = _interopRequireDefault(require("@babel/helper-split-export-declaration"));
_helperSplitExportDeclaration = function () {
return data;
};
return data;
}
var _fields = require("./fields");
var _decorators = require("./decorators");
var _misc = require("./misc");
var _features = require("./features");
var _package = _interopRequireDefault(require("../package.json"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const version = _package.default.version.split(".").reduce((v, x) => v * 1e5 + +x, 0);
const versionKey = "@babel/plugin-class-features/version";
function createClassFeaturePlugin({
name,
feature,
loose,
manipulateOptions
}) {
return {
name,
manipulateOptions,
pre() {
(0, _features.enableFeature)(this.file, feature, loose);
if (!this.file.get(versionKey) || this.file.get(versionKey) < version) {
this.file.set(versionKey, version);
}
},
visitor: {
Class(path, state) {
if (this.file.get(versionKey) !== version) return;
(0, _features.verifyUsedFeatures)(path, this.file);
const loose = (0, _features.isLoose)(this.file, feature);
let constructor;
let isDecorated = (0, _decorators.hasOwnDecorators)(path.node);
const props = [];
const elements = [];
const computedPaths = [];
const privateNames = new Set();
const body = path.get("body");
for (const path of body.get("body")) {
(0, _features.verifyUsedFeatures)(path, this.file);
if (path.node.computed) {
computedPaths.push(path);
}
if (path.isPrivate()) {
const {
name
} = path.node.key.id;
const getName = `get ${name}`;
const setName = `set ${name}`;
if (path.node.kind === "get") {
if (privateNames.has(getName) || privateNames.has(name) && !privateNames.has(setName)) {
throw path.buildCodeFrameError("Duplicate private field");
}
privateNames.add(getName).add(name);
} else if (path.node.kind === "set") {
if (privateNames.has(setName) || privateNames.has(name) && !privateNames.has(getName)) {
throw path.buildCodeFrameError("Duplicate private field");
}
privateNames.add(setName).add(name);
} else {
if (privateNames.has(name) && !privateNames.has(getName) && !privateNames.has(setName) || privateNames.has(name) && (privateNames.has(getName) || privateNames.has(setName))) {
throw path.buildCodeFrameError("Duplicate private field");
}
privateNames.add(name);
}
}
if (path.isClassMethod({
kind: "constructor"
})) {
constructor = path;
} else {
elements.push(path);
if (path.isProperty() || path.isPrivate()) {
props.push(path);
}
}
if (!isDecorated) isDecorated = (0, _decorators.hasOwnDecorators)(path.node);
}
if (!props.length && !isDecorated) return;
let ref;
if (path.isClassExpression() || !path.node.id) {
(0, _helperFunctionName().default)(path);
ref = path.scope.generateUidIdentifier("class");
} else {
ref = path.node.id;
}
const privateNamesMap = (0, _fields.buildPrivateNamesMap)(props);
const privateNamesNodes = (0, _fields.buildPrivateNamesNodes)(privateNamesMap, loose, state);
(0, _fields.transformPrivateNamesUsage)(ref, path, privateNamesMap, loose, state);
let keysNodes, staticNodes, instanceNodes, wrapClass;
if (isDecorated) {
staticNodes = keysNodes = [];
({
instanceNodes,
wrapClass
} = (0, _decorators.buildDecoratedClass)(ref, path, elements, this.file));
} else {
keysNodes = (0, _misc.extractComputedKeys)(ref, path, computedPaths, this.file);
({
staticNodes,
instanceNodes,
wrapClass
} = (0, _fields.buildFieldsInitNodes)(ref, path.node.superClass, props, privateNamesMap, state, loose));
}
if (instanceNodes.length > 0) {
(0, _misc.injectInitialization)(path, constructor, instanceNodes, (referenceVisitor, state) => {
if (isDecorated) return;
for (const prop of props) {
if (prop.node.static) continue;
prop.traverse(referenceVisitor, state);
}
});
}
path = wrapClass(path);
path.insertBefore(keysNodes);
path.insertAfter([...privateNamesNodes, ...staticNodes]);
},
PrivateName(path) {
if (this.file.get(versionKey) !== version) return;
throw path.buildCodeFrameError(`Unknown PrivateName "${path}"`);
},
ExportDefaultDeclaration(path) {
if (this.file.get(versionKey) !== version) return;
const decl = path.get("declaration");
if (decl.isClassDeclaration() && (0, _decorators.hasDecorators)(decl.node)) {
if (decl.node.id) {
(0, _helperSplitExportDeclaration().default)(path);
} else {
decl.node.type = "ClassExpression";
}
}
}
}
};
}

View File

@ -0,0 +1,128 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.injectInitialization = injectInitialization;
exports.extractComputedKeys = extractComputedKeys;
function _core() {
const data = require("@babel/core");
_core = function () {
return data;
};
return data;
}
function _helperReplaceSupers() {
const data = require("@babel/helper-replace-supers");
_helperReplaceSupers = function () {
return data;
};
return data;
}
const findBareSupers = _core().traverse.visitors.merge([{
Super(path) {
const {
node,
parentPath
} = path;
if (parentPath.isCallExpression({
callee: node
})) {
this.push(parentPath);
}
}
}, _helperReplaceSupers().environmentVisitor]);
const referenceVisitor = {
"TSTypeAnnotation|TypeAnnotation"(path) {
path.skip();
},
ReferencedIdentifier(path) {
if (this.scope.hasOwnBinding(path.node.name)) {
this.scope.rename(path.node.name);
path.skip();
}
}
};
const classFieldDefinitionEvaluationTDZVisitor = _core().traverse.visitors.merge([{
ReferencedIdentifier(path) {
if (this.classBinding && this.classBinding === path.scope.getBinding(path.node.name)) {
const classNameTDZError = this.file.addHelper("classNameTDZError");
const throwNode = _core().types.callExpression(classNameTDZError, [_core().types.stringLiteral(path.node.name)]);
path.replaceWith(_core().types.sequenceExpression([throwNode, path.node]));
path.skip();
}
}
}, _helperReplaceSupers().environmentVisitor]);
function injectInitialization(path, constructor, nodes, renamer) {
if (!nodes.length) return;
const isDerived = !!path.node.superClass;
if (!constructor) {
const newConstructor = _core().types.classMethod("constructor", _core().types.identifier("constructor"), [], _core().types.blockStatement([]));
if (isDerived) {
newConstructor.params = [_core().types.restElement(_core().types.identifier("args"))];
newConstructor.body.body.push(_core().template.statement.ast`super(...args)`);
}
[constructor] = path.get("body").unshiftContainer("body", newConstructor);
}
if (renamer) {
renamer(referenceVisitor, {
scope: constructor.scope
});
}
if (isDerived) {
const bareSupers = [];
constructor.traverse(findBareSupers, bareSupers);
for (const bareSuper of bareSupers) {
bareSuper.insertAfter(nodes);
}
} else {
constructor.get("body").unshiftContainer("body", nodes);
}
}
function extractComputedKeys(ref, path, computedPaths, file) {
const declarations = [];
for (const computedPath of computedPaths) {
computedPath.traverse(classFieldDefinitionEvaluationTDZVisitor, {
classBinding: path.node.id && path.scope.getBinding(path.node.id.name),
file
});
const computedNode = computedPath.node;
if (!computedPath.get("key").isConstantExpression()) {
const ident = path.scope.generateUidIdentifierBasedOnNode(computedNode.key);
path.scope.push({
id: ident,
kind: "let"
});
declarations.push(_core().types.expressionStatement(_core().types.assignmentExpression("=", _core().types.cloneNode(ident), computedNode.key)));
computedNode.key = _core().types.cloneNode(ident);
}
}
return declarations;
}

View File

@ -0,0 +1,64 @@
{
"_from": "@babel/helper-create-class-features-plugin@^7.5.5",
"_id": "@babel/helper-create-class-features-plugin@7.5.5",
"_inBundle": false,
"_integrity": "sha512-ZsxkyYiRA7Bg+ZTRpPvB6AbOFKTFFK4LrvTet8lInm0V468MWCaSYJE+I7v2z2r8KNLtYiV+K5kTCnR7dvyZjg==",
"_location": "/@babel/helper-create-class-features-plugin",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "@babel/helper-create-class-features-plugin@^7.5.5",
"name": "@babel/helper-create-class-features-plugin",
"escapedName": "@babel%2fhelper-create-class-features-plugin",
"scope": "@babel",
"rawSpec": "^7.5.5",
"saveSpec": null,
"fetchSpec": "^7.5.5"
},
"_requiredBy": [
"/@babel/plugin-proposal-class-properties"
],
"_resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.5.tgz",
"_shasum": "401f302c8ddbc0edd36f7c6b2887d8fa1122e5a4",
"_spec": "@babel/helper-create-class-features-plugin@^7.5.5",
"_where": "/Users/stefanfejes/Projects/30-seconds-of-python-code/node_modules/@babel/plugin-proposal-class-properties",
"author": {
"name": "The Babel Team",
"url": "https://babeljs.io/team"
},
"bundleDependencies": false,
"dependencies": {
"@babel/helper-function-name": "^7.1.0",
"@babel/helper-member-expression-to-functions": "^7.5.5",
"@babel/helper-optimise-call-expression": "^7.0.0",
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/helper-replace-supers": "^7.5.5",
"@babel/helper-split-export-declaration": "^7.4.4"
},
"deprecated": false,
"description": "Compile class public and private fields, private methods and decorators to ES6",
"devDependencies": {
"@babel/core": "^7.5.5",
"@babel/helper-plugin-test-runner": "^7.0.0"
},
"gitHead": "0407f034f09381b95e9cabefbf6b176c76485a43",
"keywords": [
"babel",
"babel-plugin"
],
"license": "MIT",
"main": "lib/index.js",
"name": "@babel/helper-create-class-features-plugin",
"peerDependencies": {
"@babel/core": "^7.0.0"
},
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/babel/babel/tree/master/packages/babel-helper-create-class-features-plugin"
},
"version": "7.5.5"
}