| [9af201e] | 1 | "use strict";
|
|---|
| 2 |
|
|---|
| 3 | exports.__esModule = true;
|
|---|
| 4 | exports.PossibleGlobalObjects = void 0;
|
|---|
| 5 | exports.createUtilsGetter = createUtilsGetter;
|
|---|
| 6 | exports.getImportSource = getImportSource;
|
|---|
| 7 | exports.getRequireSource = getRequireSource;
|
|---|
| 8 | exports.has = has;
|
|---|
| 9 | exports.intersection = intersection;
|
|---|
| 10 | exports.resolveKey = resolveKey;
|
|---|
| 11 | exports.resolveSource = resolveSource;
|
|---|
| 12 | var _babel = _interopRequireWildcard(require("@babel/core"));
|
|---|
| 13 | function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|---|
| 14 | const {
|
|---|
| 15 | types: t,
|
|---|
| 16 | template: template
|
|---|
| 17 | } = _babel.default || _babel;
|
|---|
| 18 | const PossibleGlobalObjects = exports.PossibleGlobalObjects = new Set(["global", "globalThis", "self", "window"]);
|
|---|
| 19 | function intersection(a, b) {
|
|---|
| 20 | const result = new Set();
|
|---|
| 21 | a.forEach(v => b.has(v) && result.add(v));
|
|---|
| 22 | return result;
|
|---|
| 23 | }
|
|---|
| 24 | function has(object, key) {
|
|---|
| 25 | return Object.prototype.hasOwnProperty.call(object, key);
|
|---|
| 26 | }
|
|---|
| 27 | function resolve(path, seen = new Set()) {
|
|---|
| 28 | if (seen.has(path)) return;
|
|---|
| 29 | seen.add(path);
|
|---|
| 30 | if (path.isVariableDeclarator()) {
|
|---|
| 31 | if (path.get("id").isIdentifier()) {
|
|---|
| 32 | return resolve(path.get("init"), seen);
|
|---|
| 33 | }
|
|---|
| 34 | } else if (path.isReferencedIdentifier()) {
|
|---|
| 35 | const binding = path.scope.getBinding(path.node.name);
|
|---|
| 36 | if (!binding) return path;
|
|---|
| 37 | if (!binding.constant) return;
|
|---|
| 38 | return resolve(binding.path, seen);
|
|---|
| 39 | }
|
|---|
| 40 | return path;
|
|---|
| 41 | }
|
|---|
| 42 | function resolveId(path) {
|
|---|
| 43 | if (path.isIdentifier() && !path.scope.hasBinding(path.node.name, /* noGlobals */true)) {
|
|---|
| 44 | return path.node.name;
|
|---|
| 45 | }
|
|---|
| 46 |
|
|---|
| 47 | // globalThis.Object / window.Array / self.Map / global.Set -> resolve to
|
|---|
| 48 | // the property name, because accessing a built-in through a global object
|
|---|
| 49 | // reference is equivalent to accessing it directly.
|
|---|
| 50 | if (path.isMemberExpression() && !path.node.computed) {
|
|---|
| 51 | const object = path.get("object");
|
|---|
| 52 | const property = path.get("property");
|
|---|
| 53 | if (object.isIdentifier() && !object.scope.hasBinding(object.node.name, /* noGlobals */true) && PossibleGlobalObjects.has(object.node.name) && property.isIdentifier()) {
|
|---|
| 54 | return property.node.name;
|
|---|
| 55 | }
|
|---|
| 56 | }
|
|---|
| 57 | const resolved = resolve(path);
|
|---|
| 58 | if (resolved != null && resolved.isIdentifier()) {
|
|---|
| 59 | return resolved.node.name;
|
|---|
| 60 | }
|
|---|
| 61 | }
|
|---|
| 62 | function resolveKey(path, computed = false) {
|
|---|
| 63 | const {
|
|---|
| 64 | scope
|
|---|
| 65 | } = path;
|
|---|
| 66 | if (path.isStringLiteral()) return path.node.value;
|
|---|
| 67 | const isIdentifier = path.isIdentifier();
|
|---|
| 68 | if (isIdentifier && !(computed || path.parent.computed)) {
|
|---|
| 69 | return path.node.name;
|
|---|
| 70 | }
|
|---|
| 71 | if (computed && path.isMemberExpression() && path.get("object").isIdentifier({
|
|---|
| 72 | name: "Symbol"
|
|---|
| 73 | }) && !scope.hasBinding("Symbol", /* noGlobals */true)) {
|
|---|
| 74 | const sym = resolveKey(path.get("property"), path.node.computed);
|
|---|
| 75 | if (sym) return "Symbol." + sym;
|
|---|
| 76 | }
|
|---|
| 77 | if (isIdentifier ? scope.hasBinding(path.node.name, /* noGlobals */true) : path.isPure()) {
|
|---|
| 78 | const {
|
|---|
| 79 | value
|
|---|
| 80 | } = path.evaluate();
|
|---|
| 81 | if (typeof value === "string") return value;
|
|---|
| 82 | }
|
|---|
| 83 | }
|
|---|
| 84 | function resolveInstance(obj, seen) {
|
|---|
| 85 | const source = resolveSource(obj, seen);
|
|---|
| 86 | return source.placement === "prototype" ? source.id : null;
|
|---|
| 87 | }
|
|---|
| 88 | function resolveSource(obj, seen) {
|
|---|
| 89 | if (seen.has(obj)) {
|
|---|
| 90 | return {
|
|---|
| 91 | id: null,
|
|---|
| 92 | placement: null
|
|---|
| 93 | };
|
|---|
| 94 | }
|
|---|
| 95 | seen.add(obj);
|
|---|
| 96 | if (obj.isMemberExpression() && obj.get("property").isIdentifier({
|
|---|
| 97 | name: "prototype"
|
|---|
| 98 | })) {
|
|---|
| 99 | const id = resolveId(obj.get("object"));
|
|---|
| 100 | if (id) {
|
|---|
| 101 | return {
|
|---|
| 102 | id,
|
|---|
| 103 | placement: "prototype"
|
|---|
| 104 | };
|
|---|
| 105 | }
|
|---|
| 106 | return {
|
|---|
| 107 | id: null,
|
|---|
| 108 | placement: null
|
|---|
| 109 | };
|
|---|
| 110 | }
|
|---|
| 111 | const id = resolveId(obj);
|
|---|
| 112 | if (id) {
|
|---|
| 113 | return {
|
|---|
| 114 | id,
|
|---|
| 115 | placement: "static"
|
|---|
| 116 | };
|
|---|
| 117 | }
|
|---|
| 118 | const path = resolve(obj);
|
|---|
| 119 | switch (path == null ? void 0 : path.type) {
|
|---|
| 120 | case "NullLiteral":
|
|---|
| 121 | return {
|
|---|
| 122 | id: null,
|
|---|
| 123 | placement: null
|
|---|
| 124 | };
|
|---|
| 125 | case "RegExpLiteral":
|
|---|
| 126 | return {
|
|---|
| 127 | id: "RegExp",
|
|---|
| 128 | placement: "prototype"
|
|---|
| 129 | };
|
|---|
| 130 | case "StringLiteral":
|
|---|
| 131 | case "TemplateLiteral":
|
|---|
| 132 | return {
|
|---|
| 133 | id: "String",
|
|---|
| 134 | placement: "prototype"
|
|---|
| 135 | };
|
|---|
| 136 | case "NumericLiteral":
|
|---|
| 137 | return {
|
|---|
| 138 | id: "Number",
|
|---|
| 139 | placement: "prototype"
|
|---|
| 140 | };
|
|---|
| 141 | case "BooleanLiteral":
|
|---|
| 142 | return {
|
|---|
| 143 | id: "Boolean",
|
|---|
| 144 | placement: "prototype"
|
|---|
| 145 | };
|
|---|
| 146 | case "BigIntLiteral":
|
|---|
| 147 | return {
|
|---|
| 148 | id: "BigInt",
|
|---|
| 149 | placement: "prototype"
|
|---|
| 150 | };
|
|---|
| 151 | case "ObjectExpression":
|
|---|
| 152 | return {
|
|---|
| 153 | id: "Object",
|
|---|
| 154 | placement: "prototype"
|
|---|
| 155 | };
|
|---|
| 156 | case "ArrayExpression":
|
|---|
| 157 | return {
|
|---|
| 158 | id: "Array",
|
|---|
| 159 | placement: "prototype"
|
|---|
| 160 | };
|
|---|
| 161 | case "FunctionExpression":
|
|---|
| 162 | case "ArrowFunctionExpression":
|
|---|
| 163 | case "ClassExpression":
|
|---|
| 164 | return {
|
|---|
| 165 | id: "Function",
|
|---|
| 166 | placement: "prototype"
|
|---|
| 167 | };
|
|---|
| 168 | // new Constructor() -> resolve the constructor name
|
|---|
| 169 | case "NewExpression":
|
|---|
| 170 | {
|
|---|
| 171 | const calleeId = resolveId(path.get("callee"));
|
|---|
| 172 | if (calleeId) return {
|
|---|
| 173 | id: calleeId,
|
|---|
| 174 | placement: "prototype"
|
|---|
| 175 | };
|
|---|
| 176 | return {
|
|---|
| 177 | id: null,
|
|---|
| 178 | placement: null
|
|---|
| 179 | };
|
|---|
| 180 | }
|
|---|
| 181 | // Unary expressions -> result type depends on operator
|
|---|
| 182 | case "UnaryExpression":
|
|---|
| 183 | {
|
|---|
| 184 | const {
|
|---|
| 185 | operator
|
|---|
| 186 | } = path.node;
|
|---|
| 187 | if (operator === "typeof") return {
|
|---|
| 188 | id: "String",
|
|---|
| 189 | placement: "prototype"
|
|---|
| 190 | };
|
|---|
| 191 | if (operator === "!" || operator === "delete") return {
|
|---|
| 192 | id: "Boolean",
|
|---|
| 193 | placement: "prototype"
|
|---|
| 194 | };
|
|---|
| 195 | // Unary + always produces Number (throws on BigInt)
|
|---|
| 196 | if (operator === "+") return {
|
|---|
| 197 | id: "Number",
|
|---|
| 198 | placement: "prototype"
|
|---|
| 199 | };
|
|---|
| 200 | // Unary - and ~ can produce Number or BigInt depending on operand
|
|---|
| 201 | if (operator === "-" || operator === "~") {
|
|---|
| 202 | const arg = resolveInstance(path.get("argument"), seen);
|
|---|
| 203 | if (arg === "BigInt") return {
|
|---|
| 204 | id: "BigInt",
|
|---|
| 205 | placement: "prototype"
|
|---|
| 206 | };
|
|---|
| 207 | if (arg !== null) return {
|
|---|
| 208 | id: "Number",
|
|---|
| 209 | placement: "prototype"
|
|---|
| 210 | };
|
|---|
| 211 | return {
|
|---|
| 212 | id: null,
|
|---|
| 213 | placement: null
|
|---|
| 214 | };
|
|---|
| 215 | }
|
|---|
| 216 | return {
|
|---|
| 217 | id: null,
|
|---|
| 218 | placement: null
|
|---|
| 219 | };
|
|---|
| 220 | }
|
|---|
| 221 | // ++i, i++ produce Number or BigInt depending on the argument
|
|---|
| 222 | case "UpdateExpression":
|
|---|
| 223 | {
|
|---|
| 224 | const arg = resolveInstance(path.get("argument"), seen);
|
|---|
| 225 | if (arg === "BigInt") return {
|
|---|
| 226 | id: "BigInt",
|
|---|
| 227 | placement: "prototype"
|
|---|
| 228 | };
|
|---|
| 229 | if (arg !== null) return {
|
|---|
| 230 | id: "Number",
|
|---|
| 231 | placement: "prototype"
|
|---|
| 232 | };
|
|---|
| 233 | return {
|
|---|
| 234 | id: null,
|
|---|
| 235 | placement: null
|
|---|
| 236 | };
|
|---|
| 237 | }
|
|---|
| 238 | // Binary expressions -> result type depends on operator
|
|---|
| 239 | case "BinaryExpression":
|
|---|
| 240 | {
|
|---|
| 241 | const {
|
|---|
| 242 | operator
|
|---|
| 243 | } = path.node;
|
|---|
| 244 | if (operator === "==" || operator === "!=" || operator === "===" || operator === "!==" || operator === "<" || operator === ">" || operator === "<=" || operator === ">=" || operator === "instanceof" || operator === "in") {
|
|---|
| 245 | return {
|
|---|
| 246 | id: "Boolean",
|
|---|
| 247 | placement: "prototype"
|
|---|
| 248 | };
|
|---|
| 249 | }
|
|---|
| 250 | // >>> always produces Number
|
|---|
| 251 | if (operator === ">>>") {
|
|---|
| 252 | return {
|
|---|
| 253 | id: "Number",
|
|---|
| 254 | placement: "prototype"
|
|---|
| 255 | };
|
|---|
| 256 | }
|
|---|
| 257 | // Arithmetic and bitwise operators can produce Number or BigInt
|
|---|
| 258 | if (operator === "-" || operator === "*" || operator === "/" || operator === "%" || operator === "**" || operator === "&" || operator === "|" || operator === "^" || operator === "<<" || operator === ">>") {
|
|---|
| 259 | const left = resolveInstance(path.get("left"), seen);
|
|---|
| 260 | const right = resolveInstance(path.get("right"), seen);
|
|---|
| 261 | if (left === "BigInt" && right === "BigInt") {
|
|---|
| 262 | return {
|
|---|
| 263 | id: "BigInt",
|
|---|
| 264 | placement: "prototype"
|
|---|
| 265 | };
|
|---|
| 266 | }
|
|---|
| 267 | if (left !== null && right !== null) {
|
|---|
| 268 | return {
|
|---|
| 269 | id: "Number",
|
|---|
| 270 | placement: "prototype"
|
|---|
| 271 | };
|
|---|
| 272 | }
|
|---|
| 273 | return {
|
|---|
| 274 | id: null,
|
|---|
| 275 | placement: null
|
|---|
| 276 | };
|
|---|
| 277 | }
|
|---|
| 278 | // + depends on operand types: string wins, otherwise number or bigint
|
|---|
| 279 | if (operator === "+") {
|
|---|
| 280 | const left = resolveInstance(path.get("left"), seen);
|
|---|
| 281 | const right = resolveInstance(path.get("right"), seen);
|
|---|
| 282 | if (left === "String" || right === "String") {
|
|---|
| 283 | return {
|
|---|
| 284 | id: "String",
|
|---|
| 285 | placement: "prototype"
|
|---|
| 286 | };
|
|---|
| 287 | }
|
|---|
| 288 | if (left === "Number" && right === "Number") {
|
|---|
| 289 | return {
|
|---|
| 290 | id: "Number",
|
|---|
| 291 | placement: "prototype"
|
|---|
| 292 | };
|
|---|
| 293 | }
|
|---|
| 294 | if (left === "BigInt" && right === "BigInt") {
|
|---|
| 295 | return {
|
|---|
| 296 | id: "BigInt",
|
|---|
| 297 | placement: "prototype"
|
|---|
| 298 | };
|
|---|
| 299 | }
|
|---|
| 300 | }
|
|---|
| 301 | return {
|
|---|
| 302 | id: null,
|
|---|
| 303 | placement: null
|
|---|
| 304 | };
|
|---|
| 305 | }
|
|---|
| 306 | // (a, b, c) -> the result is the last expression
|
|---|
| 307 | case "SequenceExpression":
|
|---|
| 308 | {
|
|---|
| 309 | const expressions = path.get("expressions");
|
|---|
| 310 | return resolveSource(expressions[expressions.length - 1], seen);
|
|---|
| 311 | }
|
|---|
| 312 | // a = b -> the result is the right side
|
|---|
| 313 | case "AssignmentExpression":
|
|---|
| 314 | {
|
|---|
| 315 | if (path.node.operator === "=") {
|
|---|
| 316 | return resolveSource(path.get("right"), seen);
|
|---|
| 317 | }
|
|---|
| 318 | return {
|
|---|
| 319 | id: null,
|
|---|
| 320 | placement: null
|
|---|
| 321 | };
|
|---|
| 322 | }
|
|---|
| 323 | // a ? b : c -> if both branches resolve to the same type, use it
|
|---|
| 324 | case "ConditionalExpression":
|
|---|
| 325 | {
|
|---|
| 326 | const consequent = resolveSource(path.get("consequent"), seen);
|
|---|
| 327 | const alternate = resolveSource(path.get("alternate"), seen);
|
|---|
| 328 | if (consequent.id && consequent.id === alternate.id) {
|
|---|
| 329 | return consequent;
|
|---|
| 330 | }
|
|---|
| 331 | return {
|
|---|
| 332 | id: null,
|
|---|
| 333 | placement: null
|
|---|
| 334 | };
|
|---|
| 335 | }
|
|---|
| 336 | // (expr) -> unwrap parenthesized expressions
|
|---|
| 337 | case "ParenthesizedExpression":
|
|---|
| 338 | return resolveSource(path.get("expression"), seen);
|
|---|
| 339 | // TypeScript / Flow type wrappers -> unwrap to the inner expression
|
|---|
| 340 | case "TSAsExpression":
|
|---|
| 341 | case "TSSatisfiesExpression":
|
|---|
| 342 | case "TSNonNullExpression":
|
|---|
| 343 | case "TSInstantiationExpression":
|
|---|
| 344 | case "TSTypeAssertion":
|
|---|
| 345 | case "TypeCastExpression":
|
|---|
| 346 | return resolveSource(path.get("expression"), seen);
|
|---|
| 347 | }
|
|---|
| 348 | return {
|
|---|
| 349 | id: null,
|
|---|
| 350 | placement: null
|
|---|
| 351 | };
|
|---|
| 352 | }
|
|---|
| 353 | function getImportSource({
|
|---|
| 354 | node
|
|---|
| 355 | }) {
|
|---|
| 356 | if (node.specifiers.length === 0) return node.source.value;
|
|---|
| 357 | }
|
|---|
| 358 | function getRequireSource({
|
|---|
| 359 | node
|
|---|
| 360 | }) {
|
|---|
| 361 | if (!t.isExpressionStatement(node)) return;
|
|---|
| 362 | const {
|
|---|
| 363 | expression
|
|---|
| 364 | } = node;
|
|---|
| 365 | if (t.isCallExpression(expression) && t.isIdentifier(expression.callee) && expression.callee.name === "require" && expression.arguments.length === 1 && t.isStringLiteral(expression.arguments[0])) {
|
|---|
| 366 | return expression.arguments[0].value;
|
|---|
| 367 | }
|
|---|
| 368 | }
|
|---|
| 369 | function hoist(node) {
|
|---|
| 370 | // @ts-expect-error
|
|---|
| 371 | node._blockHoist = 3;
|
|---|
| 372 | return node;
|
|---|
| 373 | }
|
|---|
| 374 | function createUtilsGetter(cache) {
|
|---|
| 375 | return path => {
|
|---|
| 376 | const prog = path.findParent(p => p.isProgram());
|
|---|
| 377 | return {
|
|---|
| 378 | injectGlobalImport(url, moduleName) {
|
|---|
| 379 | cache.storeAnonymous(prog, url, moduleName, (isScript, source) => {
|
|---|
| 380 | return isScript ? template.statement.ast`require(${source})` : t.importDeclaration([], source);
|
|---|
| 381 | });
|
|---|
| 382 | },
|
|---|
| 383 | injectNamedImport(url, name, hint = name, moduleName) {
|
|---|
| 384 | return cache.storeNamed(prog, url, name, moduleName, (isScript, source, name) => {
|
|---|
| 385 | const id = prog.scope.generateUidIdentifier(hint);
|
|---|
| 386 | return {
|
|---|
| 387 | node: isScript ? hoist(template.statement.ast`
|
|---|
| 388 | var ${id} = require(${source}).${name}
|
|---|
| 389 | `) : t.importDeclaration([t.importSpecifier(id, name)], source),
|
|---|
| 390 | name: id.name
|
|---|
| 391 | };
|
|---|
| 392 | });
|
|---|
| 393 | },
|
|---|
| 394 | injectDefaultImport(url, hint = url, moduleName) {
|
|---|
| 395 | return cache.storeNamed(prog, url, "default", moduleName, (isScript, source) => {
|
|---|
| 396 | const id = prog.scope.generateUidIdentifier(hint);
|
|---|
| 397 | return {
|
|---|
| 398 | node: isScript ? hoist(template.statement.ast`var ${id} = require(${source})`) : t.importDeclaration([t.importDefaultSpecifier(id)], source),
|
|---|
| 399 | name: id.name
|
|---|
| 400 | };
|
|---|
| 401 | });
|
|---|
| 402 | }
|
|---|
| 403 | };
|
|---|
| 404 | };
|
|---|
| 405 | } |
|---|