shift73k/assets_old/node_modules/@babel/preset-modules/lib/plugins/transform-tagged-template-caching/index.js

75 lines
No EOL
3.1 KiB
JavaScript

"use strict";
exports.__esModule = true;
exports.default = void 0;
/**
* Converts destructured parameters with default values to non-shorthand syntax.
* This fixes the only Tagged Templates-related bug in ES Modules-supporting browsers (Safari 10 & 11).
* Use this plugin instead of `@babel/plugin-transform-template-literals` when targeting ES Modules.
*
* @example
* // Bug 1: Safari 10/11 doesn't reliably return the same Strings value.
* // The value changes depending on invocation and function optimization state.
* function f() { return Object`` }
* f() === new f() // false, should be true.
*
* @example
* // Bug 2: Safari 10/11 use the same cached strings value when the string parts are the same.
* // This behavior comes from an earlier version of the spec, and can cause tricky bugs.
* Object``===Object`` // true, should be false.
*
* Benchmarks: https://jsperf.com/compiled-tagged-template-performance
*/
var _default = ({
types: t
}) => ({
name: "transform-tagged-template-caching",
visitor: {
TaggedTemplateExpression(path, state) {
// tagged templates we've already dealt with
let processed = state.get("processed");
if (!processed) {
processed = new Map();
state.set("processed", processed);
}
if (processed.has(path.node)) return path.skip(); // Grab the expressions from the original tag.
// tag`a${'hello'}` // ['hello']
const expressions = path.node.quasi.expressions; // Create an identity function helper:
// identity = t => t
let identity = state.get("identity");
if (!identity) {
identity = path.scope.getProgramParent().generateDeclaredUidIdentifier("_");
state.set("identity", identity);
const binding = path.scope.getBinding(identity.name);
binding.path.get("init").replaceWith(t.arrowFunctionExpression( // re-use the helper identifier for compressability
[t.identifier("t")], t.identifier("t")));
} // Use the identity function helper to get a reference to the template's Strings.
// We replace all expressions with `0` ensure Strings has the same shape.
// identity`a${0}`
const template = t.taggedTemplateExpression(identity, t.templateLiteral(path.node.quasi.quasis, expressions.map(() => t.numericLiteral(0))));
processed.set(template, true); // Install an inline cache at the callsite using the global variable:
// _t || (_t = identity`a${0}`)
const ident = path.scope.getProgramParent().generateDeclaredUidIdentifier("t");
path.scope.getBinding(ident.name).path.parent.kind = "let";
const inlineCache = t.logicalExpression("||", ident, t.assignmentExpression("=", ident, template)); // The original tag function becomes a plain function call.
// The expressions omitted from the cached Strings tag are directly applied as arguments.
// tag(_t || (_t = Object`a${0}`), 'hello')
const node = t.callExpression(path.node.tag, [inlineCache, ...expressions]);
path.replaceWith(node);
}
}
});
exports.default = _default;
module.exports = exports.default;