dcp-client 4.4.10-0 → 4.4.11-0
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 +0 -2
- package/dist/dcp-client-bundle.js +1 -1
- package/dist/dcp-client-bundle.js.map +1 -1
- package/libexec/sandbox/access-lists.js +251 -227
- package/libexec/sandbox/bootstrap.js +16 -2
- package/libexec/sandbox/bravojs-env.js +4 -5
- package/libexec/sandbox/calculate-capabilities.js +3 -1
- package/libexec/sandbox/lift-webgpu.js +232 -197
- package/libexec/sandbox/native-event-loop.js +3 -3
- package/libexec/sandbox/sa-ww-simulation.js +6 -0
- package/package.json +3 -3
|
@@ -63,218 +63,253 @@
|
|
|
63
63
|
* @date May 2023
|
|
64
64
|
*/
|
|
65
65
|
self.wrapScriptLoading({ scriptName: 'lift-webgpu' }, function liftWebGPU$$fn(protectedStorage, ring0PostMessage) {
|
|
66
|
-
|
|
67
|
-
return;
|
|
68
|
-
|
|
69
|
-
const TimeInterval = protectedStorage.TimeInterval;
|
|
70
|
-
const globalTrackers = protectedStorage.bigBrother.globalTrackers;
|
|
71
|
-
const webGPUTimer = globalTrackers.webGPUIntervals;
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Factories to create wrappers for all webGPU function (except submit & onSubmittedWorkDone) to time them when they
|
|
75
|
-
* are run, recording the duration of the function calls on the webGPU timer.
|
|
76
|
-
*/
|
|
77
|
-
function webGPUAsyncTimingFactory(fn)
|
|
66
|
+
protectedStorage.webGPUInitialization = async function webGPUInitialization()
|
|
78
67
|
{
|
|
79
|
-
|
|
68
|
+
// dcp-native lazy-loading for webgpu.
|
|
69
|
+
if (typeof initWebGPU === 'function')
|
|
80
70
|
{
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return original;
|
|
71
|
+
const webgpuReady = await initWebGPU();
|
|
72
|
+
if (!webgpuReady)
|
|
73
|
+
return;
|
|
85
74
|
}
|
|
86
|
-
}
|
|
87
75
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
76
|
+
if ((typeof navigator === 'undefined') || !('gpu' in navigator))
|
|
77
|
+
return;
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
const submitDescriptor = Object.getOwnPropertyDescriptor(GPUQueue.prototype, 'submit');
|
|
81
|
+
const navigatorDescriptor = Object.getOwnPropertyDescriptor(globalThis, 'navigator');
|
|
82
|
+
const GPUDescriptor = Object.getOwnPropertyDescriptor(globalThis, 'GPU');
|
|
83
|
+
|
|
84
|
+
// Fatal: globalThis.navigator OR globalThis.GPU are non-writable/configurable. This would prevent these scripts from being able
|
|
85
|
+
// to block access to webgpu for jobs that do not explicitly require it - allowing jobs to bypass scheduling decisions based
|
|
86
|
+
// on gpu availability must crash the sandbox, may want to stop the worker as well
|
|
87
|
+
if (!((GPUDescriptor.writable || GPUDescriptor.configurable )
|
|
88
|
+
&& (navigatorDescriptor.writable || navigatorDescriptor.configurable)))
|
|
91
89
|
{
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
webGPUTimer.push(duration.stop());
|
|
95
|
-
return ret;
|
|
90
|
+
postMessage({ request: 'unrecoverable-evaluator', message: 'webgpu exists but is not wrapable' });
|
|
91
|
+
close();
|
|
96
92
|
}
|
|
97
|
-
}
|
|
98
93
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
// the standard dictates these functions will return promises
|
|
106
|
-
const promiseReturningFunctions = new Set([
|
|
107
|
-
'requestDevice',
|
|
108
|
-
'requestAdapterInfo',
|
|
109
|
-
'createComputePipelineAsync',
|
|
110
|
-
'createRenderPipelineAsync',
|
|
111
|
-
'mapAsync', // this would overestimate in some cases, a potential discussion
|
|
112
|
-
'getCompilationInfo',
|
|
113
|
-
'onSubmittedWorkDone',
|
|
114
|
-
'popErrorScope',
|
|
115
|
-
'requestAdapter',
|
|
116
|
-
]);
|
|
117
|
-
|
|
118
|
-
// TODO: consider what to do with 'destroy'
|
|
119
|
-
// while they appear to be blocking, the meat of the work happens on the gpu driver thread
|
|
120
|
-
const blockingFunctions = new Set([
|
|
121
|
-
// GPU
|
|
122
|
-
'getPreferedCanvasFormat',
|
|
123
|
-
|
|
124
|
-
// GPUDevice
|
|
125
|
-
'createBuffer',
|
|
126
|
-
'createTexture',
|
|
127
|
-
'createSampler',
|
|
128
|
-
'importExternalTexture',
|
|
129
|
-
'createBindGroupLayout',
|
|
130
|
-
'createPipelineLayout',
|
|
131
|
-
'createBindGroup',
|
|
132
|
-
'createShaderModule',
|
|
133
|
-
'createComputePipeline',
|
|
134
|
-
'createRenderPipeline',
|
|
135
|
-
'createCommandEncoder',
|
|
136
|
-
'createRenderBundleEncoder',
|
|
137
|
-
'createQuerySet',
|
|
138
|
-
|
|
139
|
-
// GPUBuffer
|
|
140
|
-
'getMappedRange',
|
|
141
|
-
'unmap',
|
|
142
|
-
|
|
143
|
-
// GPUTexture
|
|
144
|
-
'createView',
|
|
145
|
-
|
|
146
|
-
// GPUPipelineBase
|
|
147
|
-
'getBindGroupLayout',
|
|
148
|
-
|
|
149
|
-
// GPUDebugCommandsMixin
|
|
150
|
-
'pushDebugGroup',
|
|
151
|
-
'popDebugGroup',
|
|
152
|
-
'insertDebugWorker',
|
|
153
|
-
|
|
154
|
-
// GPUCommandEncoder
|
|
155
|
-
'beginRenderPass',
|
|
156
|
-
'beginComputePass',
|
|
157
|
-
'copyBufferToBuffer',
|
|
158
|
-
'copyBufferToTexture',
|
|
159
|
-
'copyTextureToBuffer',
|
|
160
|
-
'copyTextureToTexture',
|
|
161
|
-
'clearBuffer',
|
|
162
|
-
'writeTimestamp',
|
|
163
|
-
'resolveQuerySet',
|
|
164
|
-
'finish',
|
|
165
|
-
|
|
166
|
-
// GPUBindingsCommandMixin
|
|
167
|
-
'setBindGroup',
|
|
168
|
-
|
|
169
|
-
// GPUComputePassEncoder
|
|
170
|
-
'setPipeline',
|
|
171
|
-
'dispatchWorkgroups',
|
|
172
|
-
'dispatchWorkgroupsIndirect',
|
|
173
|
-
'end',
|
|
174
|
-
|
|
175
|
-
// GPURenderPassEncoder
|
|
176
|
-
'setViewPort',
|
|
177
|
-
'setScissorRect',
|
|
178
|
-
'setBlendConstant',
|
|
179
|
-
'setStencilReference',
|
|
180
|
-
'beginOcclusionQuery',
|
|
181
|
-
'endOcclusionQuery',
|
|
182
|
-
'executeBundles',
|
|
183
|
-
'end',
|
|
184
|
-
|
|
185
|
-
// GPURenderCommandsMixin
|
|
186
|
-
'setPipeline',
|
|
187
|
-
'setIndexBuffer',
|
|
188
|
-
'draw',
|
|
189
|
-
'drawIndexed',
|
|
190
|
-
'drawIndirect',
|
|
191
|
-
'drawIndexedIndirect',
|
|
192
|
-
|
|
193
|
-
// GPURenderBundleEncoder
|
|
194
|
-
'finish',
|
|
195
|
-
|
|
196
|
-
// GPUCanvasContext
|
|
197
|
-
'configure',
|
|
198
|
-
'unconfigure',
|
|
199
|
-
|
|
200
|
-
// GPUQueue
|
|
201
|
-
'writeBuffer',
|
|
202
|
-
'writeTexture',
|
|
203
|
-
'copyExternalImageToTexture',
|
|
204
|
-
|
|
205
|
-
'pushErrorScope',
|
|
206
|
-
]);
|
|
207
|
-
|
|
208
|
-
// Iterating through all things 'GPU' on global object, some may not be classes. Skip those without a prototype.
|
|
209
|
-
if (!self[GPUClass].prototype)
|
|
94
|
+
// Non-fatal: GPUQueue.prototype.submit is non-writable/configurable. This would prevent our gpu timing code from functioning
|
|
95
|
+
// properly, so we cannot use webGPU for this sandbox, however by writing over the navigator.gpu and globalThis.GPU symbols,
|
|
96
|
+
// we can fully block webGPU access, allowing the sandbox to live for CPU-compute purposes.
|
|
97
|
+
if (!(submitDescriptor.writable || submitDescriptor.configurable))
|
|
98
|
+
{
|
|
99
|
+
protectedStorage.forceDisableWebGPU = true;
|
|
210
100
|
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const TimeInterval = protectedStorage.TimeInterval;
|
|
104
|
+
const globalTrackers = protectedStorage.bigBrother.globalTrackers;
|
|
105
|
+
const webGPUTimer = globalTrackers.webGPUIntervals;
|
|
211
106
|
|
|
212
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Factories to create wrappers for all webGPU function (except submit & onSubmittedWorkDone) to time them when they
|
|
109
|
+
* are run, recording the duration of the function calls on the webGPU timer.
|
|
110
|
+
*/
|
|
111
|
+
function webGPUAsyncTimingFactory(fn)
|
|
213
112
|
{
|
|
214
|
-
|
|
113
|
+
return function promiseWebGPUWrapper(...args)
|
|
215
114
|
{
|
|
216
|
-
const
|
|
217
|
-
|
|
115
|
+
const duration = new TimeInterval();
|
|
116
|
+
const original = fn.apply(this, args);
|
|
117
|
+
original.finally(() => webGPUTimer.push(duration.stop()));
|
|
118
|
+
return original;
|
|
218
119
|
}
|
|
219
|
-
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function webGPUSyncTimingFactory(fn)
|
|
123
|
+
{
|
|
124
|
+
return function syncWebGPUWrapper(...args)
|
|
220
125
|
{
|
|
221
|
-
const
|
|
222
|
-
|
|
126
|
+
const duration = new TimeInterval();
|
|
127
|
+
const ret = fn.apply(this, args);
|
|
128
|
+
webGPUTimer.push(duration.stop());
|
|
129
|
+
return ret;
|
|
223
130
|
}
|
|
224
131
|
}
|
|
225
|
-
}
|
|
226
132
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Wrap various webGPU functions such that their usage will be tracked
|
|
135
|
+
*
|
|
136
|
+
*/
|
|
137
|
+
function liftWebGPUPrototype(GPUClass)
|
|
138
|
+
{
|
|
139
|
+
// the standard dictates these functions will return promises
|
|
140
|
+
const promiseReturningFunctions = new Set([
|
|
141
|
+
'requestDevice',
|
|
142
|
+
'requestAdapterInfo',
|
|
143
|
+
'createComputePipelineAsync',
|
|
144
|
+
'createRenderPipelineAsync',
|
|
145
|
+
'mapAsync', // this would overestimate in some cases, a potential discussion
|
|
146
|
+
'getCompilationInfo',
|
|
147
|
+
'onSubmittedWorkDone',
|
|
148
|
+
'popErrorScope',
|
|
149
|
+
'requestAdapter',
|
|
150
|
+
]);
|
|
151
|
+
|
|
152
|
+
// TODO: consider what to do with 'destroy'
|
|
153
|
+
// while they appear to be blocking, the meat of the work happens on the gpu driver thread
|
|
154
|
+
const blockingFunctions = new Set([
|
|
155
|
+
// GPU
|
|
156
|
+
'getPreferedCanvasFormat',
|
|
157
|
+
|
|
158
|
+
// GPUDevice
|
|
159
|
+
'createBuffer',
|
|
160
|
+
'createTexture',
|
|
161
|
+
'createSampler',
|
|
162
|
+
'importExternalTexture',
|
|
163
|
+
'createBindGroupLayout',
|
|
164
|
+
'createPipelineLayout',
|
|
165
|
+
'createBindGroup',
|
|
166
|
+
'createShaderModule',
|
|
167
|
+
'createComputePipeline',
|
|
168
|
+
'createRenderPipeline',
|
|
169
|
+
'createCommandEncoder',
|
|
170
|
+
'createRenderBundleEncoder',
|
|
171
|
+
'createQuerySet',
|
|
172
|
+
|
|
173
|
+
// GPUBuffer
|
|
174
|
+
'getMappedRange',
|
|
175
|
+
'unmap',
|
|
176
|
+
|
|
177
|
+
// GPUTexture
|
|
178
|
+
'createView',
|
|
179
|
+
|
|
180
|
+
// GPUPipelineBase
|
|
181
|
+
'getBindGroupLayout',
|
|
182
|
+
|
|
183
|
+
// GPUDebugCommandsMixin
|
|
184
|
+
'pushDebugGroup',
|
|
185
|
+
'popDebugGroup',
|
|
186
|
+
'insertDebugWorker',
|
|
279
187
|
|
|
188
|
+
// GPUCommandEncoder
|
|
189
|
+
'beginRenderPass',
|
|
190
|
+
'beginComputePass',
|
|
191
|
+
'copyBufferToBuffer',
|
|
192
|
+
'copyBufferToTexture',
|
|
193
|
+
'copyTextureToBuffer',
|
|
194
|
+
'copyTextureToTexture',
|
|
195
|
+
'clearBuffer',
|
|
196
|
+
'writeTimestamp',
|
|
197
|
+
'resolveQuerySet',
|
|
198
|
+
'finish',
|
|
199
|
+
|
|
200
|
+
// GPUBindingsCommandMixin
|
|
201
|
+
'setBindGroup',
|
|
202
|
+
|
|
203
|
+
// GPUComputePassEncoder
|
|
204
|
+
'setPipeline',
|
|
205
|
+
'dispatchWorkgroups',
|
|
206
|
+
'dispatchWorkgroupsIndirect',
|
|
207
|
+
'end',
|
|
208
|
+
|
|
209
|
+
// GPURenderPassEncoder
|
|
210
|
+
'setViewPort',
|
|
211
|
+
'setScissorRect',
|
|
212
|
+
'setBlendConstant',
|
|
213
|
+
'setStencilReference',
|
|
214
|
+
'beginOcclusionQuery',
|
|
215
|
+
'endOcclusionQuery',
|
|
216
|
+
'executeBundles',
|
|
217
|
+
'end',
|
|
218
|
+
|
|
219
|
+
// GPURenderCommandsMixin
|
|
220
|
+
'setPipeline',
|
|
221
|
+
'setIndexBuffer',
|
|
222
|
+
'draw',
|
|
223
|
+
'drawIndexed',
|
|
224
|
+
'drawIndirect',
|
|
225
|
+
'drawIndexedIndirect',
|
|
226
|
+
|
|
227
|
+
// GPURenderBundleEncoder
|
|
228
|
+
'finish',
|
|
229
|
+
|
|
230
|
+
// GPUCanvasContext
|
|
231
|
+
'configure',
|
|
232
|
+
'unconfigure',
|
|
233
|
+
|
|
234
|
+
// GPUQueue
|
|
235
|
+
'writeBuffer',
|
|
236
|
+
'writeTexture',
|
|
237
|
+
'copyExternalImageToTexture',
|
|
238
|
+
|
|
239
|
+
'pushErrorScope',
|
|
240
|
+
]);
|
|
241
|
+
|
|
242
|
+
// Iterating through all things 'GPU' on global object, some may not be classes. Skip those without a prototype.
|
|
243
|
+
if (!self[GPUClass].prototype)
|
|
244
|
+
return;
|
|
245
|
+
|
|
246
|
+
for (let prop of Object.keys(self[GPUClass].prototype))
|
|
247
|
+
{
|
|
248
|
+
if (promiseReturningFunctions.has(prop))
|
|
249
|
+
{
|
|
250
|
+
const fn = self[GPUClass].prototype[prop];
|
|
251
|
+
self[GPUClass].prototype[prop] = webGPUAsyncTimingFactory(fn);
|
|
252
|
+
}
|
|
253
|
+
else if (blockingFunctions.has(prop))
|
|
254
|
+
{
|
|
255
|
+
const fn = self[GPUClass].prototype[prop];
|
|
256
|
+
self[GPUClass].prototype[prop] = webGPUSyncTimingFactory(fn);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Want to use the submit/onSubmittedWorkDone original functions for timing.
|
|
262
|
+
const underlyingOnSubmittedWorkDone = GPUQueue.prototype.onSubmittedWorkDone;
|
|
263
|
+
const underlyingSubmit = GPUQueue.prototype.submit;
|
|
264
|
+
|
|
265
|
+
// some of them will get re-wrapped, that's fine, we always refer to the original function
|
|
266
|
+
const requiredWrappingGPUClasses = [
|
|
267
|
+
'GPU',
|
|
268
|
+
'GPUAdapter',
|
|
269
|
+
'GPUDevice',
|
|
270
|
+
'GPUBuffer',
|
|
271
|
+
'GPUTexture',
|
|
272
|
+
'GPUShaderModule',
|
|
273
|
+
'GPUComputePipeline',
|
|
274
|
+
'GPURenderPipeline',
|
|
275
|
+
'GPUCommandEncoder',
|
|
276
|
+
'GPUComputePassEncoder',
|
|
277
|
+
'GPURenderPassEncoder',
|
|
278
|
+
'GPURenderBundleEncoder',
|
|
279
|
+
'GPUQueue',
|
|
280
|
+
'GPUQuerySet',
|
|
281
|
+
'GPUCanvasContext',
|
|
282
|
+
];
|
|
283
|
+
|
|
284
|
+
requiredWrappingGPUClasses.forEach(liftWebGPUPrototype);
|
|
285
|
+
|
|
286
|
+
let locked = false;
|
|
287
|
+
const submittedDonePromises = [];
|
|
288
|
+
protectedStorage.webGPU = {
|
|
289
|
+
lock: () => { locked = true; },
|
|
290
|
+
unlock: () => { locked = false; },
|
|
291
|
+
waitAllCommandToFinish: () => { return Promise.allSettled(submittedDonePromises); },
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// our submit keeps a global tracker of all submissions, so we can track the time of each submission
|
|
295
|
+
GPUQueue.prototype.submit = function submit(commandBuffers)
|
|
296
|
+
{
|
|
297
|
+
if (locked)
|
|
298
|
+
throw new Error('Attempted to submit webGPU queue after work function resolved');
|
|
299
|
+
underlyingSubmit.call(this, commandBuffers);
|
|
300
|
+
|
|
301
|
+
const submitTime = performance.now();
|
|
302
|
+
const submitDonePromise = underlyingOnSubmittedWorkDone.call(this).then(() => {
|
|
303
|
+
const idx = submittedDonePromises.indexOf(submitDonePromise);
|
|
304
|
+
submittedDonePromises.splice(idx);
|
|
305
|
+
|
|
306
|
+
const completedAt = performance.now();
|
|
307
|
+
const duration = new TimeInterval();
|
|
308
|
+
duration.overrideInterval(submitTime, completedAt);
|
|
309
|
+
webGPUTimer.push(duration);
|
|
310
|
+
});
|
|
311
|
+
submittedDonePromises.push(submitDonePromise);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
}
|
|
280
315
|
});
|
|
@@ -52,7 +52,7 @@ self.wrapScriptLoading({ scriptName: 'native-event-loop' }, function nativeEvent
|
|
|
52
52
|
{
|
|
53
53
|
sortTimers();
|
|
54
54
|
let timer = timers.shift();
|
|
55
|
-
let now =
|
|
55
|
+
let now = Date.now();
|
|
56
56
|
if (!timer)
|
|
57
57
|
throw new Error('Logic error: trying to run timer when no timer exists') /* should be impossible */
|
|
58
58
|
if (timer.when > now) /* should be impossible, but at least we can handle this */
|
|
@@ -65,7 +65,7 @@ self.wrapScriptLoading({ scriptName: 'native-event-loop' }, function nativeEvent
|
|
|
65
65
|
|
|
66
66
|
if (timer.recur)
|
|
67
67
|
{
|
|
68
|
-
timer.when =
|
|
68
|
+
timer.when = Date.now() + timer.recur;
|
|
69
69
|
timers.push(timer);
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -101,7 +101,7 @@ self.wrapScriptLoading({ scriptName: 'native-event-loop' }, function nativeEvent
|
|
|
101
101
|
timers.serial = +timers.serial + 1;
|
|
102
102
|
timer = {
|
|
103
103
|
fn: callback,
|
|
104
|
-
when:
|
|
104
|
+
when: Date.now() + (+timeout || 0),
|
|
105
105
|
serial: timers.serial,
|
|
106
106
|
valueOf: function () { return this.serial; }
|
|
107
107
|
}
|
|
@@ -69,6 +69,12 @@ try {
|
|
|
69
69
|
send({type: 'workerMessage', message });
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
self.close = function close()
|
|
73
|
+
{
|
|
74
|
+
writeln('DIE: worker close called');
|
|
75
|
+
die();
|
|
76
|
+
}
|
|
77
|
+
|
|
72
78
|
self.addEventListener = function workerControl$$Worker$addEventListener (type, listener) {
|
|
73
79
|
if (typeof eventListeners[type] === 'undefined') { eventListeners[type] = [] }
|
|
74
80
|
eventListeners[type].push(listener)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dcp-client",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.11-0",
|
|
4
4
|
"description": "Core libraries for accessing DCP network",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dcp"
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"polyfill-crypto.getrandomvalues": "^1.0.0",
|
|
44
44
|
"regedit": "^3.0.3",
|
|
45
45
|
"semver": "^7.3.5",
|
|
46
|
-
"webpack": "5.92.0",
|
|
47
46
|
"source-map-support": "0.5.21",
|
|
47
|
+
"webpack": "5.92.0",
|
|
48
48
|
"webpack-cli": "^4.7.2",
|
|
49
49
|
"yargs": "16.2.0"
|
|
50
50
|
},
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"@kingsds/eslint-config": "1.0.1",
|
|
53
53
|
"eslint": "7.30.0",
|
|
54
54
|
"express": "^4.18.2",
|
|
55
|
-
"peter": "2.4.
|
|
55
|
+
"peter": "2.4.7"
|
|
56
56
|
},
|
|
57
57
|
"engines": {
|
|
58
58
|
"node": ">=18",
|