isolated-function 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -0
- package/package.json +1 -1
- package/src/compile/index.js +7 -6
- package/src/compile/transform-dependencies.js +1 -1
- package/src/index.js +15 -7
- package/src/template/index.js +15 -6
package/README.md
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
- [Auto install dependencies](#auto-install-dependencies)
|
|
23
23
|
- [Execution profiling](#execution-profiling)
|
|
24
24
|
- [Resource limits](#resource-limits)
|
|
25
|
+
- [Logging](#logging)
|
|
25
26
|
- [Error handling](#error-handling)
|
|
26
27
|
- [API](#api)
|
|
27
28
|
- [isolatedFunction(code, \[options\])](#isolatedfunctioncode-options)
|
|
@@ -30,6 +31,7 @@
|
|
|
30
31
|
- [memory](#memory)
|
|
31
32
|
- [throwError](#throwerror)
|
|
32
33
|
- [timeout](#timeout)
|
|
34
|
+
- [tmpdir](#tmpdir)
|
|
33
35
|
- [=\> (fn(\[...args\]), teardown())](#-fnargs-teardown)
|
|
34
36
|
- [fn](#fn)
|
|
35
37
|
- [teardown](#teardown)
|
|
@@ -166,6 +168,32 @@ await fn(100)
|
|
|
166
168
|
// => TimeoutError: Execution timed out
|
|
167
169
|
```
|
|
168
170
|
|
|
171
|
+
### Logging
|
|
172
|
+
|
|
173
|
+
The logs are collected into a `logging` object returned after the execution:
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
const [fn, teardown] = isolatedFunction(() => {
|
|
177
|
+
console.log('console.log')
|
|
178
|
+
console.info('console.info')
|
|
179
|
+
console.debug('console.debug')
|
|
180
|
+
console.warn('console.warn')
|
|
181
|
+
console.error('console.error')
|
|
182
|
+
return 'done'
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
const { logging } await fn()
|
|
186
|
+
|
|
187
|
+
console.log(logging)
|
|
188
|
+
// {
|
|
189
|
+
// log: ['console.log'],
|
|
190
|
+
// info: ['console.info'],
|
|
191
|
+
// debug: ['console.debug'],
|
|
192
|
+
// warn: ['console.warn'],
|
|
193
|
+
// error: ['console.error']
|
|
194
|
+
// }
|
|
195
|
+
```
|
|
196
|
+
|
|
169
197
|
### Error handling
|
|
170
198
|
|
|
171
199
|
Any error during **isolated-function** execution will be propagated:
|
|
@@ -232,6 +260,13 @@ Default: `Infinity`
|
|
|
232
260
|
|
|
233
261
|
Timeout after a specified amount of time, in milliseconds.
|
|
234
262
|
|
|
263
|
+
##### tmpdir
|
|
264
|
+
|
|
265
|
+
Type: `function`<br>
|
|
266
|
+
Default: `fs.mkdtemp(path.join(require('os').tmpdir(), 'compile-'))`
|
|
267
|
+
|
|
268
|
+
The temporal folder to use for installing code dependencies.
|
|
269
|
+
|
|
235
270
|
### => (fn([...args]), teardown())
|
|
236
271
|
|
|
237
272
|
#### fn
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "isolated-function",
|
|
3
3
|
"description": "Runs untrusted code in a Node.js v8 sandbox.",
|
|
4
4
|
"homepage": "https://github.com/Kikobeats/isolated-function",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.8",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./src/index.js"
|
package/src/compile/index.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const { execSync } = require('child_process')
|
|
4
4
|
const esbuild = require('esbuild')
|
|
5
5
|
const fs = require('fs/promises')
|
|
6
|
-
const { tmpdir } = require('os')
|
|
7
6
|
const $ = require('tinyspawn')
|
|
8
7
|
const path = require('path')
|
|
9
8
|
|
|
@@ -22,8 +21,10 @@ const packageManager = (() => {
|
|
|
22
21
|
}
|
|
23
22
|
})()
|
|
24
23
|
|
|
25
|
-
const
|
|
26
|
-
|
|
24
|
+
const tmpdirDefault = () => fs.mkdtemp(path.join(require('os').tmpdir(), 'compile-'))
|
|
25
|
+
|
|
26
|
+
const getTmp = async (content, tmpdir) => {
|
|
27
|
+
const cwd = await tmpdir()
|
|
27
28
|
await fs.mkdir(cwd, { recursive: true })
|
|
28
29
|
|
|
29
30
|
const filepath = path.join(cwd, 'index.js')
|
|
@@ -33,10 +34,10 @@ const getTmp = async content => {
|
|
|
33
34
|
return { filepath, cwd, content, cleanup }
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
module.exports = async snippet => {
|
|
37
|
+
module.exports = async (snippet, tmpdir = tmpdirDefault) => {
|
|
37
38
|
const compiledTemplate = generateTemplate(snippet)
|
|
38
39
|
const dependencies = detectDependencies(compiledTemplate)
|
|
39
|
-
const tmp = await getTmp(transformDependencies(compiledTemplate))
|
|
40
|
+
const tmp = await getTmp(transformDependencies(compiledTemplate), tmpdir)
|
|
40
41
|
|
|
41
42
|
await $(packageManager.init, { cwd: tmp.cwd })
|
|
42
43
|
await $(`${packageManager.install} ${dependencies.join(' ')}`, {
|
|
@@ -52,7 +53,7 @@ module.exports = async snippet => {
|
|
|
52
53
|
})
|
|
53
54
|
|
|
54
55
|
await tmp.cleanup()
|
|
55
|
-
return getTmp(result.outputFiles[0].text)
|
|
56
|
+
return getTmp(result.outputFiles[0].text, tmpdir)
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
module.exports.detectDependencies = detectDependencies
|
package/src/index.js
CHANGED
|
@@ -15,14 +15,18 @@ const createError = ({ name, message, ...props }) => {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const flags = ({ filename, memory }) => {
|
|
18
|
-
const flags = [
|
|
18
|
+
const flags = [
|
|
19
|
+
'--disable-warning=ExperimentalWarning',
|
|
20
|
+
'--experimental-permission',
|
|
21
|
+
`--allow-fs-read=${filename}`
|
|
22
|
+
]
|
|
19
23
|
if (memory) flags.push(`--max-old-space-size=${memory}`)
|
|
20
24
|
return flags.join(' ')
|
|
21
25
|
}
|
|
22
26
|
|
|
23
|
-
module.exports = (snippet, { timeout, memory, throwError = true } = {}) => {
|
|
27
|
+
module.exports = (snippet, { tmpdir, timeout, memory, throwError = true } = {}) => {
|
|
24
28
|
if (!['function', 'string'].includes(typeof snippet)) throw new TypeError('Expected a function')
|
|
25
|
-
const compilePromise = compile(snippet)
|
|
29
|
+
const compilePromise = compile(snippet, tmpdir)
|
|
26
30
|
|
|
27
31
|
const fn = async (...args) => {
|
|
28
32
|
let duration
|
|
@@ -39,11 +43,15 @@ module.exports = (snippet, { timeout, memory, throwError = true } = {}) => {
|
|
|
39
43
|
timeout,
|
|
40
44
|
killSignal: 'SIGKILL'
|
|
41
45
|
})
|
|
42
|
-
const { isFulfilled, value, profiling } = JSON.parse(stdout)
|
|
46
|
+
const { isFulfilled, value, profiling, logging } = JSON.parse(stdout)
|
|
43
47
|
profiling.duration = duration()
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
return isFulfilled
|
|
49
|
+
? { isFulfilled, value, profiling, logging }
|
|
50
|
+
: throwError
|
|
51
|
+
? (() => {
|
|
52
|
+
throw deserializeError(value)
|
|
53
|
+
})()
|
|
54
|
+
: { isFulfilled: false, value: deserializeError(value), profiling, logging }
|
|
47
55
|
} catch (error) {
|
|
48
56
|
if (error.signalCode === 'SIGTRAP') {
|
|
49
57
|
throw createError({
|
package/src/template/index.js
CHANGED
|
@@ -2,10 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
const SERIALIZE_ERROR = require('./serialize-error')
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
module.exports = snippet => `
|
|
6
6
|
const args = JSON.parse(process.argv[2])
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const logging = Object.create(null)
|
|
9
|
+
|
|
10
|
+
for (const method of ['log', 'info', 'debug', 'warn', 'error']) {
|
|
11
|
+
console[method] = function (...args) {
|
|
12
|
+
const input = args.join(' ')
|
|
13
|
+
logging[method] === undefined ? logging[method] = [input] : logging[method].push(input)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
;(async (send) => {
|
|
18
|
+
process.stdout.write = function () {}
|
|
9
19
|
let value
|
|
10
20
|
let isFulfilled
|
|
11
21
|
|
|
@@ -16,12 +26,11 @@ const generateTemplate = snippet => `
|
|
|
16
26
|
value = ${SERIALIZE_ERROR}(error)
|
|
17
27
|
isFulfilled = false
|
|
18
28
|
} finally {
|
|
19
|
-
|
|
29
|
+
send(JSON.stringify({
|
|
20
30
|
isFulfilled,
|
|
31
|
+
logging,
|
|
21
32
|
value,
|
|
22
33
|
profiling: { memory: process.memoryUsage().rss }
|
|
23
34
|
}))
|
|
24
35
|
}
|
|
25
|
-
})()`
|
|
26
|
-
|
|
27
|
-
module.exports = generateTemplate
|
|
36
|
+
})(process.stdout.write.bind(process.stdout))`
|