@rsvelte/vite-plugin-svelte-native 0.2.7 → 0.3.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/index.cjs +128 -5
- package/index.d.ts +36 -8
- package/package.json +6 -6
- package/parse-envelope.js +74 -3
package/index.cjs
CHANGED
|
@@ -51,6 +51,72 @@ try {
|
|
|
51
51
|
);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
// The NAPI boundary can't accept function values, so resolve them here: evaluate
|
|
55
|
+
// `customElement`/`css`/`runes` and hand back `warningFilter` for the caller to
|
|
56
|
+
// post-filter warnings (which never affect codegen).
|
|
57
|
+
function prepareCompileOptions(options) {
|
|
58
|
+
if (options == null) return { options, warningFilter: undefined };
|
|
59
|
+
const { customElement, css, runes, warningFilter } = options;
|
|
60
|
+
const hasParametric =
|
|
61
|
+
typeof customElement === 'function' ||
|
|
62
|
+
typeof css === 'function' ||
|
|
63
|
+
typeof runes === 'function';
|
|
64
|
+
const hasWarningFilter = typeof warningFilter === 'function';
|
|
65
|
+
if (!hasParametric && !hasWarningFilter) {
|
|
66
|
+
return { options, warningFilter: undefined };
|
|
67
|
+
}
|
|
68
|
+
// Svelte defaults `filename` to '(unknown)' before invoking these functions.
|
|
69
|
+
const meta = { filename: options.filename ?? '(unknown)' };
|
|
70
|
+
const resolved = { ...options };
|
|
71
|
+
if (typeof customElement === 'function') resolved.customElement = customElement(meta);
|
|
72
|
+
if (typeof css === 'function') resolved.css = css(meta);
|
|
73
|
+
if (typeof runes === 'function') resolved.runes = runes(meta);
|
|
74
|
+
if (hasWarningFilter) delete resolved.warningFilter;
|
|
75
|
+
return { options: resolved, warningFilter: hasWarningFilter ? warningFilter : undefined };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Port of Svelte's `hash()` (submodules/svelte/packages/svelte/src/utils.js),
|
|
79
|
+
// handed to a user `cssHash` callback so custom scope classes match upstream's digest.
|
|
80
|
+
const regexReturnCharacters = /\r/g;
|
|
81
|
+
function hash(str) {
|
|
82
|
+
str = str.replace(regexReturnCharacters, '');
|
|
83
|
+
let h = 5381;
|
|
84
|
+
let i = str.length;
|
|
85
|
+
while (i--) h = ((h << 5) - h) ^ str.charCodeAt(i);
|
|
86
|
+
return (h >>> 0).toString(36);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Adapt a user `cssHash` to the bridge shape. It must never reject: a rejected
|
|
90
|
+
// Promise crossing the NAPI boundary can crash V8 during threadsafe-function
|
|
91
|
+
// teardown — so a throw becomes `{ error }` (Rust turns it into a compile failure)
|
|
92
|
+
// and a non-string return becomes `{ value: null }` (Rust falls back to the default hash).
|
|
93
|
+
function makeCssHashCallback(userCssHash) {
|
|
94
|
+
return async (name, filename, css) => {
|
|
95
|
+
try {
|
|
96
|
+
const result = await userCssHash({ hash, css, name, filename });
|
|
97
|
+
return { value: typeof result === 'string' ? result : null };
|
|
98
|
+
} catch (err) {
|
|
99
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function applyWarningFilter(result, warningFilter) {
|
|
105
|
+
if (!warningFilter || result == null) return result;
|
|
106
|
+
const warnings = result.warnings;
|
|
107
|
+
if (Array.isArray(warnings) && warnings.length) {
|
|
108
|
+
// `warnings` is a lazy getter on the envelope-decoded result; redefine it
|
|
109
|
+
// as a plain data property so the filtered array replaces the accessor.
|
|
110
|
+
Object.defineProperty(result, 'warnings', {
|
|
111
|
+
value: warnings.filter((warning) => warningFilter(warning)),
|
|
112
|
+
writable: true,
|
|
113
|
+
enumerable: true,
|
|
114
|
+
configurable: true,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
|
|
54
120
|
// `compile` / `compileModule` are wrapped to route through the
|
|
55
121
|
// raw-transfer envelope (`compileEnvelope`): the Rust side hands us
|
|
56
122
|
// one `Buffer`, the JS side lazy-decodes only the fields the caller
|
|
@@ -62,11 +128,23 @@ try {
|
|
|
62
128
|
// directly. The legacy JSON path is preserved as `compileLegacy` for
|
|
63
129
|
// parity testing and as an escape hatch.
|
|
64
130
|
function compile(source, options) {
|
|
65
|
-
|
|
131
|
+
if (typeof options?.cssHash === 'function') {
|
|
132
|
+
// A dynamic cssHash needs the Rust→JS callback bridge, which would deadlock
|
|
133
|
+
// the JS event loop on the sync path; direct the caller to `compileAsync`.
|
|
134
|
+
throw new Error(
|
|
135
|
+
'[@rsvelte/vite-plugin-svelte-native] A dynamic `cssHash` function requires the async compile path; call `compileAsync(source, options)` instead. (A constant hash can use `cssHashOverride`.)',
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
const { options: resolved, warningFilter } = prepareCompileOptions(options);
|
|
139
|
+
return applyWarningFilter(decodeEnvelope(binding.compileEnvelope(source, resolved)), warningFilter);
|
|
66
140
|
}
|
|
67
141
|
|
|
68
142
|
function compileModule(source, options) {
|
|
69
|
-
|
|
143
|
+
const { options: resolved, warningFilter } = prepareCompileOptions(options);
|
|
144
|
+
return applyWarningFilter(
|
|
145
|
+
decodeEnvelope(binding.compileModuleEnvelope(source, resolved)),
|
|
146
|
+
warningFilter,
|
|
147
|
+
);
|
|
70
148
|
}
|
|
71
149
|
|
|
72
150
|
// `compileBatch([{source, options}, …])` compiles N files in
|
|
@@ -74,8 +152,29 @@ function compileModule(source, options) {
|
|
|
74
152
|
// exactly once. The returned array is the same length as the input;
|
|
75
153
|
// each slot is either a `CompileResult` or an `Error` (parse
|
|
76
154
|
// failures don't abort the whole batch).
|
|
155
|
+
// Batch compilation runs on rayon workers with no JS event loop to service the
|
|
156
|
+
// callback, so a dynamic cssHash can't be bridged here — reject it rather than drop it.
|
|
157
|
+
function assertNoDynamicCssHash(options) {
|
|
158
|
+
if (typeof options?.cssHash === 'function') {
|
|
159
|
+
throw new Error(
|
|
160
|
+
'[@rsvelte/vite-plugin-svelte-native] A dynamic `cssHash` function is not supported in compileBatch; compile such files individually with `compileAsync`.',
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
77
165
|
function compileBatch(inputs) {
|
|
78
|
-
|
|
166
|
+
const filters = [];
|
|
167
|
+
const prepared = inputs.map((input, i) => {
|
|
168
|
+
assertNoDynamicCssHash(input.options);
|
|
169
|
+
const { options, warningFilter } = prepareCompileOptions(input.options);
|
|
170
|
+
if (warningFilter) filters[i] = warningFilter;
|
|
171
|
+
return options === input.options ? input : { source: input.source, options };
|
|
172
|
+
});
|
|
173
|
+
const results = decodeBatch(binding.compileBatch(prepared));
|
|
174
|
+
if (filters.length) {
|
|
175
|
+
results.forEach((result, i) => applyWarningFilter(result, filters[i]));
|
|
176
|
+
}
|
|
177
|
+
return results;
|
|
79
178
|
}
|
|
80
179
|
|
|
81
180
|
// `compileAsync` / `compileBatchAsync` release the JS event loop
|
|
@@ -84,11 +183,35 @@ function compileBatch(inputs) {
|
|
|
84
183
|
// (Vite middleware, SSR pre-render) — the await yields control
|
|
85
184
|
// instead of blocking V8.
|
|
86
185
|
async function compileAsync(source, options) {
|
|
87
|
-
|
|
186
|
+
const { options: resolved, warningFilter } = prepareCompileOptions(options);
|
|
187
|
+
if (typeof options?.cssHash === 'function') {
|
|
188
|
+
// The bridge entry returns a plain (JSON) CompileResult, not an envelope.
|
|
189
|
+
const result = await binding.compileWithCssHash(
|
|
190
|
+
source,
|
|
191
|
+
resolved,
|
|
192
|
+
makeCssHashCallback(options.cssHash),
|
|
193
|
+
);
|
|
194
|
+
return applyWarningFilter(result, warningFilter);
|
|
195
|
+
}
|
|
196
|
+
return applyWarningFilter(
|
|
197
|
+
decodeEnvelope(await binding.compileEnvelopeAsync(source, resolved)),
|
|
198
|
+
warningFilter,
|
|
199
|
+
);
|
|
88
200
|
}
|
|
89
201
|
|
|
90
202
|
async function compileBatchAsync(inputs) {
|
|
91
|
-
|
|
203
|
+
const filters = [];
|
|
204
|
+
const prepared = inputs.map((input, i) => {
|
|
205
|
+
assertNoDynamicCssHash(input.options);
|
|
206
|
+
const { options, warningFilter } = prepareCompileOptions(input.options);
|
|
207
|
+
if (warningFilter) filters[i] = warningFilter;
|
|
208
|
+
return options === input.options ? input : { source: input.source, options };
|
|
209
|
+
});
|
|
210
|
+
const results = decodeBatch(await binding.compileBatchAsync(prepared));
|
|
211
|
+
if (filters.length) {
|
|
212
|
+
results.forEach((result, i) => applyWarningFilter(result, filters[i]));
|
|
213
|
+
}
|
|
214
|
+
return results;
|
|
92
215
|
}
|
|
93
216
|
|
|
94
217
|
// Re-export every NAPI function as its own named binding so node's
|
package/index.d.ts
CHANGED
|
@@ -22,29 +22,56 @@ export interface CompileOptions {
|
|
|
22
22
|
rootDir?: string;
|
|
23
23
|
/** Component identifier hint. */
|
|
24
24
|
name?: string;
|
|
25
|
-
/**
|
|
26
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Compile as a custom element. A function form `({ filename }) => boolean`
|
|
27
|
+
* is evaluated once at the binding boundary.
|
|
28
|
+
*/
|
|
29
|
+
customElement?: boolean | ((meta: { filename: string }) => boolean);
|
|
27
30
|
/** Generate `accessors`. */
|
|
28
31
|
accessors?: boolean;
|
|
29
32
|
/** HTML namespace. */
|
|
30
33
|
namespace?: 'html' | 'svg' | 'mathml';
|
|
31
34
|
/** Hint that bindings are immutable. */
|
|
32
35
|
immutable?: boolean;
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Output CSS injected into the bundle or as an external asset. A function
|
|
38
|
+
* form `({ filename }) => 'injected' | 'external'` is evaluated once at the
|
|
39
|
+
* binding boundary.
|
|
40
|
+
*/
|
|
41
|
+
css?:
|
|
42
|
+
| 'injected'
|
|
43
|
+
| 'external'
|
|
44
|
+
| ((meta: { filename: string }) => 'injected' | 'external');
|
|
45
|
+
/**
|
|
46
|
+
* Custom hash function for CSS scoping. Called once per component with the
|
|
47
|
+
* component's CSS; the returned string becomes the scope class. Because it
|
|
48
|
+
* depends on the CSS, it is bridged into the compiler through a threadsafe
|
|
49
|
+
* callback and is only supported on the async path — use `compileAsync`.
|
|
50
|
+
* The synchronous `compile` throws if given a `cssHash` function; pass a
|
|
51
|
+
* pre-computed constant via `cssHashOverride` instead.
|
|
52
|
+
*/
|
|
36
53
|
cssHash?: (args: {
|
|
37
54
|
hash: (input: string) => string;
|
|
38
55
|
css: string;
|
|
39
56
|
name: string;
|
|
40
|
-
filename: string
|
|
57
|
+
filename: string;
|
|
41
58
|
}) => string;
|
|
59
|
+
/**
|
|
60
|
+
* Pre-computed constant CSS scope hash. Escape hatch for callers (e.g.
|
|
61
|
+
* `@rsvelte/vite-plugin-svelte`'s HMR path) that already know the hash and
|
|
62
|
+
* want to skip the `cssHash` callback bridge entirely.
|
|
63
|
+
*/
|
|
64
|
+
cssHashOverride?: string;
|
|
42
65
|
/** Preserve HTML comments in output. */
|
|
43
66
|
preserveComments?: boolean;
|
|
44
67
|
/** Preserve whitespace in the template. */
|
|
45
68
|
preserveWhitespace?: boolean;
|
|
46
|
-
/**
|
|
47
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Force runes mode (`true`), legacy (`false`), or auto-detect (`undefined`).
|
|
71
|
+
* A function form `({ filename }) => boolean | undefined` is evaluated once
|
|
72
|
+
* at the binding boundary.
|
|
73
|
+
*/
|
|
74
|
+
runes?: boolean | ((meta: { filename: string }) => boolean | undefined);
|
|
48
75
|
/** Disclose the compiler version in the output banner. */
|
|
49
76
|
discloseVersion?: boolean;
|
|
50
77
|
/** Source-map options (forwarded through magic-string). */
|
|
@@ -70,6 +97,7 @@ export interface ModuleCompileOptions {
|
|
|
70
97
|
generate?: 'client' | 'server' | false;
|
|
71
98
|
filename?: string;
|
|
72
99
|
rootDir?: string;
|
|
100
|
+
/** Filter compiler warnings (applied to the returned `warnings` array). */
|
|
73
101
|
warningFilter?: (warning: Warning) => boolean;
|
|
74
102
|
}
|
|
75
103
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rsvelte/vite-plugin-svelte-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "NAPI bindings to the rsvelte compiler — used by the @rsvelte vite-plugin-svelte shim",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"index.d.ts"
|
|
30
30
|
],
|
|
31
31
|
"optionalDependencies": {
|
|
32
|
-
"@rsvelte/vite-plugin-svelte-native-darwin-arm64": "^0.
|
|
33
|
-
"@rsvelte/vite-plugin-svelte-native-darwin-x64": "^0.
|
|
34
|
-
"@rsvelte/vite-plugin-svelte-native-linux-arm64-gnu": "^0.
|
|
35
|
-
"@rsvelte/vite-plugin-svelte-native-linux-x64-gnu": "^0.
|
|
36
|
-
"@rsvelte/vite-plugin-svelte-native-win32-x64-msvc": "^0.
|
|
32
|
+
"@rsvelte/vite-plugin-svelte-native-darwin-arm64": "^0.3.0",
|
|
33
|
+
"@rsvelte/vite-plugin-svelte-native-darwin-x64": "^0.3.0",
|
|
34
|
+
"@rsvelte/vite-plugin-svelte-native-linux-arm64-gnu": "^0.3.0",
|
|
35
|
+
"@rsvelte/vite-plugin-svelte-native-linux-x64-gnu": "^0.3.0",
|
|
36
|
+
"@rsvelte/vite-plugin-svelte-native-win32-x64-msvc": "^0.3.0"
|
|
37
37
|
},
|
|
38
38
|
"publishConfig": {
|
|
39
39
|
"access": "public"
|
package/parse-envelope.js
CHANGED
|
@@ -15,7 +15,11 @@
|
|
|
15
15
|
const { isWindowOutOfBounds, windowOutOfBoundsMessage } = require('./lib/bounds-check.js');
|
|
16
16
|
|
|
17
17
|
const MAGIC = 0x3156_5052; // "RPV1" little-endian
|
|
18
|
-
|
|
18
|
+
// Bumped for the function-node AST-fidelity changes (FunctionExpression field
|
|
19
|
+
// reorder, `typeParameters` on function-like nodes, Identifier `optional`);
|
|
20
|
+
// v4 adds the object-method `typeParameters`-after-`body` flag byte.
|
|
21
|
+
// Keep in lockstep with `napi_raw_parse.rs`'s `VERSION`.
|
|
22
|
+
const VERSION = 4;
|
|
19
23
|
const HEADER_LEN = 24;
|
|
20
24
|
|
|
21
25
|
// Tags — must mirror napi_raw_parse.rs.
|
|
@@ -155,6 +159,11 @@ const JS_NULL = 0xca;
|
|
|
155
159
|
// 0xcb was the former whole-node JS_RAW_JSON escape (removed — TS type
|
|
156
160
|
// annotations now ride a per-node trailer; see readOptTypeAnnotation).
|
|
157
161
|
const JS_TS_PARAMETER_PROPERTY = 0xcc;
|
|
162
|
+
const JS_TS_AS_EXPRESSION = 0xcd;
|
|
163
|
+
const JS_TS_SATISFIES_EXPRESSION = 0xce;
|
|
164
|
+
const JS_TS_NON_NULL_EXPRESSION = 0xcf;
|
|
165
|
+
const JS_TS_TYPE_ASSERTION = 0xd0;
|
|
166
|
+
const JS_TS_INSTANTIATION_EXPRESSION = 0xd1;
|
|
158
167
|
|
|
159
168
|
// LiteralValue inner tag (within a JS_LITERAL payload).
|
|
160
169
|
const LV_NULL = 0;
|
|
@@ -581,6 +590,16 @@ function readNodeBody(ctx, tag, start, end) {
|
|
|
581
590
|
return readJsBareExpr(ctx, 'TSParameterProperty', start, end);
|
|
582
591
|
case JS_TS_MODULE_DECLARATION:
|
|
583
592
|
return readJsTSModuleDeclaration(ctx, start, end);
|
|
593
|
+
case JS_TS_AS_EXPRESSION:
|
|
594
|
+
return readJsTSAssertion(ctx, 'TSAsExpression', start, end, true);
|
|
595
|
+
case JS_TS_SATISFIES_EXPRESSION:
|
|
596
|
+
return readJsTSAssertion(ctx, 'TSSatisfiesExpression', start, end, true);
|
|
597
|
+
case JS_TS_NON_NULL_EXPRESSION:
|
|
598
|
+
return readJsTSAssertion(ctx, 'TSNonNullExpression', start, end, false);
|
|
599
|
+
case JS_TS_TYPE_ASSERTION:
|
|
600
|
+
return readJsTSTypeAssertion(ctx, start, end);
|
|
601
|
+
case JS_TS_INSTANTIATION_EXPRESSION:
|
|
602
|
+
return readJsTSInstantiationExpression(ctx, start, end);
|
|
584
603
|
case JS_COMMENT:
|
|
585
604
|
return readJsComment_(ctx, start, end);
|
|
586
605
|
|
|
@@ -683,9 +702,11 @@ function readOptNode(ctx) {
|
|
|
683
702
|
function readJsIdentifier(ctx, start, end) {
|
|
684
703
|
const loc = readTypedLoc(ctx);
|
|
685
704
|
const name = readStr(ctx);
|
|
705
|
+
const optional = readBool(ctx);
|
|
686
706
|
const node = { type: 'Identifier', start, end };
|
|
687
707
|
if (loc !== null) node.loc = loc;
|
|
688
708
|
node.name = name;
|
|
709
|
+
if (optional) node.optional = true;
|
|
689
710
|
const typeAnnotation = readOptTypeAnnotation(ctx);
|
|
690
711
|
if (typeAnnotation !== null) node.typeAnnotation = typeAnnotation;
|
|
691
712
|
return node;
|
|
@@ -794,19 +815,24 @@ function readJsNewExpression(ctx, start, end) {
|
|
|
794
815
|
function readJsFunctionExpression(ctx, start, end) {
|
|
795
816
|
const loc = readTypedLoc(ctx);
|
|
796
817
|
const id = readOptNode(ctx);
|
|
818
|
+
const expression = readBool(ctx);
|
|
797
819
|
const generator = readBool(ctx);
|
|
798
820
|
const asyncFlag = readBool(ctx);
|
|
799
|
-
const
|
|
821
|
+
const typeParameters = readOptTypeAnnotation(ctx);
|
|
800
822
|
const params = readChildArray(ctx);
|
|
801
823
|
const body = readOptNode(ctx);
|
|
824
|
+
// Object-method inner functions carry `typeParameters` after `body` (acorn).
|
|
825
|
+
const typeParametersAfterBody = readBool(ctx);
|
|
802
826
|
const node = { type: 'FunctionExpression', start, end };
|
|
803
827
|
if (loc !== null) node.loc = loc;
|
|
804
828
|
node.id = id;
|
|
829
|
+
node.expression = expression;
|
|
805
830
|
node.generator = generator;
|
|
806
831
|
node.async = asyncFlag;
|
|
807
|
-
node.
|
|
832
|
+
if (typeParameters !== null && !typeParametersAfterBody) node.typeParameters = typeParameters;
|
|
808
833
|
node.params = params;
|
|
809
834
|
node.body = body;
|
|
835
|
+
if (typeParameters !== null && typeParametersAfterBody) node.typeParameters = typeParameters;
|
|
810
836
|
return node;
|
|
811
837
|
}
|
|
812
838
|
|
|
@@ -831,6 +857,7 @@ function readJsArrowFunctionExpression(ctx, start, end) {
|
|
|
831
857
|
const asyncFlag = readBool(ctx);
|
|
832
858
|
const params = readChildArray(ctx);
|
|
833
859
|
const body = readNode(ctx);
|
|
860
|
+
const typeParameters = readOptTypeAnnotation(ctx);
|
|
834
861
|
const node = { type: 'ArrowFunctionExpression', start, end };
|
|
835
862
|
if (loc !== null) node.loc = loc;
|
|
836
863
|
node.id = id;
|
|
@@ -839,6 +866,7 @@ function readJsArrowFunctionExpression(ctx, start, end) {
|
|
|
839
866
|
node.async = asyncFlag;
|
|
840
867
|
node.params = params;
|
|
841
868
|
node.body = body;
|
|
869
|
+
if (typeParameters !== null) node.typeParameters = typeParameters;
|
|
842
870
|
return node;
|
|
843
871
|
}
|
|
844
872
|
|
|
@@ -975,6 +1003,45 @@ function readJsChainExpression(ctx, start, end) {
|
|
|
975
1003
|
return node;
|
|
976
1004
|
}
|
|
977
1005
|
|
|
1006
|
+
// TS assertion wrappers (`x as T` / `x satisfies T` / `x!`). As/Satisfies carry
|
|
1007
|
+
// a `typeAnnotation` trailer; NonNull does not (`hasTypeAnnotation` is false).
|
|
1008
|
+
function readJsTSAssertion(ctx, typeName, start, end, hasTypeAnnotation) {
|
|
1009
|
+
const loc = readTypedLoc(ctx);
|
|
1010
|
+
const expression = readNode(ctx);
|
|
1011
|
+
const node = { type: typeName, start, end };
|
|
1012
|
+
if (loc !== null) node.loc = loc;
|
|
1013
|
+
node.expression = expression;
|
|
1014
|
+
if (hasTypeAnnotation) {
|
|
1015
|
+
const typeAnnotation = readOptTypeAnnotation(ctx);
|
|
1016
|
+
if (typeAnnotation !== null) node.typeAnnotation = typeAnnotation;
|
|
1017
|
+
}
|
|
1018
|
+
return node;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
function readJsTSTypeAssertion(ctx, start, end) {
|
|
1022
|
+
// Wire order: loc, expression, typeAnnotation — but svelte/compiler emits
|
|
1023
|
+
// `typeAnnotation` before `expression`, so build the object in that order.
|
|
1024
|
+
const loc = readTypedLoc(ctx);
|
|
1025
|
+
const expression = readNode(ctx);
|
|
1026
|
+
const typeAnnotation = readOptTypeAnnotation(ctx);
|
|
1027
|
+
const node = { type: 'TSTypeAssertion', start, end };
|
|
1028
|
+
if (loc !== null) node.loc = loc;
|
|
1029
|
+
if (typeAnnotation !== null) node.typeAnnotation = typeAnnotation;
|
|
1030
|
+
node.expression = expression;
|
|
1031
|
+
return node;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
function readJsTSInstantiationExpression(ctx, start, end) {
|
|
1035
|
+
const loc = readTypedLoc(ctx);
|
|
1036
|
+
const expression = readNode(ctx);
|
|
1037
|
+
const typeArguments = readOptTypeAnnotation(ctx);
|
|
1038
|
+
const node = { type: 'TSInstantiationExpression', start, end };
|
|
1039
|
+
if (loc !== null) node.loc = loc;
|
|
1040
|
+
node.expression = expression;
|
|
1041
|
+
if (typeArguments !== null) node.typeArguments = typeArguments;
|
|
1042
|
+
return node;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
978
1045
|
function readJsMetaProperty(ctx, start, end) {
|
|
979
1046
|
const loc = readTypedLoc(ctx);
|
|
980
1047
|
const meta = readNode(ctx);
|
|
@@ -1116,15 +1183,19 @@ function readJsVariableDeclarator(ctx, start, end) {
|
|
|
1116
1183
|
function readJsFunctionDeclaration(ctx, start, end) {
|
|
1117
1184
|
const loc = readTypedLoc(ctx);
|
|
1118
1185
|
const id = readOptNode(ctx);
|
|
1186
|
+
const expression = readBool(ctx);
|
|
1119
1187
|
const generator = readBool(ctx);
|
|
1120
1188
|
const asyncFlag = readBool(ctx);
|
|
1189
|
+
const typeParameters = readOptTypeAnnotation(ctx);
|
|
1121
1190
|
const params = readChildArray(ctx);
|
|
1122
1191
|
const body = readOptNode(ctx);
|
|
1123
1192
|
const node = { type: 'FunctionDeclaration', start, end };
|
|
1124
1193
|
if (loc !== null) node.loc = loc;
|
|
1125
1194
|
node.id = id;
|
|
1195
|
+
node.expression = expression;
|
|
1126
1196
|
node.generator = generator;
|
|
1127
1197
|
node.async = asyncFlag;
|
|
1198
|
+
if (typeParameters !== null) node.typeParameters = typeParameters;
|
|
1128
1199
|
node.params = params;
|
|
1129
1200
|
node.body = body;
|
|
1130
1201
|
return node;
|