@tsrx/react 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/package.json +2 -2
- package/src/transform.js +10 -120
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "React compiler built on @tsrx/core",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.1.
|
|
6
|
+
"version": "0.1.1",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"publishConfig": {
|
|
9
9
|
"access": "public"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"esrap": "^2.1.0",
|
|
27
27
|
"zimmerframe": "^1.1.2",
|
|
28
|
-
"@tsrx/core": "0.0.
|
|
28
|
+
"@tsrx/core": "0.0.7"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"react": ">=18"
|
package/src/transform.js
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
isInterleavedBody as is_interleaved_body_core,
|
|
18
18
|
isCapturableJsxChild as is_capturable_jsx_child,
|
|
19
19
|
captureJsxChild,
|
|
20
|
+
isHoistSafeJsxNode as is_hoist_safe_jsx_node,
|
|
20
21
|
} from '@tsrx/core';
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -894,116 +895,6 @@ function references_scope_bindings(node, scope_bindings) {
|
|
|
894
895
|
return false;
|
|
895
896
|
}
|
|
896
897
|
|
|
897
|
-
/**
|
|
898
|
-
* @param {AST.Literal} node
|
|
899
|
-
* @returns {boolean}
|
|
900
|
-
*/
|
|
901
|
-
function is_static_literal(node) {
|
|
902
|
-
return (
|
|
903
|
-
node.value === null ||
|
|
904
|
-
typeof node.value === 'string' ||
|
|
905
|
-
typeof node.value === 'number' ||
|
|
906
|
-
typeof node.value === 'boolean' ||
|
|
907
|
-
typeof node.value === 'bigint'
|
|
908
|
-
);
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
/**
|
|
912
|
-
* @param {any} node
|
|
913
|
-
* @returns {boolean}
|
|
914
|
-
*/
|
|
915
|
-
function is_hoist_safe_expression(node) {
|
|
916
|
-
if (!node || typeof node !== 'object') return false;
|
|
917
|
-
|
|
918
|
-
switch (node.type) {
|
|
919
|
-
case 'Literal':
|
|
920
|
-
return is_static_literal(node);
|
|
921
|
-
case 'TemplateLiteral':
|
|
922
|
-
return node.expressions.length === 0;
|
|
923
|
-
case 'UnaryExpression':
|
|
924
|
-
return node.operator !== 'delete' && is_hoist_safe_expression(node.argument);
|
|
925
|
-
case 'BinaryExpression':
|
|
926
|
-
case 'LogicalExpression':
|
|
927
|
-
return is_hoist_safe_expression(node.left) && is_hoist_safe_expression(node.right);
|
|
928
|
-
case 'ConditionalExpression':
|
|
929
|
-
return (
|
|
930
|
-
is_hoist_safe_expression(node.test) &&
|
|
931
|
-
is_hoist_safe_expression(node.consequent) &&
|
|
932
|
-
is_hoist_safe_expression(node.alternate)
|
|
933
|
-
);
|
|
934
|
-
case 'SequenceExpression':
|
|
935
|
-
return node.expressions.every(is_hoist_safe_expression);
|
|
936
|
-
case 'ParenthesizedExpression':
|
|
937
|
-
return is_hoist_safe_expression(node.expression);
|
|
938
|
-
case 'JSXElement':
|
|
939
|
-
return is_hoist_safe_jsx_node(node);
|
|
940
|
-
case 'JSXFragment':
|
|
941
|
-
return node.children.every(is_hoist_safe_jsx_child);
|
|
942
|
-
default:
|
|
943
|
-
return false;
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
/**
|
|
948
|
-
* @param {any} node
|
|
949
|
-
* @returns {boolean}
|
|
950
|
-
*/
|
|
951
|
-
function is_hoist_safe_jsx_child(node) {
|
|
952
|
-
if (!node || typeof node !== 'object') return false;
|
|
953
|
-
|
|
954
|
-
switch (node.type) {
|
|
955
|
-
case 'JSXText':
|
|
956
|
-
return true;
|
|
957
|
-
case 'JSXElement':
|
|
958
|
-
return is_hoist_safe_jsx_node(node);
|
|
959
|
-
case 'JSXFragment':
|
|
960
|
-
return node.children.every(is_hoist_safe_jsx_child);
|
|
961
|
-
case 'JSXExpressionContainer':
|
|
962
|
-
return (
|
|
963
|
-
node.expression.type !== 'JSXEmptyExpression' && is_hoist_safe_expression(node.expression)
|
|
964
|
-
);
|
|
965
|
-
default:
|
|
966
|
-
return false;
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
/**
|
|
971
|
-
* @param {ESTreeJSX.JSXAttribute | ESTreeJSX.JSXSpreadAttribute} attribute
|
|
972
|
-
* @returns {boolean}
|
|
973
|
-
*/
|
|
974
|
-
function is_hoist_safe_jsx_attribute(attribute) {
|
|
975
|
-
if (attribute.type === 'JSXSpreadAttribute') return false;
|
|
976
|
-
if (attribute.value == null) return true;
|
|
977
|
-
|
|
978
|
-
if (attribute.value.type === 'Literal') {
|
|
979
|
-
return is_static_literal(attribute.value);
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
if (attribute.value.type === 'JSXExpressionContainer') {
|
|
983
|
-
return (
|
|
984
|
-
attribute.value.expression.type !== 'JSXEmptyExpression' &&
|
|
985
|
-
is_hoist_safe_expression(attribute.value.expression)
|
|
986
|
-
);
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
return false;
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
/**
|
|
993
|
-
* @param {ESTreeJSX.JSXElement | ESTreeJSX.JSXFragment} node
|
|
994
|
-
* @returns {boolean}
|
|
995
|
-
*/
|
|
996
|
-
function is_hoist_safe_jsx_node(node) {
|
|
997
|
-
if (node.type === 'JSXFragment') {
|
|
998
|
-
return node.children.every(is_hoist_safe_jsx_child);
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
return (
|
|
1002
|
-
node.openingElement.attributes.every(is_hoist_safe_jsx_attribute) &&
|
|
1003
|
-
node.children.every(is_hoist_safe_jsx_child)
|
|
1004
|
-
);
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
898
|
/**
|
|
1008
899
|
* Hoist static JSX elements from render_nodes to module level.
|
|
1009
900
|
* A JSX element is static if it doesn't reference any component-scope bindings.
|
|
@@ -1712,24 +1603,23 @@ function for_of_statement_to_jsx_child(node, transform_context) {
|
|
|
1712
1603
|
);
|
|
1713
1604
|
}
|
|
1714
1605
|
|
|
1715
|
-
if (node.key) {
|
|
1716
|
-
throw create_compile_error(
|
|
1717
|
-
node.key,
|
|
1718
|
-
'React TSRX does not support `key` in `for` control flow. Put the key on the rendered element instead, for example `<div key={i}>...</div>`.',
|
|
1719
|
-
);
|
|
1720
|
-
}
|
|
1721
|
-
|
|
1722
1606
|
const loop_params = get_for_of_iteration_params(node.left, node.index);
|
|
1723
1607
|
const loop_body = node.body.type === 'BlockStatement' ? node.body.body : [node.body];
|
|
1724
1608
|
const has_hooks = body_contains_top_level_hook_call(loop_body);
|
|
1725
|
-
const
|
|
1609
|
+
const body_key_expression = find_key_expression_in_body(loop_body);
|
|
1610
|
+
const explicit_key_expression =
|
|
1611
|
+
body_key_expression ?? (node.key ? clone_expression_node(node.key) : undefined);
|
|
1726
1612
|
const key_expression =
|
|
1727
1613
|
has_hooks && explicit_key_expression == null && node.index
|
|
1728
1614
|
? clone_expression_node(node.index)
|
|
1729
1615
|
: explicit_key_expression;
|
|
1730
1616
|
const implicit_non_hook_key_expression =
|
|
1731
|
-
!has_hooks &&
|
|
1732
|
-
?
|
|
1617
|
+
!has_hooks && body_key_expression == null
|
|
1618
|
+
? node.key
|
|
1619
|
+
? clone_expression_node(node.key)
|
|
1620
|
+
: node.index
|
|
1621
|
+
? clone_expression_node(node.index)
|
|
1622
|
+
: undefined
|
|
1733
1623
|
: undefined;
|
|
1734
1624
|
|
|
1735
1625
|
// Add loop params to available bindings so hoisted helpers receive them as props
|