uni-ticket-system/node_modules/@dcloudio/uni-cli-shared/dist/vite/plugins/inject.js

196 lines
8.1 KiB
JavaScript
Raw Normal View History

2023-12-05 02:11:10 +00:00
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniViteInjectPlugin = void 0;
const path_1 = require("path");
const debug_1 = __importDefault(require("debug"));
const pluginutils_1 = require("@rollup/pluginutils");
const estree_walker_1 = require("estree-walker");
const shared_1 = require("@vue/shared");
const magic_string_1 = __importDefault(require("magic-string"));
const utils_1 = require("../utils");
const debugInject = (0, debug_1.default)('uni:inject');
const debugInjectTry = (0, debug_1.default)('uni:inject-try');
function uniViteInjectPlugin(name, options) {
if (!options)
throw new Error('Missing options');
const filter = (0, pluginutils_1.createFilter)(options.include, options.exclude);
const modules = (0, shared_1.extend)({}, options);
delete modules.include;
delete modules.exclude;
delete modules.sourceMap;
delete modules.callback;
const reassignments = new Set();
const modulesMap = new Map();
const namespaceModulesMap = new Map();
Object.keys(modules).forEach((name) => {
if (name.endsWith('.')) {
namespaceModulesMap.set(name, modules[name]);
}
modulesMap.set(name, modules[name]);
});
const hasNamespace = namespaceModulesMap.size > 0;
// Fix paths on Windows
if (path_1.sep !== '/') {
normalizeModulesMap(modulesMap);
normalizeModulesMap(namespaceModulesMap);
}
const firstpass = new RegExp(`(?:${Array.from(modulesMap.keys()).map(escape).join('|')})`, 'g');
const sourceMap = options.sourceMap !== false;
const callback = options.callback;
return {
name,
// 确保在 commonjs 之后,否则会混合 es6 module 与 cjs 的代码,导致 commonjs 失效
enforce: 'post',
transform(code, id) {
if (!filter(id))
return null;
if (!(0, utils_1.isJsFile)(id))
return null;
debugInjectTry(id);
if (code.search(firstpass) === -1)
return null;
if (path_1.sep !== '/')
id = id.split(path_1.sep).join('/');
const ast = this.parse(code);
const imports = new Set();
ast.body.forEach((node) => {
if (node.type === 'ImportDeclaration') {
node.specifiers.forEach((specifier) => {
imports.add(specifier.local.name);
});
}
});
// analyse scopes
let scope = (0, pluginutils_1.attachScopes)(ast, 'scope');
const magicString = new magic_string_1.default(code);
const newImports = new Map();
function handleReference(node, name, keypath, parent) {
let mod = modulesMap.get(keypath);
if (!mod && hasNamespace) {
const mods = keypath.split('.');
if (mods.length === 2) {
mod = namespaceModulesMap.get(mods[0] + '.');
if (mod) {
if ((0, shared_1.isArray)(mod)) {
const testFn = mod[1];
if (testFn(mods[1])) {
mod = [mod[0], mods[1]];
}
else {
mod = undefined;
}
}
else {
mod = [mod, mods[1]];
}
}
}
}
if (mod && !imports.has(name) && !scope.contains(name)) {
if ((0, shared_1.isString)(mod))
mod = [mod, 'default'];
if (mod[0] === id)
return false;
const hash = `${keypath}:${mod[0]}:${mod[1]}`;
// 当 API 被覆盖定义后,不再摇树
if (reassignments.has(hash)) {
return false;
}
if (parent &&
(0, utils_1.isAssignmentExpression)(parent) &&
parent.left === node) {
reassignments.add(hash);
return false;
}
const importLocalName = name === keypath ? name : (0, pluginutils_1.makeLegalIdentifier)(`$inject_${keypath}`);
if (!newImports.has(hash)) {
if (mod[1] === '*') {
newImports.set(hash, `import * as ${importLocalName} from '${mod[0]}';`);
}
else {
newImports.set(hash, `import { ${mod[1]} as ${importLocalName} } from '${mod[0]}';`);
callback && callback(newImports, mod);
}
}
if (name !== keypath) {
magicString.overwrite(node.start, node.end, importLocalName, {
storeName: true,
});
}
return true;
}
return false;
}
(0, estree_walker_1.walk)(ast, {
enter(node, parent) {
if (sourceMap) {
magicString.addSourcemapLocation(node.start);
magicString.addSourcemapLocation(node.end);
}
if (node.scope) {
scope = node.scope;
}
if ((0, utils_1.isProperty)(node) && node.shorthand) {
const { name } = node.key;
handleReference(node, name, name);
this.skip();
return;
}
if ((0, utils_1.isReference)(node, parent)) {
const { name, keypath } = flatten(node);
const handled = handleReference(node, name, keypath, parent);
if (handled) {
this.skip();
}
}
},
leave(node) {
if (node.scope) {
scope = scope.parent;
}
},
});
debugInject(id, newImports.size);
if (newImports.size === 0) {
return {
code,
// 不能返回 ast ,否则会导致代码不能被再次修改
// 比如 App.vue 中console.log('uniCloud') 触发了 inject 检测,检测完,发现不需要
// 此时返回 ast会导致 import { setupApp } from '@dcloudio/uni-h5' 不会被编译
// ast
map: null,
};
}
const importBlock = Array.from(newImports.values()).join('\n\n');
magicString.prepend(`${importBlock}\n\n`);
return {
code: magicString.toString(),
map: sourceMap ? magicString.generateMap({ hires: true }) : null,
};
},
};
}
exports.uniViteInjectPlugin = uniViteInjectPlugin;
const escape = (str) => str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
const flatten = (startNode) => {
const parts = [];
let node = startNode;
while ((0, utils_1.isMemberExpression)(node)) {
parts.unshift(node.property.name);
node = node.object;
}
const { name } = node;
parts.unshift(name);
return { name, keypath: parts.join('.') };
};
function normalizeModulesMap(modulesMap) {
modulesMap.forEach((mod, key) => {
modulesMap.set(key, (0, shared_1.isArray)(mod)
? [mod[0].split(path_1.sep).join('/'), mod[1]]
: mod.split(path_1.sep).join('/'));
});
}