@tsrx/core 0.1.24 → 0.1.25
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 +1 -1
- package/src/plugin.js +42 -1
- package/src/transform/jsx/index.js +730 -1850
- package/types/index.d.ts +0 -2
- package/types/jsx-platform.d.ts +3 -8
|
@@ -49,7 +49,6 @@ import {
|
|
|
49
49
|
create_style_ref_setup_statements,
|
|
50
50
|
get_style_element_stylesheet,
|
|
51
51
|
} from '../style-ref.js';
|
|
52
|
-
import { is_function_or_component_node } from '../../utils/ast.js';
|
|
53
52
|
import {
|
|
54
53
|
is_interleaved_body as is_interleaved_body_core,
|
|
55
54
|
is_capturable_jsx_child,
|
|
@@ -57,10 +56,6 @@ import {
|
|
|
57
56
|
} from '../jsx-interleave.js';
|
|
58
57
|
import { is_hoist_safe_jsx_node } from '../jsx-hoist.js';
|
|
59
58
|
|
|
60
|
-
const HOOK_OUTER_ASSIGNMENT_ERROR =
|
|
61
|
-
'Hook calls inside conditional or repeated TSRX scopes must keep their results local to the generated hook component.';
|
|
62
|
-
const HOOK_CALLBACK_OUTER_MUTATION_ERROR =
|
|
63
|
-
'Hook callbacks inside conditional or repeated TSRX scopes must not mutate bindings declared outside the generated hook component.';
|
|
64
59
|
const TEMPLATE_FRAGMENT_ERROR =
|
|
65
60
|
'JSX fragment syntax is not needed in TSRX templates. TSRX renders in immediate mode, so everything is already a fragment. Use `<>...</>` only in expression position.';
|
|
66
61
|
const TSRX_FOR_RETURN_ERROR =
|
|
@@ -89,44 +84,6 @@ function report_jsx_fragment_in_tsrx_error(node, transform_context) {
|
|
|
89
84
|
);
|
|
90
85
|
}
|
|
91
86
|
|
|
92
|
-
/**
|
|
93
|
-
* @param {AST.Node} node
|
|
94
|
-
* @param {string[]} names
|
|
95
|
-
* @param {string} hook_name
|
|
96
|
-
* @param {TransformContext} transform_context
|
|
97
|
-
* @returns {void}
|
|
98
|
-
*/
|
|
99
|
-
function report_hook_outer_assignment_error(node, names, hook_name, transform_context) {
|
|
100
|
-
const target =
|
|
101
|
-
names.length === 1 ? `\`${names[0]}\`` : names.map((name) => `\`${name}\``).join(', ');
|
|
102
|
-
error(
|
|
103
|
-
`${HOOK_OUTER_ASSIGNMENT_ERROR} The ${hook_name} result is assigned to ${target}, which is declared outside that generated component. Declare the hook result inside the TSRX branch, or move the hook into an explicit child component and pass values with props.`,
|
|
104
|
-
transform_context.filename,
|
|
105
|
-
node,
|
|
106
|
-
transform_context.errors,
|
|
107
|
-
transform_context.comments,
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* @param {AST.Node} node
|
|
113
|
-
* @param {string[]} names
|
|
114
|
-
* @param {string} hook_name
|
|
115
|
-
* @param {TransformContext} transform_context
|
|
116
|
-
* @returns {void}
|
|
117
|
-
*/
|
|
118
|
-
function report_hook_callback_outer_mutation_error(node, names, hook_name, transform_context) {
|
|
119
|
-
const target =
|
|
120
|
-
names.length === 1 ? `\`${names[0]}\`` : names.map((name) => `\`${name}\``).join(', ');
|
|
121
|
-
error(
|
|
122
|
-
`${HOOK_CALLBACK_OUTER_MUTATION_ERROR} The ${hook_name} callback mutates ${target}. Read outer values through props or dependencies, and move mutable state into an explicit child component when it needs to change over time.`,
|
|
123
|
-
transform_context.filename,
|
|
124
|
-
node,
|
|
125
|
-
transform_context.errors,
|
|
126
|
-
transform_context.comments,
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
87
|
/**
|
|
131
88
|
* Local alias for the shared `JsxTransformContext`. Kept as a typedef so the
|
|
132
89
|
* rest of this file's `@param {TransformContext}` annotations don't all have
|
|
@@ -1038,1273 +995,898 @@ function is_interleaved_body(body_nodes) {
|
|
|
1038
995
|
}
|
|
1039
996
|
|
|
1040
997
|
/**
|
|
1041
|
-
* @param {any}
|
|
998
|
+
* @param {any[]} body_nodes
|
|
1042
999
|
* @param {TransformContext} transform_context
|
|
1000
|
+
* @param {boolean} include_platform_setup
|
|
1043
1001
|
* @returns {boolean}
|
|
1044
1002
|
*/
|
|
1045
|
-
function
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1003
|
+
function body_contains_top_level_hook_call(
|
|
1004
|
+
body_nodes,
|
|
1005
|
+
transform_context,
|
|
1006
|
+
include_platform_setup = false,
|
|
1007
|
+
) {
|
|
1008
|
+
return body_nodes.some((node) =>
|
|
1009
|
+
statement_contains_top_level_hook_call(node, transform_context, include_platform_setup),
|
|
1052
1010
|
);
|
|
1053
1011
|
}
|
|
1054
1012
|
|
|
1055
1013
|
/**
|
|
1056
1014
|
* @param {any} node
|
|
1057
1015
|
* @param {TransformContext} transform_context
|
|
1058
|
-
* @
|
|
1059
|
-
*/
|
|
1060
|
-
function create_hook_split_block(node, transform_context) {
|
|
1061
|
-
if (
|
|
1062
|
-
transform_context.platform.hooks?.componentBodyHookHelpers !== true ||
|
|
1063
|
-
!should_extract_hook_helpers(transform_context) ||
|
|
1064
|
-
node.body?.type !== 'BlockStatement'
|
|
1065
|
-
) {
|
|
1066
|
-
return null;
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
const source_body = node.body.body || [];
|
|
1070
|
-
const branch_rewrite = rewrite_component_body_branch_hook_returns(source_body, transform_context);
|
|
1071
|
-
const body = branch_rewrite.body;
|
|
1072
|
-
const split_index = find_hook_split_index(body, transform_context);
|
|
1073
|
-
if (split_index === -1 && !branch_rewrite.changed) {
|
|
1074
|
-
return null;
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
let block_body;
|
|
1078
|
-
if (split_index === -1) {
|
|
1079
|
-
block_body = expand_native_tsrx_return_statement_list(body, transform_context);
|
|
1080
|
-
} else {
|
|
1081
|
-
const split_statement = body[split_index];
|
|
1082
|
-
const continuation_body = body.slice(split_index + 1);
|
|
1083
|
-
const helper = create_hook_safe_helper(
|
|
1084
|
-
expand_native_tsrx_return_statement_list(continuation_body, transform_context),
|
|
1085
|
-
undefined,
|
|
1086
|
-
get_body_source_node(continuation_body) || split_statement,
|
|
1087
|
-
transform_context,
|
|
1088
|
-
);
|
|
1089
|
-
|
|
1090
|
-
block_body = [
|
|
1091
|
-
...body.slice(0, split_index + 1),
|
|
1092
|
-
...helper.setup_statements,
|
|
1093
|
-
set_loc(b.return(helper.component_element), split_statement),
|
|
1094
|
-
];
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
const block = b.block(block_body, node.body);
|
|
1098
|
-
block.metadata = {
|
|
1099
|
-
...(block.metadata || {}),
|
|
1100
|
-
hook_split_block: true,
|
|
1101
|
-
};
|
|
1102
|
-
return block;
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
/**
|
|
1106
|
-
* @param {any[]} body_nodes
|
|
1107
|
-
* @param {TransformContext} transform_context
|
|
1016
|
+
* @param {boolean} include_platform_setup
|
|
1108
1017
|
* @returns {boolean}
|
|
1109
1018
|
*/
|
|
1110
|
-
function
|
|
1111
|
-
return
|
|
1112
|
-
statement_contains_component_body_branch_hook_return(node, transform_context),
|
|
1113
|
-
);
|
|
1019
|
+
function statement_contains_top_level_hook_call(node, transform_context, include_platform_setup) {
|
|
1020
|
+
return node_contains_top_level_hook_call(node, false, transform_context, include_platform_setup);
|
|
1114
1021
|
}
|
|
1115
1022
|
|
|
1116
1023
|
/**
|
|
1117
1024
|
* @param {any} node
|
|
1025
|
+
* @param {boolean} inside_nested_function
|
|
1118
1026
|
* @param {TransformContext} transform_context
|
|
1027
|
+
* @param {boolean} include_platform_setup
|
|
1119
1028
|
* @returns {boolean}
|
|
1120
1029
|
*/
|
|
1121
|
-
function
|
|
1030
|
+
function node_contains_top_level_hook_call(
|
|
1031
|
+
node,
|
|
1032
|
+
inside_nested_function,
|
|
1033
|
+
transform_context,
|
|
1034
|
+
include_platform_setup,
|
|
1035
|
+
) {
|
|
1122
1036
|
if (!node || typeof node !== 'object') {
|
|
1123
1037
|
return false;
|
|
1124
1038
|
}
|
|
1125
1039
|
|
|
1126
|
-
if (
|
|
1127
|
-
|
|
1040
|
+
if (
|
|
1041
|
+
inside_nested_function &&
|
|
1042
|
+
(node.type === 'FunctionDeclaration' ||
|
|
1043
|
+
node.type === 'FunctionExpression' ||
|
|
1044
|
+
node.type === 'ArrowFunctionExpression')
|
|
1045
|
+
) {
|
|
1046
|
+
return false;
|
|
1128
1047
|
}
|
|
1129
1048
|
|
|
1130
|
-
if (
|
|
1049
|
+
if (
|
|
1050
|
+
node.type === 'FunctionDeclaration' ||
|
|
1051
|
+
node.type === 'FunctionExpression' ||
|
|
1052
|
+
node.type === 'ArrowFunctionExpression'
|
|
1053
|
+
) {
|
|
1054
|
+
const next_inside_nested_function = true;
|
|
1055
|
+
for (const key of Object.keys(node)) {
|
|
1056
|
+
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
1057
|
+
continue;
|
|
1058
|
+
}
|
|
1059
|
+
if (
|
|
1060
|
+
node_contains_top_level_hook_call(
|
|
1061
|
+
node[key],
|
|
1062
|
+
next_inside_nested_function,
|
|
1063
|
+
transform_context,
|
|
1064
|
+
include_platform_setup,
|
|
1065
|
+
)
|
|
1066
|
+
) {
|
|
1067
|
+
return true;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1131
1070
|
return false;
|
|
1132
1071
|
}
|
|
1133
1072
|
|
|
1134
|
-
if (
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1073
|
+
if (
|
|
1074
|
+
!inside_nested_function &&
|
|
1075
|
+
node.type === 'CallExpression' &&
|
|
1076
|
+
(is_hook_callee(node.callee) ||
|
|
1077
|
+
(include_platform_setup &&
|
|
1078
|
+
transform_context.platform.hooks?.isTopLevelSetupCall?.(node, transform_context) === true))
|
|
1079
|
+
) {
|
|
1080
|
+
return true;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
if (Array.isArray(node)) {
|
|
1084
|
+
return node.some((child) =>
|
|
1085
|
+
node_contains_top_level_hook_call(
|
|
1086
|
+
child,
|
|
1087
|
+
inside_nested_function,
|
|
1088
|
+
transform_context,
|
|
1089
|
+
include_platform_setup,
|
|
1090
|
+
),
|
|
1140
1091
|
);
|
|
1141
1092
|
}
|
|
1142
1093
|
|
|
1143
|
-
|
|
1144
|
-
|
|
1094
|
+
for (const key of Object.keys(node)) {
|
|
1095
|
+
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
1096
|
+
continue;
|
|
1097
|
+
}
|
|
1098
|
+
if (
|
|
1099
|
+
node_contains_top_level_hook_call(
|
|
1100
|
+
node[key],
|
|
1101
|
+
inside_nested_function,
|
|
1102
|
+
transform_context,
|
|
1103
|
+
include_platform_setup,
|
|
1104
|
+
)
|
|
1105
|
+
) {
|
|
1106
|
+
return true;
|
|
1107
|
+
}
|
|
1145
1108
|
}
|
|
1146
1109
|
|
|
1147
1110
|
return false;
|
|
1148
1111
|
}
|
|
1149
1112
|
|
|
1150
1113
|
/**
|
|
1151
|
-
* @param {any
|
|
1152
|
-
* @
|
|
1153
|
-
* @returns {{ body: any[], changed: boolean }}
|
|
1154
|
-
*/
|
|
1155
|
-
function rewrite_component_body_branch_hook_returns(body_nodes, transform_context) {
|
|
1156
|
-
let changed = false;
|
|
1157
|
-
const body = body_nodes.map((node) => {
|
|
1158
|
-
const next_node = rewrite_component_body_branch_hook_return_statement(node, transform_context);
|
|
1159
|
-
if (next_node !== node) {
|
|
1160
|
-
changed = true;
|
|
1161
|
-
}
|
|
1162
|
-
return next_node;
|
|
1163
|
-
});
|
|
1164
|
-
return changed ? { body, changed } : { body: body_nodes, changed: false };
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
/**
|
|
1168
|
-
* @param {any} node
|
|
1169
|
-
* @param {TransformContext} transform_context
|
|
1170
|
-
* @returns {any}
|
|
1114
|
+
* @param {any} callee
|
|
1115
|
+
* @returns {boolean}
|
|
1171
1116
|
*/
|
|
1172
|
-
function
|
|
1173
|
-
if (!
|
|
1174
|
-
return node;
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
if (is_plain_if_statement(node)) {
|
|
1178
|
-
const consequent = rewrite_component_body_hook_return_branch(
|
|
1179
|
-
node.consequent,
|
|
1180
|
-
transform_context,
|
|
1181
|
-
);
|
|
1182
|
-
const alternate = node.alternate
|
|
1183
|
-
? rewrite_component_body_hook_return_branch(node.alternate, transform_context)
|
|
1184
|
-
: { node: node.alternate, changed: false };
|
|
1117
|
+
function is_hook_callee(callee) {
|
|
1118
|
+
if (!callee) return false;
|
|
1185
1119
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
}
|
|
1189
|
-
return set_loc(b.if(node.test, consequent.node, alternate.node), node);
|
|
1120
|
+
if (callee.type === 'Identifier') {
|
|
1121
|
+
return /^use[A-Z0-9]/.test(callee.name);
|
|
1190
1122
|
}
|
|
1191
1123
|
|
|
1192
|
-
if (
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
return
|
|
1124
|
+
if (
|
|
1125
|
+
!callee.computed &&
|
|
1126
|
+
callee.type === 'MemberExpression' &&
|
|
1127
|
+
callee.property?.type === 'Identifier'
|
|
1128
|
+
) {
|
|
1129
|
+
return /^use[A-Z0-9]/.test(callee.property.name);
|
|
1198
1130
|
}
|
|
1199
1131
|
|
|
1200
|
-
return
|
|
1132
|
+
return false;
|
|
1201
1133
|
}
|
|
1202
1134
|
|
|
1203
1135
|
/**
|
|
1204
|
-
* @param {
|
|
1205
|
-
* @param {
|
|
1206
|
-
* @returns {
|
|
1136
|
+
* @param {AST.Identifier[]} bindings
|
|
1137
|
+
* @param {Set<string>} [mapped_bindings]
|
|
1138
|
+
* @returns {AST.ObjectPattern}
|
|
1207
1139
|
*/
|
|
1208
|
-
function
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1140
|
+
function create_helper_props_pattern(bindings, mapped_bindings = new Set()) {
|
|
1141
|
+
return /** @type {any} */ ({
|
|
1142
|
+
type: 'ObjectPattern',
|
|
1143
|
+
properties: bindings.map((binding) =>
|
|
1144
|
+
create_helper_props_property(binding, mapped_bindings.has(binding.name)),
|
|
1145
|
+
),
|
|
1146
|
+
metadata: { path: [] },
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1212
1149
|
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1150
|
+
/**
|
|
1151
|
+
* @param {AST.Identifier} binding
|
|
1152
|
+
* @param {boolean} [map_binding]
|
|
1153
|
+
* @returns {AST.Property}
|
|
1154
|
+
*/
|
|
1155
|
+
function create_helper_props_property(binding, map_binding = false) {
|
|
1156
|
+
const key = map_binding ? clone_identifier(binding) : create_generated_identifier(binding.name);
|
|
1157
|
+
const value = map_binding ? clone_identifier(binding) : create_generated_identifier(binding.name);
|
|
1220
1158
|
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
const body = rewritten.body;
|
|
1224
|
-
const needs_helper = branch_needs_component_body_hook_helper_body(body, transform_context);
|
|
1159
|
+
return b.prop('init', key, value, false, true);
|
|
1160
|
+
}
|
|
1225
1161
|
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1162
|
+
/**
|
|
1163
|
+
* @param {AST.Identifier} helper_id
|
|
1164
|
+
* @param {AST.Identifier[]} bindings
|
|
1165
|
+
* @param {any} source_node
|
|
1166
|
+
* @param {{
|
|
1167
|
+
* mapWrapper?: boolean,
|
|
1168
|
+
* mapBindingNames?: boolean,
|
|
1169
|
+
* mapBindingValues?: boolean,
|
|
1170
|
+
* }} [mapping]
|
|
1171
|
+
* @returns {ESTreeJSX.JSXElement}
|
|
1172
|
+
*/
|
|
1173
|
+
function create_helper_component_element(helper_id, bindings, source_node, mapping = {}) {
|
|
1174
|
+
const { mapWrapper = true, mapBindingNames = true, mapBindingValues = true } = mapping;
|
|
1175
|
+
const attributes = bindings.map((binding) =>
|
|
1176
|
+
b.jsx_attribute(
|
|
1177
|
+
identifier_to_jsx_name(
|
|
1178
|
+
mapBindingNames ? clone_identifier(binding) : create_generated_identifier(binding.name),
|
|
1179
|
+
),
|
|
1180
|
+
to_jsx_expression_container(
|
|
1181
|
+
mapBindingValues ? clone_identifier(binding) : create_generated_identifier(binding.name),
|
|
1182
|
+
binding,
|
|
1183
|
+
),
|
|
1184
|
+
),
|
|
1185
|
+
);
|
|
1236
1186
|
|
|
1237
|
-
const
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
get_body_source_node(body) || branch,
|
|
1242
|
-
transform_context,
|
|
1187
|
+
const opening_element = b.jsx_opening_element(
|
|
1188
|
+
identifier_to_jsx_name(clone_identifier(helper_id)),
|
|
1189
|
+
attributes,
|
|
1190
|
+
true,
|
|
1243
1191
|
);
|
|
1244
|
-
const
|
|
1245
|
-
|
|
1246
|
-
branch,
|
|
1192
|
+
const element = b.jsx_element_fresh(
|
|
1193
|
+
mapWrapper ? set_loc(opening_element, source_node) : opening_element,
|
|
1247
1194
|
);
|
|
1248
|
-
|
|
1195
|
+
|
|
1196
|
+
return mapWrapper ? set_loc(element, source_node) : element;
|
|
1249
1197
|
}
|
|
1250
1198
|
|
|
1251
1199
|
/**
|
|
1252
|
-
* @param {any}
|
|
1253
|
-
* @param {
|
|
1254
|
-
* @returns {
|
|
1200
|
+
* @param {{ base_name: string, next_id: number, helpers: any[], statics: any[] }} helper_state
|
|
1201
|
+
* @param {string} suffix
|
|
1202
|
+
* @returns {string}
|
|
1255
1203
|
*/
|
|
1256
|
-
function
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
}
|
|
1260
|
-
const body = branch.type === 'BlockStatement' ? branch.body || [] : [branch];
|
|
1261
|
-
return branch_needs_component_body_hook_helper_body(body, transform_context);
|
|
1204
|
+
function create_helper_name(helper_state, suffix) {
|
|
1205
|
+
helper_state.next_id += 1;
|
|
1206
|
+
return `${helper_state.base_name}__${suffix}${helper_state.next_id}`;
|
|
1262
1207
|
}
|
|
1263
1208
|
|
|
1264
1209
|
/**
|
|
1265
|
-
* @param {
|
|
1266
|
-
* @
|
|
1267
|
-
* @returns {boolean}
|
|
1210
|
+
* @param {string} base_name
|
|
1211
|
+
* @returns {{ base_name: string, next_id: number, helpers: any[], statics: any[] }}
|
|
1268
1212
|
*/
|
|
1269
|
-
function
|
|
1270
|
-
return
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1213
|
+
function create_helper_state(base_name) {
|
|
1214
|
+
return {
|
|
1215
|
+
base_name,
|
|
1216
|
+
next_id: 0,
|
|
1217
|
+
helpers: [],
|
|
1218
|
+
statics: [],
|
|
1219
|
+
};
|
|
1274
1220
|
}
|
|
1275
1221
|
|
|
1276
1222
|
/**
|
|
1277
|
-
* @param {any[]}
|
|
1278
|
-
* @returns {
|
|
1223
|
+
* @param {{ helpers: any[], statics: any[] }} helper_state
|
|
1224
|
+
* @returns {{ generated_helpers: any[], generated_statics: any[] } | null}
|
|
1279
1225
|
*/
|
|
1280
|
-
function
|
|
1281
|
-
|
|
1226
|
+
function create_generated_helper_metadata(helper_state) {
|
|
1227
|
+
if (helper_state.helpers.length === 0 && helper_state.statics.length === 0) {
|
|
1228
|
+
return null;
|
|
1229
|
+
}
|
|
1230
|
+
return {
|
|
1231
|
+
generated_helpers: helper_state.helpers,
|
|
1232
|
+
generated_statics: helper_state.statics,
|
|
1233
|
+
};
|
|
1282
1234
|
}
|
|
1283
1235
|
|
|
1284
1236
|
/**
|
|
1285
|
-
* @param {any
|
|
1286
|
-
* @
|
|
1287
|
-
* @param {boolean} include_platform_setup
|
|
1288
|
-
* @returns {boolean}
|
|
1237
|
+
* @param {any} metadata
|
|
1238
|
+
* @returns {any}
|
|
1289
1239
|
*/
|
|
1290
|
-
function
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
);
|
|
1240
|
+
function strip_function_transform_metadata(metadata) {
|
|
1241
|
+
const { native_tsrx, ...next_metadata } = metadata || {};
|
|
1242
|
+
return next_metadata;
|
|
1294
1243
|
}
|
|
1295
1244
|
|
|
1296
1245
|
/**
|
|
1297
|
-
* @param {
|
|
1298
|
-
* @param {TransformContext}
|
|
1299
|
-
* @
|
|
1300
|
-
* @returns {boolean}
|
|
1246
|
+
* @param {AST.BlockStatement} node
|
|
1247
|
+
* @param {{ next: () => any, visit: (node: any, state?: TransformContext) => any, state: TransformContext, path: AST.Node[] }} context
|
|
1248
|
+
* @returns {any}
|
|
1301
1249
|
*/
|
|
1302
|
-
function
|
|
1303
|
-
node
|
|
1304
|
-
|
|
1305
|
-
include_platform_setup,
|
|
1306
|
-
) {
|
|
1307
|
-
if (!node || typeof node !== 'object') {
|
|
1308
|
-
return false;
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
if (is_function_or_class_boundary(node)) {
|
|
1312
|
-
return false;
|
|
1250
|
+
function transform_block_statement(node, { next, visit, state, path }) {
|
|
1251
|
+
if (node.metadata?.native_return_block) {
|
|
1252
|
+
return next() ?? node;
|
|
1313
1253
|
}
|
|
1314
1254
|
|
|
1315
|
-
if (
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
) {
|
|
1321
|
-
return false;
|
|
1255
|
+
if (get_active_native_tsrx_function(path)?.metadata?.native_tsrx_body) {
|
|
1256
|
+
const block = create_native_tsrx_statement_list_block(node, state);
|
|
1257
|
+
if (block) {
|
|
1258
|
+
return visit(block, state);
|
|
1259
|
+
}
|
|
1322
1260
|
}
|
|
1323
1261
|
|
|
1324
|
-
return
|
|
1262
|
+
return next() ?? node;
|
|
1325
1263
|
}
|
|
1326
1264
|
|
|
1327
1265
|
/**
|
|
1328
|
-
* @param {any
|
|
1329
|
-
* @param {TransformContext}
|
|
1330
|
-
* @returns {
|
|
1266
|
+
* @param {any} node
|
|
1267
|
+
* @param {{ next: () => any, visit: (node: any, state?: TransformContext) => any, state: TransformContext, path: AST.Node[] }} context
|
|
1268
|
+
* @returns {any}
|
|
1331
1269
|
*/
|
|
1332
|
-
function
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1270
|
+
function transform_return_statement(node, { next, visit, state, path }) {
|
|
1271
|
+
const active_native_tsrx_function = get_active_native_tsrx_function(path);
|
|
1272
|
+
if (active_native_tsrx_function && is_native_tsrx_node(node.argument)) {
|
|
1273
|
+
if (!active_native_tsrx_function.metadata?.native_tsrx_body) {
|
|
1274
|
+
const statements = mark_native_pretransformed_jsx(
|
|
1275
|
+
create_native_tsrx_render_statements(node.argument, state),
|
|
1276
|
+
);
|
|
1277
|
+
if (statements.length === 1) {
|
|
1278
|
+
return visit(statements[0], state);
|
|
1279
|
+
}
|
|
1280
|
+
const block = b.block(statements, node.argument);
|
|
1281
|
+
block.metadata = {
|
|
1282
|
+
...(block.metadata || {}),
|
|
1283
|
+
native_return_block: true,
|
|
1284
|
+
};
|
|
1285
|
+
return visit(block, state);
|
|
1340
1286
|
}
|
|
1287
|
+
return visit(create_native_tsrx_render_block(node.argument, state), state);
|
|
1341
1288
|
}
|
|
1342
1289
|
|
|
1343
|
-
return
|
|
1290
|
+
return next() ?? node;
|
|
1344
1291
|
}
|
|
1345
1292
|
|
|
1346
1293
|
/**
|
|
1347
1294
|
* @param {any} node
|
|
1348
|
-
* @
|
|
1295
|
+
* @param {{ state: TransformContext, path: AST.Node[] }} context
|
|
1296
|
+
* @returns {any}
|
|
1349
1297
|
*/
|
|
1350
|
-
function
|
|
1351
|
-
|
|
1352
|
-
|
|
1298
|
+
function transform_jsx_code_block(node, { state, path }) {
|
|
1299
|
+
const body_nodes = get_jsx_code_block_body_nodes(node, state);
|
|
1300
|
+
const parent = /** @type {any} */ (path.at(-1));
|
|
1301
|
+
|
|
1302
|
+
if (parent && parent.body === node && is_function_or_class_boundary(parent)) {
|
|
1303
|
+
const block = b.block(
|
|
1304
|
+
mark_native_pretransformed_jsx(build_render_statements(body_nodes, true, state)),
|
|
1305
|
+
node,
|
|
1306
|
+
);
|
|
1307
|
+
block.metadata = {
|
|
1308
|
+
...(block.metadata || {}),
|
|
1309
|
+
native_return_block: true,
|
|
1310
|
+
};
|
|
1311
|
+
return block;
|
|
1353
1312
|
}
|
|
1354
1313
|
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
statement_contains_component_body_return(node.alternate)
|
|
1314
|
+
const expression = b.call(
|
|
1315
|
+
b.arrow([], b.block(build_render_statements(body_nodes, true, state), node)),
|
|
1358
1316
|
);
|
|
1317
|
+
|
|
1318
|
+
return in_jsx_child_context(path) ? to_jsx_expression_container(expression, node) : expression;
|
|
1359
1319
|
}
|
|
1360
1320
|
|
|
1361
1321
|
/**
|
|
1362
|
-
* @param {
|
|
1363
|
-
* @returns {
|
|
1322
|
+
* @param {AST.Node[]} path
|
|
1323
|
+
* @returns {any | null}
|
|
1364
1324
|
*/
|
|
1365
|
-
function
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
return true;
|
|
1325
|
+
function get_active_native_tsrx_function(path) {
|
|
1326
|
+
for (let i = path.length - 1; i >= 0; i -= 1) {
|
|
1327
|
+
const node = /** @type {any} */ (path[i]);
|
|
1328
|
+
if (is_function_or_class_boundary(node)) {
|
|
1329
|
+
return node.metadata?.native_tsrx ? node : null;
|
|
1330
|
+
}
|
|
1372
1331
|
}
|
|
1332
|
+
return null;
|
|
1333
|
+
}
|
|
1373
1334
|
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1335
|
+
/**
|
|
1336
|
+
* @param {any} node
|
|
1337
|
+
* @param {{ next: () => any, state: TransformContext, path: AST.Node[] }} context
|
|
1338
|
+
* @returns {any}
|
|
1339
|
+
*/
|
|
1340
|
+
function transform_function(node, context) {
|
|
1341
|
+
// Lower a `@{ … }` function body (JSXCodeBlock) to an ordinary block: the
|
|
1342
|
+
// setup statements followed by `return <render>` when the block produces a
|
|
1343
|
+
// render output. The parser already marks the render JSX as native_tsrx, so
|
|
1344
|
+
// from here it flows through the existing native-component machinery exactly
|
|
1345
|
+
// like the older fenced `{ return <> … </> }` shape.
|
|
1346
|
+
const has_jsx_code_block_body = node.body?.type === 'JSXCodeBlock';
|
|
1347
|
+
lower_jsx_code_block_function_body(node);
|
|
1377
1348
|
|
|
1378
|
-
if (
|
|
1379
|
-
|
|
1349
|
+
if (
|
|
1350
|
+
has_jsx_code_block_body ||
|
|
1351
|
+
node.metadata?.native_tsrx_function ||
|
|
1352
|
+
function_has_native_tsrx_return(node)
|
|
1353
|
+
) {
|
|
1354
|
+
return transform_native_tsrx_function(node, context, {
|
|
1355
|
+
nativeBody: has_jsx_code_block_body || !!node.metadata?.native_tsrx_function,
|
|
1356
|
+
});
|
|
1380
1357
|
}
|
|
1381
1358
|
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
}
|
|
1359
|
+
return transform_function_with_hook_helpers(node, context);
|
|
1360
|
+
}
|
|
1385
1361
|
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1362
|
+
/**
|
|
1363
|
+
* @param {any} node
|
|
1364
|
+
* @returns {void}
|
|
1365
|
+
*/
|
|
1366
|
+
function lower_jsx_code_block_function_body(node) {
|
|
1367
|
+
if (node.body?.type !== 'JSXCodeBlock') return;
|
|
1392
1368
|
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1369
|
+
const code_block = node.body;
|
|
1370
|
+
const statements = [...code_block.body];
|
|
1371
|
+
if (code_block.render != null) {
|
|
1372
|
+
let render = code_block.render;
|
|
1373
|
+
if (!is_native_tsrx_node(render)) {
|
|
1374
|
+
// A control-flow output (@if/@for/@switch/@try) isn't itself a native
|
|
1375
|
+
// template node, so `return @if (…) { … }` wouldn't be recognized as a
|
|
1376
|
+
// component render output. Wrap it in a native fragment so it flows
|
|
1377
|
+
// through the same children-rendering path as a `<> … </>` render.
|
|
1378
|
+
const fragment = b.jsx_fragment([render]);
|
|
1379
|
+
fragment.metadata = { ...fragment.metadata, native_tsrx: true };
|
|
1380
|
+
render = fragment;
|
|
1381
|
+
}
|
|
1382
|
+
statements.push(b.return(render, code_block.render));
|
|
1397
1383
|
}
|
|
1398
|
-
|
|
1399
|
-
if (
|
|
1400
|
-
|
|
1401
|
-
statement_contains_component_body_return(node.block) ||
|
|
1402
|
-
statement_contains_component_body_return(node.handler?.body) ||
|
|
1403
|
-
statement_contains_component_body_return(node.finalizer)
|
|
1404
|
-
);
|
|
1384
|
+
node.body = b.block(statements, code_block);
|
|
1385
|
+
if (node.type === 'ArrowFunctionExpression') {
|
|
1386
|
+
node.expression = false;
|
|
1405
1387
|
}
|
|
1406
|
-
|
|
1407
|
-
return false;
|
|
1408
1388
|
}
|
|
1409
1389
|
|
|
1410
1390
|
/**
|
|
1411
|
-
* @param {any
|
|
1412
|
-
* @param {TransformContext}
|
|
1413
|
-
* @param {boolean}
|
|
1414
|
-
* @returns {
|
|
1391
|
+
* @param {any} node
|
|
1392
|
+
* @param {{ next: () => any, state: TransformContext }} context
|
|
1393
|
+
* @param {{ nativeBody?: boolean }} [options]
|
|
1394
|
+
* @returns {any}
|
|
1415
1395
|
*/
|
|
1416
|
-
function
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1396
|
+
function transform_native_tsrx_function(node, { next, state }, { nativeBody = false } = {}) {
|
|
1397
|
+
const helper_state =
|
|
1398
|
+
state.helper_state || create_helper_state(get_function_helper_base_name(node));
|
|
1399
|
+
const saved_helper_state = state.helper_state;
|
|
1400
|
+
const saved_bindings = state.available_bindings;
|
|
1401
|
+
const saved_hook_helpers_enabled = state.hook_helpers_enabled;
|
|
1402
|
+
|
|
1403
|
+
state.helper_state = helper_state;
|
|
1404
|
+
state.hook_helpers_enabled = is_uppercase_function_like(node);
|
|
1405
|
+
node.metadata = {
|
|
1406
|
+
...(node.metadata || {}),
|
|
1407
|
+
native_tsrx: true,
|
|
1408
|
+
...(nativeBody ? { native_tsrx_body: true } : {}),
|
|
1409
|
+
};
|
|
1410
|
+
state.available_bindings = merge_binding_maps(
|
|
1411
|
+
saved_bindings,
|
|
1412
|
+
collect_function_scope_bindings(node),
|
|
1423
1413
|
);
|
|
1424
|
-
}
|
|
1425
1414
|
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1415
|
+
validate_native_await(node, state);
|
|
1416
|
+
|
|
1417
|
+
const inner = /** @type {any} */ (next() ?? node);
|
|
1418
|
+
if (
|
|
1419
|
+
inner !== node &&
|
|
1420
|
+
node.type === 'ArrowFunctionExpression' &&
|
|
1421
|
+
is_native_tsrx_node(node.body) &&
|
|
1422
|
+
inner.body?.type === 'BlockStatement'
|
|
1423
|
+
) {
|
|
1424
|
+
inner.expression = false;
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
state.helper_state = saved_helper_state;
|
|
1428
|
+
state.available_bindings = saved_bindings;
|
|
1429
|
+
state.hook_helpers_enabled = saved_hook_helpers_enabled;
|
|
1430
|
+
|
|
1431
|
+
inner.metadata = {
|
|
1432
|
+
...strip_function_transform_metadata(inner.metadata),
|
|
1433
|
+
native_tsrx_function: true,
|
|
1434
|
+
...(nativeBody ? { native_tsrx_body: true } : {}),
|
|
1435
|
+
...(!saved_helper_state ? create_generated_helper_metadata(helper_state) || {} : {}),
|
|
1436
|
+
};
|
|
1437
|
+
|
|
1438
|
+
return inner;
|
|
1434
1439
|
}
|
|
1435
1440
|
|
|
1436
1441
|
/**
|
|
1437
1442
|
* @param {any} node
|
|
1438
|
-
* @param {boolean} inside_nested_function
|
|
1439
1443
|
* @param {TransformContext} transform_context
|
|
1440
|
-
* @
|
|
1441
|
-
* @returns {boolean}
|
|
1444
|
+
* @returns {void}
|
|
1442
1445
|
*/
|
|
1443
|
-
function
|
|
1444
|
-
node
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
include_platform_setup,
|
|
1448
|
-
) {
|
|
1449
|
-
if (!node || typeof node !== 'object') {
|
|
1450
|
-
return false;
|
|
1446
|
+
function validate_native_await(node, transform_context) {
|
|
1447
|
+
const await_node = find_native_await(node);
|
|
1448
|
+
if (!await_node) {
|
|
1449
|
+
return;
|
|
1451
1450
|
}
|
|
1452
1451
|
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
(node.
|
|
1456
|
-
|
|
1457
|
-
node.type === 'ArrowFunctionExpression')
|
|
1458
|
-
) {
|
|
1459
|
-
return false;
|
|
1452
|
+
const validator = transform_context.platform.hooks?.validateComponentAwait;
|
|
1453
|
+
if (validator) {
|
|
1454
|
+
validator(await_node, node, transform_context, false, transform_context.source || '');
|
|
1455
|
+
return;
|
|
1460
1456
|
}
|
|
1461
1457
|
|
|
1462
|
-
if (
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
continue;
|
|
1471
|
-
}
|
|
1472
|
-
if (
|
|
1473
|
-
node_contains_top_level_hook_call(
|
|
1474
|
-
node[key],
|
|
1475
|
-
next_inside_nested_function,
|
|
1476
|
-
transform_context,
|
|
1477
|
-
include_platform_setup,
|
|
1478
|
-
)
|
|
1479
|
-
) {
|
|
1480
|
-
return true;
|
|
1481
|
-
}
|
|
1482
|
-
}
|
|
1483
|
-
return false;
|
|
1458
|
+
if (transform_context.platform.validation.requireUseServerForAwait) {
|
|
1459
|
+
error(
|
|
1460
|
+
'Top-level `await` in TSRX functions requires a module-level `"use server"` directive.',
|
|
1461
|
+
transform_context.filename,
|
|
1462
|
+
await_node,
|
|
1463
|
+
transform_context.errors,
|
|
1464
|
+
transform_context.comments,
|
|
1465
|
+
);
|
|
1484
1466
|
}
|
|
1467
|
+
}
|
|
1485
1468
|
|
|
1469
|
+
/**
|
|
1470
|
+
* @param {any} node
|
|
1471
|
+
* @returns {any | null}
|
|
1472
|
+
*/
|
|
1473
|
+
function find_native_await(node) {
|
|
1486
1474
|
if (
|
|
1487
|
-
|
|
1488
|
-
node.type
|
|
1489
|
-
(
|
|
1490
|
-
(include_platform_setup &&
|
|
1491
|
-
transform_context.platform.hooks?.isTopLevelSetupCall?.(node, transform_context) === true))
|
|
1475
|
+
node.type === 'ArrowFunctionExpression' &&
|
|
1476
|
+
node.body?.type !== 'BlockStatement' &&
|
|
1477
|
+
node_contains_native_tsrx_template(node.body)
|
|
1492
1478
|
) {
|
|
1493
|
-
return
|
|
1479
|
+
return find_first_top_level_await(node.body, false);
|
|
1494
1480
|
}
|
|
1495
1481
|
|
|
1496
|
-
if (
|
|
1497
|
-
return node.
|
|
1498
|
-
node_contains_top_level_hook_call(
|
|
1499
|
-
child,
|
|
1500
|
-
inside_nested_function,
|
|
1501
|
-
transform_context,
|
|
1502
|
-
include_platform_setup,
|
|
1503
|
-
),
|
|
1504
|
-
);
|
|
1482
|
+
if (node.body?.type === 'JSXCodeBlock') {
|
|
1483
|
+
return find_native_await_in_list(get_raw_jsx_code_block_body_nodes(node.body));
|
|
1505
1484
|
}
|
|
1506
1485
|
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
}
|
|
1511
|
-
if (
|
|
1512
|
-
node_contains_top_level_hook_call(
|
|
1513
|
-
node[key],
|
|
1514
|
-
inside_nested_function,
|
|
1515
|
-
transform_context,
|
|
1516
|
-
include_platform_setup,
|
|
1517
|
-
)
|
|
1518
|
-
) {
|
|
1519
|
-
return true;
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1486
|
+
const body = node.body?.type === 'BlockStatement' ? node.body.body || [] : [];
|
|
1487
|
+
return find_native_await_in_list(body);
|
|
1488
|
+
}
|
|
1522
1489
|
|
|
1523
|
-
|
|
1490
|
+
/**
|
|
1491
|
+
* @param {any[]} statements
|
|
1492
|
+
* @returns {any | null}
|
|
1493
|
+
*/
|
|
1494
|
+
function find_native_await_in_list(statements) {
|
|
1495
|
+
for (const statement of statements) {
|
|
1496
|
+
const found = find_native_await_in_statement(statement);
|
|
1497
|
+
if (found) return found;
|
|
1498
|
+
}
|
|
1499
|
+
return null;
|
|
1524
1500
|
}
|
|
1525
1501
|
|
|
1526
1502
|
/**
|
|
1527
|
-
* @param {any}
|
|
1528
|
-
* @returns {
|
|
1503
|
+
* @param {any} statement
|
|
1504
|
+
* @returns {any | null}
|
|
1529
1505
|
*/
|
|
1530
|
-
function
|
|
1531
|
-
if (!
|
|
1506
|
+
function find_native_await_in_statement(statement) {
|
|
1507
|
+
if (!statement || typeof statement !== 'object') return null;
|
|
1532
1508
|
|
|
1533
|
-
if (
|
|
1534
|
-
return
|
|
1509
|
+
if (statement.type === 'ReturnStatement' && is_native_tsrx_node(statement.argument)) {
|
|
1510
|
+
return find_first_top_level_await_in_tsrx_function_body(statement.argument.children || []);
|
|
1535
1511
|
}
|
|
1536
1512
|
|
|
1537
1513
|
if (
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
callee.property?.type === 'Identifier'
|
|
1514
|
+
statement.type === 'ReturnStatement' &&
|
|
1515
|
+
node_contains_native_tsrx_template(statement.argument)
|
|
1541
1516
|
) {
|
|
1542
|
-
return
|
|
1517
|
+
return find_first_top_level_await(statement.argument, false);
|
|
1543
1518
|
}
|
|
1544
1519
|
|
|
1545
|
-
|
|
1546
|
-
|
|
1520
|
+
if (is_function_or_class_boundary(statement)) {
|
|
1521
|
+
return null;
|
|
1522
|
+
}
|
|
1547
1523
|
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
* @returns {AST.ObjectPattern}
|
|
1552
|
-
*/
|
|
1553
|
-
function create_helper_props_pattern(bindings, mapped_bindings = new Set()) {
|
|
1554
|
-
return /** @type {any} */ ({
|
|
1555
|
-
type: 'ObjectPattern',
|
|
1556
|
-
properties: bindings.map((binding) =>
|
|
1557
|
-
create_helper_props_property(binding, mapped_bindings.has(binding.name)),
|
|
1558
|
-
),
|
|
1559
|
-
metadata: { path: [] },
|
|
1560
|
-
});
|
|
1561
|
-
}
|
|
1524
|
+
if (statement.type === 'BlockStatement') {
|
|
1525
|
+
return find_native_await_in_list(statement.body || []);
|
|
1526
|
+
}
|
|
1562
1527
|
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
const key = map_binding ? clone_identifier(binding) : create_generated_identifier(binding.name);
|
|
1570
|
-
const value = map_binding ? clone_identifier(binding) : create_generated_identifier(binding.name);
|
|
1528
|
+
if (is_if_control_node(statement)) {
|
|
1529
|
+
return (
|
|
1530
|
+
find_native_await_in_statement(statement.consequent) ||
|
|
1531
|
+
find_native_await_in_statement(statement.alternate)
|
|
1532
|
+
);
|
|
1533
|
+
}
|
|
1571
1534
|
|
|
1572
|
-
|
|
1535
|
+
if (is_switch_control_node(statement)) {
|
|
1536
|
+
for (const switch_case of statement.cases || []) {
|
|
1537
|
+
const found = find_native_await_in_list(switch_case.consequent || []);
|
|
1538
|
+
if (found) return found;
|
|
1539
|
+
}
|
|
1540
|
+
return null;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
if (is_try_control_node(statement)) {
|
|
1544
|
+
return (
|
|
1545
|
+
find_native_await_in_statement(statement.block) ||
|
|
1546
|
+
find_native_await_in_statement(statement.handler?.body) ||
|
|
1547
|
+
find_native_await_in_statement(statement.finalizer)
|
|
1548
|
+
);
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
return find_first_top_level_await(statement, false);
|
|
1573
1552
|
}
|
|
1574
1553
|
|
|
1575
1554
|
/**
|
|
1576
|
-
* @param {
|
|
1577
|
-
* @param {
|
|
1578
|
-
* @
|
|
1579
|
-
* @param {{
|
|
1580
|
-
* mapWrapper?: boolean,
|
|
1581
|
-
* mapBindingNames?: boolean,
|
|
1582
|
-
* mapBindingValues?: boolean,
|
|
1583
|
-
* }} [mapping]
|
|
1584
|
-
* @returns {ESTreeJSX.JSXElement}
|
|
1555
|
+
* @param {any} node
|
|
1556
|
+
* @param {{ next: () => any, state: TransformContext }} context
|
|
1557
|
+
* @returns {any}
|
|
1585
1558
|
*/
|
|
1586
|
-
function
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
identifier_to_jsx_name(
|
|
1591
|
-
mapBindingNames ? clone_identifier(binding) : create_generated_identifier(binding.name),
|
|
1592
|
-
),
|
|
1593
|
-
to_jsx_expression_container(
|
|
1594
|
-
mapBindingValues ? clone_identifier(binding) : create_generated_identifier(binding.name),
|
|
1595
|
-
binding,
|
|
1596
|
-
),
|
|
1597
|
-
),
|
|
1598
|
-
);
|
|
1559
|
+
function transform_function_with_hook_helpers(node, { next, state }) {
|
|
1560
|
+
if (!state.platform.hooks?.moduleScopedHookComponents) {
|
|
1561
|
+
return next() ?? node;
|
|
1562
|
+
}
|
|
1599
1563
|
|
|
1600
|
-
const
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
);
|
|
1605
|
-
const element = b.jsx_element_fresh(
|
|
1606
|
-
mapWrapper ? set_loc(opening_element, source_node) : opening_element,
|
|
1607
|
-
);
|
|
1564
|
+
const has_hook_bearing_tsrx = function_contains_hook_bearing_tsrx(node, state);
|
|
1565
|
+
if (state.helper_state || !is_uppercase_function_like(node) || !has_hook_bearing_tsrx) {
|
|
1566
|
+
return next() ?? node;
|
|
1567
|
+
}
|
|
1608
1568
|
|
|
1609
|
-
|
|
1569
|
+
const helper_state = create_helper_state(get_function_helper_base_name(node));
|
|
1570
|
+
const saved_helper_state = state.helper_state;
|
|
1571
|
+
const saved_bindings = state.available_bindings;
|
|
1572
|
+
const saved_hook_helpers_enabled = state.hook_helpers_enabled;
|
|
1573
|
+
|
|
1574
|
+
state.helper_state = helper_state;
|
|
1575
|
+
state.hook_helpers_enabled = true;
|
|
1576
|
+
state.available_bindings = collect_function_scope_bindings(node);
|
|
1577
|
+
|
|
1578
|
+
const inner = /** @type {any} */ (next() ?? node);
|
|
1579
|
+
|
|
1580
|
+
state.helper_state = saved_helper_state;
|
|
1581
|
+
state.available_bindings = saved_bindings;
|
|
1582
|
+
state.hook_helpers_enabled = saved_hook_helpers_enabled;
|
|
1583
|
+
|
|
1584
|
+
inner.metadata = {
|
|
1585
|
+
...strip_function_transform_metadata(inner.metadata),
|
|
1586
|
+
...(create_generated_helper_metadata(helper_state) || {}),
|
|
1587
|
+
};
|
|
1588
|
+
|
|
1589
|
+
return inner;
|
|
1610
1590
|
}
|
|
1611
1591
|
|
|
1612
1592
|
/**
|
|
1613
|
-
* @param {
|
|
1614
|
-
* @param {string} suffix
|
|
1593
|
+
* @param {any} node
|
|
1615
1594
|
* @returns {string}
|
|
1616
1595
|
*/
|
|
1617
|
-
function
|
|
1618
|
-
|
|
1619
|
-
return `${helper_state.base_name}__${suffix}${helper_state.next_id}`;
|
|
1596
|
+
function get_function_helper_base_name(node) {
|
|
1597
|
+
return get_function_like_name(node) || 'TSRXTemplate';
|
|
1620
1598
|
}
|
|
1621
1599
|
|
|
1622
1600
|
/**
|
|
1623
|
-
* @param {
|
|
1624
|
-
* @returns {
|
|
1601
|
+
* @param {any} node
|
|
1602
|
+
* @returns {boolean}
|
|
1625
1603
|
*/
|
|
1626
|
-
function
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
next_id: 0,
|
|
1630
|
-
helpers: [],
|
|
1631
|
-
statics: [],
|
|
1632
|
-
};
|
|
1604
|
+
function is_uppercase_function_like(node) {
|
|
1605
|
+
const name = get_function_like_name(node);
|
|
1606
|
+
return !!(name && /^[A-Z]/.test(name));
|
|
1633
1607
|
}
|
|
1634
1608
|
|
|
1635
1609
|
/**
|
|
1636
|
-
* @param {
|
|
1637
|
-
* @returns {
|
|
1610
|
+
* @param {any} node
|
|
1611
|
+
* @returns {string | null}
|
|
1638
1612
|
*/
|
|
1639
|
-
function
|
|
1640
|
-
if (
|
|
1641
|
-
return
|
|
1613
|
+
function get_function_like_name(node) {
|
|
1614
|
+
if (node.id?.type === 'Identifier') {
|
|
1615
|
+
return node.id.name;
|
|
1642
1616
|
}
|
|
1643
|
-
return {
|
|
1644
|
-
generated_helpers: helper_state.helpers,
|
|
1645
|
-
generated_statics: helper_state.statics,
|
|
1646
|
-
};
|
|
1647
|
-
}
|
|
1648
1617
|
|
|
1649
|
-
/**
|
|
1650
|
-
|
|
1651
|
-
* @returns {any}
|
|
1652
|
-
*/
|
|
1653
|
-
function strip_function_transform_metadata(metadata) {
|
|
1654
|
-
const { native_tsrx, hook_split, ...next_metadata } = metadata || {};
|
|
1655
|
-
return next_metadata;
|
|
1656
|
-
}
|
|
1618
|
+
const parent = /** @type {any} */ (node.metadata?.path?.at(-1));
|
|
1619
|
+
if (!parent) return null;
|
|
1657
1620
|
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
* @param {{ next: () => any, visit: (node: any, state?: TransformContext) => any, state: TransformContext, path: AST.Node[] }} context
|
|
1661
|
-
* @returns {any}
|
|
1662
|
-
*/
|
|
1663
|
-
function transform_block_statement(node, { next, visit, state, path }) {
|
|
1664
|
-
if (node.metadata?.hook_split_block || node.metadata?.native_return_block) {
|
|
1665
|
-
return next() ?? node;
|
|
1621
|
+
if (parent.type === 'VariableDeclarator' && parent.init === node) {
|
|
1622
|
+
return get_static_binding_name(parent.id);
|
|
1666
1623
|
}
|
|
1667
1624
|
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
const block = create_hook_split_block(parent, state);
|
|
1671
|
-
if (block) {
|
|
1672
|
-
return visit(block, state);
|
|
1673
|
-
}
|
|
1625
|
+
if (parent.type === 'Property' && parent.value === node) {
|
|
1626
|
+
return get_static_property_name(parent.key);
|
|
1674
1627
|
}
|
|
1675
1628
|
|
|
1676
|
-
if (
|
|
1677
|
-
|
|
1678
|
-
if (block) {
|
|
1679
|
-
return visit(block, state);
|
|
1680
|
-
}
|
|
1629
|
+
if (parent.type === 'MethodDefinition' && parent.value === node) {
|
|
1630
|
+
return get_static_property_name(parent.key);
|
|
1681
1631
|
}
|
|
1682
1632
|
|
|
1683
|
-
|
|
1633
|
+
if (parent.type === 'AssignmentExpression' && parent.right === node) {
|
|
1634
|
+
return get_static_binding_name(parent.left);
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
return null;
|
|
1684
1638
|
}
|
|
1685
1639
|
|
|
1686
1640
|
/**
|
|
1687
1641
|
* @param {any} node
|
|
1688
|
-
* @
|
|
1689
|
-
* @returns {any}
|
|
1642
|
+
* @returns {string | null}
|
|
1690
1643
|
*/
|
|
1691
|
-
function
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
if (!active_native_tsrx_function.metadata?.native_tsrx_body) {
|
|
1695
|
-
const statements = mark_native_pretransformed_jsx(
|
|
1696
|
-
create_native_tsrx_render_statements(node.argument, state),
|
|
1697
|
-
);
|
|
1698
|
-
if (statements.length === 1) {
|
|
1699
|
-
return visit(statements[0], state);
|
|
1700
|
-
}
|
|
1701
|
-
const block = b.block(statements, node.argument);
|
|
1702
|
-
block.metadata = {
|
|
1703
|
-
...(block.metadata || {}),
|
|
1704
|
-
native_return_block: true,
|
|
1705
|
-
};
|
|
1706
|
-
return visit(block, state);
|
|
1707
|
-
}
|
|
1708
|
-
return visit(create_native_tsrx_render_block(node.argument, state), state);
|
|
1644
|
+
function get_static_binding_name(node) {
|
|
1645
|
+
if (node?.type === 'Identifier') {
|
|
1646
|
+
return node.name;
|
|
1709
1647
|
}
|
|
1710
|
-
|
|
1711
|
-
|
|
1648
|
+
if (node?.type === 'MemberExpression' && !node.computed) {
|
|
1649
|
+
return get_static_property_name(node.property);
|
|
1650
|
+
}
|
|
1651
|
+
return null;
|
|
1712
1652
|
}
|
|
1713
1653
|
|
|
1714
1654
|
/**
|
|
1715
|
-
* @param {any}
|
|
1716
|
-
* @
|
|
1717
|
-
* @returns {any}
|
|
1655
|
+
* @param {any} key
|
|
1656
|
+
* @returns {string | null}
|
|
1718
1657
|
*/
|
|
1719
|
-
function
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
if (parent && parent.body === node && is_function_or_class_boundary(parent)) {
|
|
1724
|
-
const block = b.block(
|
|
1725
|
-
mark_native_pretransformed_jsx(build_render_statements(body_nodes, true, state)),
|
|
1726
|
-
node,
|
|
1727
|
-
);
|
|
1728
|
-
block.metadata = {
|
|
1729
|
-
...(block.metadata || {}),
|
|
1730
|
-
native_return_block: true,
|
|
1731
|
-
};
|
|
1732
|
-
return block;
|
|
1658
|
+
function get_static_property_name(key) {
|
|
1659
|
+
if (key?.type === 'Identifier') {
|
|
1660
|
+
return key.name;
|
|
1733
1661
|
}
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
return in_jsx_child_context(path) ? to_jsx_expression_container(expression, node) : expression;
|
|
1662
|
+
if (key?.type === 'Literal' && typeof key.value === 'string') {
|
|
1663
|
+
return key.value;
|
|
1664
|
+
}
|
|
1665
|
+
return null;
|
|
1740
1666
|
}
|
|
1741
1667
|
|
|
1742
1668
|
/**
|
|
1743
|
-
* @param {
|
|
1744
|
-
* @returns {
|
|
1669
|
+
* @param {any} node
|
|
1670
|
+
* @returns {Map<string, AST.Identifier>}
|
|
1745
1671
|
*/
|
|
1746
|
-
function
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1672
|
+
function collect_function_scope_bindings(node) {
|
|
1673
|
+
const bindings = collect_param_bindings(node.params || []);
|
|
1674
|
+
if (node.body?.type === 'BlockStatement') {
|
|
1675
|
+
for (const statement of node.body.body || []) {
|
|
1676
|
+
if (statement.type === 'ReturnStatement' && is_native_tsrx_node(statement.argument)) {
|
|
1677
|
+
for (const child of get_tsrx_render_children(statement.argument)) {
|
|
1678
|
+
collect_statement_bindings(child, bindings);
|
|
1679
|
+
}
|
|
1680
|
+
} else {
|
|
1681
|
+
collect_statement_bindings(statement, bindings);
|
|
1682
|
+
}
|
|
1751
1683
|
}
|
|
1752
1684
|
}
|
|
1753
|
-
return
|
|
1685
|
+
return bindings;
|
|
1754
1686
|
}
|
|
1755
1687
|
|
|
1756
1688
|
/**
|
|
1757
|
-
* @param {
|
|
1758
|
-
* @param {
|
|
1759
|
-
* @returns {
|
|
1689
|
+
* @param {Map<string, AST.Identifier>} outer
|
|
1690
|
+
* @param {Map<string, AST.Identifier>} inner
|
|
1691
|
+
* @returns {Map<string, AST.Identifier>}
|
|
1760
1692
|
*/
|
|
1761
|
-
function
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
// from here it flows through the existing native-component machinery exactly
|
|
1766
|
-
// like the older fenced `{ return <> … </> }` shape.
|
|
1767
|
-
const has_jsx_code_block_body = node.body?.type === 'JSXCodeBlock';
|
|
1768
|
-
lower_jsx_code_block_function_body(node);
|
|
1769
|
-
|
|
1770
|
-
if (
|
|
1771
|
-
has_jsx_code_block_body ||
|
|
1772
|
-
node.metadata?.native_tsrx_function ||
|
|
1773
|
-
function_has_native_tsrx_return(node)
|
|
1774
|
-
) {
|
|
1775
|
-
return transform_native_tsrx_function(node, context, {
|
|
1776
|
-
nativeBody: has_jsx_code_block_body || !!node.metadata?.native_tsrx_function,
|
|
1777
|
-
});
|
|
1693
|
+
function merge_binding_maps(outer, inner) {
|
|
1694
|
+
const merged = new Map(outer);
|
|
1695
|
+
for (const [name, binding] of inner) {
|
|
1696
|
+
merged.set(name, binding);
|
|
1778
1697
|
}
|
|
1779
|
-
|
|
1780
|
-
return transform_function_with_hook_helpers(node, context);
|
|
1698
|
+
return merged;
|
|
1781
1699
|
}
|
|
1782
1700
|
|
|
1783
1701
|
/**
|
|
1784
1702
|
* @param {any} node
|
|
1785
|
-
* @returns {
|
|
1703
|
+
* @returns {boolean}
|
|
1786
1704
|
*/
|
|
1787
|
-
function
|
|
1788
|
-
if (node
|
|
1705
|
+
function function_has_native_tsrx_return(node) {
|
|
1706
|
+
if (!node) return false;
|
|
1789
1707
|
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
if (code_block.render != null) {
|
|
1793
|
-
let render = code_block.render;
|
|
1794
|
-
if (!is_native_tsrx_node(render)) {
|
|
1795
|
-
// A control-flow output (@if/@for/@switch/@try) isn't itself a native
|
|
1796
|
-
// template node, so `return @if (…) { … }` wouldn't be recognized as a
|
|
1797
|
-
// component render output. Wrap it in a native fragment so it flows
|
|
1798
|
-
// through the same children-rendering path as a `<> … </>` render.
|
|
1799
|
-
const fragment = b.jsx_fragment([render]);
|
|
1800
|
-
fragment.metadata = { ...fragment.metadata, native_tsrx: true };
|
|
1801
|
-
render = fragment;
|
|
1802
|
-
}
|
|
1803
|
-
statements.push(b.return(render, code_block.render));
|
|
1708
|
+
if (node.body?.type === 'JSXCodeBlock') {
|
|
1709
|
+
return true;
|
|
1804
1710
|
}
|
|
1805
|
-
|
|
1806
|
-
if (node.type === 'ArrowFunctionExpression') {
|
|
1807
|
-
node.
|
|
1711
|
+
|
|
1712
|
+
if (node.type === 'ArrowFunctionExpression' && node.body?.type !== 'BlockStatement') {
|
|
1713
|
+
return node_contains_native_tsrx_template(node.body);
|
|
1808
1714
|
}
|
|
1715
|
+
|
|
1716
|
+
const body = node.body?.type === 'BlockStatement' ? node.body.body : [];
|
|
1717
|
+
return statements_contain_native_tsrx_return(body);
|
|
1809
1718
|
}
|
|
1810
1719
|
|
|
1811
1720
|
/**
|
|
1812
|
-
* @param {any}
|
|
1813
|
-
* @
|
|
1814
|
-
* @param {{ nativeBody?: boolean }} [options]
|
|
1815
|
-
* @returns {any}
|
|
1721
|
+
* @param {any[]} statements
|
|
1722
|
+
* @returns {boolean}
|
|
1816
1723
|
*/
|
|
1817
|
-
function
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
const saved_helper_state = state.helper_state;
|
|
1821
|
-
const saved_bindings = state.available_bindings;
|
|
1822
|
-
const saved_hook_helpers_enabled = state.hook_helpers_enabled;
|
|
1724
|
+
function statements_contain_native_tsrx_return(statements) {
|
|
1725
|
+
return statements.some((statement) => statement_contains_native_tsrx_return(statement));
|
|
1726
|
+
}
|
|
1823
1727
|
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
...(nativeBody && needs_hook_split(node, state) ? { hook_split: true } : {}),
|
|
1831
|
-
};
|
|
1832
|
-
state.available_bindings = merge_binding_maps(
|
|
1833
|
-
saved_bindings,
|
|
1834
|
-
collect_function_scope_bindings(node),
|
|
1835
|
-
);
|
|
1728
|
+
/**
|
|
1729
|
+
* @param {any} statement
|
|
1730
|
+
* @returns {boolean}
|
|
1731
|
+
*/
|
|
1732
|
+
function statement_contains_native_tsrx_return(statement) {
|
|
1733
|
+
if (!statement || typeof statement !== 'object') return false;
|
|
1836
1734
|
|
|
1837
|
-
|
|
1735
|
+
if (statement.type === 'ReturnStatement') {
|
|
1736
|
+
return node_contains_native_tsrx_template(statement.argument);
|
|
1737
|
+
}
|
|
1838
1738
|
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
inner !== node &&
|
|
1842
|
-
node.type === 'ArrowFunctionExpression' &&
|
|
1843
|
-
is_native_tsrx_node(node.body) &&
|
|
1844
|
-
inner.body?.type === 'BlockStatement'
|
|
1845
|
-
) {
|
|
1846
|
-
inner.expression = false;
|
|
1739
|
+
if (is_function_or_class_boundary(statement)) {
|
|
1740
|
+
return false;
|
|
1847
1741
|
}
|
|
1848
1742
|
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
state.hook_helpers_enabled = saved_hook_helpers_enabled;
|
|
1852
|
-
|
|
1853
|
-
inner.metadata = {
|
|
1854
|
-
...strip_function_transform_metadata(inner.metadata),
|
|
1855
|
-
native_tsrx_function: true,
|
|
1856
|
-
...(nativeBody ? { native_tsrx_body: true } : {}),
|
|
1857
|
-
...(!saved_helper_state ? create_generated_helper_metadata(helper_state) || {} : {}),
|
|
1858
|
-
};
|
|
1859
|
-
|
|
1860
|
-
return inner;
|
|
1861
|
-
}
|
|
1862
|
-
|
|
1863
|
-
/**
|
|
1864
|
-
* @param {any} node
|
|
1865
|
-
* @param {TransformContext} transform_context
|
|
1866
|
-
* @returns {void}
|
|
1867
|
-
*/
|
|
1868
|
-
function validate_native_await(node, transform_context) {
|
|
1869
|
-
const await_node = find_native_await(node);
|
|
1870
|
-
if (!await_node) {
|
|
1871
|
-
return;
|
|
1743
|
+
if (statement.type === 'BlockStatement') {
|
|
1744
|
+
return statements_contain_native_tsrx_return(statement.body || []);
|
|
1872
1745
|
}
|
|
1873
1746
|
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1747
|
+
if (is_if_control_node(statement)) {
|
|
1748
|
+
return (
|
|
1749
|
+
statement_contains_native_tsrx_return(statement.consequent) ||
|
|
1750
|
+
statement_contains_native_tsrx_return(statement.alternate)
|
|
1751
|
+
);
|
|
1878
1752
|
}
|
|
1879
1753
|
|
|
1880
|
-
if (
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
transform_context.filename,
|
|
1884
|
-
await_node,
|
|
1885
|
-
transform_context.errors,
|
|
1886
|
-
transform_context.comments,
|
|
1754
|
+
if (is_switch_control_node(statement)) {
|
|
1755
|
+
return (statement.cases || []).some((/** @type {any} */ c) =>
|
|
1756
|
+
statements_contain_native_tsrx_return(c.consequent || []),
|
|
1887
1757
|
);
|
|
1888
1758
|
}
|
|
1889
|
-
}
|
|
1890
1759
|
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
node.body?.type !== 'BlockStatement' &&
|
|
1899
|
-
node_contains_native_tsrx_template(node.body)
|
|
1900
|
-
) {
|
|
1901
|
-
return find_first_top_level_await(node.body, false);
|
|
1760
|
+
if (is_try_control_node(statement)) {
|
|
1761
|
+
return (
|
|
1762
|
+
statement_contains_native_tsrx_return(statement.block) ||
|
|
1763
|
+
statement_contains_native_tsrx_return(statement.pending) ||
|
|
1764
|
+
statement_contains_native_tsrx_return(statement.handler?.body) ||
|
|
1765
|
+
statement_contains_native_tsrx_return(statement.finalizer)
|
|
1766
|
+
);
|
|
1902
1767
|
}
|
|
1903
1768
|
|
|
1904
|
-
|
|
1905
|
-
|
|
1769
|
+
for (const key of Object.keys(statement)) {
|
|
1770
|
+
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
1771
|
+
continue;
|
|
1772
|
+
}
|
|
1773
|
+
const value = statement[key];
|
|
1774
|
+
if (Array.isArray(value)) {
|
|
1775
|
+
if (statements_contain_native_tsrx_return(value)) return true;
|
|
1776
|
+
} else if (statement_contains_native_tsrx_return(value)) {
|
|
1777
|
+
return true;
|
|
1778
|
+
}
|
|
1906
1779
|
}
|
|
1907
1780
|
|
|
1908
|
-
|
|
1909
|
-
return find_native_await_in_list(body);
|
|
1910
|
-
}
|
|
1911
|
-
|
|
1912
|
-
/**
|
|
1913
|
-
* @param {any[]} statements
|
|
1914
|
-
* @returns {any | null}
|
|
1915
|
-
*/
|
|
1916
|
-
function find_native_await_in_list(statements) {
|
|
1917
|
-
for (const statement of statements) {
|
|
1918
|
-
const found = find_native_await_in_statement(statement);
|
|
1919
|
-
if (found) return found;
|
|
1920
|
-
}
|
|
1921
|
-
return null;
|
|
1781
|
+
return false;
|
|
1922
1782
|
}
|
|
1923
1783
|
|
|
1924
1784
|
/**
|
|
1925
|
-
* @param {any}
|
|
1926
|
-
* @returns {
|
|
1785
|
+
* @param {any} node
|
|
1786
|
+
* @returns {boolean}
|
|
1927
1787
|
*/
|
|
1928
|
-
function
|
|
1929
|
-
if (!
|
|
1930
|
-
|
|
1931
|
-
if (statement.type === 'ReturnStatement' && is_native_tsrx_node(statement.argument)) {
|
|
1932
|
-
return find_first_top_level_await_in_tsrx_function_body(statement.argument.children || []);
|
|
1933
|
-
}
|
|
1934
|
-
|
|
1935
|
-
if (
|
|
1936
|
-
statement.type === 'ReturnStatement' &&
|
|
1937
|
-
node_contains_native_tsrx_template(statement.argument)
|
|
1938
|
-
) {
|
|
1939
|
-
return find_first_top_level_await(statement.argument, false);
|
|
1940
|
-
}
|
|
1941
|
-
|
|
1942
|
-
if (is_function_or_class_boundary(statement)) {
|
|
1943
|
-
return null;
|
|
1944
|
-
}
|
|
1788
|
+
function node_contains_native_tsrx_template(node) {
|
|
1789
|
+
if (!node || typeof node !== 'object') return false;
|
|
1790
|
+
if (is_native_tsrx_node(node)) return true;
|
|
1945
1791
|
|
|
1946
|
-
if (
|
|
1947
|
-
return
|
|
1792
|
+
if (is_function_or_class_boundary(node)) {
|
|
1793
|
+
return false;
|
|
1948
1794
|
}
|
|
1949
1795
|
|
|
1950
|
-
if (
|
|
1951
|
-
return (
|
|
1952
|
-
find_native_await_in_statement(statement.consequent) ||
|
|
1953
|
-
find_native_await_in_statement(statement.alternate)
|
|
1954
|
-
);
|
|
1796
|
+
if (Array.isArray(node)) {
|
|
1797
|
+
return node.some(node_contains_native_tsrx_template);
|
|
1955
1798
|
}
|
|
1956
1799
|
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1800
|
+
for (const key of Object.keys(node)) {
|
|
1801
|
+
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
1802
|
+
continue;
|
|
1803
|
+
}
|
|
1804
|
+
if (node_contains_native_tsrx_template(node[key])) {
|
|
1805
|
+
return true;
|
|
1961
1806
|
}
|
|
1962
|
-
return null;
|
|
1963
|
-
}
|
|
1964
|
-
|
|
1965
|
-
if (is_try_control_node(statement)) {
|
|
1966
|
-
return (
|
|
1967
|
-
find_native_await_in_statement(statement.block) ||
|
|
1968
|
-
find_native_await_in_statement(statement.handler?.body) ||
|
|
1969
|
-
find_native_await_in_statement(statement.finalizer)
|
|
1970
|
-
);
|
|
1971
1807
|
}
|
|
1972
1808
|
|
|
1973
|
-
return
|
|
1809
|
+
return false;
|
|
1974
1810
|
}
|
|
1975
1811
|
|
|
1976
1812
|
/**
|
|
1977
1813
|
* @param {any} node
|
|
1978
|
-
* @param {{ next: () => any, state: TransformContext }} context
|
|
1979
1814
|
* @returns {any}
|
|
1980
1815
|
*/
|
|
1981
|
-
function
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
}
|
|
1986
|
-
|
|
1987
|
-
const helper_state = create_helper_state(get_function_helper_base_name(node));
|
|
1988
|
-
const saved_helper_state = state.helper_state;
|
|
1989
|
-
const saved_bindings = state.available_bindings;
|
|
1990
|
-
const saved_hook_helpers_enabled = state.hook_helpers_enabled;
|
|
1991
|
-
|
|
1992
|
-
state.helper_state = helper_state;
|
|
1993
|
-
state.hook_helpers_enabled = true;
|
|
1994
|
-
state.available_bindings = collect_function_scope_bindings(node);
|
|
1995
|
-
|
|
1996
|
-
const inner = /** @type {any} */ (next() ?? node);
|
|
1997
|
-
|
|
1998
|
-
state.helper_state = saved_helper_state;
|
|
1999
|
-
state.available_bindings = saved_bindings;
|
|
2000
|
-
state.hook_helpers_enabled = saved_hook_helpers_enabled;
|
|
1816
|
+
function collect_tsrx_stylesheet(node) {
|
|
1817
|
+
/** @type {any[]} */
|
|
1818
|
+
const styles = [];
|
|
1819
|
+
collect_style_elements(node.children || [], styles);
|
|
2001
1820
|
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
}
|
|
1821
|
+
if (styles.length === 0) return null;
|
|
1822
|
+
if (styles.length > 1) {
|
|
1823
|
+
throw new Error('TSRX fragments can only have one style tag');
|
|
1824
|
+
}
|
|
2006
1825
|
|
|
2007
|
-
return
|
|
1826
|
+
return styles[0];
|
|
2008
1827
|
}
|
|
2009
1828
|
|
|
2010
1829
|
/**
|
|
2011
1830
|
* @param {any} node
|
|
2012
|
-
* @
|
|
1831
|
+
* @param {TransformContext} transform_context
|
|
1832
|
+
* @returns {{ css: any, style_refs: any[], fragment: any } | null}
|
|
2013
1833
|
*/
|
|
2014
|
-
function
|
|
2015
|
-
|
|
1834
|
+
function prepare_tsrx_fragment_styles(node, transform_context) {
|
|
1835
|
+
const css = collect_tsrx_stylesheet(node);
|
|
1836
|
+
if (!css) return null;
|
|
1837
|
+
|
|
1838
|
+
const style_refs = collect_style_ref_attributes(node);
|
|
1839
|
+
apply_css_definition_metadata(node, css, transform_context, style_refs.length > 0);
|
|
1840
|
+
transform_context.stylesheets.push(css);
|
|
1841
|
+
const fragment = annotate_tsrx_with_hash(
|
|
1842
|
+
node,
|
|
1843
|
+
css.hash,
|
|
1844
|
+
transform_context.platform.jsx.classAttrName ??
|
|
1845
|
+
(transform_context.platform.jsx.rewriteClassAttr ? 'className' : 'class'),
|
|
1846
|
+
transform_context.typeOnly,
|
|
1847
|
+
);
|
|
1848
|
+
return { css, style_refs, fragment };
|
|
2016
1849
|
}
|
|
2017
1850
|
|
|
2018
1851
|
/**
|
|
1852
|
+
* @template T
|
|
2019
1853
|
* @param {any} node
|
|
2020
|
-
* @
|
|
1854
|
+
* @param {TransformContext} transform_context
|
|
1855
|
+
* @param {(style_context: { css: any, style_refs: any[], fragment: any } | null) => T} callback
|
|
1856
|
+
* @returns {T}
|
|
2021
1857
|
*/
|
|
2022
|
-
function
|
|
2023
|
-
const
|
|
2024
|
-
return
|
|
1858
|
+
function with_tsrx_fragment_styles(node, transform_context, callback) {
|
|
1859
|
+
const style_context = prepare_tsrx_fragment_styles(node, transform_context);
|
|
1860
|
+
return callback(style_context);
|
|
2025
1861
|
}
|
|
2026
1862
|
|
|
2027
1863
|
/**
|
|
2028
|
-
* @param {any}
|
|
2029
|
-
* @
|
|
1864
|
+
* @param {any} fragment
|
|
1865
|
+
* @param {{ css: any, style_refs: any[], fragment: any } | null} style_context
|
|
1866
|
+
* @param {TransformContext} transform_context
|
|
1867
|
+
* @returns {AST.Statement[]}
|
|
2030
1868
|
*/
|
|
2031
|
-
function
|
|
2032
|
-
if (
|
|
2033
|
-
return
|
|
2034
|
-
}
|
|
2035
|
-
|
|
2036
|
-
const parent = /** @type {any} */ (node.metadata?.path?.at(-1));
|
|
2037
|
-
if (!parent) return null;
|
|
2038
|
-
|
|
2039
|
-
if (parent.type === 'VariableDeclarator' && parent.init === node) {
|
|
2040
|
-
return get_static_binding_name(parent.id);
|
|
2041
|
-
}
|
|
2042
|
-
|
|
2043
|
-
if (parent.type === 'Property' && parent.value === node) {
|
|
2044
|
-
return get_static_property_name(parent.key);
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
if (parent.type === 'MethodDefinition' && parent.value === node) {
|
|
2048
|
-
return get_static_property_name(parent.key);
|
|
2049
|
-
}
|
|
2050
|
-
|
|
2051
|
-
if (parent.type === 'AssignmentExpression' && parent.right === node) {
|
|
2052
|
-
return get_static_binding_name(parent.left);
|
|
1869
|
+
function create_tsrx_style_ref_setup_statements(fragment, style_context, transform_context) {
|
|
1870
|
+
if (!style_context || style_context.style_refs.length === 0) {
|
|
1871
|
+
return [];
|
|
2053
1872
|
}
|
|
2054
1873
|
|
|
2055
|
-
return
|
|
1874
|
+
return create_style_ref_setup_statements(
|
|
1875
|
+
style_context.style_refs,
|
|
1876
|
+
create_style_class_map(fragment, style_context.css),
|
|
1877
|
+
{
|
|
1878
|
+
allowMutableRefTarget: transform_context.platform.jsx.multiRefStrategy === 'array',
|
|
1879
|
+
createTempIdentifier: () =>
|
|
1880
|
+
create_generated_identifier(create_style_ref_temp_name(transform_context)),
|
|
1881
|
+
},
|
|
1882
|
+
);
|
|
2056
1883
|
}
|
|
2057
1884
|
|
|
2058
1885
|
/**
|
|
2059
1886
|
* @param {any} node
|
|
2060
|
-
* @
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
if (node?.type === 'Identifier') {
|
|
2064
|
-
return node.name;
|
|
2065
|
-
}
|
|
2066
|
-
if (node?.type === 'MemberExpression' && !node.computed) {
|
|
2067
|
-
return get_static_property_name(node.property);
|
|
2068
|
-
}
|
|
2069
|
-
return null;
|
|
2070
|
-
}
|
|
2071
|
-
|
|
2072
|
-
/**
|
|
2073
|
-
* @param {any} key
|
|
2074
|
-
* @returns {string | null}
|
|
2075
|
-
*/
|
|
2076
|
-
function get_static_property_name(key) {
|
|
2077
|
-
if (key?.type === 'Identifier') {
|
|
2078
|
-
return key.name;
|
|
2079
|
-
}
|
|
2080
|
-
if (key?.type === 'Literal' && typeof key.value === 'string') {
|
|
2081
|
-
return key.value;
|
|
2082
|
-
}
|
|
2083
|
-
return null;
|
|
2084
|
-
}
|
|
2085
|
-
|
|
2086
|
-
/**
|
|
2087
|
-
* @param {any} node
|
|
2088
|
-
* @returns {Map<string, AST.Identifier>}
|
|
2089
|
-
*/
|
|
2090
|
-
function collect_function_scope_bindings(node) {
|
|
2091
|
-
const bindings = collect_param_bindings(node.params || []);
|
|
2092
|
-
if (node.body?.type === 'BlockStatement') {
|
|
2093
|
-
for (const statement of node.body.body || []) {
|
|
2094
|
-
if (statement.type === 'ReturnStatement' && is_native_tsrx_node(statement.argument)) {
|
|
2095
|
-
for (const child of get_tsrx_render_children(statement.argument)) {
|
|
2096
|
-
collect_statement_bindings(child, bindings);
|
|
2097
|
-
}
|
|
2098
|
-
} else {
|
|
2099
|
-
collect_statement_bindings(statement, bindings);
|
|
2100
|
-
}
|
|
2101
|
-
}
|
|
2102
|
-
}
|
|
2103
|
-
return bindings;
|
|
2104
|
-
}
|
|
2105
|
-
|
|
2106
|
-
/**
|
|
2107
|
-
* @param {Map<string, AST.Identifier>} outer
|
|
2108
|
-
* @param {Map<string, AST.Identifier>} inner
|
|
2109
|
-
* @returns {Map<string, AST.Identifier>}
|
|
2110
|
-
*/
|
|
2111
|
-
function merge_binding_maps(outer, inner) {
|
|
2112
|
-
const merged = new Map(outer);
|
|
2113
|
-
for (const [name, binding] of inner) {
|
|
2114
|
-
merged.set(name, binding);
|
|
2115
|
-
}
|
|
2116
|
-
return merged;
|
|
2117
|
-
}
|
|
2118
|
-
|
|
2119
|
-
/**
|
|
2120
|
-
* @param {any} node
|
|
2121
|
-
* @returns {boolean}
|
|
2122
|
-
*/
|
|
2123
|
-
function function_has_native_tsrx_return(node) {
|
|
2124
|
-
if (!node) return false;
|
|
2125
|
-
|
|
2126
|
-
if (node.body?.type === 'JSXCodeBlock') {
|
|
2127
|
-
return true;
|
|
2128
|
-
}
|
|
2129
|
-
|
|
2130
|
-
if (node.type === 'ArrowFunctionExpression' && node.body?.type !== 'BlockStatement') {
|
|
2131
|
-
return node_contains_native_tsrx_template(node.body);
|
|
2132
|
-
}
|
|
2133
|
-
|
|
2134
|
-
const body = node.body?.type === 'BlockStatement' ? node.body.body : [];
|
|
2135
|
-
return statements_contain_native_tsrx_return(body);
|
|
2136
|
-
}
|
|
2137
|
-
|
|
2138
|
-
/**
|
|
2139
|
-
* @param {any[]} statements
|
|
2140
|
-
* @returns {boolean}
|
|
2141
|
-
*/
|
|
2142
|
-
function statements_contain_native_tsrx_return(statements) {
|
|
2143
|
-
return statements.some((statement) => statement_contains_native_tsrx_return(statement));
|
|
2144
|
-
}
|
|
2145
|
-
|
|
2146
|
-
/**
|
|
2147
|
-
* @param {any} statement
|
|
2148
|
-
* @returns {boolean}
|
|
2149
|
-
*/
|
|
2150
|
-
function statement_contains_native_tsrx_return(statement) {
|
|
2151
|
-
if (!statement || typeof statement !== 'object') return false;
|
|
2152
|
-
|
|
2153
|
-
if (statement.type === 'ReturnStatement') {
|
|
2154
|
-
return node_contains_native_tsrx_template(statement.argument);
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2157
|
-
if (is_function_or_class_boundary(statement)) {
|
|
2158
|
-
return false;
|
|
2159
|
-
}
|
|
2160
|
-
|
|
2161
|
-
if (statement.type === 'BlockStatement') {
|
|
2162
|
-
return statements_contain_native_tsrx_return(statement.body || []);
|
|
2163
|
-
}
|
|
2164
|
-
|
|
2165
|
-
if (is_if_control_node(statement)) {
|
|
2166
|
-
return (
|
|
2167
|
-
statement_contains_native_tsrx_return(statement.consequent) ||
|
|
2168
|
-
statement_contains_native_tsrx_return(statement.alternate)
|
|
2169
|
-
);
|
|
2170
|
-
}
|
|
2171
|
-
|
|
2172
|
-
if (is_switch_control_node(statement)) {
|
|
2173
|
-
return (statement.cases || []).some((/** @type {any} */ c) =>
|
|
2174
|
-
statements_contain_native_tsrx_return(c.consequent || []),
|
|
2175
|
-
);
|
|
2176
|
-
}
|
|
2177
|
-
|
|
2178
|
-
if (is_try_control_node(statement)) {
|
|
2179
|
-
return (
|
|
2180
|
-
statement_contains_native_tsrx_return(statement.block) ||
|
|
2181
|
-
statement_contains_native_tsrx_return(statement.pending) ||
|
|
2182
|
-
statement_contains_native_tsrx_return(statement.handler?.body) ||
|
|
2183
|
-
statement_contains_native_tsrx_return(statement.finalizer)
|
|
2184
|
-
);
|
|
2185
|
-
}
|
|
2186
|
-
|
|
2187
|
-
for (const key of Object.keys(statement)) {
|
|
2188
|
-
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
2189
|
-
continue;
|
|
2190
|
-
}
|
|
2191
|
-
const value = statement[key];
|
|
2192
|
-
if (Array.isArray(value)) {
|
|
2193
|
-
if (statements_contain_native_tsrx_return(value)) return true;
|
|
2194
|
-
} else if (statement_contains_native_tsrx_return(value)) {
|
|
2195
|
-
return true;
|
|
2196
|
-
}
|
|
2197
|
-
}
|
|
2198
|
-
|
|
2199
|
-
return false;
|
|
2200
|
-
}
|
|
2201
|
-
|
|
2202
|
-
/**
|
|
2203
|
-
* @param {any} node
|
|
2204
|
-
* @returns {boolean}
|
|
2205
|
-
*/
|
|
2206
|
-
function node_contains_native_tsrx_template(node) {
|
|
2207
|
-
if (!node || typeof node !== 'object') return false;
|
|
2208
|
-
if (is_native_tsrx_node(node)) return true;
|
|
2209
|
-
|
|
2210
|
-
if (is_function_or_class_boundary(node)) {
|
|
2211
|
-
return false;
|
|
2212
|
-
}
|
|
2213
|
-
|
|
2214
|
-
if (Array.isArray(node)) {
|
|
2215
|
-
return node.some(node_contains_native_tsrx_template);
|
|
2216
|
-
}
|
|
2217
|
-
|
|
2218
|
-
for (const key of Object.keys(node)) {
|
|
2219
|
-
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
2220
|
-
continue;
|
|
2221
|
-
}
|
|
2222
|
-
if (node_contains_native_tsrx_template(node[key])) {
|
|
2223
|
-
return true;
|
|
2224
|
-
}
|
|
2225
|
-
}
|
|
2226
|
-
|
|
2227
|
-
return false;
|
|
2228
|
-
}
|
|
2229
|
-
|
|
2230
|
-
/**
|
|
2231
|
-
* @param {any} node
|
|
2232
|
-
* @returns {any}
|
|
2233
|
-
*/
|
|
2234
|
-
function collect_tsrx_stylesheet(node) {
|
|
2235
|
-
/** @type {any[]} */
|
|
2236
|
-
const styles = [];
|
|
2237
|
-
collect_style_elements(node.children || [], styles);
|
|
2238
|
-
|
|
2239
|
-
if (styles.length === 0) return null;
|
|
2240
|
-
if (styles.length > 1) {
|
|
2241
|
-
throw new Error('TSRX fragments can only have one style tag');
|
|
2242
|
-
}
|
|
2243
|
-
|
|
2244
|
-
return styles[0];
|
|
2245
|
-
}
|
|
2246
|
-
|
|
2247
|
-
/**
|
|
2248
|
-
* @param {any} node
|
|
2249
|
-
* @param {TransformContext} transform_context
|
|
2250
|
-
* @returns {{ css: any, style_refs: any[], fragment: any } | null}
|
|
2251
|
-
*/
|
|
2252
|
-
function prepare_tsrx_fragment_styles(node, transform_context) {
|
|
2253
|
-
const css = collect_tsrx_stylesheet(node);
|
|
2254
|
-
if (!css) return null;
|
|
2255
|
-
|
|
2256
|
-
const style_refs = collect_style_ref_attributes(node);
|
|
2257
|
-
apply_css_definition_metadata(node, css, transform_context, style_refs.length > 0);
|
|
2258
|
-
transform_context.stylesheets.push(css);
|
|
2259
|
-
const fragment = annotate_tsrx_with_hash(
|
|
2260
|
-
node,
|
|
2261
|
-
css.hash,
|
|
2262
|
-
transform_context.platform.jsx.classAttrName ??
|
|
2263
|
-
(transform_context.platform.jsx.rewriteClassAttr ? 'className' : 'class'),
|
|
2264
|
-
transform_context.typeOnly,
|
|
2265
|
-
);
|
|
2266
|
-
return { css, style_refs, fragment };
|
|
2267
|
-
}
|
|
2268
|
-
|
|
2269
|
-
/**
|
|
2270
|
-
* @template T
|
|
2271
|
-
* @param {any} node
|
|
2272
|
-
* @param {TransformContext} transform_context
|
|
2273
|
-
* @param {(style_context: { css: any, style_refs: any[], fragment: any } | null) => T} callback
|
|
2274
|
-
* @returns {T}
|
|
2275
|
-
*/
|
|
2276
|
-
function with_tsrx_fragment_styles(node, transform_context, callback) {
|
|
2277
|
-
const style_context = prepare_tsrx_fragment_styles(node, transform_context);
|
|
2278
|
-
return callback(style_context);
|
|
2279
|
-
}
|
|
2280
|
-
|
|
2281
|
-
/**
|
|
2282
|
-
* @param {any} fragment
|
|
2283
|
-
* @param {{ css: any, style_refs: any[], fragment: any } | null} style_context
|
|
2284
|
-
* @param {TransformContext} transform_context
|
|
2285
|
-
* @returns {AST.Statement[]}
|
|
2286
|
-
*/
|
|
2287
|
-
function create_tsrx_style_ref_setup_statements(fragment, style_context, transform_context) {
|
|
2288
|
-
if (!style_context || style_context.style_refs.length === 0) {
|
|
2289
|
-
return [];
|
|
2290
|
-
}
|
|
2291
|
-
|
|
2292
|
-
return create_style_ref_setup_statements(
|
|
2293
|
-
style_context.style_refs,
|
|
2294
|
-
create_style_class_map(fragment, style_context.css),
|
|
2295
|
-
{
|
|
2296
|
-
allowMutableRefTarget: transform_context.platform.jsx.multiRefStrategy === 'array',
|
|
2297
|
-
createTempIdentifier: () =>
|
|
2298
|
-
create_generated_identifier(create_style_ref_temp_name(transform_context)),
|
|
2299
|
-
},
|
|
2300
|
-
);
|
|
2301
|
-
}
|
|
2302
|
-
|
|
2303
|
-
/**
|
|
2304
|
-
* @param {any} node
|
|
2305
|
-
* @param {any} stylesheet
|
|
2306
|
-
* @param {TransformContext} transform_context
|
|
2307
|
-
* @returns {AST.Expression}
|
|
1887
|
+
* @param {any} stylesheet
|
|
1888
|
+
* @param {TransformContext} transform_context
|
|
1889
|
+
* @returns {AST.Expression}
|
|
2308
1890
|
*/
|
|
2309
1891
|
function create_style_expression_value(node, stylesheet, transform_context) {
|
|
2310
1892
|
const class_map = create_style_class_map_from_stylesheet(stylesheet);
|
|
@@ -2844,7 +2426,10 @@ function should_use_module_scoped_hook_components(transform_context) {
|
|
|
2844
2426
|
* @returns {boolean}
|
|
2845
2427
|
*/
|
|
2846
2428
|
function should_extract_hook_helpers(transform_context) {
|
|
2847
|
-
return !!
|
|
2429
|
+
return !!(
|
|
2430
|
+
transform_context.hook_helpers_enabled &&
|
|
2431
|
+
transform_context.platform.hooks?.moduleScopedHookComponents
|
|
2432
|
+
);
|
|
2848
2433
|
}
|
|
2849
2434
|
|
|
2850
2435
|
/**
|
|
@@ -3406,11 +2991,6 @@ function build_hoisted_for_of_with_hooks(node, transform_context) {
|
|
|
3406
2991
|
for (const param of loop_params) {
|
|
3407
2992
|
collect_pattern_bindings(param, transform_context.available_bindings);
|
|
3408
2993
|
}
|
|
3409
|
-
validate_hook_safe_body_does_not_assign_hook_results_to_outer_bindings(
|
|
3410
|
-
original_loop_body,
|
|
3411
|
-
transform_context,
|
|
3412
|
-
loop_scoped_names,
|
|
3413
|
-
);
|
|
3414
2994
|
|
|
3415
2995
|
const all_helper_bindings = get_referenced_helper_bindings(
|
|
3416
2996
|
original_loop_body,
|
|
@@ -3695,659 +3275,54 @@ function to_jsx_element(
|
|
|
3695
3275
|
}
|
|
3696
3276
|
|
|
3697
3277
|
/**
|
|
3698
|
-
* @param {any[]} children
|
|
3699
|
-
* @param {TransformContext} transform_context
|
|
3700
|
-
* @returns {any[]}
|
|
3701
|
-
*/
|
|
3702
|
-
|
|
3703
|
-
function create_element_children(children, transform_context) {
|
|
3704
|
-
if (children.length === 0) {
|
|
3705
|
-
return [];
|
|
3706
|
-
}
|
|
3707
|
-
|
|
3708
|
-
if (children.every(is_inline_element_child) && !children_contain_return_semantics(children)) {
|
|
3709
|
-
const saved_inside_element_child = transform_context.inside_element_child;
|
|
3710
|
-
transform_context.inside_element_child = true;
|
|
3711
|
-
try {
|
|
3712
|
-
return children.map((/** @type {any} */ child) => to_jsx_child(child, transform_context));
|
|
3713
|
-
} finally {
|
|
3714
|
-
transform_context.inside_element_child = saved_inside_element_child;
|
|
3715
|
-
}
|
|
3716
|
-
}
|
|
3717
|
-
|
|
3718
|
-
const saved_inside_element_child = transform_context.inside_element_child;
|
|
3719
|
-
transform_context.inside_element_child = true;
|
|
3720
|
-
try {
|
|
3721
|
-
return [statement_body_to_jsx_child(children, transform_context)];
|
|
3722
|
-
} finally {
|
|
3723
|
-
transform_context.inside_element_child = saved_inside_element_child;
|
|
3724
|
-
}
|
|
3725
|
-
}
|
|
3726
|
-
|
|
3727
|
-
/**
|
|
3728
|
-
* @param {any[]} children
|
|
3729
|
-
* @returns {boolean}
|
|
3730
|
-
*/
|
|
3731
|
-
function children_contain_return_semantics(children) {
|
|
3732
|
-
return children.some(child_contains_return_semantics);
|
|
3733
|
-
}
|
|
3734
|
-
|
|
3735
|
-
/**
|
|
3736
|
-
* @param {any} node
|
|
3737
|
-
* @returns {boolean}
|
|
3738
|
-
*/
|
|
3739
|
-
function child_contains_return_semantics(node) {
|
|
3740
|
-
if (!node || typeof node !== 'object') {
|
|
3741
|
-
return false;
|
|
3742
|
-
}
|
|
3743
|
-
|
|
3744
|
-
if (node.type === 'ReturnStatement') {
|
|
3745
|
-
return true;
|
|
3746
|
-
}
|
|
3747
|
-
|
|
3748
|
-
if (
|
|
3749
|
-
node.type === 'FunctionDeclaration' ||
|
|
3750
|
-
node.type === 'FunctionExpression' ||
|
|
3751
|
-
node.type === 'ArrowFunctionExpression'
|
|
3752
|
-
) {
|
|
3753
|
-
return false;
|
|
3754
|
-
}
|
|
3755
|
-
|
|
3756
|
-
if (Array.isArray(node)) {
|
|
3757
|
-
return node.some(child_contains_return_semantics);
|
|
3758
|
-
}
|
|
3759
|
-
|
|
3760
|
-
for (const key of Object.keys(node)) {
|
|
3761
|
-
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
3762
|
-
continue;
|
|
3763
|
-
}
|
|
3764
|
-
if (child_contains_return_semantics(node[key])) {
|
|
3765
|
-
return true;
|
|
3766
|
-
}
|
|
3767
|
-
}
|
|
3768
|
-
|
|
3769
|
-
return false;
|
|
3770
|
-
}
|
|
3771
|
-
|
|
3772
|
-
/**
|
|
3773
|
-
* @param {any} node
|
|
3774
|
-
* @returns {boolean}
|
|
3775
|
-
*/
|
|
3776
|
-
function is_inline_element_child(node) {
|
|
3777
|
-
return node && is_render_child_node(node);
|
|
3778
|
-
}
|
|
3779
|
-
|
|
3780
|
-
/**
|
|
3781
|
-
* @param {any[]} body_nodes
|
|
3782
|
-
* @param {TransformContext} transform_context
|
|
3783
|
-
* @returns {ESTreeJSX.JSXExpressionContainer}
|
|
3784
|
-
*/
|
|
3785
|
-
function statement_body_to_jsx_child(body_nodes, transform_context) {
|
|
3786
|
-
if (
|
|
3787
|
-
should_extract_hook_helpers(transform_context) &&
|
|
3788
|
-
body_contains_top_level_hook_call(body_nodes, transform_context, true)
|
|
3789
|
-
) {
|
|
3790
|
-
return hook_safe_statement_body_to_jsx_child(body_nodes, transform_context);
|
|
3791
|
-
}
|
|
3792
|
-
|
|
3793
|
-
return to_jsx_expression_container(
|
|
3794
|
-
b.call(b.arrow([], b.block(build_render_statements(body_nodes, true, transform_context)))),
|
|
3795
|
-
);
|
|
3796
|
-
}
|
|
3797
|
-
|
|
3798
|
-
/**
|
|
3799
|
-
* @param {any[]} body_nodes
|
|
3800
|
-
* @param {TransformContext} transform_context
|
|
3801
|
-
* @returns {ESTreeJSX.JSXExpressionContainer}
|
|
3802
|
-
*/
|
|
3803
|
-
function hook_safe_statement_body_to_jsx_child(body_nodes, transform_context) {
|
|
3804
|
-
const source_node = get_body_source_node(body_nodes);
|
|
3805
|
-
const helper = create_hook_safe_helper(body_nodes, undefined, source_node, transform_context);
|
|
3806
|
-
|
|
3807
|
-
return to_jsx_expression_container(
|
|
3808
|
-
create_hook_safe_helper_iife(helper.setup_statements, helper.component_element),
|
|
3809
|
-
source_node,
|
|
3810
|
-
);
|
|
3811
|
-
}
|
|
3812
|
-
|
|
3813
|
-
/**
|
|
3814
|
-
* @param {TransformContext} transform_context
|
|
3815
|
-
* @returns {string}
|
|
3816
|
-
*/
|
|
3817
|
-
function create_local_statement_component_name(transform_context) {
|
|
3818
|
-
transform_context.local_statement_component_index += 1;
|
|
3819
|
-
return `StatementBodyHook${transform_context.local_statement_component_index}`;
|
|
3820
|
-
}
|
|
3821
|
-
|
|
3822
|
-
/**
|
|
3823
|
-
* Wraps a list of body nodes into a component and returns
|
|
3824
|
-
* statements that return `<ComponentName prop1={prop1} ... />`.
|
|
3825
|
-
* Targets can either emit the helper component at module scope or cache the
|
|
3826
|
-
* component identity in module state while initializing it from the parent.
|
|
3827
|
-
* Used when a control flow branch contains hook calls that must be moved
|
|
3828
|
-
* into their own component boundary to satisfy the Rules of Hooks.
|
|
3829
|
-
*
|
|
3830
|
-
* @param {any[]} body_nodes
|
|
3831
|
-
* @param {any} key_expression - Optional key expression to add to the component element (for for-of loops)
|
|
3832
|
-
* @param {TransformContext} transform_context
|
|
3833
|
-
* @returns {any[]}
|
|
3834
|
-
*/
|
|
3835
|
-
function hook_safe_render_statements(body_nodes, key_expression, transform_context) {
|
|
3836
|
-
const source_node = get_body_source_node(body_nodes);
|
|
3837
|
-
const helper = create_hook_safe_helper(
|
|
3838
|
-
body_nodes,
|
|
3839
|
-
key_expression,
|
|
3840
|
-
source_node,
|
|
3841
|
-
transform_context,
|
|
3842
|
-
);
|
|
3843
|
-
const statements = [...helper.setup_statements];
|
|
3844
|
-
|
|
3845
|
-
statements.push(b.return(helper.component_element));
|
|
3846
|
-
|
|
3847
|
-
return statements;
|
|
3848
|
-
}
|
|
3849
|
-
|
|
3850
|
-
/**
|
|
3851
|
-
* @param {any[]} body_nodes
|
|
3852
|
-
* @param {Map<string, AST.Identifier>} available_bindings
|
|
3853
|
-
* @returns {AST.Identifier[]}
|
|
3854
|
-
*/
|
|
3855
|
-
function get_referenced_helper_bindings(body_nodes, available_bindings) {
|
|
3856
|
-
const helper_bindings = [];
|
|
3857
|
-
const local_bindings = new Map();
|
|
3858
|
-
|
|
3859
|
-
for (const node of body_nodes) {
|
|
3860
|
-
collect_statement_bindings(node, local_bindings);
|
|
3861
|
-
}
|
|
3862
|
-
|
|
3863
|
-
for (const [name, binding] of available_bindings) {
|
|
3864
|
-
if (local_bindings.has(name)) continue;
|
|
3865
|
-
|
|
3866
|
-
if (references_scope_bindings(body_nodes, new Map([[name, binding]]))) {
|
|
3867
|
-
helper_bindings.push(binding);
|
|
3868
|
-
}
|
|
3869
|
-
}
|
|
3870
|
-
|
|
3871
|
-
return helper_bindings;
|
|
3872
|
-
}
|
|
3873
|
-
|
|
3874
|
-
/**
|
|
3875
|
-
* @param {any[]} body_nodes
|
|
3876
|
-
* @param {TransformContext} transform_context
|
|
3877
|
-
* @param {Set<string>} [local_binding_names]
|
|
3878
|
-
* @returns {void}
|
|
3879
|
-
*/
|
|
3880
|
-
function validate_hook_safe_body_does_not_assign_hook_results_to_outer_bindings(
|
|
3881
|
-
body_nodes,
|
|
3882
|
-
transform_context,
|
|
3883
|
-
local_binding_names,
|
|
3884
|
-
) {
|
|
3885
|
-
if (!is_react_like_hook_platform(transform_context)) {
|
|
3886
|
-
return;
|
|
3887
|
-
}
|
|
3888
|
-
if (!body_contains_top_level_hook_call(body_nodes, transform_context, true)) {
|
|
3889
|
-
return;
|
|
3890
|
-
}
|
|
3891
|
-
if (!transform_context.available_bindings || transform_context.available_bindings.size === 0) {
|
|
3892
|
-
return;
|
|
3893
|
-
}
|
|
3894
|
-
|
|
3895
|
-
const shadowed_names = collect_block_binding_names(body_nodes);
|
|
3896
|
-
for (const name of local_binding_names || []) {
|
|
3897
|
-
shadowed_names.add(name);
|
|
3898
|
-
}
|
|
3899
|
-
validate_hook_outer_assignments_in_node(body_nodes, shadowed_names, transform_context, new Set());
|
|
3900
|
-
}
|
|
3901
|
-
|
|
3902
|
-
/**
|
|
3903
|
-
* @param {TransformContext} transform_context
|
|
3904
|
-
* @returns {boolean}
|
|
3905
|
-
*/
|
|
3906
|
-
function is_react_like_hook_platform(transform_context) {
|
|
3907
|
-
return (
|
|
3908
|
-
transform_context.platform.name === 'React' || transform_context.platform.name === 'Preact'
|
|
3909
|
-
);
|
|
3910
|
-
}
|
|
3911
|
-
|
|
3912
|
-
/**
|
|
3913
|
-
* @param {any[]} statements
|
|
3914
|
-
* @returns {Set<string>}
|
|
3915
|
-
*/
|
|
3916
|
-
function collect_block_binding_names(statements) {
|
|
3917
|
-
const names = new Set();
|
|
3918
|
-
for (const statement of statements || []) {
|
|
3919
|
-
collect_block_binding_names_from_statement(statement, names);
|
|
3920
|
-
}
|
|
3921
|
-
return names;
|
|
3922
|
-
}
|
|
3923
|
-
|
|
3924
|
-
/**
|
|
3925
|
-
* @param {any} statement
|
|
3926
|
-
* @param {Set<string>} names
|
|
3927
|
-
* @returns {void}
|
|
3928
|
-
*/
|
|
3929
|
-
function collect_block_binding_names_from_statement(statement, names) {
|
|
3930
|
-
if (!statement || typeof statement !== 'object') {
|
|
3931
|
-
return;
|
|
3932
|
-
}
|
|
3933
|
-
|
|
3934
|
-
if (statement.type === 'VariableDeclaration') {
|
|
3935
|
-
for (const declaration of statement.declarations || []) {
|
|
3936
|
-
collect_pattern_names(declaration.id, names);
|
|
3937
|
-
}
|
|
3938
|
-
return;
|
|
3939
|
-
}
|
|
3940
|
-
|
|
3941
|
-
if (
|
|
3942
|
-
(statement.type === 'FunctionDeclaration' || statement.type === 'ClassDeclaration') &&
|
|
3943
|
-
statement.id?.type === 'Identifier'
|
|
3944
|
-
) {
|
|
3945
|
-
names.add(statement.id.name);
|
|
3946
|
-
return;
|
|
3947
|
-
}
|
|
3948
|
-
|
|
3949
|
-
if (
|
|
3950
|
-
statement.type === 'ForOfStatement' ||
|
|
3951
|
-
statement.type === 'ForInStatement' ||
|
|
3952
|
-
(statement.type === 'JSXForExpression' &&
|
|
3953
|
-
(statement.statementType === 'ForOfStatement' ||
|
|
3954
|
-
statement.statementType === 'ForInStatement'))
|
|
3955
|
-
) {
|
|
3956
|
-
if (statement.left?.type === 'VariableDeclaration' && statement.left.kind === 'var') {
|
|
3957
|
-
for (const declaration of statement.left.declarations || []) {
|
|
3958
|
-
collect_pattern_names(declaration.id, names);
|
|
3959
|
-
}
|
|
3960
|
-
}
|
|
3961
|
-
return;
|
|
3962
|
-
}
|
|
3963
|
-
|
|
3964
|
-
if (
|
|
3965
|
-
statement.type === 'ForStatement' &&
|
|
3966
|
-
statement.init?.type === 'VariableDeclaration' &&
|
|
3967
|
-
statement.init.kind === 'var'
|
|
3968
|
-
) {
|
|
3969
|
-
for (const declaration of statement.init.declarations || []) {
|
|
3970
|
-
collect_pattern_names(declaration.id, names);
|
|
3971
|
-
}
|
|
3972
|
-
}
|
|
3973
|
-
}
|
|
3974
|
-
|
|
3975
|
-
/**
|
|
3976
|
-
* @param {any} pattern
|
|
3977
|
-
* @param {Set<string>} names
|
|
3978
|
-
* @returns {void}
|
|
3979
|
-
*/
|
|
3980
|
-
function collect_pattern_names(pattern, names) {
|
|
3981
|
-
if (!pattern || typeof pattern !== 'object') {
|
|
3982
|
-
return;
|
|
3983
|
-
}
|
|
3984
|
-
|
|
3985
|
-
if (pattern.type === 'Identifier') {
|
|
3986
|
-
names.add(pattern.name);
|
|
3987
|
-
return;
|
|
3988
|
-
}
|
|
3989
|
-
|
|
3990
|
-
if (pattern.type === 'RestElement') {
|
|
3991
|
-
collect_pattern_names(pattern.argument, names);
|
|
3992
|
-
return;
|
|
3993
|
-
}
|
|
3994
|
-
|
|
3995
|
-
if (pattern.type === 'AssignmentPattern') {
|
|
3996
|
-
collect_pattern_names(pattern.left, names);
|
|
3997
|
-
return;
|
|
3998
|
-
}
|
|
3999
|
-
|
|
4000
|
-
if (pattern.type === 'ArrayPattern') {
|
|
4001
|
-
for (const element of pattern.elements || []) {
|
|
4002
|
-
collect_pattern_names(element, names);
|
|
4003
|
-
}
|
|
4004
|
-
return;
|
|
4005
|
-
}
|
|
4006
|
-
|
|
4007
|
-
if (pattern.type === 'ObjectPattern') {
|
|
4008
|
-
for (const property of pattern.properties || []) {
|
|
4009
|
-
if (property.type === 'RestElement') {
|
|
4010
|
-
collect_pattern_names(property.argument, names);
|
|
4011
|
-
} else {
|
|
4012
|
-
collect_pattern_names(property.value, names);
|
|
4013
|
-
}
|
|
4014
|
-
}
|
|
4015
|
-
}
|
|
4016
|
-
}
|
|
4017
|
-
|
|
4018
|
-
/**
|
|
4019
|
-
* @param {any} node
|
|
4020
|
-
* @param {Set<string>} shadowed_names
|
|
4021
|
-
* @param {TransformContext} transform_context
|
|
4022
|
-
* @param {Set<string>} hook_result_names
|
|
4023
|
-
* @returns {void}
|
|
4024
|
-
*/
|
|
4025
|
-
function validate_hook_outer_assignments_in_node(
|
|
4026
|
-
node,
|
|
4027
|
-
shadowed_names,
|
|
4028
|
-
transform_context,
|
|
4029
|
-
hook_result_names,
|
|
4030
|
-
) {
|
|
4031
|
-
if (!node || typeof node !== 'object') {
|
|
4032
|
-
return;
|
|
4033
|
-
}
|
|
4034
|
-
|
|
4035
|
-
if (Array.isArray(node)) {
|
|
4036
|
-
for (const child of node) {
|
|
4037
|
-
validate_hook_outer_assignments_in_node(
|
|
4038
|
-
child,
|
|
4039
|
-
shadowed_names,
|
|
4040
|
-
transform_context,
|
|
4041
|
-
hook_result_names,
|
|
4042
|
-
);
|
|
4043
|
-
}
|
|
4044
|
-
return;
|
|
4045
|
-
}
|
|
4046
|
-
|
|
4047
|
-
if (is_function_or_component_node(node)) {
|
|
4048
|
-
return;
|
|
4049
|
-
}
|
|
4050
|
-
|
|
4051
|
-
if (node.type === 'CallExpression' && is_hook_callee(node.callee)) {
|
|
4052
|
-
validate_hook_callback_outer_mutations(node, shadowed_names, transform_context);
|
|
4053
|
-
}
|
|
4054
|
-
|
|
4055
|
-
if (node.type === 'BlockStatement') {
|
|
4056
|
-
const next_shadowed = new Set(shadowed_names);
|
|
4057
|
-
const next_hook_result_names = new Set(hook_result_names);
|
|
4058
|
-
for (const name of collect_block_binding_names(node.body || [])) {
|
|
4059
|
-
next_shadowed.add(name);
|
|
4060
|
-
}
|
|
4061
|
-
for (const child of node.body || []) {
|
|
4062
|
-
validate_hook_outer_assignments_in_node(
|
|
4063
|
-
child,
|
|
4064
|
-
next_shadowed,
|
|
4065
|
-
transform_context,
|
|
4066
|
-
next_hook_result_names,
|
|
4067
|
-
);
|
|
4068
|
-
}
|
|
4069
|
-
return;
|
|
4070
|
-
}
|
|
4071
|
-
|
|
4072
|
-
if (node.type === 'VariableDeclaration') {
|
|
4073
|
-
for (const declaration of node.declarations || []) {
|
|
4074
|
-
if (
|
|
4075
|
-
declaration.init &&
|
|
4076
|
-
expression_contains_hook_derived_value(
|
|
4077
|
-
declaration.init,
|
|
4078
|
-
transform_context,
|
|
4079
|
-
hook_result_names,
|
|
4080
|
-
)
|
|
4081
|
-
) {
|
|
4082
|
-
collect_pattern_names(declaration.id, hook_result_names);
|
|
4083
|
-
}
|
|
4084
|
-
validate_hook_outer_assignments_in_node(
|
|
4085
|
-
declaration.init,
|
|
4086
|
-
shadowed_names,
|
|
4087
|
-
transform_context,
|
|
4088
|
-
hook_result_names,
|
|
4089
|
-
);
|
|
4090
|
-
}
|
|
4091
|
-
return;
|
|
4092
|
-
}
|
|
4093
|
-
|
|
4094
|
-
if (
|
|
4095
|
-
node.type === 'AssignmentExpression' &&
|
|
4096
|
-
expression_contains_hook_derived_value(node.right, transform_context, hook_result_names)
|
|
4097
|
-
) {
|
|
4098
|
-
const outer_names = get_referenced_outer_binding_names(
|
|
4099
|
-
node.left,
|
|
4100
|
-
transform_context.available_bindings,
|
|
4101
|
-
shadowed_names,
|
|
4102
|
-
);
|
|
4103
|
-
if (outer_names.length > 0) {
|
|
4104
|
-
report_hook_outer_assignment_error(
|
|
4105
|
-
node.left,
|
|
4106
|
-
outer_names,
|
|
4107
|
-
find_first_hook_call_name(node.right) || 'hook',
|
|
4108
|
-
transform_context,
|
|
4109
|
-
);
|
|
4110
|
-
}
|
|
4111
|
-
for (const name of get_referenced_local_binding_names(node.left, shadowed_names)) {
|
|
4112
|
-
hook_result_names.add(name);
|
|
4113
|
-
}
|
|
4114
|
-
}
|
|
4115
|
-
|
|
4116
|
-
if (is_for_of_control_node(node)) {
|
|
4117
|
-
if (
|
|
4118
|
-
node.left &&
|
|
4119
|
-
node.left.type !== 'VariableDeclaration' &&
|
|
4120
|
-
expression_contains_hook_derived_value(node.right, transform_context, hook_result_names)
|
|
4121
|
-
) {
|
|
4122
|
-
const outer_names = get_referenced_outer_binding_names(
|
|
4123
|
-
node.left,
|
|
4124
|
-
transform_context.available_bindings,
|
|
4125
|
-
shadowed_names,
|
|
4126
|
-
);
|
|
4127
|
-
if (outer_names.length > 0) {
|
|
4128
|
-
report_hook_outer_assignment_error(
|
|
4129
|
-
node.left,
|
|
4130
|
-
outer_names,
|
|
4131
|
-
find_first_hook_call_name(node.right) || 'hook',
|
|
4132
|
-
transform_context,
|
|
4133
|
-
);
|
|
4134
|
-
}
|
|
4135
|
-
for (const name of get_referenced_local_binding_names(node.left, shadowed_names)) {
|
|
4136
|
-
hook_result_names.add(name);
|
|
4137
|
-
}
|
|
4138
|
-
}
|
|
4139
|
-
|
|
4140
|
-
validate_hook_outer_assignments_in_node(
|
|
4141
|
-
node.right,
|
|
4142
|
-
shadowed_names,
|
|
4143
|
-
transform_context,
|
|
4144
|
-
hook_result_names,
|
|
4145
|
-
);
|
|
4146
|
-
|
|
4147
|
-
// Loop-declared bindings (`for (const x of …)`, `for (let x of …)`) live
|
|
4148
|
-
// only in the body. They are deliberately NOT in the enclosing block's
|
|
4149
|
-
// shadowed set (see collect_block_binding_names_from_statement), so add
|
|
4150
|
-
// them just for the body recursion to keep references to the loop var
|
|
4151
|
-
// from being flagged as outer-binding mutations.
|
|
4152
|
-
const body_shadowed = new Set(shadowed_names);
|
|
4153
|
-
if (node.left && node.left.type === 'VariableDeclaration') {
|
|
4154
|
-
for (const declaration of node.left.declarations || []) {
|
|
4155
|
-
collect_pattern_names(declaration.id, body_shadowed);
|
|
4156
|
-
}
|
|
4157
|
-
}
|
|
4158
|
-
validate_hook_outer_assignments_in_node(
|
|
4159
|
-
node.body,
|
|
4160
|
-
body_shadowed,
|
|
4161
|
-
transform_context,
|
|
4162
|
-
hook_result_names,
|
|
4163
|
-
);
|
|
4164
|
-
return;
|
|
4165
|
-
}
|
|
4166
|
-
|
|
4167
|
-
for (const key of Object.keys(node)) {
|
|
4168
|
-
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
4169
|
-
continue;
|
|
4170
|
-
}
|
|
4171
|
-
validate_hook_outer_assignments_in_node(
|
|
4172
|
-
node[key],
|
|
4173
|
-
shadowed_names,
|
|
4174
|
-
transform_context,
|
|
4175
|
-
hook_result_names,
|
|
4176
|
-
);
|
|
4177
|
-
}
|
|
4178
|
-
}
|
|
4179
|
-
|
|
4180
|
-
/**
|
|
4181
|
-
* @param {any} call_node
|
|
4182
|
-
* @param {Set<string>} shadowed_names
|
|
4183
|
-
* @param {TransformContext} transform_context
|
|
4184
|
-
* @returns {void}
|
|
4185
|
-
*/
|
|
4186
|
-
function validate_hook_callback_outer_mutations(call_node, shadowed_names, transform_context) {
|
|
4187
|
-
const hook_name = get_hook_callee_name(call_node.callee);
|
|
4188
|
-
for (const argument of call_node.arguments || []) {
|
|
4189
|
-
if (!is_function_or_component_node(argument)) {
|
|
4190
|
-
continue;
|
|
4191
|
-
}
|
|
4192
|
-
const callback_shadowed_names = create_function_like_shadowed_names(argument, shadowed_names);
|
|
4193
|
-
validate_hook_callback_outer_mutations_in_node(
|
|
4194
|
-
argument.body,
|
|
4195
|
-
callback_shadowed_names,
|
|
4196
|
-
transform_context,
|
|
4197
|
-
hook_name,
|
|
4198
|
-
);
|
|
4199
|
-
}
|
|
4200
|
-
}
|
|
4201
|
-
|
|
4202
|
-
/**
|
|
4203
|
-
* @param {any} node
|
|
4204
|
-
* @param {Set<string>} shadowed_names
|
|
4205
|
-
* @returns {Set<string>}
|
|
4206
|
-
*/
|
|
4207
|
-
function create_function_like_shadowed_names(node, shadowed_names) {
|
|
4208
|
-
const next_shadowed_names = new Set(shadowed_names);
|
|
4209
|
-
for (const param of node.params || []) {
|
|
4210
|
-
collect_pattern_names(param, next_shadowed_names);
|
|
4211
|
-
}
|
|
4212
|
-
if (node.body?.type === 'BlockStatement') {
|
|
4213
|
-
for (const name of collect_block_binding_names(node.body.body || [])) {
|
|
4214
|
-
next_shadowed_names.add(name);
|
|
4215
|
-
}
|
|
4216
|
-
}
|
|
4217
|
-
return next_shadowed_names;
|
|
4218
|
-
}
|
|
4219
|
-
|
|
4220
|
-
/**
|
|
4221
|
-
* @param {any} node
|
|
4222
|
-
* @param {Set<string>} shadowed_names
|
|
3278
|
+
* @param {any[]} children
|
|
4223
3279
|
* @param {TransformContext} transform_context
|
|
4224
|
-
* @
|
|
4225
|
-
* @returns {void}
|
|
3280
|
+
* @returns {any[]}
|
|
4226
3281
|
*/
|
|
4227
|
-
function validate_hook_callback_outer_mutations_in_node(
|
|
4228
|
-
node,
|
|
4229
|
-
shadowed_names,
|
|
4230
|
-
transform_context,
|
|
4231
|
-
hook_name,
|
|
4232
|
-
) {
|
|
4233
|
-
if (!node || typeof node !== 'object') {
|
|
4234
|
-
return;
|
|
4235
|
-
}
|
|
4236
|
-
|
|
4237
|
-
if (Array.isArray(node)) {
|
|
4238
|
-
for (const child of node) {
|
|
4239
|
-
validate_hook_callback_outer_mutations_in_node(
|
|
4240
|
-
child,
|
|
4241
|
-
shadowed_names,
|
|
4242
|
-
transform_context,
|
|
4243
|
-
hook_name,
|
|
4244
|
-
);
|
|
4245
|
-
}
|
|
4246
|
-
return;
|
|
4247
|
-
}
|
|
4248
|
-
|
|
4249
|
-
if (is_function_or_component_node(node)) {
|
|
4250
|
-
validate_hook_callback_outer_mutations_in_node(
|
|
4251
|
-
node.body,
|
|
4252
|
-
create_function_like_shadowed_names(node, shadowed_names),
|
|
4253
|
-
transform_context,
|
|
4254
|
-
hook_name,
|
|
4255
|
-
);
|
|
4256
|
-
return;
|
|
4257
|
-
}
|
|
4258
|
-
|
|
4259
|
-
if (node.type === 'BlockStatement') {
|
|
4260
|
-
const next_shadowed_names = new Set(shadowed_names);
|
|
4261
|
-
for (const name of collect_block_binding_names(node.body || [])) {
|
|
4262
|
-
next_shadowed_names.add(name);
|
|
4263
|
-
}
|
|
4264
|
-
for (const child of node.body || []) {
|
|
4265
|
-
validate_hook_callback_outer_mutations_in_node(
|
|
4266
|
-
child,
|
|
4267
|
-
next_shadowed_names,
|
|
4268
|
-
transform_context,
|
|
4269
|
-
hook_name,
|
|
4270
|
-
);
|
|
4271
|
-
}
|
|
4272
|
-
return;
|
|
4273
|
-
}
|
|
4274
3282
|
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
transform_context.available_bindings,
|
|
4279
|
-
shadowed_names,
|
|
4280
|
-
);
|
|
4281
|
-
if (outer_names.length > 0) {
|
|
4282
|
-
report_hook_callback_outer_mutation_error(
|
|
4283
|
-
node.left,
|
|
4284
|
-
outer_names,
|
|
4285
|
-
hook_name,
|
|
4286
|
-
transform_context,
|
|
4287
|
-
);
|
|
4288
|
-
}
|
|
3283
|
+
function create_element_children(children, transform_context) {
|
|
3284
|
+
if (children.length === 0) {
|
|
3285
|
+
return [];
|
|
4289
3286
|
}
|
|
4290
3287
|
|
|
4291
|
-
if (
|
|
4292
|
-
const
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
report_hook_callback_outer_mutation_error(
|
|
4299
|
-
node.argument,
|
|
4300
|
-
outer_names,
|
|
4301
|
-
hook_name,
|
|
4302
|
-
transform_context,
|
|
4303
|
-
);
|
|
3288
|
+
if (children.every(is_inline_element_child) && !children_contain_return_semantics(children)) {
|
|
3289
|
+
const saved_inside_element_child = transform_context.inside_element_child;
|
|
3290
|
+
transform_context.inside_element_child = true;
|
|
3291
|
+
try {
|
|
3292
|
+
return children.map((/** @type {any} */ child) => to_jsx_child(child, transform_context));
|
|
3293
|
+
} finally {
|
|
3294
|
+
transform_context.inside_element_child = saved_inside_element_child;
|
|
4304
3295
|
}
|
|
4305
3296
|
}
|
|
4306
3297
|
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
}
|
|
4314
|
-
if (key === 'argument' && node.type === 'UpdateExpression') {
|
|
4315
|
-
continue;
|
|
4316
|
-
}
|
|
4317
|
-
validate_hook_callback_outer_mutations_in_node(
|
|
4318
|
-
node[key],
|
|
4319
|
-
shadowed_names,
|
|
4320
|
-
transform_context,
|
|
4321
|
-
hook_name,
|
|
4322
|
-
);
|
|
3298
|
+
const saved_inside_element_child = transform_context.inside_element_child;
|
|
3299
|
+
transform_context.inside_element_child = true;
|
|
3300
|
+
try {
|
|
3301
|
+
return [statement_body_to_jsx_child(children, transform_context)];
|
|
3302
|
+
} finally {
|
|
3303
|
+
transform_context.inside_element_child = saved_inside_element_child;
|
|
4323
3304
|
}
|
|
4324
3305
|
}
|
|
4325
3306
|
|
|
4326
3307
|
/**
|
|
4327
|
-
* @param {any}
|
|
4328
|
-
* @param {TransformContext} transform_context
|
|
4329
|
-
* @param {Set<string>} hook_result_names
|
|
3308
|
+
* @param {any[]} children
|
|
4330
3309
|
* @returns {boolean}
|
|
4331
3310
|
*/
|
|
4332
|
-
function
|
|
4333
|
-
return (
|
|
4334
|
-
node_contains_top_level_hook_call(node, false, transform_context, true) ||
|
|
4335
|
-
references_name_in_set(node, hook_result_names)
|
|
4336
|
-
);
|
|
3311
|
+
function children_contain_return_semantics(children) {
|
|
3312
|
+
return children.some(child_contains_return_semantics);
|
|
4337
3313
|
}
|
|
4338
3314
|
|
|
4339
3315
|
/**
|
|
4340
3316
|
* @param {any} node
|
|
4341
|
-
* @param {Set<string>} names
|
|
4342
3317
|
* @returns {boolean}
|
|
4343
3318
|
*/
|
|
4344
|
-
function
|
|
4345
|
-
if (!node || typeof node !== 'object'
|
|
3319
|
+
function child_contains_return_semantics(node) {
|
|
3320
|
+
if (!node || typeof node !== 'object') {
|
|
4346
3321
|
return false;
|
|
4347
3322
|
}
|
|
4348
3323
|
|
|
4349
|
-
if (node.type === '
|
|
4350
|
-
return
|
|
3324
|
+
if (node.type === 'ReturnStatement') {
|
|
3325
|
+
return true;
|
|
4351
3326
|
}
|
|
4352
3327
|
|
|
4353
3328
|
if (
|
|
@@ -4359,20 +3334,14 @@ function references_name_in_set(node, names) {
|
|
|
4359
3334
|
}
|
|
4360
3335
|
|
|
4361
3336
|
if (Array.isArray(node)) {
|
|
4362
|
-
return node.some(
|
|
3337
|
+
return node.some(child_contains_return_semantics);
|
|
4363
3338
|
}
|
|
4364
3339
|
|
|
4365
3340
|
for (const key of Object.keys(node)) {
|
|
4366
3341
|
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
4367
3342
|
continue;
|
|
4368
3343
|
}
|
|
4369
|
-
if (key
|
|
4370
|
-
continue;
|
|
4371
|
-
}
|
|
4372
|
-
if (key === 'key' && node.type === 'Property' && !node.computed && !node.shorthand) {
|
|
4373
|
-
continue;
|
|
4374
|
-
}
|
|
4375
|
-
if (references_name_in_set(node[key], names)) {
|
|
3344
|
+
if (child_contains_return_semantics(node[key])) {
|
|
4376
3345
|
return true;
|
|
4377
3346
|
}
|
|
4378
3347
|
}
|
|
@@ -4382,162 +3351,104 @@ function references_name_in_set(node, names) {
|
|
|
4382
3351
|
|
|
4383
3352
|
/**
|
|
4384
3353
|
* @param {any} node
|
|
4385
|
-
* @
|
|
4386
|
-
* @returns {string[]}
|
|
3354
|
+
* @returns {boolean}
|
|
4387
3355
|
*/
|
|
4388
|
-
function
|
|
4389
|
-
|
|
4390
|
-
collect_referenced_local_binding_names(node, shadowed_names, names);
|
|
4391
|
-
return [...names];
|
|
3356
|
+
function is_inline_element_child(node) {
|
|
3357
|
+
return node && is_render_child_node(node);
|
|
4392
3358
|
}
|
|
4393
3359
|
|
|
4394
3360
|
/**
|
|
4395
|
-
* @param {any}
|
|
4396
|
-
* @param {
|
|
4397
|
-
* @
|
|
4398
|
-
* @returns {void}
|
|
3361
|
+
* @param {any[]} body_nodes
|
|
3362
|
+
* @param {TransformContext} transform_context
|
|
3363
|
+
* @returns {ESTreeJSX.JSXExpressionContainer}
|
|
4399
3364
|
*/
|
|
4400
|
-
function
|
|
4401
|
-
if (
|
|
4402
|
-
|
|
3365
|
+
function statement_body_to_jsx_child(body_nodes, transform_context) {
|
|
3366
|
+
if (
|
|
3367
|
+
should_extract_hook_helpers(transform_context) &&
|
|
3368
|
+
body_contains_top_level_hook_call(body_nodes, transform_context, true)
|
|
3369
|
+
) {
|
|
3370
|
+
return hook_safe_statement_body_to_jsx_child(body_nodes, transform_context);
|
|
4403
3371
|
}
|
|
4404
3372
|
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
return;
|
|
4410
|
-
}
|
|
3373
|
+
return to_jsx_expression_container(
|
|
3374
|
+
b.call(b.arrow([], b.block(build_render_statements(body_nodes, true, transform_context)))),
|
|
3375
|
+
);
|
|
3376
|
+
}
|
|
4411
3377
|
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
3378
|
+
/**
|
|
3379
|
+
* @param {any[]} body_nodes
|
|
3380
|
+
* @param {TransformContext} transform_context
|
|
3381
|
+
* @returns {ESTreeJSX.JSXExpressionContainer}
|
|
3382
|
+
*/
|
|
3383
|
+
function hook_safe_statement_body_to_jsx_child(body_nodes, transform_context) {
|
|
3384
|
+
const source_node = get_body_source_node(body_nodes);
|
|
3385
|
+
const helper = create_hook_safe_helper(body_nodes, undefined, source_node, transform_context);
|
|
4418
3386
|
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
if (key === 'property' && node.type === 'MemberExpression' && !node.computed) {
|
|
4424
|
-
continue;
|
|
4425
|
-
}
|
|
4426
|
-
if (key === 'key' && node.type === 'Property' && !node.computed && !node.shorthand) {
|
|
4427
|
-
continue;
|
|
4428
|
-
}
|
|
4429
|
-
collect_referenced_local_binding_names(node[key], shadowed_names, names);
|
|
4430
|
-
}
|
|
3387
|
+
return to_jsx_expression_container(
|
|
3388
|
+
create_hook_safe_helper_iife(helper.setup_statements, helper.component_element),
|
|
3389
|
+
source_node,
|
|
3390
|
+
);
|
|
4431
3391
|
}
|
|
4432
3392
|
|
|
4433
3393
|
/**
|
|
4434
|
-
* @param {
|
|
4435
|
-
* @
|
|
4436
|
-
* @param {Set<string>} shadowed_names
|
|
4437
|
-
* @returns {string[]}
|
|
3394
|
+
* @param {TransformContext} transform_context
|
|
3395
|
+
* @returns {string}
|
|
4438
3396
|
*/
|
|
4439
|
-
function
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
return [...names];
|
|
3397
|
+
function create_local_statement_component_name(transform_context) {
|
|
3398
|
+
transform_context.local_statement_component_index += 1;
|
|
3399
|
+
return `StatementBodyHook${transform_context.local_statement_component_index}`;
|
|
4443
3400
|
}
|
|
4444
3401
|
|
|
4445
3402
|
/**
|
|
4446
|
-
*
|
|
4447
|
-
*
|
|
4448
|
-
*
|
|
4449
|
-
*
|
|
4450
|
-
*
|
|
3403
|
+
* Wraps a list of body nodes into a component and returns
|
|
3404
|
+
* statements that return `<ComponentName prop1={prop1} ... />`.
|
|
3405
|
+
* Targets can either emit the helper component at module scope or cache the
|
|
3406
|
+
* component identity in module state while initializing it from the parent.
|
|
3407
|
+
* Used when a control flow branch contains hook calls that must be moved
|
|
3408
|
+
* into their own component boundary to satisfy the Rules of Hooks.
|
|
3409
|
+
*
|
|
3410
|
+
* @param {any[]} body_nodes
|
|
3411
|
+
* @param {any} key_expression - Optional key expression to add to the component element (for for-of loops)
|
|
3412
|
+
* @param {TransformContext} transform_context
|
|
3413
|
+
* @returns {any[]}
|
|
4451
3414
|
*/
|
|
4452
|
-
function
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
return;
|
|
4462
|
-
}
|
|
3415
|
+
function hook_safe_render_statements(body_nodes, key_expression, transform_context) {
|
|
3416
|
+
const source_node = get_body_source_node(body_nodes);
|
|
3417
|
+
const helper = create_hook_safe_helper(
|
|
3418
|
+
body_nodes,
|
|
3419
|
+
key_expression,
|
|
3420
|
+
source_node,
|
|
3421
|
+
transform_context,
|
|
3422
|
+
);
|
|
3423
|
+
const statements = [...helper.setup_statements];
|
|
4463
3424
|
|
|
4464
|
-
|
|
4465
|
-
for (const child of node) {
|
|
4466
|
-
collect_referenced_outer_binding_names(child, available_bindings, shadowed_names, names);
|
|
4467
|
-
}
|
|
4468
|
-
return;
|
|
4469
|
-
}
|
|
3425
|
+
statements.push(b.return(helper.component_element));
|
|
4470
3426
|
|
|
4471
|
-
|
|
4472
|
-
if (key === 'loc' || key === 'start' || key === 'end' || key === 'metadata') {
|
|
4473
|
-
continue;
|
|
4474
|
-
}
|
|
4475
|
-
if (key === 'property' && node.type === 'MemberExpression' && !node.computed) {
|
|
4476
|
-
continue;
|
|
4477
|
-
}
|
|
4478
|
-
if (key === 'key' && node.type === 'Property' && !node.computed && !node.shorthand) {
|
|
4479
|
-
continue;
|
|
4480
|
-
}
|
|
4481
|
-
collect_referenced_outer_binding_names(node[key], available_bindings, shadowed_names, names);
|
|
4482
|
-
}
|
|
3427
|
+
return statements;
|
|
4483
3428
|
}
|
|
4484
3429
|
|
|
4485
3430
|
/**
|
|
4486
|
-
* @param {any}
|
|
4487
|
-
* @
|
|
3431
|
+
* @param {any[]} body_nodes
|
|
3432
|
+
* @param {Map<string, AST.Identifier>} available_bindings
|
|
3433
|
+
* @returns {AST.Identifier[]}
|
|
4488
3434
|
*/
|
|
4489
|
-
function
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
}
|
|
4493
|
-
|
|
4494
|
-
if (node.type === 'CallExpression' && is_hook_callee(node.callee)) {
|
|
4495
|
-
return get_hook_callee_name(node.callee);
|
|
4496
|
-
}
|
|
3435
|
+
function get_referenced_helper_bindings(body_nodes, available_bindings) {
|
|
3436
|
+
const helper_bindings = [];
|
|
3437
|
+
const local_bindings = new Map();
|
|
4497
3438
|
|
|
4498
|
-
|
|
4499
|
-
node
|
|
4500
|
-
node.type === 'FunctionExpression' ||
|
|
4501
|
-
node.type === 'ArrowFunctionExpression'
|
|
4502
|
-
) {
|
|
4503
|
-
return null;
|
|
3439
|
+
for (const node of body_nodes) {
|
|
3440
|
+
collect_statement_bindings(node, local_bindings);
|
|
4504
3441
|
}
|
|
4505
3442
|
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
const name = find_first_hook_call_name(child);
|
|
4509
|
-
if (name) return name;
|
|
4510
|
-
}
|
|
4511
|
-
return null;
|
|
4512
|
-
}
|
|
3443
|
+
for (const [name, binding] of available_bindings) {
|
|
3444
|
+
if (local_bindings.has(name)) continue;
|
|
4513
3445
|
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
continue;
|
|
3446
|
+
if (references_scope_bindings(body_nodes, new Map([[name, binding]]))) {
|
|
3447
|
+
helper_bindings.push(binding);
|
|
4517
3448
|
}
|
|
4518
|
-
const name = find_first_hook_call_name(node[key]);
|
|
4519
|
-
if (name) return name;
|
|
4520
3449
|
}
|
|
4521
3450
|
|
|
4522
|
-
return
|
|
4523
|
-
}
|
|
4524
|
-
|
|
4525
|
-
/**
|
|
4526
|
-
* @param {any} callee
|
|
4527
|
-
* @returns {string}
|
|
4528
|
-
*/
|
|
4529
|
-
function get_hook_callee_name(callee) {
|
|
4530
|
-
if (callee?.type === 'Identifier') {
|
|
4531
|
-
return callee.name;
|
|
4532
|
-
}
|
|
4533
|
-
if (
|
|
4534
|
-
callee?.type === 'MemberExpression' &&
|
|
4535
|
-
!callee.computed &&
|
|
4536
|
-
callee.property?.type === 'Identifier'
|
|
4537
|
-
) {
|
|
4538
|
-
return callee.property.name;
|
|
4539
|
-
}
|
|
4540
|
-
return 'hook';
|
|
3451
|
+
return helper_bindings;
|
|
4541
3452
|
}
|
|
4542
3453
|
|
|
4543
3454
|
/**
|
|
@@ -4558,11 +3469,6 @@ export function create_hook_safe_helper(
|
|
|
4558
3469
|
preallocated_helper_id,
|
|
4559
3470
|
options = {},
|
|
4560
3471
|
) {
|
|
4561
|
-
validate_hook_safe_body_does_not_assign_hook_results_to_outer_bindings(
|
|
4562
|
-
body_nodes,
|
|
4563
|
-
transform_context,
|
|
4564
|
-
);
|
|
4565
|
-
|
|
4566
3472
|
const helper_id =
|
|
4567
3473
|
preallocated_helper_id ??
|
|
4568
3474
|
create_generated_identifier(create_local_statement_component_name(transform_context));
|
|
@@ -4887,14 +3793,6 @@ function is_if_control_node(node) {
|
|
|
4887
3793
|
return node?.type === 'IfStatement' || node?.type === 'JSXIfExpression';
|
|
4888
3794
|
}
|
|
4889
3795
|
|
|
4890
|
-
/**
|
|
4891
|
-
* @param {any} node
|
|
4892
|
-
* @returns {boolean}
|
|
4893
|
-
*/
|
|
4894
|
-
function is_plain_if_statement(node) {
|
|
4895
|
-
return node?.type === 'IfStatement' && !is_template_if_node(node);
|
|
4896
|
-
}
|
|
4897
|
-
|
|
4898
3796
|
/**
|
|
4899
3797
|
* @param {any} node
|
|
4900
3798
|
* @returns {boolean}
|
|
@@ -4941,17 +3839,6 @@ function is_try_control_node(node) {
|
|
|
4941
3839
|
return node?.type === 'TryStatement' || node?.type === 'JSXTryExpression';
|
|
4942
3840
|
}
|
|
4943
3841
|
|
|
4944
|
-
/**
|
|
4945
|
-
* @param {any} node
|
|
4946
|
-
* @returns {boolean}
|
|
4947
|
-
*/
|
|
4948
|
-
function is_for_of_control_node(node) {
|
|
4949
|
-
return (
|
|
4950
|
-
node?.type === 'ForOfStatement' ||
|
|
4951
|
-
(node?.type === 'JSXForExpression' && node.statementType === 'ForOfStatement')
|
|
4952
|
-
);
|
|
4953
|
-
}
|
|
4954
|
-
|
|
4955
3842
|
/**
|
|
4956
3843
|
* @param {any} node
|
|
4957
3844
|
* @param {TransformContext} transform_context
|
|
@@ -5902,16 +4789,9 @@ function try_statement_to_jsx_child(node, transform_context) {
|
|
|
5902
4789
|
// correctly identifies references to err/reset as non-static
|
|
5903
4790
|
const saved_catch_bindings = transform_context.available_bindings;
|
|
5904
4791
|
transform_context.available_bindings = new Map(saved_catch_bindings);
|
|
5905
|
-
const catch_scoped_names = new Set();
|
|
5906
4792
|
for (const param of catch_params) {
|
|
5907
4793
|
collect_pattern_bindings(param, transform_context.available_bindings);
|
|
5908
|
-
collect_pattern_names(param, catch_scoped_names);
|
|
5909
4794
|
}
|
|
5910
|
-
validate_hook_safe_body_does_not_assign_hook_results_to_outer_bindings(
|
|
5911
|
-
catch_body_nodes,
|
|
5912
|
-
transform_context,
|
|
5913
|
-
catch_scoped_names,
|
|
5914
|
-
);
|
|
5915
4795
|
|
|
5916
4796
|
const fallback_fn = b.arrow(
|
|
5917
4797
|
catch_params,
|