@rsvelte/vite-plugin-svelte-native 0.2.6 → 0.2.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/envelope.js +6 -9
- package/index.cjs +5 -3
- package/lib/bounds-check.js +38 -0
- package/package.json +7 -6
- package/parse-envelope.js +100 -4
package/envelope.js
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
+
const { isWindowOutOfBounds, windowOutOfBoundsMessage } = require('./lib/bounds-check.js');
|
|
16
|
+
|
|
15
17
|
const MAGIC = 0x31565352; // "RSV1" little-endian
|
|
16
18
|
const VERSION = 1;
|
|
17
19
|
const HEADER_LEN = 60;
|
|
@@ -27,10 +29,8 @@ const WARN_HAS_FRAME = 1 << 3;
|
|
|
27
29
|
|
|
28
30
|
/**
|
|
29
31
|
* Validate that the byte window `[off, off + len)` lies fully inside a
|
|
30
|
-
* buffer of `bufLen` bytes
|
|
31
|
-
*
|
|
32
|
-
* silently *clamp* an out-of-range window, so a malformed envelope would
|
|
33
|
-
* decode to truncated data instead of failing loudly. Throw instead (M-012).
|
|
32
|
+
* buffer of `bufLen` bytes (see `./lib/bounds-check.js` for why this must
|
|
33
|
+
* throw rather than let `toString`/`subarray` clamp silently — M-012).
|
|
34
34
|
*
|
|
35
35
|
* @param {number} bufLen
|
|
36
36
|
* @param {number} off
|
|
@@ -38,11 +38,8 @@ const WARN_HAS_FRAME = 1 << 3;
|
|
|
38
38
|
* @param {string} label
|
|
39
39
|
*/
|
|
40
40
|
function assertWindow(bufLen, off, len, label) {
|
|
41
|
-
if (off
|
|
42
|
-
throw new Error(
|
|
43
|
-
`[rsvelte] envelope ${label} out of bounds ` +
|
|
44
|
-
`(offset ${off} + length ${len} exceeds buffer of ${bufLen} bytes)`,
|
|
45
|
-
);
|
|
41
|
+
if (isWindowOutOfBounds(off, len, bufLen)) {
|
|
42
|
+
throw new Error(`[rsvelte] envelope ${windowOutOfBoundsMessage(label, off, len, bufLen)}`);
|
|
46
43
|
}
|
|
47
44
|
}
|
|
48
45
|
|
package/index.cjs
CHANGED
|
@@ -137,6 +137,8 @@ module.exports.parseEnvelope = binding.parseEnvelope;
|
|
|
137
137
|
module.exports.decodeParseEnvelope = decodeParseEnvelope;
|
|
138
138
|
// Upstream Svelte version this binding emits code for — used by
|
|
139
139
|
// downstream consumers (the `@rsvelte/vite-plugin-svelte` fork, etc.)
|
|
140
|
-
// for `gte(VERSION, '5.36.0')`-style feature detection.
|
|
141
|
-
//
|
|
142
|
-
|
|
140
|
+
// for `gte(VERSION, '5.36.0')`-style feature detection. Kept in sync
|
|
141
|
+
// with `submodules/svelte/packages/svelte/package.json` by hand; run
|
|
142
|
+
// `node scripts/dev/check-vps-version.mjs` (also wired into CI) to
|
|
143
|
+
// catch drift.
|
|
144
|
+
module.exports.VERSION = '5.56.4';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Shared bounds-check primitive for the two raw-transfer envelope decoders
|
|
2
|
+
// (`../envelope.js` for `compileEnvelope`/`compileModuleEnvelope`, and
|
|
3
|
+
// `../parse-envelope.js` for `parseEnvelope`). Both wire formats encode
|
|
4
|
+
// offsets/lengths as u32s that the decoder otherwise trusts blindly —
|
|
5
|
+
// `Buffer.toString` / `Uint8Array.subarray` silently *clamp* an
|
|
6
|
+
// out-of-range window instead of throwing, so a malformed envelope would
|
|
7
|
+
// decode to truncated/misaligned data rather than failing loudly (M-012).
|
|
8
|
+
//
|
|
9
|
+
// Each decoder wraps this in its own `assertWindow` helper so it can throw
|
|
10
|
+
// its own Error subtype with its own message prefix (`[rsvelte] envelope …`
|
|
11
|
+
// vs `parse envelope: …`) while sharing the actual bounds arithmetic and
|
|
12
|
+
// message body.
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {number} off
|
|
18
|
+
* @param {number} len
|
|
19
|
+
* @param {number} bufLen
|
|
20
|
+
* @returns {boolean} true when the byte window `[off, off + len)` does NOT
|
|
21
|
+
* lie fully inside a buffer of `bufLen` bytes.
|
|
22
|
+
*/
|
|
23
|
+
function isWindowOutOfBounds(off, len, bufLen) {
|
|
24
|
+
return off < 0 || len < 0 || off + len > bufLen;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {string} label
|
|
29
|
+
* @param {number} off
|
|
30
|
+
* @param {number} len
|
|
31
|
+
* @param {number} bufLen
|
|
32
|
+
* @returns {string}
|
|
33
|
+
*/
|
|
34
|
+
function windowOutOfBoundsMessage(label, off, len, bufLen) {
|
|
35
|
+
return `${label} out of bounds (offset ${off} + length ${len} exceeds buffer of ${bufLen} bytes)`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = { isWindowOutOfBounds, windowOutOfBoundsMessage };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rsvelte/vite-plugin-svelte-native",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "NAPI bindings to the rsvelte compiler — used by the @rsvelte vite-plugin-svelte shim",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -24,15 +24,16 @@
|
|
|
24
24
|
"files": [
|
|
25
25
|
"envelope.js",
|
|
26
26
|
"parse-envelope.js",
|
|
27
|
+
"lib/bounds-check.js",
|
|
27
28
|
"index.cjs",
|
|
28
29
|
"index.d.ts"
|
|
29
30
|
],
|
|
30
31
|
"optionalDependencies": {
|
|
31
|
-
"@rsvelte/vite-plugin-svelte-native-darwin-arm64": "^0.2.
|
|
32
|
-
"@rsvelte/vite-plugin-svelte-native-darwin-x64": "^0.2.
|
|
33
|
-
"@rsvelte/vite-plugin-svelte-native-linux-arm64-gnu": "^0.2.
|
|
34
|
-
"@rsvelte/vite-plugin-svelte-native-linux-x64-gnu": "^0.2.
|
|
35
|
-
"@rsvelte/vite-plugin-svelte-native-win32-x64-msvc": "^0.2.
|
|
32
|
+
"@rsvelte/vite-plugin-svelte-native-darwin-arm64": "^0.2.8",
|
|
33
|
+
"@rsvelte/vite-plugin-svelte-native-darwin-x64": "^0.2.8",
|
|
34
|
+
"@rsvelte/vite-plugin-svelte-native-linux-arm64-gnu": "^0.2.8",
|
|
35
|
+
"@rsvelte/vite-plugin-svelte-native-linux-x64-gnu": "^0.2.8",
|
|
36
|
+
"@rsvelte/vite-plugin-svelte-native-win32-x64-msvc": "^0.2.8"
|
|
36
37
|
},
|
|
37
38
|
"publishConfig": {
|
|
38
39
|
"access": "public"
|
package/parse-envelope.js
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
+
const { isWindowOutOfBounds, windowOutOfBoundsMessage } = require('./lib/bounds-check.js');
|
|
16
|
+
|
|
15
17
|
const MAGIC = 0x3156_5052; // "RPV1" little-endian
|
|
16
18
|
const VERSION = 1;
|
|
17
19
|
const HEADER_LEN = 24;
|
|
@@ -74,7 +76,7 @@ const TAG_AWAIT_BLOCK = 0x72;
|
|
|
74
76
|
const TAG_KEY_BLOCK = 0x73;
|
|
75
77
|
const TAG_SNIPPET_BLOCK = 0x74;
|
|
76
78
|
|
|
77
|
-
// JsNode (estree) tags — 0x80..
|
|
79
|
+
// JsNode (estree) tags — 0x80..0xCC. Mirrors `napi_raw_parse.rs`.
|
|
78
80
|
const JS_IDENTIFIER = 0x80;
|
|
79
81
|
const JS_PRIVATE_IDENTIFIER = 0x81;
|
|
80
82
|
const JS_LITERAL = 0x82;
|
|
@@ -150,7 +152,14 @@ const JS_TS_ENUM_DECLARATION = 0xc7;
|
|
|
150
152
|
const JS_TS_MODULE_DECLARATION = 0xc8;
|
|
151
153
|
const JS_COMMENT = 0xc9;
|
|
152
154
|
const JS_NULL = 0xca;
|
|
153
|
-
|
|
155
|
+
// 0xcb was the former whole-node JS_RAW_JSON escape (removed — TS type
|
|
156
|
+
// annotations now ride a per-node trailer; see readOptTypeAnnotation).
|
|
157
|
+
const JS_TS_PARAMETER_PROPERTY = 0xcc;
|
|
158
|
+
const JS_TS_AS_EXPRESSION = 0xcd;
|
|
159
|
+
const JS_TS_SATISFIES_EXPRESSION = 0xce;
|
|
160
|
+
const JS_TS_NON_NULL_EXPRESSION = 0xcf;
|
|
161
|
+
const JS_TS_TYPE_ASSERTION = 0xd0;
|
|
162
|
+
const JS_TS_INSTANTIATION_EXPRESSION = 0xd1;
|
|
154
163
|
|
|
155
164
|
// LiteralValue inner tag (within a JS_LITERAL payload).
|
|
156
165
|
const LV_NULL = 0;
|
|
@@ -253,10 +262,31 @@ function readU32(ctx) {
|
|
|
253
262
|
function readBool(ctx) {
|
|
254
263
|
return readU8(ctx) !== 0;
|
|
255
264
|
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Validate that the byte window `[start, start + len)` lies fully inside
|
|
268
|
+
* `ctx.bytes` (see `./lib/bounds-check.js`, shared with `envelope.js`'s
|
|
269
|
+
* `assertWindow`, for why this must throw rather than let
|
|
270
|
+
* `Buffer.toString`/`Uint8Array.subarray` clamp silently — M-012).
|
|
271
|
+
*
|
|
272
|
+
* @param {object} ctx
|
|
273
|
+
* @param {number} start
|
|
274
|
+
* @param {number} len
|
|
275
|
+
* @param {string} label
|
|
276
|
+
*/
|
|
277
|
+
function assertWindow(ctx, start, len, label) {
|
|
278
|
+
if (isWindowOutOfBounds(start, len, ctx.bytes.byteLength)) {
|
|
279
|
+
throw new EnvelopeError(
|
|
280
|
+
`parse envelope: ${windowOutOfBoundsMessage(label, start, len, ctx.bytes.byteLength)}`,
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
256
285
|
function readStr(ctx) {
|
|
257
286
|
const len = readU32(ctx);
|
|
258
287
|
const start = ctx.pos;
|
|
259
288
|
const end = start + len;
|
|
289
|
+
assertWindow(ctx, start, len, 'string');
|
|
260
290
|
ctx.pos = end;
|
|
261
291
|
// Branch is monomorphic per envelope: V8 specialises after warmup.
|
|
262
292
|
return ctx.isBuffer
|
|
@@ -287,6 +317,7 @@ function readInlineJson(ctx) {
|
|
|
287
317
|
const len = readU32(ctx);
|
|
288
318
|
const start = ctx.pos;
|
|
289
319
|
const end = start + len;
|
|
320
|
+
assertWindow(ctx, start, len, 'inline JSON');
|
|
290
321
|
ctx.pos = end;
|
|
291
322
|
if (len === 0) return null;
|
|
292
323
|
return JSON.parse(
|
|
@@ -301,6 +332,16 @@ function readJsonNodePayload(ctx) {
|
|
|
301
332
|
return readInlineJson(ctx);
|
|
302
333
|
}
|
|
303
334
|
|
|
335
|
+
/**
|
|
336
|
+
* Read an optional TS `typeAnnotation` trailer: a flag byte, then (when set) a
|
|
337
|
+
* length-prefixed JSON blob. Mirrors `write_opt_type_annotation` in
|
|
338
|
+
* `napi_raw_parse.rs`. Returns `null` when absent.
|
|
339
|
+
*/
|
|
340
|
+
function readOptTypeAnnotation(ctx) {
|
|
341
|
+
if (readU8(ctx) === 0) return null;
|
|
342
|
+
return readInlineJson(ctx);
|
|
343
|
+
}
|
|
344
|
+
|
|
304
345
|
// ---------------------------------------------------------------------------
|
|
305
346
|
// Dispatch on tag
|
|
306
347
|
// ---------------------------------------------------------------------------
|
|
@@ -397,8 +438,6 @@ function readNodeBody(ctx, tag, start, end) {
|
|
|
397
438
|
// ----- JsNode (estree) ----------------------------------------
|
|
398
439
|
case JS_NULL:
|
|
399
440
|
return null;
|
|
400
|
-
case JS_RAW_JSON:
|
|
401
|
-
return readJsonNodePayload(ctx);
|
|
402
441
|
case JS_IDENTIFIER:
|
|
403
442
|
return readJsIdentifier(ctx, start, end);
|
|
404
443
|
case JS_PRIVATE_IDENTIFIER:
|
|
@@ -543,8 +582,20 @@ function readNodeBody(ctx, tag, start, end) {
|
|
|
543
582
|
return readJsTSTypeAnnotation(ctx, start, end);
|
|
544
583
|
case JS_TS_ENUM_DECLARATION:
|
|
545
584
|
return readJsBareExpr(ctx, 'TSEnumDeclaration', start, end);
|
|
585
|
+
case JS_TS_PARAMETER_PROPERTY:
|
|
586
|
+
return readJsBareExpr(ctx, 'TSParameterProperty', start, end);
|
|
546
587
|
case JS_TS_MODULE_DECLARATION:
|
|
547
588
|
return readJsTSModuleDeclaration(ctx, start, end);
|
|
589
|
+
case JS_TS_AS_EXPRESSION:
|
|
590
|
+
return readJsTSAssertion(ctx, 'TSAsExpression', start, end, true);
|
|
591
|
+
case JS_TS_SATISFIES_EXPRESSION:
|
|
592
|
+
return readJsTSAssertion(ctx, 'TSSatisfiesExpression', start, end, true);
|
|
593
|
+
case JS_TS_NON_NULL_EXPRESSION:
|
|
594
|
+
return readJsTSAssertion(ctx, 'TSNonNullExpression', start, end, false);
|
|
595
|
+
case JS_TS_TYPE_ASSERTION:
|
|
596
|
+
return readJsTSTypeAssertion(ctx, start, end);
|
|
597
|
+
case JS_TS_INSTANTIATION_EXPRESSION:
|
|
598
|
+
return readJsTSInstantiationExpression(ctx, start, end);
|
|
548
599
|
case JS_COMMENT:
|
|
549
600
|
return readJsComment_(ctx, start, end);
|
|
550
601
|
|
|
@@ -650,6 +701,8 @@ function readJsIdentifier(ctx, start, end) {
|
|
|
650
701
|
const node = { type: 'Identifier', start, end };
|
|
651
702
|
if (loc !== null) node.loc = loc;
|
|
652
703
|
node.name = name;
|
|
704
|
+
const typeAnnotation = readOptTypeAnnotation(ctx);
|
|
705
|
+
if (typeAnnotation !== null) node.typeAnnotation = typeAnnotation;
|
|
653
706
|
return node;
|
|
654
707
|
}
|
|
655
708
|
|
|
@@ -937,6 +990,45 @@ function readJsChainExpression(ctx, start, end) {
|
|
|
937
990
|
return node;
|
|
938
991
|
}
|
|
939
992
|
|
|
993
|
+
// TS assertion wrappers (`x as T` / `x satisfies T` / `x!`). As/Satisfies carry
|
|
994
|
+
// a `typeAnnotation` trailer; NonNull does not (`hasTypeAnnotation` is false).
|
|
995
|
+
function readJsTSAssertion(ctx, typeName, start, end, hasTypeAnnotation) {
|
|
996
|
+
const loc = readTypedLoc(ctx);
|
|
997
|
+
const expression = readNode(ctx);
|
|
998
|
+
const node = { type: typeName, start, end };
|
|
999
|
+
if (loc !== null) node.loc = loc;
|
|
1000
|
+
node.expression = expression;
|
|
1001
|
+
if (hasTypeAnnotation) {
|
|
1002
|
+
const typeAnnotation = readOptTypeAnnotation(ctx);
|
|
1003
|
+
if (typeAnnotation !== null) node.typeAnnotation = typeAnnotation;
|
|
1004
|
+
}
|
|
1005
|
+
return node;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
function readJsTSTypeAssertion(ctx, start, end) {
|
|
1009
|
+
// Wire order: loc, expression, typeAnnotation — but svelte/compiler emits
|
|
1010
|
+
// `typeAnnotation` before `expression`, so build the object in that order.
|
|
1011
|
+
const loc = readTypedLoc(ctx);
|
|
1012
|
+
const expression = readNode(ctx);
|
|
1013
|
+
const typeAnnotation = readOptTypeAnnotation(ctx);
|
|
1014
|
+
const node = { type: 'TSTypeAssertion', start, end };
|
|
1015
|
+
if (loc !== null) node.loc = loc;
|
|
1016
|
+
if (typeAnnotation !== null) node.typeAnnotation = typeAnnotation;
|
|
1017
|
+
node.expression = expression;
|
|
1018
|
+
return node;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
function readJsTSInstantiationExpression(ctx, start, end) {
|
|
1022
|
+
const loc = readTypedLoc(ctx);
|
|
1023
|
+
const expression = readNode(ctx);
|
|
1024
|
+
const typeArguments = readOptTypeAnnotation(ctx);
|
|
1025
|
+
const node = { type: 'TSInstantiationExpression', start, end };
|
|
1026
|
+
if (loc !== null) node.loc = loc;
|
|
1027
|
+
node.expression = expression;
|
|
1028
|
+
if (typeArguments !== null) node.typeArguments = typeArguments;
|
|
1029
|
+
return node;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
940
1032
|
function readJsMetaProperty(ctx, start, end) {
|
|
941
1033
|
const loc = readTypedLoc(ctx);
|
|
942
1034
|
const meta = readNode(ctx);
|
|
@@ -963,6 +1055,8 @@ function readJsObjectPattern(ctx, start, end) {
|
|
|
963
1055
|
const node = { type: 'ObjectPattern', start, end };
|
|
964
1056
|
if (loc !== null) node.loc = loc;
|
|
965
1057
|
node.properties = properties;
|
|
1058
|
+
const typeAnnotation = readOptTypeAnnotation(ctx);
|
|
1059
|
+
if (typeAnnotation !== null) node.typeAnnotation = typeAnnotation;
|
|
966
1060
|
return node;
|
|
967
1061
|
}
|
|
968
1062
|
|
|
@@ -972,6 +1066,8 @@ function readJsArrayPattern(ctx, start, end) {
|
|
|
972
1066
|
const node = { type: 'ArrayPattern', start, end };
|
|
973
1067
|
if (loc !== null) node.loc = loc;
|
|
974
1068
|
node.elements = elements;
|
|
1069
|
+
const typeAnnotation = readOptTypeAnnotation(ctx);
|
|
1070
|
+
if (typeAnnotation !== null) node.typeAnnotation = typeAnnotation;
|
|
975
1071
|
return node;
|
|
976
1072
|
}
|
|
977
1073
|
|