forked from rollup/plugins
-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.js
99 lines (89 loc) 路 2.81 KB
/
util.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
const path = require('path');
const commonjsPlugin = require('../..');
function commonjs(options) {
delete require.cache[require.resolve('../..')];
return commonjsPlugin(options);
}
function normalizePathSlashes(path) {
return path.replace(/\\/g, '/');
}
function requireWithContext(code, context) {
const module = { exports: {} };
const contextWithExports = { ...context, module, exports: module.exports };
const contextKeys = Object.keys(contextWithExports);
const contextValues = contextKeys.map((key) => contextWithExports[key]);
try {
// eslint-disable-next-line no-new-func
const fn = new Function(contextKeys, code);
fn.apply({}, contextValues);
} catch (error) {
error.exports = module.exports;
throw error;
}
return contextWithExports.module.exports;
}
function runCodeSplitTest(codeMap, t, configContext = {}) {
const requireFromOutputVia = (importer) => (importee) => {
const outputId = path.posix.join(path.posix.dirname(importer), importee);
const code = codeMap[outputId];
if (typeof code !== 'undefined') {
return requireWithContext(
code,
// eslint-disable-next-line no-use-before-define
{ require: requireFromOutputVia(outputId), ...context }
);
}
// eslint-disable-next-line import/no-dynamic-require, global-require
return require(importee);
};
const chunkNames = Object.keys(codeMap);
const entryName = chunkNames.length === 1 ? chunkNames[0] : 'main.js';
if (!codeMap[entryName]) {
throw new Error(
`Could not find entry "${entryName}" in generated output.\nChunks:\n${Object.keys(
codeMap
).join('\n')}`
);
}
const global = {};
const context = { t, global, globalThis: global, ...configContext };
let exports;
try {
exports = requireWithContext(codeMap[entryName], {
require: requireFromOutputVia('main.js'),
...context
});
} catch (error) {
return { error, exports: error.exports };
}
return { exports, global };
}
async function getCodeMapFromBundle(bundle, options = {}) {
const generated = await bundle.generate({
interop: 'compat',
exports: 'auto',
format: 'cjs',
...options
});
const codeMap = {};
for (const chunk of generated.output) {
codeMap[chunk.fileName] = chunk.code;
}
return codeMap;
}
async function getCodeFromBundle(bundle, customOptions = {}) {
const options = { exports: 'auto', format: 'cjs', ...customOptions };
return (await bundle.generate(options)).output[0].code;
}
async function executeBundle(bundle, t, { context, exports } = {}) {
const codeMap = await getCodeMapFromBundle(bundle, exports ? { exports } : {});
return runCodeSplitTest(codeMap, t, context);
}
module.exports = {
commonjs,
executeBundle,
getCodeFromBundle,
getCodeMapFromBundle,
normalizePathSlashes,
runCodeSplitTest
};