This commit is contained in:
Yamozha
2021-04-02 02:24:13 +03:00
parent c23950b545
commit 7256d79e2c
31493 changed files with 3036630 additions and 0 deletions

View File

@ -0,0 +1,56 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const MODULES = [
// Local Promise implementation.
'Promise',
];
/**
* Automatically imports a module if its identifier is in the AST.
*/
module.exports = function autoImporter(babel) {
const t = babel.types;
function isAppropriateModule(name, scope, state) {
const autoImported = state.autoImported;
return MODULES.indexOf(name) !== -1
&& !autoImported.hasOwnProperty(name)
&& !scope.hasBinding(name, /*skip globals*/true);
}
return {
pre: function() {
// Cache per file to avoid calling `scope.hasBinding` several
// times for the same module, which has already been auto-imported.
this.autoImported = {};
},
visitor: {
ReferencedIdentifier: function(path) {
const node = path.node;
const scope = path.scope;
if (!isAppropriateModule(node.name, scope, this)) {
return;
}
scope.getProgramParent().push({
id: t.identifier(node.name),
init: t.callExpression(
t.identifier('require'),
[t.stringLiteral(node.name)]
),
});
this.autoImported[node.name] = true;
},
},
};
};

View File

@ -0,0 +1,45 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
module.exports = function(babel) {
const t = babel.types;
// We can't construct an identifier with a type annotation all in 1 fell swoop
// so we have to create & mutate, then pass along.
const DEV_IDENTIFIER = t.identifier('__DEV__');
DEV_IDENTIFIER.typeAnnotation = t.typeAnnotation(t.booleanTypeAnnotation());
const DEV_DECLARATION = t.declareVariable(
DEV_IDENTIFIER
);
return {
pre() {
this.usesDEV = false;
},
visitor: {
Identifier: {
enter(path, file) {
this.usesDEV = this.usesDEV || path.isIdentifier({name: '__DEV__'});
},
},
Program: {
exit(path, file) {
if (!this.usesDEV) {
return;
}
// Add the declaration at the front of the body if we've used __DEV__.
path.node.body.unshift(DEV_DECLARATION);
},
},
},
};
};

View File

@ -0,0 +1,129 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
module.exports = function(babel) {
var t = babel.types;
var SEEN_SYMBOL = Symbol();
var DEV_EXPRESSION = t.binaryExpression(
'!==',
t.memberExpression(
t.memberExpression(
t.identifier('process'),
t.identifier('env'),
false
),
t.identifier('NODE_ENV'),
false
),
t.stringLiteral('production')
);
return {
visitor: {
Identifier: {
enter: function(path) {
// Do nothing when testing
if (process.env.NODE_ENV === 'test') {
return;
}
// replace __DEV__ with process.env.NODE_ENV !== 'production'
if (path.isIdentifier({name: '__DEV__'})) {
path.replaceWith(DEV_EXPRESSION);
}
},
},
CallExpression: {
exit: function(path) {
var node = path.node;
// Do nothing when testing
if (process.env.NODE_ENV === 'test') {
return;
}
// Ignore if it's already been processed
if (node[SEEN_SYMBOL]) {
return;
}
if (path.get('callee').isIdentifier({name: 'invariant'})) {
// Turns this code:
//
// invariant(condition, argument, argument);
//
// into this:
//
// if (!condition) {
// if ("production" !== process.env.NODE_ENV) {
// invariant(false, argument, argument);
// } else {
// invariant(false);
// }
// }
//
// Specifically this does 2 things:
// 1. Checks the condition first, preventing an extra function call.
// 2. Adds an environment check so that verbose error messages aren't
// shipped to production.
// The generated code is longer than the original code but will dead
// code removal in a minifier will strip that out.
var condition = node.arguments[0];
var devInvariant = t.callExpression(
node.callee,
[t.booleanLiteral(false)].concat(node.arguments.slice(1))
);
devInvariant[SEEN_SYMBOL] = true;
var prodInvariant = t.callExpression(
node.callee,
[t.booleanLiteral(false)]
);
prodInvariant[SEEN_SYMBOL] = true;
path.replaceWith(t.ifStatement(
t.unaryExpression('!', condition),
t.blockStatement([
t.ifStatement(
DEV_EXPRESSION,
t.blockStatement([
t.expressionStatement(devInvariant),
]),
t.blockStatement([
t.expressionStatement(prodInvariant),
])
),
])
));
} else if (path.get('callee').isIdentifier({name: 'warning'})) {
// Turns this code:
//
// warning(condition, argument, argument);
//
// into this:
//
// if ("production" !== process.env.NODE_ENV) {
// warning(condition, argument, argument);
// }
//
// The goal is to strip out warning calls entirely in production. We
// don't need the same optimizations for conditions that we use for
// invariant because we don't care about an extra call in __DEV__
node[SEEN_SYMBOL] = true;
path.replaceWith(t.ifStatement(
DEV_EXPRESSION,
t.blockStatement([
t.expressionStatement(
node
),
])
));
}
},
},
},
};
};

View File

