mustardscript 0.1.0 → 0.1.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/README.md +62 -20
- package/SECURITY.md +1 -1
- package/dist/index.js +2 -0
- package/dist/lib/executor.js +16 -1
- package/dist/lib/policy.js +301 -22
- package/dist/lib/progress.js +499 -113
- package/dist/lib/runtime.js +109 -40
- package/dist/lib/structured.js +327 -11
- package/dist/native-loader.js +11 -12
- package/index.d.ts +54 -6
- package/mustard.d.ts +23 -1
- package/package.json +34 -25
- package/Cargo.lock +0 -1579
- package/Cargo.toml +0 -40
- package/crates/mustard/Cargo.toml +0 -31
- package/crates/mustard/src/cancellation.rs +0 -28
- package/crates/mustard/src/diagnostic.rs +0 -145
- package/crates/mustard/src/ir.rs +0 -435
- package/crates/mustard/src/lib.rs +0 -21
- package/crates/mustard/src/limits.rs +0 -22
- package/crates/mustard/src/parser/expressions.rs +0 -723
- package/crates/mustard/src/parser/mod.rs +0 -115
- package/crates/mustard/src/parser/operators.rs +0 -105
- package/crates/mustard/src/parser/patterns.rs +0 -123
- package/crates/mustard/src/parser/scope.rs +0 -107
- package/crates/mustard/src/parser/statements.rs +0 -298
- package/crates/mustard/src/parser/tests/acceptance.rs +0 -339
- package/crates/mustard/src/parser/tests/mod.rs +0 -2
- package/crates/mustard/src/parser/tests/rejections.rs +0 -107
- package/crates/mustard/src/runtime/accounting.rs +0 -613
- package/crates/mustard/src/runtime/api.rs +0 -192
- package/crates/mustard/src/runtime/async_runtime/mod.rs +0 -5
- package/crates/mustard/src/runtime/async_runtime/promises.rs +0 -246
- package/crates/mustard/src/runtime/async_runtime/reactions.rs +0 -400
- package/crates/mustard/src/runtime/async_runtime/scheduler.rs +0 -224
- package/crates/mustard/src/runtime/builtins/arrays.rs +0 -1205
- package/crates/mustard/src/runtime/builtins/collections.rs +0 -573
- package/crates/mustard/src/runtime/builtins/install.rs +0 -501
- package/crates/mustard/src/runtime/builtins/intl.rs +0 -553
- package/crates/mustard/src/runtime/builtins/mod.rs +0 -25
- package/crates/mustard/src/runtime/builtins/objects.rs +0 -405
- package/crates/mustard/src/runtime/builtins/primitives.rs +0 -859
- package/crates/mustard/src/runtime/builtins/promises.rs +0 -335
- package/crates/mustard/src/runtime/builtins/regexp.rs +0 -356
- package/crates/mustard/src/runtime/builtins/strings.rs +0 -803
- package/crates/mustard/src/runtime/builtins/support.rs +0 -561
- package/crates/mustard/src/runtime/bytecode.rs +0 -123
- package/crates/mustard/src/runtime/compiler/assignments.rs +0 -690
- package/crates/mustard/src/runtime/compiler/bindings.rs +0 -92
- package/crates/mustard/src/runtime/compiler/context.rs +0 -46
- package/crates/mustard/src/runtime/compiler/control.rs +0 -342
- package/crates/mustard/src/runtime/compiler/expressions.rs +0 -372
- package/crates/mustard/src/runtime/compiler/mod.rs +0 -173
- package/crates/mustard/src/runtime/compiler/statements.rs +0 -459
- package/crates/mustard/src/runtime/conversions/boundary.rs +0 -293
- package/crates/mustard/src/runtime/conversions/coercions.rs +0 -217
- package/crates/mustard/src/runtime/conversions/errors.rs +0 -118
- package/crates/mustard/src/runtime/conversions/mod.rs +0 -14
- package/crates/mustard/src/runtime/conversions/operators.rs +0 -334
- package/crates/mustard/src/runtime/env.rs +0 -355
- package/crates/mustard/src/runtime/exceptions.rs +0 -377
- package/crates/mustard/src/runtime/gc.rs +0 -595
- package/crates/mustard/src/runtime/mod.rs +0 -318
- package/crates/mustard/src/runtime/properties.rs +0 -1762
- package/crates/mustard/src/runtime/serialization.rs +0 -127
- package/crates/mustard/src/runtime/shared.rs +0 -108
- package/crates/mustard/src/runtime/snapshot_validation_tests.rs +0 -93
- package/crates/mustard/src/runtime/state.rs +0 -652
- package/crates/mustard/src/runtime/tests/async_host.rs +0 -104
- package/crates/mustard/src/runtime/tests/collections.rs +0 -50
- package/crates/mustard/src/runtime/tests/diagnostics.rs +0 -36
- package/crates/mustard/src/runtime/tests/exceptions.rs +0 -122
- package/crates/mustard/src/runtime/tests/execution.rs +0 -553
- package/crates/mustard/src/runtime/tests/gc.rs +0 -533
- package/crates/mustard/src/runtime/tests/mod.rs +0 -56
- package/crates/mustard/src/runtime/tests/serialization.rs +0 -170
- package/crates/mustard/src/runtime/validation/bytecode.rs +0 -484
- package/crates/mustard/src/runtime/validation/mod.rs +0 -14
- package/crates/mustard/src/runtime/validation/policy.rs +0 -94
- package/crates/mustard/src/runtime/validation/snapshot.rs +0 -406
- package/crates/mustard/src/runtime/validation/walk.rs +0 -206
- package/crates/mustard/src/runtime/vm.rs +0 -1016
- package/crates/mustard/src/span.rs +0 -22
- package/crates/mustard/src/structured.rs +0 -107
- package/crates/mustard-bridge/Cargo.toml +0 -17
- package/crates/mustard-bridge/src/codec.rs +0 -46
- package/crates/mustard-bridge/src/dto.rs +0 -99
- package/crates/mustard-bridge/src/lib.rs +0 -12
- package/crates/mustard-bridge/src/operations.rs +0 -142
- package/crates/mustard-node/Cargo.toml +0 -24
- package/crates/mustard-node/build.rs +0 -3
- package/crates/mustard-node/src/lib.rs +0 -236
- package/crates/mustard-sidecar/Cargo.toml +0 -21
- package/crates/mustard-sidecar/src/lib.rs +0 -134
- package/crates/mustard-sidecar/src/main.rs +0 -36
- package/dist/install.js +0 -117
package/dist/lib/runtime.js
CHANGED
|
@@ -7,71 +7,123 @@ const {
|
|
|
7
7
|
throwIfAborted,
|
|
8
8
|
withCancellationSignal,
|
|
9
9
|
} = require('./cancellation.js');
|
|
10
|
+
const { resolveExecutionContext } = require('./policy.js');
|
|
10
11
|
const {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const {
|
|
17
|
-
encodeResumePayloadCancel,
|
|
18
|
-
encodeResumePayloadError,
|
|
19
|
-
encodeResumePayloadValue,
|
|
20
|
-
encodeStartOptions,
|
|
12
|
+
encodeResumePayloadCancelBuffer,
|
|
13
|
+
encodeResumePayloadErrorBuffer,
|
|
14
|
+
encodeResumePayloadValueBuffer,
|
|
15
|
+
encodeStartOptionsBuffer,
|
|
16
|
+
encodeStructuredInputsBuffer,
|
|
21
17
|
} = require('./structured.js');
|
|
22
18
|
|
|
23
19
|
function createMustardClass({ native, materializeStep, parseStep }) {
|
|
20
|
+
const programHandleRegistry =
|
|
21
|
+
typeof FinalizationRegistry === 'function'
|
|
22
|
+
? new FinalizationRegistry((programHandle) => {
|
|
23
|
+
try {
|
|
24
|
+
callNative(native.releaseProgram, programHandle);
|
|
25
|
+
} catch {
|
|
26
|
+
// Best-effort cleanup only; process shutdown can race native teardown.
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
: null;
|
|
30
|
+
|
|
24
31
|
function compileProgram(code) {
|
|
25
32
|
return callNative(native.compileProgram, code);
|
|
26
33
|
}
|
|
27
34
|
|
|
35
|
+
function releaseProgram(programHandle) {
|
|
36
|
+
callNative(native.releaseProgram, programHandle);
|
|
37
|
+
}
|
|
38
|
+
|
|
28
39
|
return class Mustard {
|
|
29
40
|
constructor(code, options = {}) {
|
|
30
|
-
this.
|
|
41
|
+
this._programHandle = compileProgram(code);
|
|
42
|
+
this._program = null;
|
|
31
43
|
this._inputNames = options.inputs ?? [];
|
|
44
|
+
this._programHandleToken = {};
|
|
45
|
+
programHandleRegistry?.register(this, this._programHandle, this._programHandleToken);
|
|
32
46
|
}
|
|
33
47
|
|
|
34
48
|
static validateProgram(code) {
|
|
35
|
-
compileProgram(code);
|
|
49
|
+
const programHandle = compileProgram(code);
|
|
50
|
+
releaseProgram(programHandle);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
_ensureProgramHandle() {
|
|
54
|
+
if (this._programHandle !== null) {
|
|
55
|
+
return this._programHandle;
|
|
56
|
+
}
|
|
57
|
+
const programHandle = callNative(native.loadProgram, this._program);
|
|
58
|
+
this._programHandle = programHandle;
|
|
59
|
+
this._programHandleToken = {};
|
|
60
|
+
programHandleRegistry?.register(this, programHandle, this._programHandleToken);
|
|
61
|
+
return programHandle;
|
|
36
62
|
}
|
|
37
63
|
|
|
38
64
|
async run(options = {}) {
|
|
39
65
|
const signal = getAbortSignal(options, 'run options');
|
|
40
66
|
throwIfAborted(signal);
|
|
41
|
-
const { hostHandlers, policy,
|
|
67
|
+
const { hostHandlers, policy, nativeContextHandle } = resolveExecutionContext(
|
|
68
|
+
options,
|
|
69
|
+
'run options',
|
|
70
|
+
);
|
|
71
|
+
const programHandle = this._ensureProgramHandle();
|
|
72
|
+
const startProgram =
|
|
73
|
+
typeof nativeContextHandle === 'string' && nativeContextHandle.length > 0
|
|
74
|
+
? native.startProgramWithExecutionContextHandleBuffer
|
|
75
|
+
: native.startProgramWithSnapshotHandleBuffer;
|
|
76
|
+
const startArgs =
|
|
77
|
+
typeof nativeContextHandle === 'string' && nativeContextHandle.length > 0
|
|
78
|
+
? [programHandle, nativeContextHandle, encodeStructuredInputsBuffer(options.inputs)]
|
|
79
|
+
: [programHandle, encodeStartOptionsBuffer(options.inputs, policy)];
|
|
42
80
|
let step = parseStep(
|
|
43
81
|
withCancellationSignal(
|
|
44
82
|
native,
|
|
45
|
-
|
|
46
|
-
|
|
83
|
+
startProgram,
|
|
84
|
+
startArgs,
|
|
47
85
|
signal,
|
|
48
86
|
),
|
|
49
87
|
);
|
|
50
88
|
while (step.type === 'suspended') {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
89
|
+
const snapshotHandle = step.snapshotHandle;
|
|
90
|
+
try {
|
|
91
|
+
const capability = hostHandlers[step.capability];
|
|
92
|
+
if (typeof capability !== 'function') {
|
|
93
|
+
throw new Error(`Missing capability: ${step.capability}`);
|
|
94
|
+
}
|
|
95
|
+
const outcome = await settleCapabilityInvocation(capability, step.args, signal);
|
|
96
|
+
if (outcome.type === 'cancelled') {
|
|
97
|
+
step = parseStep(
|
|
98
|
+
callNative(
|
|
99
|
+
native.resumeSnapshotHandleBuffer,
|
|
100
|
+
snapshotHandle,
|
|
101
|
+
encodeResumePayloadCancelBuffer(),
|
|
102
|
+
),
|
|
103
|
+
);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const payload =
|
|
107
|
+
outcome.type === 'value'
|
|
108
|
+
? encodeResumePayloadValueBuffer(outcome.value)
|
|
109
|
+
: encodeResumePayloadErrorBuffer(outcome.error);
|
|
63
110
|
step = parseStep(
|
|
64
|
-
|
|
111
|
+
withCancellationSignal(
|
|
112
|
+
native,
|
|
113
|
+
native.resumeSnapshotHandleBuffer,
|
|
114
|
+
[snapshotHandle, payload],
|
|
115
|
+
signal,
|
|
116
|
+
),
|
|
65
117
|
);
|
|
66
|
-
|
|
118
|
+
} finally {
|
|
119
|
+
if (typeof snapshotHandle === 'string' && snapshotHandle.length > 0) {
|
|
120
|
+
try {
|
|
121
|
+
callNative(native.releaseSnapshotHandle, snapshotHandle);
|
|
122
|
+
} catch {
|
|
123
|
+
// Best-effort cleanup only.
|
|
124
|
+
}
|
|
125
|
+
}
|
|
67
126
|
}
|
|
68
|
-
const payload =
|
|
69
|
-
outcome.type === 'value'
|
|
70
|
-
? encodeResumePayloadValue(outcome.value)
|
|
71
|
-
: encodeResumePayloadError(outcome.error);
|
|
72
|
-
step = parseStep(
|
|
73
|
-
withCancellationSignal(native, native.resumeProgram, [step.snapshot, payload, policyJson], signal),
|
|
74
|
-
);
|
|
75
127
|
}
|
|
76
128
|
return step.value;
|
|
77
129
|
}
|
|
@@ -79,26 +131,43 @@ function createMustardClass({ native, materializeStep, parseStep }) {
|
|
|
79
131
|
start(options = {}) {
|
|
80
132
|
const signal = getAbortSignal(options, 'start options');
|
|
81
133
|
throwIfAborted(signal);
|
|
82
|
-
const { policy, snapshotKey } =
|
|
134
|
+
const { policy, snapshotKey, nativeContextHandle } = resolveExecutionContext(
|
|
135
|
+
options,
|
|
136
|
+
'start options',
|
|
137
|
+
);
|
|
138
|
+
const programHandle = this._ensureProgramHandle();
|
|
139
|
+
const startProgram =
|
|
140
|
+
typeof nativeContextHandle === 'string' && nativeContextHandle.length > 0
|
|
141
|
+
? native.startProgramWithExecutionContextHandleBuffer
|
|
142
|
+
: native.startProgramWithSnapshotHandleBuffer;
|
|
143
|
+
const startArgs =
|
|
144
|
+
typeof nativeContextHandle === 'string' && nativeContextHandle.length > 0
|
|
145
|
+
? [programHandle, nativeContextHandle, encodeStructuredInputsBuffer(options.inputs)]
|
|
146
|
+
: [programHandle, encodeStartOptionsBuffer(options.inputs, policy)];
|
|
83
147
|
const step = parseStep(
|
|
84
148
|
withCancellationSignal(
|
|
85
149
|
native,
|
|
86
|
-
|
|
87
|
-
|
|
150
|
+
startProgram,
|
|
151
|
+
startArgs,
|
|
88
152
|
signal,
|
|
89
153
|
),
|
|
90
154
|
);
|
|
91
|
-
return materializeStep(step, policy, snapshotKey);
|
|
155
|
+
return materializeStep(step, policy, snapshotKey, programHandle);
|
|
92
156
|
}
|
|
93
157
|
|
|
94
158
|
dump() {
|
|
159
|
+
if (this._program === null) {
|
|
160
|
+
this._program = Buffer.from(callNative(native.dumpProgram, this._ensureProgramHandle()));
|
|
161
|
+
}
|
|
95
162
|
return Buffer.from(this._program);
|
|
96
163
|
}
|
|
97
164
|
|
|
98
165
|
static load(buffer) {
|
|
99
166
|
const instance = Object.create(Mustard.prototype);
|
|
100
167
|
instance._program = Buffer.from(buffer);
|
|
168
|
+
instance._programHandle = null;
|
|
101
169
|
instance._inputNames = [];
|
|
170
|
+
instance._programHandleToken = {};
|
|
102
171
|
return instance;
|
|
103
172
|
}
|
|
104
173
|
};
|
package/dist/lib/structured.js
CHANGED
|
@@ -4,6 +4,104 @@ const { types } = require('node:util');
|
|
|
4
4
|
|
|
5
5
|
const HOST_BOUNDARY_MAX_DEPTH = 128;
|
|
6
6
|
const HOST_BOUNDARY_MAX_ARRAY_LENGTH = 1_000_000;
|
|
7
|
+
const encodedStartOptionsSuffixCache = new WeakMap();
|
|
8
|
+
const encodedStartOptionsBinarySuffixCache = new WeakMap();
|
|
9
|
+
const BOUNDARY_BINARY_MAGIC = Buffer.from([0x4d, 0x53, 0x42, 0x01]);
|
|
10
|
+
const BOUNDARY_BINARY_KIND = Object.freeze({
|
|
11
|
+
START_OPTIONS: 1,
|
|
12
|
+
STRUCTURED_INPUTS: 2,
|
|
13
|
+
RESUME_PAYLOAD: 3,
|
|
14
|
+
});
|
|
15
|
+
const STRUCTURED_BINARY_TAG = Object.freeze({
|
|
16
|
+
UNDEFINED: 0,
|
|
17
|
+
NULL: 1,
|
|
18
|
+
HOLE: 2,
|
|
19
|
+
BOOL_FALSE: 3,
|
|
20
|
+
BOOL_TRUE: 4,
|
|
21
|
+
STRING: 5,
|
|
22
|
+
NUMBER_FINITE: 6,
|
|
23
|
+
NUMBER_NAN: 7,
|
|
24
|
+
NUMBER_INFINITY: 8,
|
|
25
|
+
NUMBER_NEG_INFINITY: 9,
|
|
26
|
+
NUMBER_NEG_ZERO: 10,
|
|
27
|
+
ARRAY: 11,
|
|
28
|
+
OBJECT: 12,
|
|
29
|
+
});
|
|
30
|
+
const RESUME_BINARY_TAG = Object.freeze({
|
|
31
|
+
VALUE: 0,
|
|
32
|
+
ERROR: 1,
|
|
33
|
+
CANCELLED: 2,
|
|
34
|
+
});
|
|
35
|
+
const LIMIT_FIELD_LAYOUT = Object.freeze([
|
|
36
|
+
['instruction_budget', 1 << 0],
|
|
37
|
+
['heap_limit_bytes', 1 << 1],
|
|
38
|
+
['allocation_budget', 1 << 2],
|
|
39
|
+
['call_depth_limit', 1 << 3],
|
|
40
|
+
['max_outstanding_host_calls', 1 << 4],
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
class BinaryWriter {
|
|
44
|
+
constructor(initialSize = 256) {
|
|
45
|
+
this._buffer = Buffer.allocUnsafe(initialSize);
|
|
46
|
+
this._offset = 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
_ensureCapacity(additionalBytes) {
|
|
50
|
+
const required = this._offset + additionalBytes;
|
|
51
|
+
if (required <= this._buffer.length) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
let nextLength = this._buffer.length;
|
|
55
|
+
while (nextLength < required) {
|
|
56
|
+
nextLength *= 2;
|
|
57
|
+
}
|
|
58
|
+
const nextBuffer = Buffer.allocUnsafe(nextLength);
|
|
59
|
+
this._buffer.copy(nextBuffer, 0, 0, this._offset);
|
|
60
|
+
this._buffer = nextBuffer;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
writeHeader(kind) {
|
|
64
|
+
this.writeBuffer(BOUNDARY_BINARY_MAGIC);
|
|
65
|
+
this.writeU8(kind);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
writeBuffer(value) {
|
|
69
|
+
const buffer = Buffer.from(value);
|
|
70
|
+
this._ensureCapacity(buffer.length);
|
|
71
|
+
buffer.copy(this._buffer, this._offset);
|
|
72
|
+
this._offset += buffer.length;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
writeU8(value) {
|
|
76
|
+
this._ensureCapacity(1);
|
|
77
|
+
this._buffer.writeUInt8(value, this._offset);
|
|
78
|
+
this._offset += 1;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
writeU32(value) {
|
|
82
|
+
this._ensureCapacity(4);
|
|
83
|
+
this._buffer.writeUInt32LE(value >>> 0, this._offset);
|
|
84
|
+
this._offset += 4;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
writeF64(value) {
|
|
88
|
+
this._ensureCapacity(8);
|
|
89
|
+
this._buffer.writeDoubleLE(value, this._offset);
|
|
90
|
+
this._offset += 8;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
writeString(value) {
|
|
94
|
+
const byteLength = Buffer.byteLength(value, 'utf8');
|
|
95
|
+
this.writeU32(byteLength);
|
|
96
|
+
this._ensureCapacity(byteLength);
|
|
97
|
+
this._buffer.write(value, this._offset, byteLength, 'utf8');
|
|
98
|
+
this._offset += byteLength;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
toBuffer() {
|
|
102
|
+
return Buffer.from(this._buffer.subarray(0, this._offset));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
7
105
|
|
|
8
106
|
function assertBoundaryDepth(depth, label) {
|
|
9
107
|
if (depth > HOST_BOUNDARY_MAX_DEPTH) {
|
|
@@ -73,15 +171,22 @@ function isAccessorDescriptor(descriptor) {
|
|
|
73
171
|
|
|
74
172
|
function enumerateDataProperties(value) {
|
|
75
173
|
assertNotProxy(value);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
174
|
+
const keys = Object.keys(value);
|
|
175
|
+
const entries = new Array(keys.length);
|
|
176
|
+
let entryCount = 0;
|
|
177
|
+
for (const key of keys) {
|
|
178
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
179
|
+
if (descriptor === undefined) {
|
|
180
|
+
continue;
|
|
79
181
|
}
|
|
80
182
|
if (isAccessorDescriptor(descriptor)) {
|
|
81
183
|
throw new TypeError('host objects with accessors cannot cross the host boundary');
|
|
82
184
|
}
|
|
83
|
-
|
|
84
|
-
|
|
185
|
+
entries[entryCount] = [key, descriptor];
|
|
186
|
+
entryCount += 1;
|
|
187
|
+
}
|
|
188
|
+
entries.length = entryCount;
|
|
189
|
+
return entries;
|
|
85
190
|
}
|
|
86
191
|
|
|
87
192
|
function enterStructuredTraversal(value, traversal) {
|
|
@@ -218,16 +323,178 @@ function decodeStructured(value, depth = 1) {
|
|
|
218
323
|
throw new TypeError(`Unsupported structured value: ${JSON.stringify(value)}`);
|
|
219
324
|
}
|
|
220
325
|
|
|
221
|
-
function
|
|
326
|
+
function getEncodedStartOptionsSuffix(policy) {
|
|
327
|
+
let cached = encodedStartOptionsSuffixCache.get(policy);
|
|
328
|
+
if (cached !== undefined) {
|
|
329
|
+
return cached;
|
|
330
|
+
}
|
|
331
|
+
cached =
|
|
332
|
+
`,"capabilities":${JSON.stringify(policy.capabilities)}` +
|
|
333
|
+
`,"limits":${JSON.stringify(policy.limits)}}`;
|
|
334
|
+
encodedStartOptionsSuffixCache.set(policy, cached);
|
|
335
|
+
return cached;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function writeLimitValue(writer, value) {
|
|
339
|
+
writer.writeF64(value);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function writeEncodedLimits(writer, limits = {}) {
|
|
343
|
+
let mask = 0;
|
|
344
|
+
for (const [field, bit] of LIMIT_FIELD_LAYOUT) {
|
|
345
|
+
if (limits[field] !== undefined) {
|
|
346
|
+
mask |= bit;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
writer.writeU8(mask);
|
|
350
|
+
for (const [field, bit] of LIMIT_FIELD_LAYOUT) {
|
|
351
|
+
if ((mask & bit) !== 0) {
|
|
352
|
+
writeLimitValue(writer, limits[field]);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function writeEncodedCapabilities(writer, capabilities = []) {
|
|
358
|
+
writer.writeU32(capabilities.length);
|
|
359
|
+
for (const capability of capabilities) {
|
|
360
|
+
writer.writeString(capability);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function getEncodedStartOptionsBinarySuffix(policy) {
|
|
365
|
+
let cached = encodedStartOptionsBinarySuffixCache.get(policy);
|
|
366
|
+
if (cached !== undefined) {
|
|
367
|
+
return cached;
|
|
368
|
+
}
|
|
369
|
+
const writer = new BinaryWriter();
|
|
370
|
+
writeEncodedCapabilities(writer, policy.capabilities);
|
|
371
|
+
writeEncodedLimits(writer, policy.limits);
|
|
372
|
+
cached = writer.toBuffer();
|
|
373
|
+
encodedStartOptionsBinarySuffixCache.set(policy, cached);
|
|
374
|
+
return cached;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function writeStructured(value, writer, traversal = { active: new WeakSet() }, depth = 1) {
|
|
378
|
+
assertBoundaryDepth(depth, 'host boundary');
|
|
379
|
+
if (value === undefined) {
|
|
380
|
+
writer.writeU8(STRUCTURED_BINARY_TAG.UNDEFINED);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
if (value === null) {
|
|
384
|
+
writer.writeU8(STRUCTURED_BINARY_TAG.NULL);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (typeof value === 'boolean') {
|
|
388
|
+
writer.writeU8(value ? STRUCTURED_BINARY_TAG.BOOL_TRUE : STRUCTURED_BINARY_TAG.BOOL_FALSE);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (typeof value === 'number') {
|
|
392
|
+
if (Number.isNaN(value)) {
|
|
393
|
+
writer.writeU8(STRUCTURED_BINARY_TAG.NUMBER_NAN);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (Object.is(value, -0)) {
|
|
397
|
+
writer.writeU8(STRUCTURED_BINARY_TAG.NUMBER_NEG_ZERO);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
if (value === Infinity) {
|
|
401
|
+
writer.writeU8(STRUCTURED_BINARY_TAG.NUMBER_INFINITY);
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
if (value === -Infinity) {
|
|
405
|
+
writer.writeU8(STRUCTURED_BINARY_TAG.NUMBER_NEG_INFINITY);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
writer.writeU8(STRUCTURED_BINARY_TAG.NUMBER_FINITE);
|
|
409
|
+
writer.writeF64(value);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (typeof value === 'string') {
|
|
413
|
+
writer.writeU8(STRUCTURED_BINARY_TAG.STRING);
|
|
414
|
+
writer.writeString(value);
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
if (Array.isArray(value)) {
|
|
418
|
+
assertNotProxy(value);
|
|
419
|
+
assertBoundaryArrayLength(value.length, 'host boundary');
|
|
420
|
+
writer.writeU8(STRUCTURED_BINARY_TAG.ARRAY);
|
|
421
|
+
writer.writeU32(value.length);
|
|
422
|
+
const leave = enterStructuredTraversal(value, traversal);
|
|
423
|
+
try {
|
|
424
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
425
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
426
|
+
if (descriptor === undefined) {
|
|
427
|
+
writer.writeU8(STRUCTURED_BINARY_TAG.HOLE);
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
if (isAccessorDescriptor(descriptor)) {
|
|
431
|
+
throw new TypeError('host objects with accessors cannot cross the host boundary');
|
|
432
|
+
}
|
|
433
|
+
writeStructured(descriptor.value, writer, traversal, depth + 1);
|
|
434
|
+
}
|
|
435
|
+
} finally {
|
|
436
|
+
leave();
|
|
437
|
+
}
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (typeof value === 'object') {
|
|
441
|
+
if (!isPlainStructuredObject(value)) {
|
|
442
|
+
throw new TypeError(
|
|
443
|
+
'Unsupported host value: only plain objects and arrays can cross the host boundary',
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
writer.writeU8(STRUCTURED_BINARY_TAG.OBJECT);
|
|
447
|
+
const entries = enumerateDataProperties(value);
|
|
448
|
+
writer.writeU32(entries.length);
|
|
449
|
+
const leave = enterStructuredTraversal(value, traversal);
|
|
450
|
+
try {
|
|
451
|
+
for (const [key, descriptor] of entries) {
|
|
452
|
+
writer.writeString(key);
|
|
453
|
+
writeStructured(descriptor.value, writer, traversal, depth + 1);
|
|
454
|
+
}
|
|
455
|
+
} finally {
|
|
456
|
+
leave();
|
|
457
|
+
}
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
throw new TypeError('Unsupported host value');
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function writeStructuredInputEntries(writer, inputs = {}) {
|
|
464
|
+
const entries = enumerateDataProperties(inputs);
|
|
465
|
+
writer.writeU32(entries.length);
|
|
466
|
+
for (const [key, descriptor] of entries) {
|
|
467
|
+
writer.writeString(key);
|
|
468
|
+
writeStructured(descriptor.value, writer);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function encodeStructuredInputs(inputs = {}) {
|
|
222
473
|
const encodedInputs = {};
|
|
223
474
|
for (const [key, descriptor] of enumerateDataProperties(inputs)) {
|
|
224
475
|
defineEnumerableProperty(encodedInputs, key, encodeStructured(descriptor.value));
|
|
225
476
|
}
|
|
226
|
-
return JSON.stringify(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
477
|
+
return JSON.stringify(encodedInputs);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function encodeStartOptions(inputs = {}, policy) {
|
|
481
|
+
const encodedInputs = encodeStructuredInputs(inputs);
|
|
482
|
+
return `{"inputs":${encodedInputs}${getEncodedStartOptionsSuffix(policy)}`;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function encodeStructuredInputsBuffer(inputs = {}) {
|
|
486
|
+
const writer = new BinaryWriter();
|
|
487
|
+
writer.writeHeader(BOUNDARY_BINARY_KIND.STRUCTURED_INPUTS);
|
|
488
|
+
writeStructuredInputEntries(writer, inputs);
|
|
489
|
+
return writer.toBuffer();
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function encodeStartOptionsBuffer(inputs = {}, policy) {
|
|
493
|
+
const writer = new BinaryWriter();
|
|
494
|
+
writer.writeHeader(BOUNDARY_BINARY_KIND.START_OPTIONS);
|
|
495
|
+
writeStructuredInputEntries(writer, inputs);
|
|
496
|
+
writer.writeBuffer(getEncodedStartOptionsBinarySuffix(policy));
|
|
497
|
+
return writer.toBuffer();
|
|
231
498
|
}
|
|
232
499
|
|
|
233
500
|
function encodeResumePayloadValue(value) {
|
|
@@ -237,6 +504,14 @@ function encodeResumePayloadValue(value) {
|
|
|
237
504
|
});
|
|
238
505
|
}
|
|
239
506
|
|
|
507
|
+
function encodeResumePayloadValueBuffer(value) {
|
|
508
|
+
const writer = new BinaryWriter();
|
|
509
|
+
writer.writeHeader(BOUNDARY_BINARY_KIND.RESUME_PAYLOAD);
|
|
510
|
+
writer.writeU8(RESUME_BINARY_TAG.VALUE);
|
|
511
|
+
writeStructured(value, writer);
|
|
512
|
+
return writer.toBuffer();
|
|
513
|
+
}
|
|
514
|
+
|
|
240
515
|
function readOwnDataProperty(value, key, label) {
|
|
241
516
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
242
517
|
if (descriptor === undefined) {
|
|
@@ -266,19 +541,60 @@ function encodeResumePayloadError(error) {
|
|
|
266
541
|
});
|
|
267
542
|
}
|
|
268
543
|
|
|
544
|
+
function encodeResumePayloadErrorBuffer(error) {
|
|
545
|
+
const source = error instanceof Error ? error : Object(error);
|
|
546
|
+
assertNotProxy(source);
|
|
547
|
+
const name = readOwnDataProperty(source, 'name', 'host errors');
|
|
548
|
+
const message = readOwnDataProperty(source, 'message', 'host errors');
|
|
549
|
+
const code = readOwnDataProperty(source, 'code', 'host errors');
|
|
550
|
+
const details = readOwnDataProperty(source, 'details', 'host errors');
|
|
551
|
+
const writer = new BinaryWriter();
|
|
552
|
+
writer.writeHeader(BOUNDARY_BINARY_KIND.RESUME_PAYLOAD);
|
|
553
|
+
writer.writeU8(RESUME_BINARY_TAG.ERROR);
|
|
554
|
+
writer.writeString(typeof name === 'string' ? name : 'Error');
|
|
555
|
+
writer.writeString(typeof message === 'string' ? message : '');
|
|
556
|
+
if (typeof code === 'string') {
|
|
557
|
+
writer.writeU8(1);
|
|
558
|
+
writer.writeString(code);
|
|
559
|
+
} else {
|
|
560
|
+
writer.writeU8(0);
|
|
561
|
+
}
|
|
562
|
+
if (details === undefined) {
|
|
563
|
+
writer.writeU8(0);
|
|
564
|
+
} else {
|
|
565
|
+
writer.writeU8(1);
|
|
566
|
+
writeStructured(details, writer);
|
|
567
|
+
}
|
|
568
|
+
return writer.toBuffer();
|
|
569
|
+
}
|
|
570
|
+
|
|
269
571
|
function encodeResumePayloadCancel() {
|
|
270
572
|
return JSON.stringify({
|
|
271
573
|
type: 'cancelled',
|
|
272
574
|
});
|
|
273
575
|
}
|
|
274
576
|
|
|
577
|
+
function encodeResumePayloadCancelBuffer() {
|
|
578
|
+
const writer = new BinaryWriter();
|
|
579
|
+
writer.writeHeader(BOUNDARY_BINARY_KIND.RESUME_PAYLOAD);
|
|
580
|
+
writer.writeU8(RESUME_BINARY_TAG.CANCELLED);
|
|
581
|
+
return writer.toBuffer();
|
|
582
|
+
}
|
|
583
|
+
|
|
275
584
|
module.exports = {
|
|
585
|
+
BOUNDARY_BINARY_KIND,
|
|
276
586
|
decodeStructured,
|
|
277
587
|
defineEnumerableProperty,
|
|
278
588
|
encodeResumePayloadCancel,
|
|
589
|
+
encodeResumePayloadCancelBuffer,
|
|
279
590
|
encodeResumePayloadError,
|
|
591
|
+
encodeResumePayloadErrorBuffer,
|
|
280
592
|
encodeResumePayloadValue,
|
|
593
|
+
encodeResumePayloadValueBuffer,
|
|
281
594
|
encodeStartOptions,
|
|
595
|
+
encodeStartOptionsBuffer,
|
|
596
|
+
encodeStructuredInputs,
|
|
597
|
+
encodeStructuredInputsBuffer,
|
|
282
598
|
encodeStructured,
|
|
283
599
|
enumerateDataProperties,
|
|
284
600
|
hasOwnProperty,
|
package/dist/native-loader.js
CHANGED
|
@@ -13,7 +13,7 @@ const PREBUILT_TARGETS = Object.freeze([
|
|
|
13
13
|
platform: 'win32',
|
|
14
14
|
arch: 'x64',
|
|
15
15
|
platformArchABI: 'win32-x64-msvc',
|
|
16
|
-
packageName: 'mustardscript-win32-x64-msvc',
|
|
16
|
+
packageName: '@mustardscript/binding-win32-x64-msvc',
|
|
17
17
|
localFile: 'index.win32-x64-msvc.node',
|
|
18
18
|
os: ['win32'],
|
|
19
19
|
cpu: ['x64'],
|
|
@@ -23,7 +23,7 @@ const PREBUILT_TARGETS = Object.freeze([
|
|
|
23
23
|
platform: 'darwin',
|
|
24
24
|
arch: 'x64',
|
|
25
25
|
platformArchABI: 'darwin-x64',
|
|
26
|
-
packageName: 'mustardscript-darwin-x64',
|
|
26
|
+
packageName: '@mustardscript/binding-darwin-x64',
|
|
27
27
|
localFile: 'index.darwin-x64.node',
|
|
28
28
|
os: ['darwin'],
|
|
29
29
|
cpu: ['x64'],
|
|
@@ -33,7 +33,7 @@ const PREBUILT_TARGETS = Object.freeze([
|
|
|
33
33
|
platform: 'darwin',
|
|
34
34
|
arch: 'arm64',
|
|
35
35
|
platformArchABI: 'darwin-arm64',
|
|
36
|
-
packageName: 'mustardscript-darwin-arm64',
|
|
36
|
+
packageName: '@mustardscript/binding-darwin-arm64',
|
|
37
37
|
localFile: 'index.darwin-arm64.node',
|
|
38
38
|
os: ['darwin'],
|
|
39
39
|
cpu: ['arm64'],
|
|
@@ -43,7 +43,7 @@ const PREBUILT_TARGETS = Object.freeze([
|
|
|
43
43
|
platform: 'linux',
|
|
44
44
|
arch: 'x64',
|
|
45
45
|
platformArchABI: 'linux-x64-gnu',
|
|
46
|
-
packageName: 'mustardscript-linux-x64-gnu',
|
|
46
|
+
packageName: '@mustardscript/binding-linux-x64-gnu',
|
|
47
47
|
localFile: 'index.linux-x64-gnu.node',
|
|
48
48
|
os: ['linux'],
|
|
49
49
|
cpu: ['x64'],
|
|
@@ -90,11 +90,7 @@ function getCurrentPrebuiltTarget() {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
function getLocalBuildOutputFile() {
|
|
93
|
-
return getCurrentPrebuiltTarget()?.localFile ??
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function getLocalBinaryFilenames() {
|
|
97
|
-
return [...new Set([getLocalBuildOutputFile(), 'index.node'])];
|
|
93
|
+
return getCurrentPrebuiltTarget()?.localFile ?? null;
|
|
98
94
|
}
|
|
99
95
|
|
|
100
96
|
function validatePrebuiltPackageManifest(manifest, target, packageJsonPath) {
|
|
@@ -155,7 +151,11 @@ function localBinaryCandidates(searchRoot = packageRoot()) {
|
|
|
155
151
|
continue;
|
|
156
152
|
}
|
|
157
153
|
|
|
158
|
-
|
|
154
|
+
const localFile = getLocalBuildOutputFile();
|
|
155
|
+
if (!localFile) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
for (const filename of [localFile]) {
|
|
159
159
|
const candidate = path.join(root, filename);
|
|
160
160
|
const stats = fs.statSync(candidate, { throwIfNoEntry: false });
|
|
161
161
|
if (stats?.isFile()) {
|
|
@@ -211,14 +211,13 @@ function loadNative(options = {}) {
|
|
|
211
211
|
: `${process.platform}-${process.arch}`;
|
|
212
212
|
throw new AggregateError(
|
|
213
213
|
loadErrors,
|
|
214
|
-
`Unable to locate a MustardScript native addon for ${platformHint}. Install a matching
|
|
214
|
+
`Unable to locate a MustardScript native addon for ${platformHint}. Install a matching prebuilt package for this platform.`,
|
|
215
215
|
);
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
module.exports = {
|
|
219
219
|
PREBUILT_TARGETS,
|
|
220
220
|
getCurrentPrebuiltTarget,
|
|
221
|
-
getLocalBinaryFilenames,
|
|
222
221
|
getLocalBuildOutputFile,
|
|
223
222
|
localBinaryCandidates,
|
|
224
223
|
resolveNativeAddonPath,
|