@jsreport/jsreport-core 3.1.2-test.2 → 3.4.1
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/LICENSE +166 -166
- package/README.md +310 -298
- package/index.js +29 -29
- package/lib/main/blobStorage/blobStorage.js +53 -52
- package/lib/main/blobStorage/inMemoryProvider.js +27 -27
- package/lib/main/blobStorage/mainActions.js +24 -24
- package/lib/main/createDefaultLoggerFormat.js +17 -17
- package/lib/main/defaults.js +14 -14
- package/lib/main/extensions/discover.js +20 -20
- package/lib/main/extensions/extensionsManager.js +264 -264
- package/lib/main/extensions/fileUtils.js +56 -56
- package/lib/main/extensions/findVersion.js +49 -49
- package/lib/main/extensions/locationCache.js +103 -103
- package/lib/main/extensions/sorter.js +10 -10
- package/lib/main/extensions/validateMinimalVersion.js +50 -50
- package/lib/main/folders/cascadeFolderRemove.js +25 -25
- package/lib/main/folders/getEntitiesInFolder.js +53 -53
- package/lib/main/folders/index.js +42 -42
- package/lib/main/folders/moveBetweenFolders.js +354 -354
- package/lib/main/folders/validateDuplicatedName.js +107 -107
- package/lib/main/folders/validateReservedName.js +53 -53
- package/lib/main/logger.js +254 -244
- package/lib/main/migration/resourcesToAssets.js +230 -230
- package/lib/main/migration/xlsxTemplatesToAssets.js +128 -128
- package/lib/main/monitoring.js +92 -91
- package/lib/main/optionsLoad.js +231 -237
- package/lib/main/optionsSchema.js +237 -237
- package/lib/main/profiler.js +13 -1
- package/lib/main/reporter.js +589 -579
- package/lib/main/request.js +21 -0
- package/lib/main/schemaValidator.js +252 -252
- package/lib/main/settings.js +154 -154
- package/lib/main/store/checkDuplicatedId.js +27 -27
- package/lib/main/store/collection.js +329 -329
- package/lib/main/store/documentStore.js +469 -469
- package/lib/main/store/mainActions.js +28 -28
- package/lib/main/store/memoryStoreProvider.js +99 -99
- package/lib/main/store/queue.js +48 -48
- package/lib/main/store/referenceUtils.js +251 -251
- package/lib/main/store/setupValidateId.js +43 -43
- package/lib/main/store/setupValidateShortid.js +71 -71
- package/lib/main/store/transaction.js +69 -69
- package/lib/main/store/typeUtils.js +180 -180
- package/lib/main/templates.js +34 -34
- package/lib/main/validateEntityName.js +62 -62
- package/lib/shared/createError.js +36 -36
- package/lib/shared/encryption.js +114 -114
- package/lib/shared/folders/index.js +11 -11
- package/lib/shared/folders/normalizeEntityPath.js +15 -15
- package/lib/shared/folders/resolveEntityFromPath.js +88 -88
- package/lib/shared/folders/resolveEntityPath.js +46 -46
- package/lib/shared/folders/resolveFolderFromPath.js +38 -38
- package/lib/shared/generateRequestId.js +4 -4
- package/lib/shared/listenerCollection.js +169 -169
- package/lib/shared/normalizeMetaFromLogs.js +30 -30
- package/lib/shared/reporter.js +128 -123
- package/lib/shared/request.js +64 -64
- package/lib/shared/tempFilesHandler.js +81 -81
- package/lib/shared/templates.js +82 -82
- package/lib/static/helpers.js +33 -33
- package/lib/worker/blobStorage.js +34 -34
- package/lib/worker/defaultProxyExtend.js +46 -46
- package/lib/worker/documentStore.js +49 -49
- package/lib/worker/extensionsManager.js +17 -17
- package/lib/worker/logger.js +48 -48
- package/lib/worker/render/diff.js +138 -138
- package/lib/worker/render/executeEngine.js +232 -207
- package/lib/worker/render/htmlRecipe.js +10 -10
- package/lib/worker/render/moduleHelper.js +45 -43
- package/lib/worker/render/noneEngine.js +12 -12
- package/lib/worker/render/profiler.js +162 -158
- package/lib/worker/render/render.js +202 -205
- package/lib/worker/render/resolveReferences.js +60 -60
- package/lib/worker/reporter.js +197 -191
- package/lib/worker/sandbox/runInSandbox.js +64 -12
- package/lib/worker/sandbox/safeSandbox.js +829 -828
- package/lib/worker/templates.js +80 -78
- package/lib/worker/workerHandler.js +55 -54
- package/package.json +91 -92
- package/test/blobStorage/common.js +25 -21
- package/test/store/common.js +1449 -1449
package/lib/worker/reporter.js
CHANGED
|
@@ -1,191 +1,197 @@
|
|
|
1
|
-
const ExtensionsManager = require('./extensionsManager')
|
|
2
|
-
const DocumentStore = require('./documentStore')
|
|
3
|
-
const Templates = require('./templates')
|
|
4
|
-
const createLogger = require('./logger')
|
|
5
|
-
const runInSandbox = require('./sandbox/runInSandbox')
|
|
6
|
-
const createNoneEngine = require('./render/noneEngine')
|
|
7
|
-
const htmlRecipe = require('./render/htmlRecipe')
|
|
8
|
-
const defaultProxyExtend = require('./defaultProxyExtend')
|
|
9
|
-
const Reporter = require('../shared/reporter')
|
|
10
|
-
const BlobStorage = require('./blobStorage.js')
|
|
11
|
-
const Render = require('./render/render')
|
|
12
|
-
const Profiler = require('./render/profiler.js')
|
|
13
|
-
|
|
14
|
-
class WorkerReporter extends Reporter {
|
|
15
|
-
constructor (workerData, executeMain) {
|
|
16
|
-
const { options, documentStore, extensionsDefs } = workerData
|
|
17
|
-
|
|
18
|
-
super(options)
|
|
19
|
-
|
|
20
|
-
this._executeMain = executeMain
|
|
21
|
-
this._initialized = false
|
|
22
|
-
this._documentStoreData = documentStore
|
|
23
|
-
this._requestContextMetaConfigCollection = new Map()
|
|
24
|
-
this._proxyRegistrationFns = []
|
|
25
|
-
this.requestModulesCache = new Map()
|
|
26
|
-
this._workerActions = new Map()
|
|
27
|
-
this._registerRenderAction()
|
|
28
|
-
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
this.addRequestContextMetaConfig('
|
|
58
|
-
this.addRequestContextMetaConfig('
|
|
59
|
-
this.addRequestContextMetaConfig('
|
|
60
|
-
this.addRequestContextMetaConfig('
|
|
61
|
-
this.addRequestContextMetaConfig('
|
|
62
|
-
this.addRequestContextMetaConfig('
|
|
63
|
-
this.addRequestContextMetaConfig('
|
|
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
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
1
|
+
const ExtensionsManager = require('./extensionsManager')
|
|
2
|
+
const DocumentStore = require('./documentStore')
|
|
3
|
+
const Templates = require('./templates')
|
|
4
|
+
const createLogger = require('./logger')
|
|
5
|
+
const runInSandbox = require('./sandbox/runInSandbox')
|
|
6
|
+
const createNoneEngine = require('./render/noneEngine')
|
|
7
|
+
const htmlRecipe = require('./render/htmlRecipe')
|
|
8
|
+
const defaultProxyExtend = require('./defaultProxyExtend')
|
|
9
|
+
const Reporter = require('../shared/reporter')
|
|
10
|
+
const BlobStorage = require('./blobStorage.js')
|
|
11
|
+
const Render = require('./render/render')
|
|
12
|
+
const Profiler = require('./render/profiler.js')
|
|
13
|
+
|
|
14
|
+
class WorkerReporter extends Reporter {
|
|
15
|
+
constructor (workerData, executeMain) {
|
|
16
|
+
const { options, documentStore, extensionsDefs } = workerData
|
|
17
|
+
|
|
18
|
+
super(options)
|
|
19
|
+
|
|
20
|
+
this._executeMain = executeMain
|
|
21
|
+
this._initialized = false
|
|
22
|
+
this._documentStoreData = documentStore
|
|
23
|
+
this._requestContextMetaConfigCollection = new Map()
|
|
24
|
+
this._proxyRegistrationFns = []
|
|
25
|
+
this.requestModulesCache = new Map()
|
|
26
|
+
this._workerActions = new Map()
|
|
27
|
+
this._registerRenderAction()
|
|
28
|
+
|
|
29
|
+
this.registerHelpersListeners = this.createListenerCollection('registerHelpers')
|
|
30
|
+
this.afterTemplatingEnginesExecutedListeners = this.createListenerCollection('afterTemplatingEnginesExecuted')
|
|
31
|
+
this.validateRenderListeners = this.createListenerCollection('validateRender')
|
|
32
|
+
|
|
33
|
+
this.extensionsManager = ExtensionsManager(this, extensionsDefs)
|
|
34
|
+
|
|
35
|
+
this.extendProxy((proxy, req) => defaultProxyExtend(this)(proxy, req))
|
|
36
|
+
this.beforeMainActionListeners = this.createListenerCollection('beforeMainAction')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async init () {
|
|
40
|
+
if (this._initialized === true) {
|
|
41
|
+
throw new Error('jsreport already initialized. Make sure init is called only once')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
super.init()
|
|
45
|
+
|
|
46
|
+
Templates(this)
|
|
47
|
+
|
|
48
|
+
this.profiler = Profiler(this)
|
|
49
|
+
this.logger = createLogger(this.profiler)
|
|
50
|
+
|
|
51
|
+
this._render = Render(this)
|
|
52
|
+
await this.extensionsManager.init()
|
|
53
|
+
|
|
54
|
+
this.documentStore = DocumentStore(this._documentStoreData, this.executeMainAction.bind(this))
|
|
55
|
+
this.blobStorage = BlobStorage(this.executeMainAction.bind(this))
|
|
56
|
+
|
|
57
|
+
this.addRequestContextMetaConfig('rootId', { sandboxReadOnly: true })
|
|
58
|
+
this.addRequestContextMetaConfig('id', { sandboxReadOnly: true })
|
|
59
|
+
this.addRequestContextMetaConfig('reportCounter', { sandboxReadOnly: true })
|
|
60
|
+
this.addRequestContextMetaConfig('startTimestamp', { sandboxReadOnly: true })
|
|
61
|
+
this.addRequestContextMetaConfig('logs', { sandboxReadOnly: true })
|
|
62
|
+
this.addRequestContextMetaConfig('isChildRequest', { sandboxReadOnly: true })
|
|
63
|
+
this.addRequestContextMetaConfig('originalInputDataIsEmpty', { sandboxReadOnly: true })
|
|
64
|
+
this.addRequestContextMetaConfig('skipModificationDateUpdate', { sandboxHidden: true })
|
|
65
|
+
|
|
66
|
+
this._runInSandbox = runInSandbox(this)
|
|
67
|
+
|
|
68
|
+
const { compile: compileNone, execute: executeNone } = createNoneEngine()
|
|
69
|
+
|
|
70
|
+
this.extensionsManager.engines.push({
|
|
71
|
+
name: 'none',
|
|
72
|
+
compile: compileNone,
|
|
73
|
+
execute: executeNone
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
this.extensionsManager.recipes.push({
|
|
77
|
+
name: 'html',
|
|
78
|
+
execute: htmlRecipe
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
await this.initializeListeners.fire()
|
|
82
|
+
|
|
83
|
+
this._initialized = true
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @public
|
|
88
|
+
*/
|
|
89
|
+
addRequestContextMetaConfig (property, options) {
|
|
90
|
+
this._requestContextMetaConfigCollection.set(property, options)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @public
|
|
95
|
+
*/
|
|
96
|
+
getRequestContextMetaConfig (property) {
|
|
97
|
+
if (property === undefined) {
|
|
98
|
+
const all = {}
|
|
99
|
+
|
|
100
|
+
for (const [key, value] of this._requestContextMetaConfigCollection.entries()) {
|
|
101
|
+
all[key] = value
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return all
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return this._requestContextMetaConfigCollection.get(property)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
extendProxy (registrationFn) {
|
|
111
|
+
this._proxyRegistrationFns.push(registrationFn)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
createProxy ({ req, runInSandbox, context, getTopLevelFunctions, safeRequire }) {
|
|
115
|
+
const proxyInstance = {}
|
|
116
|
+
for (const fn of this._proxyRegistrationFns) {
|
|
117
|
+
fn(proxyInstance, req, {
|
|
118
|
+
runInSandbox,
|
|
119
|
+
context,
|
|
120
|
+
getTopLevelFunctions,
|
|
121
|
+
safeRequire
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
return proxyInstance
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
render (req, parentReq) {
|
|
128
|
+
return this._render(req, parentReq)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async executeMainAction (actionName, data, req) {
|
|
132
|
+
await this.beforeMainActionListeners.fire(actionName, data, req)
|
|
133
|
+
return this._executeMain(actionName, data, req)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async runInSandbox ({
|
|
137
|
+
manager,
|
|
138
|
+
context,
|
|
139
|
+
userCode,
|
|
140
|
+
executionFn,
|
|
141
|
+
onRequire,
|
|
142
|
+
propertiesConfig,
|
|
143
|
+
currentPath,
|
|
144
|
+
errorLineNumberOffset
|
|
145
|
+
}, req) {
|
|
146
|
+
// we flush before running code in sandbox because it can potentially
|
|
147
|
+
// include code that blocks the whole process (like `while (true) {}`) and we
|
|
148
|
+
// want to ensure that the batched messages are flushed before trying to execute the code
|
|
149
|
+
await this.profiler.flush(req.context.rootId)
|
|
150
|
+
|
|
151
|
+
return this._runInSandbox({
|
|
152
|
+
manager,
|
|
153
|
+
context,
|
|
154
|
+
userCode,
|
|
155
|
+
executionFn,
|
|
156
|
+
onRequire,
|
|
157
|
+
propertiesConfig,
|
|
158
|
+
currentPath,
|
|
159
|
+
errorLineNumberOffset
|
|
160
|
+
}, req)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
registerWorkerAction (actionName, fn) {
|
|
164
|
+
this._workerActions.set(actionName, fn)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async executeWorkerAction (actionName, data, req) {
|
|
168
|
+
const action = this._workerActions.get(actionName)
|
|
169
|
+
if (!action) {
|
|
170
|
+
throw new Error(`Worker action ${actionName} not registered`)
|
|
171
|
+
}
|
|
172
|
+
return action(data, req)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
_registerRenderAction () {
|
|
176
|
+
this.registerWorkerAction('render', async (data, req) => {
|
|
177
|
+
const res = await this.render(req)
|
|
178
|
+
|
|
179
|
+
const sharedBuf = new SharedArrayBuffer(res.content.byteLength)
|
|
180
|
+
const buf = Buffer.from(sharedBuf)
|
|
181
|
+
|
|
182
|
+
res.content.copy(buf)
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
meta: res.meta,
|
|
186
|
+
content: buf
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async close () {
|
|
192
|
+
this.logger.debug('Closing jsreport worker')
|
|
193
|
+
return this.closeListeners.fire()
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
module.exports = WorkerReporter
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const LRU = require('lru-cache')
|
|
2
|
-
const
|
|
2
|
+
const stackTrace = require('stack-trace')
|
|
3
3
|
const { customAlphabet } = require('nanoid')
|
|
4
|
+
const safeSandbox = require('./safeSandbox')
|
|
4
5
|
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10)
|
|
5
6
|
|
|
6
7
|
module.exports = (reporter) => {
|
|
@@ -27,7 +28,7 @@ module.exports = (reporter) => {
|
|
|
27
28
|
context.__topLevelFunctions = {}
|
|
28
29
|
context.__handleError = (err) => handleError(reporter, err)
|
|
29
30
|
|
|
30
|
-
const { run, restore, contextifyValue, decontextifyValue, unproxyValue, sandbox, safeRequire } = safeSandbox(context, {
|
|
31
|
+
const { sourceFilesInfo, run, restore, contextifyValue, decontextifyValue, unproxyValue, sandbox, safeRequire } = safeSandbox(context, {
|
|
31
32
|
onLog: (log) => {
|
|
32
33
|
reporter.logger[log.level](log.message, { ...req, timestamp: log.timestamp })
|
|
33
34
|
},
|
|
@@ -61,7 +62,51 @@ module.exports = (reporter) => {
|
|
|
61
62
|
})
|
|
62
63
|
|
|
63
64
|
jsreportProxy = reporter.createProxy({ req, runInSandbox: run, context: sandbox, getTopLevelFunctions, safeRequire })
|
|
64
|
-
|
|
65
|
+
|
|
66
|
+
jsreportProxy.currentPath = async () => {
|
|
67
|
+
// we get the current path by throwing an error, which give us a stack trace
|
|
68
|
+
// which we analyze and see if some source file is associated to an entity
|
|
69
|
+
// if it is then we can properly get the path associated to it, if not we
|
|
70
|
+
// fallback to the current path passed as options
|
|
71
|
+
const filesCount = sourceFilesInfo.size
|
|
72
|
+
let resolvedPath = currentPath
|
|
73
|
+
|
|
74
|
+
if (filesCount > 0) {
|
|
75
|
+
const err = new Error('get me stack trace please')
|
|
76
|
+
const trace = stackTrace.parse(err)
|
|
77
|
+
|
|
78
|
+
for (let i = 0; i < trace.length; i++) {
|
|
79
|
+
const current = trace[i]
|
|
80
|
+
|
|
81
|
+
if (sourceFilesInfo.has(current.getFileName())) {
|
|
82
|
+
const { entity, entitySet } = sourceFilesInfo.get(current.getFileName())
|
|
83
|
+
|
|
84
|
+
if (entity != null && entitySet != null) {
|
|
85
|
+
resolvedPath = await reporter.folders.resolveEntityPath(entity, entitySet, req)
|
|
86
|
+
break
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return resolvedPath
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
jsreportProxy.currentDirectoryPath = async () => {
|
|
96
|
+
const currentPath = await jsreportProxy.currentPath()
|
|
97
|
+
|
|
98
|
+
if (currentPath != null) {
|
|
99
|
+
const localPath = currentPath.substring(0, currentPath.lastIndexOf('/'))
|
|
100
|
+
|
|
101
|
+
if (localPath === '') {
|
|
102
|
+
return '/'
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return localPath
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return currentPath
|
|
109
|
+
}
|
|
65
110
|
|
|
66
111
|
// NOTE: it is important that cleanup, restore methods are not called from a function attached to the
|
|
67
112
|
// sandbox, because the arguments and return value of such function call will be sandboxed again, to solve this
|
|
@@ -75,15 +120,22 @@ module.exports = (reporter) => {
|
|
|
75
120
|
const functionNames = getTopLevelFunctions(userCode)
|
|
76
121
|
const functionsCode = `return {${functionNames.map(h => `"${h}": ${h}`).join(',')}}`
|
|
77
122
|
const executionCode = `;(async () => { ${userCode}; ${functionsCode} })()
|
|
78
|
-
.then((topLevelFunctions) =>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
123
|
+
.then((topLevelFunctions) => {
|
|
124
|
+
const mergedTopLevelFunctions = { ...topLevelFunctions, ...__topLevelFunctions }
|
|
125
|
+
|
|
126
|
+
// expose top level functions to the sandbox context
|
|
127
|
+
// so helpers can call other helpers (from shared asset helpers, or .registerHelpers call from proxy)
|
|
128
|
+
for (const [topLevelFnName, topLevelFn] of Object.entries(mergedTopLevelFunctions)) {
|
|
129
|
+
this[topLevelFnName] = topLevelFn
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return ${executionFnName}({
|
|
133
|
+
topLevelFunctions: mergedTopLevelFunctions,
|
|
134
|
+
require,
|
|
135
|
+
console,
|
|
136
|
+
context: this
|
|
137
|
+
})
|
|
138
|
+
}).catch(__handleError);`
|
|
87
139
|
|
|
88
140
|
return run(executionCode, {
|
|
89
141
|
filename: 'sandbox.js',
|