@ -0,0 +1,241 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
'use strict';
/**
* This transform inlines top-level require(...) aliases with to enable lazy
* loading of dependencies. It is able to inline both single references and
* child property references.
*
* For instance:
* var Foo = require('foo');
* f(Foo);
*
* Will be transformed into:
* f(require('foo'));
*
* When the assigment expression has a property access, it will be inlined too,
* keeping the property. For instance:
* var Bar = require('foo').bar;
* g(Bar);
*
* Will be transformed into:
* g(require('foo').bar);
*
* Destructuring also works the same way. For instance:
* const {Baz} = require('foo');
* h(Baz);
*
* Is also successfully inlined into:
* g(require('foo').Baz);
*/
module.exports = babel => ({
name: 'inline-requires',
visitor: {
Program: {
exit(path, state) {
const ignoredRequires = new Set();
const inlineableCalls = new Set(['require']);
if (state.opts != null) {
if (state.opts.ignoredRequires != null) {
for (const name of state.opts.ignoredRequires) {
ignoredRequires.add(name);
}
}
if (state.opts.inlineableCalls != null) {
for (const name of state.opts.inlineableCalls) {
inlineableCalls.add(name);
}
}
}
path.scope.crawl();
path.traverse(
{
CallExpression(path, state) {
const parseResult =
parseInlineableAlias(path, state) ||
parseInlineableMemberAlias(path, state);
if (parseResult == null) {
return;
}
const {declarationPath, moduleName} = parseResult;
const init = declarationPath.node.init;
const name = declarationPath.node.id
? declarationPath.node.id.name
: null;
const binding = declarationPath.scope.getBinding(name);
if (binding.constantViolations.length > 0) {
return;
}
deleteLocation(init);
babel.traverse(init, {
noScope: true,
enter: path => deleteLocation(path.node),
});
let thrown = false;
for (const referencePath of binding.referencePaths) {
excludeMemberAssignment(moduleName, referencePath, state);
try {
referencePath.replaceWith(init);
} catch (error) {
thrown = true;
}
}
// If a replacement failed (e.g. replacing a type annotation),
// avoid removing the initial require just to be safe.
if (!thrown) {
declarationPath.remove();
}
},
},
{
ignoredRequires,
inlineableCalls,
membersAssigned: new Map(),
},
);
},
},
},
});
function excludeMemberAssignment(moduleName, referencePath, state) {
const assignment = referencePath.parentPath.parent;
const isValid =
assignment.type === 'AssignmentExpression' &&
assignment.left.type === 'MemberExpression' &&
assignment.left.object === referencePath.node;
if (!isValid) {
return;
}
const memberPropertyName = getMemberPropertyName(assignment.left);
if (memberPropertyName == null) {
return;
}
let membersAssigned = state.membersAssigned.get(moduleName);
if (membersAssigned == null) {
membersAssigned = new Set();
state.membersAssigned.set(moduleName, membersAssigned);
}
membersAssigned.add(memberPropertyName);
}
function isExcludedMemberAssignment(moduleName, memberPropertyName, state) {
const excludedAliases = state.membersAssigned.get(moduleName);
return excludedAliases != null && excludedAliases.has(memberPropertyName);
}
function getMemberPropertyName(node) {
if (node.type !== 'MemberExpression') {
return null;
}
if (node.property.type === 'Identifier') {
return node.property.name;
}
if (node.property.type === 'StringLiteral') {
return node.property.value;
}
return null;
}
function deleteLocation(node) {
delete node.start;
delete node.end;
delete node.loc;
}
function parseInlineableAlias(path, state) {
const moduleName = getInlineableModule(path.node, state);
const isValid =
moduleName != null &&
path.parent.type === 'VariableDeclarator' &&
path.parent.id.type === 'Identifier' &&
path.parentPath.parent.type === 'VariableDeclaration' &&
path.parentPath.parentPath.parent.type === 'Program';
return !isValid || path.parentPath.node == null
? null
: {
declarationPath: path.parentPath,
moduleName,
};
}
function parseInlineableMemberAlias(path, state) {
const moduleName = getInlineableModule(path.node, state);
const isValid =
moduleName != null &&
path.parent.type === 'MemberExpression' &&
path.parentPath.parent.type === 'VariableDeclarator' &&
path.parentPath.parent.id.type === 'Identifier' &&
path.parentPath.parentPath.parent.type === 'VariableDeclaration' &&
path.parentPath.parentPath.parentPath.parent.type === 'Program';
const memberPropertyName = getMemberPropertyName(path.parent);
return !isValid ||
path.parentPath.parentPath.node == null ||
isExcludedMemberAssignment(moduleName, memberPropertyName, state)
? null
: {
declarationPath: path.parentPath.parentPath,
moduleName,
};
}
function getInlineableModule(node, state) {
const isInlineable =
node.type === 'CallExpression' &&
node.callee.type === 'Identifier' &&
state.inlineableCalls.has(node.callee.name) &&
node['arguments'].length >= 1;
if (!isInlineable) {
return null;
}
// require('foo');
let moduleName =
node['arguments'][0].type === 'StringLiteral'
? node['arguments'][0].value
: null;
// require(require.resolve('foo'));
if (moduleName == null) {
moduleName =
node['arguments'][0].type === 'CallExpression' &&
node['arguments'][0].callee.type === 'MemberExpression' &&
node['arguments'][0].callee.object.type === 'Identifier' &&
state.inlineableCalls.has(node['arguments'][0].callee.object.name) &&
node['arguments'][0].callee.property.type === 'Identifier' &&
node['arguments'][0].callee.property.name === 'resolve' &&
node['arguments'][0]['arguments'].length >= 1 &&
node['arguments'][0]['arguments'][0].type === 'StringLiteral'
? node['arguments'][0]['arguments'][0].value
: null;
}
return moduleName == null || state.ignoredRequires.has(moduleName)
? null
: moduleName;
}

