Files
Fluxup_PAP/node_modules/babel-preset-expo/build/define-plugin.js
2026-03-10 16:18:05 +00:00

136 lines
5.7 KiB
JavaScript

"use strict";
/**
* Copyright © 2024 650 Industries.
* Copyright (c) 2016 Formidable
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const TYPEOF_PREFIX = 'typeof ';
function definePlugin({ types: t, }) {
/**
* Replace a node with a given value. If the replacement results in a BinaryExpression, it will be
* evaluated. For example, if the result of the replacement is `var x = "production" === "production"`
* The evaluation will make a second replacement resulting in `var x = true`
*/
function replaceAndEvaluateNode(nodePath, replacement) {
nodePath.replaceWith(t.valueToNode(replacement));
if (nodePath.parentPath?.isBinaryExpression()) {
const result = nodePath.parentPath.evaluate();
if (result.confident) {
nodePath.parentPath.replaceWith(t.valueToNode(result.value));
}
}
}
/** Get the root identifier name from a member expression (e.g., "process" from "process.env.NODE_ENV") */
function getMemberExpressionRoot(node) {
let current = node;
while (t.isMemberExpression(current)) {
current = current.object;
}
return t.isIdentifier(current) ? current.name : null;
}
return {
name: 'expo-define-globals',
pre() {
// Pre-process replacements once per file
const identifiers = new Map();
const memberPatterns = [];
const typeofValues = new Map();
const memberRoots = new Set();
for (const key of Object.keys(this.opts)) {
const value = this.opts[key];
if (key.startsWith(TYPEOF_PREFIX)) {
// "typeof window" -> typeofValues["window"]
typeofValues.set(key.slice(TYPEOF_PREFIX.length), value);
}
else if (key.includes('.')) {
// "process.env.NODE_ENV" -> memberPatterns, extract "process" as root
memberPatterns.push([key, value]);
const root = key.split('.')[0];
memberRoots.add(root);
}
else {
// "__DEV__" -> identifiers
identifiers.set(key, value);
}
}
this.processed = {
identifiers,
memberPatterns,
typeofValues,
memberRoots,
};
},
visitor: {
// process.env.NODE_ENV;
MemberExpression(nodePath, state) {
// Prevent rewriting if the member expression is on the left-hand side of an assignment
if (t.isAssignmentExpression(nodePath.parent) && nodePath.parent.left === nodePath.node) {
return;
}
const { memberPatterns, memberRoots } = state.processed;
if (memberPatterns.length === 0)
return;
// Quick filter: check if root matches any known pattern root
const root = getMemberExpressionRoot(nodePath.node);
if (!root || !memberRoots.has(root))
return;
// Check against patterns
for (const [pattern, replacement] of memberPatterns) {
if (nodePath.matchesPattern(pattern)) {
replaceAndEvaluateNode(nodePath, replacement);
return;
}
}
},
// const x = { version: VERSION };
ReferencedIdentifier(nodePath, state) {
const { identifiers } = state.processed;
if (identifiers.size === 0)
return;
const name = nodePath.node.name;
// Quick check: is this identifier in our replacements?
if (!identifiers.has(name))
return;
// Check for binding (locally defined variable shadows replacement)
if (nodePath.scope?.getBinding(name))
return;
// Don't transform import identifiers (mimics webpack's DefinePlugin behavior)
const container = nodePath.container;
if (container &&
!Array.isArray(container) &&
'type' in container &&
(container.type === 'ImportDefaultSpecifier' || container.type === 'ImportSpecifier')) {
return;
}
// Do not transform Object keys / properties unless they are computed like {[key]: value}
if ((nodePath.key === 'key' || nodePath.key === 'property') &&
nodePath.parent &&
'computed' in nodePath.parent &&
nodePath.parent.computed === false) {
return;
}
replaceAndEvaluateNode(nodePath, identifiers.get(name));
},
// typeof window
UnaryExpression(nodePath, state) {
if (nodePath.node.operator !== 'typeof')
return;
const { typeofValues } = state.processed;
if (typeofValues.size === 0)
return;
const argument = nodePath.node.argument;
if (!t.isIdentifier(argument))
return;
const replacement = typeofValues.get(argument.name);
if (replacement !== undefined) {
replaceAndEvaluateNode(nodePath, replacement);
}
},
},
};
}
exports.default = definePlugin;