-
Notifications
You must be signed in to change notification settings - Fork 69
/
endo.js
105 lines (95 loc) · 3.18 KB
/
endo.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
100
101
102
103
104
105
const fs = require('node:fs')
const url = require('node:url')
const crypto = require('node:crypto')
require('ses')
lockdown()
const rawModules = {}
const syntheticModulesCompartment = new Compartment(
{},
{},
{
name: 'syntheticModules',
resolveHook: (moduleSpecifier) => moduleSpecifier,
importHook: async (moduleSpecifier) => {
const ns =
rawModules[moduleSpecifier].default || rawModules[moduleSpecifier]
const staticModuleRecord = Object.freeze({
imports: [],
exports: Array.from(new Set(Object.keys(ns).concat(['default']))),
execute: (moduleExports) => {
Object.assign(moduleExports, ns)
moduleExports.default = ns
},
})
return staticModuleRecord
},
}
)
const addToCompartment = async (name, nsObject) => {
rawModules[name] = nsObject
return (await syntheticModulesCompartment.import(name)).namespace
}
main().catch((err) => {
console.error(err)
process.exit(1)
})
async function main() {
const { makeReadPowers } = await import(
'@endo/compartment-mapper/node-powers.js'
)
const { importLocation } = await import('@endo/compartment-mapper')
const { transforms } = await import('ses/tools.js')
const { evadeHtmlCommentTest, evadeImportExpressionTest, applyTransforms } =
transforms
const modules = {
stream: await addToCompartment('stream', require('node:stream')),
events: await addToCompartment('events', require('node:events')),
buffer: await addToCompartment('buffer', require('node:buffer')),
util: await addToCompartment('util', require('node:util')),
crypto: await addToCompartment('crypto', require('node:crypto')),
assert: await addToCompartment('assert', require('node:assert')),
path: await addToCompartment('path', require('node:path')),
fs: await addToCompartment('fs', require('node:fs')),
}
const readPowers = makeReadPowers({ fs, url, crypto })
const moduleLocation = url.pathToFileURL(process.cwd() + '/entry.js')
await importLocation(readPowers, moduleLocation, {
modules,
globals: {
console,
process,
Buffer,
},
moduleTransforms: {
cjs: makeSesModuleTransform('cjs'),
mjs: makeSesModuleTransform('mjs'),
},
})
function makeSesModuleTransform(language) {
return function sesModuleTransform(sourceBytes) {
const transformedSource = _applySesEvasions(sourceBytes.toString())
const bytes = Buffer.from(transformedSource, 'utf8')
return { bytes, parser: language }
}
}
function _applySesEvasions(source) {
const result = applySesEvasions(source)
// if (result !== source) {
// console.log('transformed source')
// console.log(result.split('\n').map((line, i) => `${i + 1}: ${line}`).join('\n'))
// console.log('check that the transform result is valid js')
// transforms.rejectHtmlComments(result)
// }
return result
}
function applySesEvasions(source) {
return applyTransforms(source, [
evadeHtmlCommentTest,
evadeImportExpressionTest,
(src) => {
const someDirectEvalPattern = /(^|[^.])\beval(\s*\()/g
return src.replaceAll(someDirectEvalPattern, '$1(0,eval)(')
},
])
}
}