View File

@ -0,0 +1,50 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
module.exports = function autoImporter(babel) {
const t = babel.types;
function getAssignIdent(path, file, state) {
if (!state.id) {
state.id = path.scope.generateUidIdentifier('assign');
path.scope.getProgramParent().push({
id: state.id,
init: t.callExpression(
t.identifier('require'),
[t.stringLiteral('object-assign')]
),
});
}
return state.id;
}
return {
pre: function() {
// map from module to generated identifier
this.id = null;
},
visitor: {
CallExpression: function(path, file) {
if (path.get('callee').matchesPattern('Object.assign')) {
// generate identifier and require if it hasn't been already
var id = getAssignIdent(path, file, this);
path.node.callee = id;
}
},
MemberExpression: function(path, file) {
if (path.matchesPattern('Object.assign')) {
var id = getAssignIdent(path, file, this);
path.replaceWith(id);
}
},
},
};
};

View File

@ -0,0 +1,150 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
/**
* Rewrites module string literals according to the `map` and `prefix` options.
* This allows other npm packages to be published and used directly without
* being a part of the same build.
*/
function mapModule(state, module) {
var moduleMap = state.opts.map || {};
if (moduleMap.hasOwnProperty(module)) {
return moduleMap[module];
}
// Jest understands the haste module system, so leave modules intact.
if (process.env.NODE_ENV !== 'test') {
var modulePrefix = state.opts.prefix;
if (modulePrefix == null) {
modulePrefix = './';
}
return modulePrefix + module;
}
return null;
}
var jestMethods = [
'dontMock',
'genMockFromModule',
'mock',
'setMock',
'unmock',
];
function isJestProperty(t, property) {
return t.isIdentifier(property) && jestMethods.indexOf(property.name) !== -1;
}
module.exports = function(babel) {
var t = babel.types;
/**
* Transforms `require('Foo')` and `require.requireActual('Foo')`.
*/
function transformRequireCall(path, state) {
var calleePath = path.get('callee');
if (
!t.isIdentifier(calleePath.node, {name: 'require'}) &&
!(
t.isMemberExpression(calleePath.node) &&
t.isIdentifier(calleePath.node.object, {name: 'require'}) &&
t.isIdentifier(calleePath.node.property, {name: 'requireActual'})
)
) {
return;
}
var args = path.get('arguments');
if (!args.length) {
return;
}
var moduleArg = args[0];
if (moduleArg.node.type === 'StringLiteral') {
var module = mapModule(state, moduleArg.node.value);
if (module) {
moduleArg.replaceWith(t.stringLiteral(module));
}
}
}
/**
* Transforms `import type Bar from 'foo'`
*/
function transformTypeImport(path, state) {
var source = path.get('source');
if (source.type === 'StringLiteral') {
var module = mapModule(state, source.node.value);
if (module) {
source.replaceWith(t.stringLiteral(module));
}
}
}
/**
* Transforms either individual or chained calls to `jest.dontMock('Foo')`,
* `jest.mock('Foo')`, and `jest.genMockFromModule('Foo')`.
*/
function transformJestHelper(path, state) {
var calleePath = path.get('callee');
var args = path.get('arguments');
if (!args.length) {
return;
}
var moduleArg = args[0];
if (
moduleArg.node.type === 'StringLiteral' &&
calleePath.node &&
isJestProperty(t, calleePath.node.property)
) {
var module = mapModule(state, moduleArg.node.value);
if (module) {
moduleArg.replaceWith(t.stringLiteral(module));
}
}
}
const jestIdentifier = {
Identifier(path) {
if (path.node.name === 'jest') {
this.isJest = true;
}
},
};
function transformJestCall(path, state) {
let params = {isJest: false};
path.traverse(jestIdentifier, params);
if (params.isJest) {
transformJestHelper(path, state);
}
}
return {
visitor: {
CallExpression: {
exit(path, state) {
if (path.node.seen) {
return;
}
transformRequireCall(path, state);
transformJestCall(path, state);
path.node.seen = true;
},
},
ImportDeclaration: {
exit(path, state) {
let importKind = path.node.importKind;
if (importKind === 'type' || importKind === 'typeof') {
transformTypeImport(path, state);
}
}
}
},
};
};