@tsrx/core 0.1.63 → 0.1.65

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.
@@ -1477,10 +1477,23 @@ export function convert_source_map_to_mappings(
1477
1477
  if (node.type === 'AssignmentPattern') {
1478
1478
  // We need a mapping for the whole AssignmentPattern for diagnostics
1479
1479
  // Only enable diagnostic verification here to avoid duplicate mappings
1480
- // that can cause things like double definitions
1481
- mappings.push(
1482
- get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
1483
- );
1480
+ // that can cause things like double definitions. A type-only lazy
1481
+ // pattern drops its leading `&`, so there is no generated source-map
1482
+ // position for the AssignmentPattern's authored start; its child
1483
+ // mappings still provide diagnostics for the emitted pattern/default.
1484
+ if (
1485
+ (node.left.type !== 'ObjectPattern' && node.left.type !== 'ArrayPattern') ||
1486
+ !node.left.lazy
1487
+ ) {
1488
+ mappings.push(
1489
+ get_mapping_from_node(
1490
+ node,
1491
+ src_to_gen_map,
1492
+ gen_line_offsets,
1493
+ mapping_data_verify_only,
1494
+ ),
1495
+ );
1496
+ }
1484
1497
  }
1485
1498
 
1486
1499
  return;
package/src/utils/ast.js CHANGED
@@ -167,14 +167,9 @@ export function is_code_block_function_body(node, parent) {
167
167
  * @returns {boolean}
168
168
  */
169
169
  export function is_statement_position(parent, child) {
170
+ if (is_statement_list_item(parent, child)) return true;
171
+
170
172
  switch (parent.type) {
171
- case 'Program':
172
- case 'BlockStatement':
173
- return parent.body.includes(/** @type {AST.Statement} */ (child));
174
- case 'SwitchCase':
175
- return parent.consequent.includes(/** @type {AST.Statement} */ (child));
176
- case 'JSXCodeBlock':
177
- return parent.body.includes(/** @type {AST.Statement} */ (child));
178
173
  case 'IfStatement':
179
174
  return parent.consequent === child || parent.alternate === child;
180
175
  case 'ForStatement':
@@ -190,6 +185,94 @@ export function is_statement_position(parent, child) {
190
185
  }
191
186
  }
192
187
 
188
+ /**
189
+ * Returns whether `child` is a direct item in a statement list. Unlike
190
+ * {@link is_statement_position}, this deliberately excludes single-statement
191
+ * control-flow bodies: transforms may replace a list item with declarations,
192
+ * but a declaration is not valid in those braceless statement slots.
193
+ *
194
+ * @param {AST.Node} parent
195
+ * @param {AST.Node} child
196
+ * @returns {boolean}
197
+ */
198
+ export function is_statement_list_item(parent, child) {
199
+ switch (parent.type) {
200
+ case 'Program':
201
+ case 'BlockStatement':
202
+ case 'JSXCodeBlock':
203
+ return parent.body.includes(/** @type {AST.Statement} */ (child));
204
+ case 'SwitchCase':
205
+ return parent.consequent.includes(/** @type {AST.Statement} */ (child));
206
+ default:
207
+ return false;
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Whether `parent` preserves `child` as the same expression value. Looking
213
+ * through these wrappers keeps strict and editor-oriented ASTs on the same
214
+ * semantic path.
215
+ *
216
+ * @param {AST.Node} parent
217
+ * @param {AST.Node} child
218
+ * @returns {boolean}
219
+ */
220
+ export function is_transparent_expression_wrapper(parent, child) {
221
+ return (
222
+ (parent.type === 'ParenthesizedExpression' ||
223
+ parent.type === 'TSAsExpression' ||
224
+ parent.type === 'TSSatisfiesExpression' ||
225
+ parent.type === 'TSNonNullExpression' ||
226
+ parent.type === 'TSInstantiationExpression' ||
227
+ parent.type === 'TSTypeAssertion' ||
228
+ parent.type === 'ChainExpression') &&
229
+ /** @type {{ expression?: AST.Node }} */ (parent).expression === child
230
+ );
231
+ }
232
+
233
+ /**
234
+ * Whether a lazy destructuring assignment can be lowered from an expression
235
+ * statement into a declaration without changing the syntactic category of its
236
+ * parent slot. Transparent expression wrappers are allowed, but the assignment
237
+ * must otherwise be the whole statement and that statement must be a direct
238
+ * item in a statement list.
239
+ *
240
+ * This is the shared semantic boundary for both target-neutral diagnostics and
241
+ * lazy-ID allocation. Keeping those callers on one predicate ensures collect
242
+ * mode never allocates an ID for a shape that analysis has diagnosed.
243
+ *
244
+ * @param {AST.AssignmentExpression} node
245
+ * @param {AST.Node[]} path
246
+ * @returns {boolean}
247
+ */
248
+ export function is_supported_lazy_assignment_position(node, path) {
249
+ if (
250
+ node.operator !== '=' ||
251
+ (node.left.type !== 'ObjectPattern' && node.left.type !== 'ArrayPattern') ||
252
+ !node.left.lazy
253
+ ) {
254
+ return false;
255
+ }
256
+
257
+ /** @type {AST.Node} */
258
+ let child = node;
259
+
260
+ for (let i = path.length - 1; i >= 0; i -= 1) {
261
+ const parent = path[i];
262
+ if (is_transparent_expression_wrapper(parent, child)) {
263
+ child = parent;
264
+ continue;
265
+ }
266
+
267
+ if (parent.type !== 'ExpressionStatement' || parent.expression !== child) return false;
268
+
269
+ const container = path[i - 1];
270
+ return !!container && is_statement_list_item(container, parent);
271
+ }
272
+
273
+ return false;
274
+ }
275
+
193
276
  /**
194
277
  * Returns the closest native TSRX function in an ancestry path. By default,
195
278
  * function and class boundaries stop the search so callers only match direct
package/types/index.d.ts CHANGED
@@ -170,6 +170,8 @@ export interface BaseNodeMetaData {
170
170
  forceMapping?: boolean;
171
171
  generated_loop_skip_if?: boolean;
172
172
  lazy_id?: string;
173
+ /** The current var scope contains a lazy `var` binding in a JavaScript loop header. */
174
+ has_lazy_var_loop_descendants?: boolean;
173
175
  disable_verification?: boolean;
174
176
  /** Identifiers whose source ranges also map to this generated identifier. */
175
177
  extra_source_mappings?: Array<(AST.Identifier | AST.PrivateIdentifier) & AST.NodeWithLocation>;