-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmod.js
57 lines (51 loc) · 1.8 KB
/
mod.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
export default {
name: 'eval',
setup({initialOptions, onLoad, onResolve, esbuild}) {
let options = {
...initialOptions,
bundle: true,
format: 'esm',
write: false,
metafile: true
}
onResolve({filter: /[?&]eval\b/}, ({path, resolveDir}) => {
let {pathname} = new URL(path, `file://${resolveDir}/`)
return {namespace: 'eval', path: pathname}
})
onLoad({filter: /.*/, namespace: 'eval'}, async ({path}) => {
let {metafile, outputFiles} = await esbuild.build({...options, entryPoints: [path]})
let file = outputFiles.find(f => /\.m?js$/.test(f.path))
let watchFiles = Object.keys(metafile.inputs)
let dataurl = await new Promise(cb => {
let reader = new FileReader()
let blob = new Blob([file.contents])
reader.onload = () => cb(reader.result)
reader.readAsDataURL(blob)
})
let entries = await import(dataurl).then(Object.entries)
let contents = entries.reduce((js, [k, v]) => {
let ident = k === 'default' ? `${k} ` : `let ${k}=`
return js + `export ${ident}${stringify(v)}\n`
}, '')
return {loader: 'js', contents, watchFiles}
})
}
}
function stringify(v) {
switch (typeof v) {
case 'object':
if (v === null) return 'null'
if (v instanceof Uint8Array) return `Uint8Array.from(atob('${btoa(String.fromCharCode(...v))}'),x=>x.charCodeAt())`
if (Array.isArray(v)) return `[${v.map(stringify)}]`
return `{${Object.entries(v).map(e => e.map(stringify).join(':'))}}`
case 'function':
try { return String(eval(`(${v})`)) }
catch (e) { return String(v).replace(/^async|^/, '$& function ') }
case 'bigint':
return `${v}n`
case 'undefined':
return 'undefined'
default:
return JSON.stringify(v)
}
}