@tsrx/solid 0.0.26 → 0.0.28
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/package.json +6 -2
- package/src/index.js +4 -1
- package/src/ref.js +1 -0
- package/src/transform.js +206 -5
- package/types/index.d.ts +5 -16
- package/types/ref.d.ts +1 -0
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Solid compiler built on @tsrx/core",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.0.
|
|
6
|
+
"version": "0.0.28",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"publishConfig": {
|
|
9
9
|
"access": "public"
|
|
@@ -17,12 +17,16 @@
|
|
|
17
17
|
".": {
|
|
18
18
|
"types": "./types/index.d.ts",
|
|
19
19
|
"default": "./src/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./ref": {
|
|
22
|
+
"types": "./types/ref.d.ts",
|
|
23
|
+
"default": "./src/ref.js"
|
|
20
24
|
}
|
|
21
25
|
},
|
|
22
26
|
"dependencies": {
|
|
23
27
|
"esrap": "^2.1.0",
|
|
24
28
|
"zimmerframe": "^1.1.2",
|
|
25
|
-
"@tsrx/core": "0.0.
|
|
29
|
+
"@tsrx/core": "0.0.28"
|
|
26
30
|
},
|
|
27
31
|
"peerDependencies": {
|
|
28
32
|
"solid-js": ">=1.8 || >=2.0.0-beta"
|
package/src/index.js
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import { createVolarMappingsResult, dedupeMappings, parseModule } from '@tsrx/core';
|
|
5
5
|
import { transform } from './transform.js';
|
|
6
6
|
|
|
7
|
+
export { isRefProp } from './ref.js';
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* Parse tsrx-solid source code to an ESTree AST.
|
|
9
11
|
* @param {string} source
|
|
@@ -22,7 +24,7 @@ export function parse(source, filename, options) {
|
|
|
22
24
|
* @param {string} source
|
|
23
25
|
* @param {string} [filename]
|
|
24
26
|
* @param {{ collect?: boolean, loose?: boolean }} [options]
|
|
25
|
-
* @returns {{ code: string, map: any, css:
|
|
27
|
+
* @returns {{ code: string, map: any, css: string, cssHash: string | null, errors: CompileError[] }}
|
|
26
28
|
*/
|
|
27
29
|
export function compile(source, filename, options) {
|
|
28
30
|
const errors = /** @type {CompileError[]} */ ([]);
|
|
@@ -63,6 +65,7 @@ export function compile_to_volar_mappings(source, filename, options) {
|
|
|
63
65
|
const transformed = transform(ast, source, filename, {
|
|
64
66
|
collect: true,
|
|
65
67
|
loose: !!options?.loose,
|
|
68
|
+
typeOnly: true,
|
|
66
69
|
errors,
|
|
67
70
|
comments,
|
|
68
71
|
});
|
package/src/ref.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@tsrx/core/runtime/ref';
|
package/src/transform.js
CHANGED
|
@@ -9,13 +9,18 @@ import {
|
|
|
9
9
|
toJsxAttribute,
|
|
10
10
|
validateAtMostOneRefAttribute,
|
|
11
11
|
setLocation,
|
|
12
|
+
addJsxSetupDeclaration as add_jsx_setup_declaration,
|
|
12
13
|
applyLazyTransforms as apply_lazy_transforms,
|
|
13
14
|
collectLazyBindingsFromComponent as collect_lazy_bindings_from_component,
|
|
15
|
+
extractJsxSetupDeclarations as extract_jsx_setup_declarations,
|
|
14
16
|
replaceLazyParams as replace_lazy_params,
|
|
15
17
|
rewriteLoopContinuesToBareReturns as rewrite_loop_continues_to_bare_returns,
|
|
18
|
+
isRefPropExpression as is_ref_prop_expression,
|
|
16
19
|
isInterleavedBody as is_interleaved_body_core,
|
|
17
20
|
isCapturableJsxChild as is_capturable_jsx_child,
|
|
18
21
|
captureJsxChild,
|
|
22
|
+
CREATE_REF_PROP_INTERNAL_NAME,
|
|
23
|
+
NORMALIZE_SPREAD_PROPS_INTERNAL_NAME,
|
|
19
24
|
tsxNodeToJsxExpression as tsx_node_to_jsx_expression,
|
|
20
25
|
// Shared AST builders (truly platform-agnostic utilities).
|
|
21
26
|
clone_expression_node,
|
|
@@ -26,6 +31,7 @@ import {
|
|
|
26
31
|
flatten_switch_consequent,
|
|
27
32
|
get_for_of_iteration_params,
|
|
28
33
|
identifier_to_jsx_name,
|
|
34
|
+
is_bare_render_expression,
|
|
29
35
|
is_dynamic_element_id,
|
|
30
36
|
is_jsx_child,
|
|
31
37
|
set_loc,
|
|
@@ -48,6 +54,7 @@ import { builders as b } from '@tsrx/core';
|
|
|
48
54
|
* needs_match: boolean,
|
|
49
55
|
* needs_errored: boolean,
|
|
50
56
|
* needs_loading: boolean,
|
|
57
|
+
* needs_normalize_spread_props: boolean,
|
|
51
58
|
* }} TransformContext
|
|
52
59
|
*/
|
|
53
60
|
|
|
@@ -78,6 +85,7 @@ const solid_platform = {
|
|
|
78
85
|
// import injection goes through `hooks.injectImports`.
|
|
79
86
|
suspense: 'solid-js',
|
|
80
87
|
errorBoundary: 'solid-js',
|
|
88
|
+
refProp: '@tsrx/solid/ref',
|
|
81
89
|
},
|
|
82
90
|
jsx: {
|
|
83
91
|
rewriteClassAttr: false,
|
|
@@ -102,6 +110,7 @@ const solid_platform = {
|
|
|
102
110
|
needs_match: false,
|
|
103
111
|
needs_errored: false,
|
|
104
112
|
needs_loading: false,
|
|
113
|
+
needs_normalize_spread_props: false,
|
|
105
114
|
}),
|
|
106
115
|
validateComponentAwait: (await_expression, _component, ctx, _requires, source) => {
|
|
107
116
|
const await_start = get_await_keyword_start(await_expression, source);
|
|
@@ -176,7 +185,11 @@ function component_to_function_declaration(component, transform_context) {
|
|
|
176
185
|
const params = component.params || [];
|
|
177
186
|
const body = /** @type {any[]} */ (component.body || []);
|
|
178
187
|
|
|
179
|
-
|
|
188
|
+
// In type-only mode the lazy rewrite is skipped so destructuring patterns
|
|
189
|
+
// survive into the virtual TSX and TypeScript can flow real types.
|
|
190
|
+
const lazy_bindings = transform_context.typeOnly
|
|
191
|
+
? new Map()
|
|
192
|
+
: collect_lazy_bindings_from_component(params, body, transform_context);
|
|
180
193
|
|
|
181
194
|
// Detect top-level early-return patterns such as `if (cond) { return; }`
|
|
182
195
|
// and `if (cond) { <p />; return; }`.
|
|
@@ -239,6 +252,7 @@ function component_to_function_declaration(component, transform_context) {
|
|
|
239
252
|
}
|
|
240
253
|
if (early_interleaved) {
|
|
241
254
|
const jsx = to_jsx_child(child, transform_context);
|
|
255
|
+
outer.push(...extract_jsx_setup_declarations(jsx));
|
|
242
256
|
if (is_capturable_jsx_child(jsx)) {
|
|
243
257
|
const { declaration, reference } = captureJsxChild(jsx, early_capture_index++);
|
|
244
258
|
outer.push(declaration);
|
|
@@ -283,6 +297,7 @@ function component_to_function_declaration(component, transform_context) {
|
|
|
283
297
|
for (const child of effective_body) {
|
|
284
298
|
if (is_jsx_child(child)) {
|
|
285
299
|
const jsx = to_jsx_child(child, transform_context);
|
|
300
|
+
statements.push(...extract_jsx_setup_declarations(jsx));
|
|
286
301
|
if (interleaved && is_capturable_jsx_child(jsx)) {
|
|
287
302
|
const { declaration, reference } = captureJsxChild(jsx, capture_index++);
|
|
288
303
|
statements.push(declaration);
|
|
@@ -290,6 +305,8 @@ function component_to_function_declaration(component, transform_context) {
|
|
|
290
305
|
} else {
|
|
291
306
|
render_nodes.push(jsx);
|
|
292
307
|
}
|
|
308
|
+
} else if (is_bare_render_expression(child)) {
|
|
309
|
+
render_nodes.push(to_jsx_expression_container(child, child));
|
|
293
310
|
} else {
|
|
294
311
|
statements.push(child);
|
|
295
312
|
}
|
|
@@ -475,6 +492,7 @@ function body_to_jsx_child(body_nodes, transform_context) {
|
|
|
475
492
|
|
|
476
493
|
if (is_jsx_child(child)) {
|
|
477
494
|
const jsx = to_jsx_child(child, transform_context);
|
|
495
|
+
statements.push(...extract_jsx_setup_declarations(jsx));
|
|
478
496
|
if (interleaved && is_capturable_jsx_child(jsx)) {
|
|
479
497
|
const { declaration, reference } = captureJsxChild(jsx, capture_index++);
|
|
480
498
|
statements.push(declaration);
|
|
@@ -482,6 +500,8 @@ function body_to_jsx_child(body_nodes, transform_context) {
|
|
|
482
500
|
} else {
|
|
483
501
|
children.push(jsx);
|
|
484
502
|
}
|
|
503
|
+
} else if (is_bare_render_expression(child)) {
|
|
504
|
+
children.push(to_jsx_expression_container(child, child));
|
|
485
505
|
} else {
|
|
486
506
|
statements.push(child);
|
|
487
507
|
}
|
|
@@ -660,7 +680,11 @@ function loop_body_to_callback_statements(body_nodes, transform_context) {
|
|
|
660
680
|
}
|
|
661
681
|
|
|
662
682
|
if (is_jsx_child(child)) {
|
|
663
|
-
|
|
683
|
+
const jsx = to_jsx_child(child, transform_context);
|
|
684
|
+
statements.push(...extract_jsx_setup_declarations(jsx));
|
|
685
|
+
children.push(jsx);
|
|
686
|
+
} else if (is_bare_render_expression(child)) {
|
|
687
|
+
children.push(to_jsx_expression_container(child, child));
|
|
664
688
|
} else {
|
|
665
689
|
statements.push(child);
|
|
666
690
|
}
|
|
@@ -1339,6 +1363,53 @@ const TEMPLATE_FRAGMENT_ERROR =
|
|
|
1339
1363
|
* @param {TransformContext} transform_context
|
|
1340
1364
|
*/
|
|
1341
1365
|
function inject_solid_imports(program, transform_context) {
|
|
1366
|
+
if (transform_context.needs_ref_prop || transform_context.needs_normalize_spread_props) {
|
|
1367
|
+
const specifiers = [];
|
|
1368
|
+
|
|
1369
|
+
if (transform_context.needs_ref_prop) {
|
|
1370
|
+
specifiers.push({
|
|
1371
|
+
type: 'ImportSpecifier',
|
|
1372
|
+
imported: { type: 'Identifier', name: 'create_ref_prop', metadata: { path: [] } },
|
|
1373
|
+
local: {
|
|
1374
|
+
type: 'Identifier',
|
|
1375
|
+
name: CREATE_REF_PROP_INTERNAL_NAME,
|
|
1376
|
+
metadata: { path: [] },
|
|
1377
|
+
},
|
|
1378
|
+
metadata: { path: [] },
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
if (transform_context.needs_normalize_spread_props) {
|
|
1383
|
+
specifiers.push({
|
|
1384
|
+
type: 'ImportSpecifier',
|
|
1385
|
+
imported: {
|
|
1386
|
+
type: 'Identifier',
|
|
1387
|
+
name: 'normalize_spread_props',
|
|
1388
|
+
metadata: { path: [] },
|
|
1389
|
+
},
|
|
1390
|
+
local: {
|
|
1391
|
+
type: 'Identifier',
|
|
1392
|
+
name: NORMALIZE_SPREAD_PROPS_INTERNAL_NAME,
|
|
1393
|
+
metadata: { path: [] },
|
|
1394
|
+
},
|
|
1395
|
+
metadata: { path: [] },
|
|
1396
|
+
});
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
program.body.unshift(
|
|
1400
|
+
/** @type {any} */ ({
|
|
1401
|
+
type: 'ImportDeclaration',
|
|
1402
|
+
specifiers,
|
|
1403
|
+
source: {
|
|
1404
|
+
type: 'Literal',
|
|
1405
|
+
value: '@tsrx/solid/ref',
|
|
1406
|
+
raw: "'@tsrx/solid/ref'",
|
|
1407
|
+
},
|
|
1408
|
+
metadata: { path: [] },
|
|
1409
|
+
}),
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1342
1413
|
const needed = [];
|
|
1343
1414
|
if (transform_context.needs_show) needed.push('Show');
|
|
1344
1415
|
if (transform_context.needs_for) needed.push('For');
|
|
@@ -1599,16 +1670,146 @@ function has_text_content_attribute(attributes) {
|
|
|
1599
1670
|
* @returns {any[]}
|
|
1600
1671
|
*/
|
|
1601
1672
|
function transform_element_attributes(raw_attrs, is_composite, transform_context) {
|
|
1602
|
-
void is_composite;
|
|
1603
1673
|
validateAtMostOneRefAttribute(raw_attrs, /** @type {any} */ (transform_context));
|
|
1604
1674
|
/** @type {any[]} */
|
|
1605
1675
|
const result = [];
|
|
1606
1676
|
|
|
1607
|
-
for (const attr of
|
|
1677
|
+
for (const attr of normalize_solid_named_ref_attributes(
|
|
1678
|
+
raw_attrs,
|
|
1679
|
+
!is_composite,
|
|
1680
|
+
transform_context,
|
|
1681
|
+
)) {
|
|
1608
1682
|
if (!attr) continue;
|
|
1609
1683
|
result.push(toJsxAttribute(attr, /** @type {any} */ (transform_context)));
|
|
1610
1684
|
}
|
|
1611
|
-
return mergeDuplicateRefs(
|
|
1685
|
+
return mergeDuplicateRefs(
|
|
1686
|
+
normalize_solid_host_ref_spreads(result, !is_composite, transform_context),
|
|
1687
|
+
/** @type {any} */ (transform_context),
|
|
1688
|
+
);
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
/**
|
|
1692
|
+
* @param {any[]} attrs
|
|
1693
|
+
* @param {boolean} is_host
|
|
1694
|
+
* @param {TransformContext} transform_context
|
|
1695
|
+
* @returns {any[]}
|
|
1696
|
+
*/
|
|
1697
|
+
function normalize_solid_named_ref_attributes(attrs, is_host, transform_context) {
|
|
1698
|
+
if (!is_host) return attrs;
|
|
1699
|
+
|
|
1700
|
+
return attrs.map((attr) => {
|
|
1701
|
+
if (
|
|
1702
|
+
!attr ||
|
|
1703
|
+
attr.type !== 'Attribute' ||
|
|
1704
|
+
attr.name?.type !== 'Identifier' ||
|
|
1705
|
+
attr.name.name === 'ref' ||
|
|
1706
|
+
!(
|
|
1707
|
+
attr.value?.type === 'RefExpression' ||
|
|
1708
|
+
is_ref_prop_expression(attr.value) ||
|
|
1709
|
+
(attr.value?.type === 'JSXExpressionContainer' &&
|
|
1710
|
+
is_ref_prop_expression(attr.value.expression))
|
|
1711
|
+
)
|
|
1712
|
+
) {
|
|
1713
|
+
return attr;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
if (transform_context.typeOnly) {
|
|
1717
|
+
return {
|
|
1718
|
+
...attr,
|
|
1719
|
+
name: {
|
|
1720
|
+
...attr.name,
|
|
1721
|
+
metadata: { ...(attr.name.metadata || {}), disable_verification: true },
|
|
1722
|
+
},
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
return {
|
|
1727
|
+
...attr,
|
|
1728
|
+
name: { ...attr.name, name: 'ref' },
|
|
1729
|
+
};
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
/**
|
|
1734
|
+
* @param {any[]} attrs
|
|
1735
|
+
* @param {boolean} is_host
|
|
1736
|
+
* @param {TransformContext} transform_context
|
|
1737
|
+
* @returns {any[]}
|
|
1738
|
+
*/
|
|
1739
|
+
function normalize_solid_host_ref_spreads(attrs, is_host, transform_context) {
|
|
1740
|
+
if (!is_host) return attrs;
|
|
1741
|
+
|
|
1742
|
+
const ref_exprs = attrs
|
|
1743
|
+
.filter((attr) => is_solid_jsx_ref_attribute(attr))
|
|
1744
|
+
.map((attr) => attr.value.expression);
|
|
1745
|
+
const needs_synthetic_spread_ref = ref_exprs.length > 0;
|
|
1746
|
+
|
|
1747
|
+
return attrs.flatMap((attr) => {
|
|
1748
|
+
if (!attr || attr.type !== 'JSXSpreadAttribute') {
|
|
1749
|
+
return [attr];
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
transform_context.needs_normalize_spread_props = true;
|
|
1753
|
+
const normalized = b.call(NORMALIZE_SPREAD_PROPS_INTERNAL_NAME, attr.argument);
|
|
1754
|
+
|
|
1755
|
+
if (needs_synthetic_spread_ref) {
|
|
1756
|
+
const normalized_id = create_generated_identifier(
|
|
1757
|
+
create_solid_spread_props_name(transform_context),
|
|
1758
|
+
);
|
|
1759
|
+
const spread = {
|
|
1760
|
+
...attr,
|
|
1761
|
+
argument: clone_identifier(normalized_id),
|
|
1762
|
+
};
|
|
1763
|
+
const ref_attr = b.jsx_attribute(
|
|
1764
|
+
b.jsx_id('ref'),
|
|
1765
|
+
b.jsx_expression_container(b.member(clone_identifier(normalized_id), 'ref'), attr),
|
|
1766
|
+
false,
|
|
1767
|
+
attr,
|
|
1768
|
+
);
|
|
1769
|
+
ref_attr.metadata = { ...(ref_attr.metadata || {}) };
|
|
1770
|
+
/** @type {any} */ (ref_attr.metadata).from_ref_keyword = true;
|
|
1771
|
+
add_jsx_setup_declaration(spread, b.let(clone_identifier(normalized_id), normalized));
|
|
1772
|
+
|
|
1773
|
+
return [spread, ref_attr];
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
return [
|
|
1777
|
+
{
|
|
1778
|
+
...attr,
|
|
1779
|
+
argument: normalized,
|
|
1780
|
+
},
|
|
1781
|
+
];
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
/**
|
|
1786
|
+
* @param {TransformContext} transform_context
|
|
1787
|
+
* @returns {string}
|
|
1788
|
+
*/
|
|
1789
|
+
function create_solid_spread_props_name(transform_context) {
|
|
1790
|
+
if (transform_context.helper_state) {
|
|
1791
|
+
transform_context.helper_state.next_id += 1;
|
|
1792
|
+
return `${transform_context.helper_state.base_name}__spread_props${transform_context.helper_state.next_id}`;
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
transform_context.local_statement_component_index += 1;
|
|
1796
|
+
return `_tsrx_spread_props_${transform_context.local_statement_component_index}`;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
/**
|
|
1800
|
+
* @param {any} attr
|
|
1801
|
+
* @returns {boolean}
|
|
1802
|
+
*/
|
|
1803
|
+
function is_solid_jsx_ref_attribute(attr) {
|
|
1804
|
+
return !!(
|
|
1805
|
+
attr &&
|
|
1806
|
+
attr.type === 'JSXAttribute' &&
|
|
1807
|
+
attr.name?.type === 'JSXIdentifier' &&
|
|
1808
|
+
attr.name.name === 'ref' &&
|
|
1809
|
+
attr.value?.type === 'JSXExpressionContainer' &&
|
|
1810
|
+
attr.value.expression &&
|
|
1811
|
+
attr.value.expression.type !== 'JSXEmptyExpression'
|
|
1812
|
+
);
|
|
1612
1813
|
}
|
|
1613
1814
|
|
|
1614
1815
|
/**
|
package/types/index.d.ts
CHANGED
|
@@ -1,21 +1,10 @@
|
|
|
1
1
|
import type { Program } from 'estree';
|
|
2
|
-
import type {
|
|
2
|
+
import type { CompileFn, ParseOptions, VolarCompileFn } from '@tsrx/core/types';
|
|
3
3
|
|
|
4
4
|
export function parse(source: string, filename?: string, options?: ParseOptions): Program;
|
|
5
5
|
|
|
6
|
-
export
|
|
7
|
-
source: string,
|
|
8
|
-
filename?: string,
|
|
9
|
-
options?: { collect?: boolean; loose?: boolean },
|
|
10
|
-
): {
|
|
11
|
-
code: string;
|
|
12
|
-
map: unknown;
|
|
13
|
-
css: { code: string; hash: string } | null;
|
|
14
|
-
errors: CompileError[];
|
|
15
|
-
};
|
|
6
|
+
export { isRefProp } from './ref.js';
|
|
16
7
|
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
options?: ParseOptions,
|
|
21
|
-
): VolarMappingsResult;
|
|
8
|
+
export const compile: CompileFn;
|
|
9
|
+
|
|
10
|
+
export const compile_to_volar_mappings: VolarCompileFn;
|
package/types/ref.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@tsrx/core/runtime/ref';
|