esrap 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/handlers.js +621 -793
- package/src/index.js +80 -26
- package/src/types.d.ts +33 -3
package/src/handlers.js
CHANGED
|
@@ -1,23 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/** @type {import('./types').Newline} */
|
|
2
|
+
const newline = { type: 'Newline' };
|
|
3
|
+
|
|
4
|
+
/** @type {import('./types').Indent} */
|
|
5
|
+
const indent = { type: 'Indent' };
|
|
6
|
+
|
|
7
|
+
/** @type {import('./types').Dedent} */
|
|
8
|
+
const dedent = { type: 'Dedent' };
|
|
3
9
|
|
|
4
10
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
* @param {import('./types').Command[]} children
|
|
12
|
+
* @returns {import('./types').Sequence}
|
|
13
|
+
*/
|
|
14
|
+
function create_sequence(...children) {
|
|
15
|
+
return { type: 'Sequence', children };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Rough estimate of the combined width of a group of commands
|
|
20
|
+
* @param {import('./types').Command[]} commands
|
|
21
|
+
* @param {number} from
|
|
22
|
+
* @param {number} to
|
|
10
23
|
*/
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
|
|
24
|
+
function measure(commands, from, to = commands.length) {
|
|
25
|
+
let total = 0;
|
|
26
|
+
for (let i = from; i < to; i += 1) {
|
|
27
|
+
const command = commands[i];
|
|
28
|
+
if (typeof command === 'string') {
|
|
29
|
+
total += command.length;
|
|
30
|
+
} else if (command.type === 'Chunk') {
|
|
31
|
+
total += command.content.length;
|
|
32
|
+
} else if (command.type === 'Sequence') {
|
|
33
|
+
// assume this is ', '
|
|
34
|
+
total += 2;
|
|
35
|
+
}
|
|
14
36
|
}
|
|
37
|
+
|
|
38
|
+
return total;
|
|
15
39
|
}
|
|
16
40
|
|
|
17
41
|
/**
|
|
18
42
|
* @param {import('estree').Node} node
|
|
19
43
|
* @param {import('./types').State} state
|
|
20
|
-
* @returns {import('./types').Chunk[]}
|
|
21
44
|
*/
|
|
22
45
|
export function handle(node, state) {
|
|
23
46
|
const handler = handlers[node.type];
|
|
@@ -26,54 +49,46 @@ export function handle(node, state) {
|
|
|
26
49
|
throw new Error(`Not implemented ${node.type}`);
|
|
27
50
|
}
|
|
28
51
|
|
|
29
|
-
// @ts-expect-error
|
|
30
|
-
const result = handler(node, state);
|
|
31
|
-
|
|
32
52
|
if (node.leadingComments) {
|
|
33
|
-
prepend_comments(
|
|
53
|
+
prepend_comments(node.leadingComments, state, false);
|
|
34
54
|
}
|
|
35
55
|
|
|
56
|
+
// @ts-expect-error
|
|
57
|
+
handler(node, state);
|
|
58
|
+
|
|
36
59
|
if (node.trailingComments) {
|
|
37
60
|
state.comments.push(node.trailingComments[0]); // there is only ever one
|
|
38
61
|
}
|
|
39
|
-
|
|
40
|
-
return result;
|
|
41
62
|
}
|
|
42
63
|
|
|
43
64
|
/**
|
|
44
65
|
* @param {string} content
|
|
45
|
-
* @param {import('estree').Node}
|
|
66
|
+
* @param {import('estree').Node} node
|
|
46
67
|
* @returns {import('./types').Chunk}
|
|
47
68
|
*/
|
|
48
69
|
function c(content, node) {
|
|
49
70
|
return {
|
|
71
|
+
type: 'Chunk',
|
|
50
72
|
content,
|
|
51
|
-
loc: node?.loc ?? null
|
|
52
|
-
has_newline: /\n/.test(content)
|
|
73
|
+
loc: node?.loc ?? null
|
|
53
74
|
};
|
|
54
75
|
}
|
|
55
76
|
|
|
56
77
|
/**
|
|
57
|
-
* @param {import('./types').Chunk[]} chunks
|
|
58
78
|
* @param {import('estree').Comment[]} comments
|
|
59
79
|
* @param {import('./types').State} state
|
|
80
|
+
* @param {boolean} newlines
|
|
60
81
|
*/
|
|
61
|
-
function prepend_comments(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
/** @type {any} */ (comment).has_trailing_newline ? `\n${state.indent}` : ` `
|
|
72
|
-
}`
|
|
73
|
-
)
|
|
74
|
-
.join(``)
|
|
75
|
-
)
|
|
76
|
-
);
|
|
82
|
+
function prepend_comments(comments, state, newlines) {
|
|
83
|
+
for (const comment of comments) {
|
|
84
|
+
state.commands.push({ type: 'Comment', comment });
|
|
85
|
+
|
|
86
|
+
if (newlines || comment.type === 'Line' || /\n/.test(comment.value)) {
|
|
87
|
+
state.commands.push(newline);
|
|
88
|
+
} else {
|
|
89
|
+
state.commands.push(' ');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
77
92
|
}
|
|
78
93
|
|
|
79
94
|
const OPERATOR_PRECEDENCE = {
|
|
@@ -205,45 +220,6 @@ function has_call_expression(node) {
|
|
|
205
220
|
}
|
|
206
221
|
}
|
|
207
222
|
|
|
208
|
-
/** @param {import('./types').Chunk[]} chunks */
|
|
209
|
-
const has_newline = (chunks) => {
|
|
210
|
-
for (let i = 0; i < chunks.length; i += 1) {
|
|
211
|
-
if (chunks[i].has_newline) return true;
|
|
212
|
-
}
|
|
213
|
-
return false;
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
/** @param {import('./types').Chunk[]} chunks */
|
|
217
|
-
const get_length = (chunks) => {
|
|
218
|
-
let total = 0;
|
|
219
|
-
for (let i = 0; i < chunks.length; i += 1) {
|
|
220
|
-
total += chunks[i].content.length;
|
|
221
|
-
}
|
|
222
|
-
return total;
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* @param {number} a
|
|
227
|
-
* @param {number} b
|
|
228
|
-
*/
|
|
229
|
-
const sum = (a, b) => a + b;
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* @param {import('./types').Chunk[][]} nodes
|
|
233
|
-
* @param {import('./types').Chunk} separator
|
|
234
|
-
* @returns {import('./types').Chunk[]}
|
|
235
|
-
*/
|
|
236
|
-
const join = (nodes, separator) => {
|
|
237
|
-
if (nodes.length === 0) return [];
|
|
238
|
-
|
|
239
|
-
const joined = [...nodes[0]];
|
|
240
|
-
for (let i = 1; i < nodes.length; i += 1) {
|
|
241
|
-
joined.push(separator);
|
|
242
|
-
push_array(joined, nodes[i]);
|
|
243
|
-
}
|
|
244
|
-
return joined;
|
|
245
|
-
};
|
|
246
|
-
|
|
247
223
|
const grouped_expression_types = [
|
|
248
224
|
'ImportDeclaration',
|
|
249
225
|
'VariableDeclaration',
|
|
@@ -256,174 +232,175 @@ const grouped_expression_types = [
|
|
|
256
232
|
* @param {import('./types').State} state
|
|
257
233
|
*/
|
|
258
234
|
const handle_body = (nodes, state) => {
|
|
259
|
-
/** @type {import('./types').Chunk[][][]} */
|
|
260
|
-
const groups = [];
|
|
261
|
-
|
|
262
|
-
/** @type {import('./types').Chunk[][]} */
|
|
263
|
-
let group = [];
|
|
264
|
-
|
|
265
235
|
let last_statement = /** @type {import('estree').Node} */ ({ type: 'EmptyStatement' });
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (group.length > 0) {
|
|
269
|
-
groups.push(group);
|
|
270
|
-
group = [];
|
|
271
|
-
}
|
|
272
|
-
}
|
|
236
|
+
let first = true;
|
|
237
|
+
let needs_margin = false;
|
|
273
238
|
|
|
274
239
|
for (const statement of nodes) {
|
|
275
240
|
if (statement.type === 'EmptyStatement') continue;
|
|
276
241
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
) {
|
|
282
|
-
flush();
|
|
283
|
-
}
|
|
242
|
+
const margin = create_sequence();
|
|
243
|
+
|
|
244
|
+
if (!first) state.commands.push(margin, newline);
|
|
245
|
+
first = false;
|
|
284
246
|
|
|
285
247
|
const leadingComments = statement.leadingComments;
|
|
286
248
|
delete statement.leadingComments;
|
|
287
249
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
});
|
|
250
|
+
if (leadingComments && leadingComments.length > 0) {
|
|
251
|
+
prepend_comments(leadingComments, state, true);
|
|
252
|
+
}
|
|
292
253
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const standalone =
|
|
296
|
-
has_newline(chunks) ||
|
|
297
|
-
(leadingComments?.[0]?.type === 'Block' && leadingComments[0].value.startsWith('*'));
|
|
254
|
+
const child_state = { ...state, multiline: false };
|
|
255
|
+
handle(statement, child_state);
|
|
298
256
|
|
|
299
|
-
if (
|
|
300
|
-
|
|
301
|
-
|
|
257
|
+
if (
|
|
258
|
+
child_state.multiline ||
|
|
259
|
+
needs_margin ||
|
|
260
|
+
((grouped_expression_types.includes(statement.type) ||
|
|
261
|
+
grouped_expression_types.includes(last_statement.type)) &&
|
|
262
|
+
last_statement.type !== statement.type)
|
|
263
|
+
) {
|
|
264
|
+
margin.children.push('\n');
|
|
302
265
|
}
|
|
303
266
|
|
|
304
267
|
let add_newline = false;
|
|
305
268
|
|
|
306
269
|
while (state.comments.length) {
|
|
307
270
|
const comment = /** @type {import('estree').Comment} */ (state.comments.shift());
|
|
308
|
-
const prefix = add_newline ? `\n${state.indent}` : ` `;
|
|
309
|
-
|
|
310
|
-
chunks.push(
|
|
311
|
-
c(
|
|
312
|
-
comment.type === 'Block' ? `${prefix}/*${comment.value}*/` : `${prefix}//${comment.value}`
|
|
313
|
-
)
|
|
314
|
-
);
|
|
315
271
|
|
|
272
|
+
state.commands.push(add_newline ? newline : ' ', { type: 'Comment', comment });
|
|
316
273
|
add_newline = comment.type === 'Line';
|
|
317
274
|
}
|
|
318
275
|
|
|
319
|
-
|
|
320
|
-
flush();
|
|
321
|
-
group.push(chunks);
|
|
322
|
-
flush();
|
|
323
|
-
} else {
|
|
324
|
-
group.push(chunks);
|
|
325
|
-
}
|
|
326
|
-
|
|
276
|
+
needs_margin = child_state.multiline;
|
|
327
277
|
last_statement = statement;
|
|
328
278
|
}
|
|
279
|
+
};
|
|
329
280
|
|
|
330
|
-
|
|
281
|
+
/**
|
|
282
|
+
* @param {import('estree').VariableDeclaration} node
|
|
283
|
+
* @param {import('./types').State} state
|
|
284
|
+
*/
|
|
285
|
+
const handle_var_declaration = (node, state) => {
|
|
286
|
+
const index = state.commands.length;
|
|
331
287
|
|
|
332
|
-
const
|
|
288
|
+
const open = create_sequence();
|
|
289
|
+
const join = create_sequence();
|
|
290
|
+
const child_state = { ...state, multiline: false };
|
|
333
291
|
|
|
334
|
-
|
|
335
|
-
if (i > 0) {
|
|
336
|
-
chunks.push(c(`\n\n${state.indent}`));
|
|
337
|
-
}
|
|
292
|
+
state.commands.push(`${node.kind} `, open);
|
|
338
293
|
|
|
339
|
-
|
|
340
|
-
if (j > 0) {
|
|
341
|
-
chunks.push(c(`\n${state.indent}`));
|
|
342
|
-
}
|
|
294
|
+
let first = true;
|
|
343
295
|
|
|
344
|
-
|
|
345
|
-
|
|
296
|
+
for (const d of node.declarations) {
|
|
297
|
+
if (!first) state.commands.push(join);
|
|
298
|
+
first = false;
|
|
299
|
+
|
|
300
|
+
handle(d, child_state);
|
|
346
301
|
}
|
|
347
302
|
|
|
348
|
-
|
|
303
|
+
const multiline =
|
|
304
|
+
child_state.multiline || (node.declarations.length > 1 && measure(state.commands, index) > 50);
|
|
305
|
+
|
|
306
|
+
if (multiline) {
|
|
307
|
+
state.multiline = true;
|
|
308
|
+
if (node.declarations.length > 1) open.children.push(indent);
|
|
309
|
+
join.children.push(',', newline);
|
|
310
|
+
if (node.declarations.length > 1) state.commands.push(dedent);
|
|
311
|
+
} else {
|
|
312
|
+
join.children.push(', ');
|
|
313
|
+
}
|
|
349
314
|
};
|
|
350
315
|
|
|
351
316
|
/**
|
|
352
|
-
* @
|
|
317
|
+
* @template {import('estree').Node} T
|
|
318
|
+
* @param {Array<T | null>} nodes
|
|
353
319
|
* @param {import('./types').State} state
|
|
320
|
+
* @param {boolean} spaces
|
|
321
|
+
* @param {(node: T, state: import('./types').State) => void} fn
|
|
354
322
|
*/
|
|
355
|
-
|
|
356
|
-
|
|
323
|
+
function sequence(nodes, state, spaces, fn) {
|
|
324
|
+
if (nodes.length === 0) return;
|
|
357
325
|
|
|
358
|
-
const
|
|
359
|
-
handle(d, {
|
|
360
|
-
...state,
|
|
361
|
-
indent: state.indent + (node.declarations.length === 1 ? '' : '\t')
|
|
362
|
-
})
|
|
363
|
-
);
|
|
326
|
+
const index = state.commands.length;
|
|
364
327
|
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
(state.indent.length + declarators.length - 1) * 2 >
|
|
369
|
-
80;
|
|
328
|
+
const open = create_sequence();
|
|
329
|
+
const join = create_sequence();
|
|
330
|
+
const close = create_sequence();
|
|
370
331
|
|
|
371
|
-
|
|
332
|
+
state.commands.push(open);
|
|
372
333
|
|
|
373
|
-
|
|
334
|
+
const child_state = { ...state, multiline: false };
|
|
374
335
|
|
|
375
|
-
|
|
376
|
-
};
|
|
336
|
+
let prev;
|
|
377
337
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
/** @type {import('./types').Chunk[][]} */
|
|
387
|
-
const elements = [];
|
|
388
|
-
|
|
389
|
-
/** @type {import('./types').Chunk[]} */
|
|
390
|
-
let sparse_commas = [];
|
|
391
|
-
|
|
392
|
-
for (let i = 0; i < node.elements.length; i += 1) {
|
|
393
|
-
// can't use map/forEach because of sparse arrays
|
|
394
|
-
const element = node.elements[i];
|
|
395
|
-
if (element) {
|
|
396
|
-
elements.push([
|
|
397
|
-
...sparse_commas,
|
|
398
|
-
...handle(element, {
|
|
399
|
-
...state,
|
|
400
|
-
indent: state.indent + '\t'
|
|
401
|
-
})
|
|
402
|
-
]);
|
|
403
|
-
sparse_commas = [];
|
|
404
|
-
} else {
|
|
405
|
-
sparse_commas.push(c(','));
|
|
338
|
+
for (let i = 0; i < nodes.length; i += 1) {
|
|
339
|
+
const node = nodes[i];
|
|
340
|
+
const is_first = i === 0;
|
|
341
|
+
const is_last = i === nodes.length - 1;
|
|
342
|
+
|
|
343
|
+
if (node) {
|
|
344
|
+
if (!is_first && !prev) {
|
|
345
|
+
state.commands.push(join);
|
|
406
346
|
}
|
|
407
|
-
}
|
|
408
347
|
|
|
409
|
-
|
|
410
|
-
elements.some(has_newline) ||
|
|
411
|
-
elements.map(get_length).reduce(sum, 0) + (state.indent.length + elements.length - 1) * 2 >
|
|
412
|
-
80;
|
|
348
|
+
fn(node, child_state);
|
|
413
349
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
350
|
+
if (!is_last) {
|
|
351
|
+
state.commands.push(',');
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (state.comments.length > 0) {
|
|
355
|
+
state.commands.push(' ');
|
|
356
|
+
|
|
357
|
+
while (state.comments.length) {
|
|
358
|
+
const comment = /** @type {import('estree').Comment} */ (state.comments.shift());
|
|
359
|
+
state.commands.push({ type: 'Comment', comment });
|
|
360
|
+
if (!is_last) state.commands.push(join);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
child_state.multiline = true;
|
|
364
|
+
} else {
|
|
365
|
+
if (!is_last) state.commands.push(join);
|
|
366
|
+
}
|
|
419
367
|
} else {
|
|
420
|
-
|
|
421
|
-
|
|
368
|
+
// This is only used for ArrayPattern and ArrayExpression, but
|
|
369
|
+
// it makes more sense to have the logic here than there, because
|
|
370
|
+
// otherwise we'd duplicate a lot more stuff
|
|
371
|
+
state.commands.push(',');
|
|
422
372
|
}
|
|
423
373
|
|
|
424
|
-
|
|
374
|
+
prev = node;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
state.commands.push(close);
|
|
378
|
+
|
|
379
|
+
const multiline = child_state.multiline || measure(state.commands, index) > 50;
|
|
380
|
+
|
|
381
|
+
if (multiline) {
|
|
382
|
+
state.multiline = true;
|
|
383
|
+
|
|
384
|
+
open.children.push(indent, newline);
|
|
385
|
+
join.children.push(newline);
|
|
386
|
+
close.children.push(dedent, newline);
|
|
387
|
+
} else {
|
|
388
|
+
if (spaces) open.children.push(' ');
|
|
389
|
+
join.children.push(' ');
|
|
390
|
+
if (spaces) close.children.push(' ');
|
|
391
|
+
}
|
|
392
|
+
}
|
|
425
393
|
|
|
426
|
-
|
|
394
|
+
/** @satisfies {Record<string, (node: any, state: import('./types').State) => undefined>} */
|
|
395
|
+
const shared = {
|
|
396
|
+
/**
|
|
397
|
+
* @param {import('estree').ArrayExpression | import('estree').ArrayPattern} node
|
|
398
|
+
* @param {import('./types').State} state
|
|
399
|
+
*/
|
|
400
|
+
'ArrayExpression|ArrayPattern': (node, state) => {
|
|
401
|
+
state.commands.push('[');
|
|
402
|
+
sequence(/** @type {import('estree').Node[]} */ (node.elements), state, false, handle);
|
|
403
|
+
state.commands.push(']');
|
|
427
404
|
},
|
|
428
405
|
|
|
429
406
|
/**
|
|
@@ -431,11 +408,6 @@ const shared = {
|
|
|
431
408
|
* @param {import('./types').State} state
|
|
432
409
|
*/
|
|
433
410
|
'BinaryExpression|LogicalExpression': (node, state) => {
|
|
434
|
-
/**
|
|
435
|
-
* @type any[]
|
|
436
|
-
*/
|
|
437
|
-
const chunks = [];
|
|
438
|
-
|
|
439
411
|
// TODO
|
|
440
412
|
// const is_in = node.operator === 'in';
|
|
441
413
|
// if (is_in) {
|
|
@@ -444,24 +416,22 @@ const shared = {
|
|
|
444
416
|
// }
|
|
445
417
|
|
|
446
418
|
if (needs_parens(node.left, node, false)) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
419
|
+
state.commands.push('(');
|
|
420
|
+
handle(node.left, state);
|
|
421
|
+
state.commands.push(')');
|
|
450
422
|
} else {
|
|
451
|
-
|
|
423
|
+
handle(node.left, state);
|
|
452
424
|
}
|
|
453
425
|
|
|
454
|
-
|
|
426
|
+
state.commands.push(` ${node.operator} `);
|
|
455
427
|
|
|
456
428
|
if (needs_parens(node.right, node, true)) {
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
429
|
+
state.commands.push('(');
|
|
430
|
+
handle(node.right, state);
|
|
431
|
+
state.commands.push(')');
|
|
460
432
|
} else {
|
|
461
|
-
|
|
433
|
+
handle(node.right, state);
|
|
462
434
|
}
|
|
463
|
-
|
|
464
|
-
return chunks;
|
|
465
435
|
},
|
|
466
436
|
|
|
467
437
|
/**
|
|
@@ -469,13 +439,98 @@ const shared = {
|
|
|
469
439
|
* @param {import('./types').State} state
|
|
470
440
|
*/
|
|
471
441
|
'BlockStatement|ClassBody': (node, state) => {
|
|
472
|
-
if (node.body.length === 0)
|
|
442
|
+
if (node.body.length === 0) {
|
|
443
|
+
state.commands.push('{}');
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
473
446
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
447
|
+
state.multiline = true;
|
|
448
|
+
|
|
449
|
+
state.commands.push('{', indent, newline);
|
|
450
|
+
handle_body(node.body, state);
|
|
451
|
+
state.commands.push(dedent, newline, '}');
|
|
452
|
+
},
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* @param {import('estree').CallExpression | import('estree').NewExpression} node
|
|
456
|
+
* @param {import('./types').State} state
|
|
457
|
+
*/
|
|
458
|
+
'CallExpression|NewExpression': (node, state) => {
|
|
459
|
+
const index = state.commands.length;
|
|
460
|
+
|
|
461
|
+
if (node.type === 'NewExpression') {
|
|
462
|
+
state.commands.push('new ');
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const needs_parens =
|
|
466
|
+
EXPRESSIONS_PRECEDENCE[node.callee.type] < EXPRESSIONS_PRECEDENCE.CallExpression ||
|
|
467
|
+
(node.type === 'NewExpression' && has_call_expression(node.callee));
|
|
468
|
+
|
|
469
|
+
if (needs_parens) {
|
|
470
|
+
state.commands.push('(');
|
|
471
|
+
handle(node.callee, state);
|
|
472
|
+
state.commands.push(')');
|
|
473
|
+
} else {
|
|
474
|
+
handle(node.callee, state);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
if (/** @type {import('estree').SimpleCallExpression} */ (node).optional) {
|
|
478
|
+
state.commands.push('?.');
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const open = create_sequence();
|
|
482
|
+
const join = create_sequence();
|
|
483
|
+
const close = create_sequence();
|
|
484
|
+
|
|
485
|
+
state.commands.push('(', open);
|
|
486
|
+
|
|
487
|
+
// if the final argument is multiline, it doesn't need to force all the
|
|
488
|
+
// other arguments to also be multiline
|
|
489
|
+
const child_state = { ...state, multiline: false };
|
|
490
|
+
const final_state = { ...state, multiline: false };
|
|
491
|
+
|
|
492
|
+
for (let i = 0; i < node.arguments.length; i += 1) {
|
|
493
|
+
if (i > 0) {
|
|
494
|
+
if (state.comments.length > 0) {
|
|
495
|
+
state.commands.push(', ');
|
|
496
|
+
|
|
497
|
+
while (state.comments.length) {
|
|
498
|
+
const comment = /** @type {import('estree').Comment} */ (state.comments.shift());
|
|
499
|
+
|
|
500
|
+
state.commands.push({ type: 'Comment', comment });
|
|
501
|
+
|
|
502
|
+
if (comment.type === 'Line') {
|
|
503
|
+
child_state.multiline = true;
|
|
504
|
+
state.commands.push(newline);
|
|
505
|
+
} else {
|
|
506
|
+
state.commands.push(' ');
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
} else {
|
|
510
|
+
state.commands.push(join);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const p = node.arguments[i];
|
|
515
|
+
|
|
516
|
+
handle(p, i === node.arguments.length - 1 ? final_state : child_state);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
state.commands.push(close, ')');
|
|
520
|
+
|
|
521
|
+
const multiline = child_state.multiline;
|
|
522
|
+
|
|
523
|
+
if (multiline || final_state.multiline) {
|
|
524
|
+
state.multiline = true;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (multiline) {
|
|
528
|
+
open.children.push(indent, newline);
|
|
529
|
+
join.children.push(',', newline);
|
|
530
|
+
close.children.push(dedent, newline);
|
|
531
|
+
} else {
|
|
532
|
+
join.children.push(', ');
|
|
533
|
+
}
|
|
479
534
|
},
|
|
480
535
|
|
|
481
536
|
/**
|
|
@@ -483,22 +538,20 @@ const shared = {
|
|
|
483
538
|
* @param {import('./types').State} state
|
|
484
539
|
*/
|
|
485
540
|
'ClassDeclaration|ClassExpression': (node, state) => {
|
|
486
|
-
|
|
541
|
+
state.commands.push('class ');
|
|
487
542
|
|
|
488
543
|
if (node.id) {
|
|
489
|
-
|
|
490
|
-
|
|
544
|
+
handle(node.id, state);
|
|
545
|
+
state.commands.push(' ');
|
|
491
546
|
}
|
|
492
547
|
|
|
493
548
|
if (node.superClass) {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
549
|
+
state.commands.push('extends ');
|
|
550
|
+
handle(node.superClass, state);
|
|
551
|
+
state.commands.push(' ');
|
|
497
552
|
}
|
|
498
553
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
return chunks;
|
|
554
|
+
handle(node.body, state);
|
|
502
555
|
},
|
|
503
556
|
|
|
504
557
|
/**
|
|
@@ -506,20 +559,20 @@ const shared = {
|
|
|
506
559
|
* @param {import('./types').State} state
|
|
507
560
|
*/
|
|
508
561
|
'ForInStatement|ForOfStatement': (node, state) => {
|
|
509
|
-
|
|
562
|
+
state.commands.push('for ');
|
|
563
|
+
if (node.type === 'ForOfStatement' && node.await) state.commands.push('await ');
|
|
564
|
+
state.commands.push('(');
|
|
510
565
|
|
|
511
566
|
if (node.left.type === 'VariableDeclaration') {
|
|
512
|
-
|
|
567
|
+
handle_var_declaration(node.left, state);
|
|
513
568
|
} else {
|
|
514
|
-
|
|
569
|
+
handle(node.left, state);
|
|
515
570
|
}
|
|
516
571
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
return chunks;
|
|
572
|
+
state.commands.push(node.type === 'ForInStatement' ? ` in ` : ` of `);
|
|
573
|
+
handle(node.right, state);
|
|
574
|
+
state.commands.push(') ');
|
|
575
|
+
handle(node.body, state);
|
|
523
576
|
},
|
|
524
577
|
|
|
525
578
|
/**
|
|
@@ -527,38 +580,15 @@ const shared = {
|
|
|
527
580
|
* @param {import('./types').State} state
|
|
528
581
|
*/
|
|
529
582
|
'FunctionDeclaration|FunctionExpression': (node, state) => {
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
if (node.
|
|
533
|
-
chunks.push(c(node.generator ? 'function* ' : 'function '));
|
|
534
|
-
if (node.id) push_array(chunks, handle(node.id, state));
|
|
535
|
-
chunks.push(c('('));
|
|
536
|
-
|
|
537
|
-
const params = node.params.map((p) =>
|
|
538
|
-
handle(p, {
|
|
539
|
-
...state,
|
|
540
|
-
indent: state.indent + '\t'
|
|
541
|
-
})
|
|
542
|
-
);
|
|
583
|
+
if (node.async) state.commands.push('async ');
|
|
584
|
+
state.commands.push(node.generator ? 'function* ' : 'function ');
|
|
585
|
+
if (node.id) handle(node.id, state);
|
|
543
586
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
587
|
+
state.commands.push('(');
|
|
588
|
+
sequence(node.params, state, false, handle);
|
|
589
|
+
state.commands.push(') ');
|
|
547
590
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
if (multiple_lines) {
|
|
551
|
-
chunks.push(c(`\n${state.indent}\t`));
|
|
552
|
-
push_array(chunks, join(params, separator));
|
|
553
|
-
chunks.push(c(`\n${state.indent}`));
|
|
554
|
-
} else {
|
|
555
|
-
push_array(chunks, join(params, separator));
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
chunks.push(c(') '));
|
|
559
|
-
push_array(chunks, handle(node.body, state));
|
|
560
|
-
|
|
561
|
-
return chunks;
|
|
591
|
+
handle(node.body, state);
|
|
562
592
|
},
|
|
563
593
|
|
|
564
594
|
/**
|
|
@@ -566,7 +596,8 @@ const shared = {
|
|
|
566
596
|
* @param {import('./types').State} state
|
|
567
597
|
*/
|
|
568
598
|
'RestElement|SpreadElement': (node, state) => {
|
|
569
|
-
|
|
599
|
+
state.commands.push('...');
|
|
600
|
+
handle(node.argument, state);
|
|
570
601
|
}
|
|
571
602
|
};
|
|
572
603
|
|
|
@@ -577,47 +608,34 @@ const handlers = {
|
|
|
577
608
|
ArrayPattern: shared['ArrayExpression|ArrayPattern'],
|
|
578
609
|
|
|
579
610
|
ArrowFunctionExpression: (node, state) => {
|
|
580
|
-
|
|
611
|
+
if (node.async) state.commands.push('async ');
|
|
581
612
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
push_array(chunks, handle(node.params[0], state));
|
|
586
|
-
} else {
|
|
587
|
-
const params = node.params.map((param) =>
|
|
588
|
-
handle(param, {
|
|
589
|
-
...state,
|
|
590
|
-
indent: state.indent + '\t'
|
|
591
|
-
})
|
|
592
|
-
);
|
|
593
|
-
|
|
594
|
-
chunks.push(c('('));
|
|
595
|
-
push_array(chunks, join(params, c(', ')));
|
|
596
|
-
chunks.push(c(')'));
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
chunks.push(c(' => '));
|
|
613
|
+
state.commands.push('(');
|
|
614
|
+
sequence(node.params, state, false, handle);
|
|
615
|
+
state.commands.push(') => ');
|
|
600
616
|
|
|
601
617
|
if (
|
|
602
618
|
node.body.type === 'ObjectExpression' ||
|
|
603
619
|
(node.body.type === 'AssignmentExpression' && node.body.left.type === 'ObjectPattern')
|
|
604
620
|
) {
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
621
|
+
state.commands.push('(');
|
|
622
|
+
handle(node.body, state);
|
|
623
|
+
state.commands.push(')');
|
|
608
624
|
} else {
|
|
609
|
-
|
|
625
|
+
handle(node.body, state);
|
|
610
626
|
}
|
|
611
|
-
|
|
612
|
-
return chunks;
|
|
613
627
|
},
|
|
614
628
|
|
|
615
629
|
AssignmentExpression(node, state) {
|
|
616
|
-
|
|
630
|
+
handle(node.left, state);
|
|
631
|
+
state.commands.push(` ${node.operator} `);
|
|
632
|
+
handle(node.right, state);
|
|
617
633
|
},
|
|
618
634
|
|
|
619
635
|
AssignmentPattern(node, state) {
|
|
620
|
-
|
|
636
|
+
handle(node.left, state);
|
|
637
|
+
state.commands.push(' = ');
|
|
638
|
+
handle(node.right, state);
|
|
621
639
|
},
|
|
622
640
|
|
|
623
641
|
AwaitExpression(node, state) {
|
|
@@ -625,13 +643,16 @@ const handlers = {
|
|
|
625
643
|
const precedence = EXPRESSIONS_PRECEDENCE[node.argument.type];
|
|
626
644
|
|
|
627
645
|
if (precedence && precedence < EXPRESSIONS_PRECEDENCE.AwaitExpression) {
|
|
628
|
-
|
|
646
|
+
state.commands.push('await (');
|
|
647
|
+
handle(node.argument, state);
|
|
648
|
+
state.commands.push(')');
|
|
629
649
|
} else {
|
|
630
|
-
|
|
650
|
+
state.commands.push('await ');
|
|
651
|
+
handle(node.argument, state);
|
|
631
652
|
}
|
|
653
|
+
} else {
|
|
654
|
+
state.commands.push('await');
|
|
632
655
|
}
|
|
633
|
-
|
|
634
|
-
return [c('await')];
|
|
635
656
|
},
|
|
636
657
|
|
|
637
658
|
BinaryExpression: shared['BinaryExpression|LogicalExpression'],
|
|
@@ -639,75 +660,19 @@ const handlers = {
|
|
|
639
660
|
BlockStatement: shared['BlockStatement|ClassBody'],
|
|
640
661
|
|
|
641
662
|
BreakStatement(node, state) {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
/**
|
|
647
|
-
* @type any[]
|
|
648
|
-
*/
|
|
649
|
-
const chunks = [];
|
|
650
|
-
|
|
651
|
-
if (EXPRESSIONS_PRECEDENCE[node.callee.type] < EXPRESSIONS_PRECEDENCE.CallExpression) {
|
|
652
|
-
chunks.push(c('('));
|
|
653
|
-
push_array(chunks, handle(node.callee, state));
|
|
654
|
-
chunks.push(c(')'));
|
|
655
|
-
} else {
|
|
656
|
-
push_array(chunks, handle(node.callee, state));
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
if (/** @type {import('estree').SimpleCallExpression} */ (node).optional) {
|
|
660
|
-
chunks.push(c('?.'));
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
let has_inline_comment = false;
|
|
664
|
-
let arg_chunks = [];
|
|
665
|
-
outer: for (const arg of node.arguments) {
|
|
666
|
-
const chunks = [];
|
|
667
|
-
while (state.comments.length) {
|
|
668
|
-
const comment = /** @type {import('estree').Comment} */ (state.comments.shift());
|
|
669
|
-
if (comment.type === 'Line') {
|
|
670
|
-
has_inline_comment = true;
|
|
671
|
-
break outer;
|
|
672
|
-
}
|
|
673
|
-
chunks.push(c(comment.type === 'Block' ? `/*${comment.value}*/ ` : `//${comment.value}`));
|
|
674
|
-
}
|
|
675
|
-
push_array(chunks, handle(arg, state));
|
|
676
|
-
arg_chunks.push(chunks);
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
const multiple_lines = has_inline_comment || arg_chunks.slice(0, -1).some(has_newline); // TODO or length exceeds 80
|
|
680
|
-
if (multiple_lines) {
|
|
681
|
-
// need to handle args again. TODO find alternative approach?
|
|
682
|
-
const args = node.arguments.map((arg, i) => {
|
|
683
|
-
const chunks = handle(arg, {
|
|
684
|
-
...state,
|
|
685
|
-
indent: `${state.indent}\t`
|
|
686
|
-
});
|
|
687
|
-
if (i < node.arguments.length - 1) chunks.push(c(','));
|
|
688
|
-
while (state.comments.length) {
|
|
689
|
-
const comment = /** @type {import('estree').Comment} */ (state.comments.shift());
|
|
690
|
-
chunks.push(
|
|
691
|
-
c(comment.type === 'Block' ? ` /*${comment.value}*/ ` : ` //${comment.value}`)
|
|
692
|
-
);
|
|
693
|
-
}
|
|
694
|
-
return chunks;
|
|
695
|
-
});
|
|
696
|
-
|
|
697
|
-
chunks.push(c(`(\n${state.indent}\t`));
|
|
698
|
-
push_array(chunks, join(args, c(`\n${state.indent}\t`)));
|
|
699
|
-
chunks.push(c(`\n${state.indent})`));
|
|
663
|
+
if (node.label) {
|
|
664
|
+
state.commands.push('break ');
|
|
665
|
+
handle(node.label, state);
|
|
666
|
+
state.commands.push(';');
|
|
700
667
|
} else {
|
|
701
|
-
|
|
702
|
-
push_array(chunks, join(arg_chunks, c(', ')));
|
|
703
|
-
chunks.push(c(')'));
|
|
668
|
+
state.commands.push('break;');
|
|
704
669
|
}
|
|
705
|
-
|
|
706
|
-
return chunks;
|
|
707
670
|
},
|
|
708
671
|
|
|
672
|
+
CallExpression: shared['CallExpression|NewExpression'],
|
|
673
|
+
|
|
709
674
|
ChainExpression(node, state) {
|
|
710
|
-
|
|
675
|
+
handle(node.expression, state);
|
|
711
676
|
},
|
|
712
677
|
|
|
713
678
|
ClassBody: shared['BlockStatement|ClassBody'],
|
|
@@ -717,118 +682,103 @@ const handlers = {
|
|
|
717
682
|
ClassExpression: shared['ClassDeclaration|ClassExpression'],
|
|
718
683
|
|
|
719
684
|
ConditionalExpression(node, state) {
|
|
720
|
-
/**
|
|
721
|
-
* @type any[]
|
|
722
|
-
*/
|
|
723
|
-
const chunks = [];
|
|
724
|
-
|
|
725
685
|
if (EXPRESSIONS_PRECEDENCE[node.test.type] > EXPRESSIONS_PRECEDENCE.ConditionalExpression) {
|
|
726
|
-
|
|
686
|
+
handle(node.test, state);
|
|
727
687
|
} else {
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
688
|
+
state.commands.push('(');
|
|
689
|
+
handle(node.test, state);
|
|
690
|
+
state.commands.push(')');
|
|
731
691
|
}
|
|
732
692
|
|
|
733
|
-
const
|
|
693
|
+
const if_true = create_sequence();
|
|
694
|
+
const if_false = create_sequence();
|
|
734
695
|
|
|
735
|
-
const
|
|
736
|
-
const alternate = handle(node.alternate, child_state);
|
|
696
|
+
const child_state = { ...state, multiline: false };
|
|
737
697
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
698
|
+
state.commands.push(if_true);
|
|
699
|
+
handle(node.consequent, child_state);
|
|
700
|
+
state.commands.push(if_false);
|
|
701
|
+
handle(node.alternate, child_state);
|
|
742
702
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
703
|
+
const multiline = child_state.multiline;
|
|
704
|
+
|
|
705
|
+
if (multiline) {
|
|
706
|
+
if_true.children.push(indent, newline, '? ');
|
|
707
|
+
if_false.children.push(newline, ': ');
|
|
708
|
+
state.commands.push(dedent);
|
|
748
709
|
} else {
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
chunks.push(c(` : `));
|
|
752
|
-
push_array(chunks, alternate);
|
|
710
|
+
if_true.children.push(' ? ');
|
|
711
|
+
if_false.children.push(' : ');
|
|
753
712
|
}
|
|
754
|
-
|
|
755
|
-
return chunks;
|
|
756
713
|
},
|
|
757
714
|
|
|
758
715
|
ContinueStatement(node, state) {
|
|
759
|
-
|
|
716
|
+
if (node.label) {
|
|
717
|
+
state.commands.push('continue ');
|
|
718
|
+
handle(node.label, state);
|
|
719
|
+
state.commands.push(';');
|
|
720
|
+
} else {
|
|
721
|
+
state.commands.push('continue;');
|
|
722
|
+
}
|
|
760
723
|
},
|
|
761
724
|
|
|
762
725
|
DebuggerStatement(node, state) {
|
|
763
|
-
|
|
726
|
+
state.commands.push(c('debugger', node), ';');
|
|
764
727
|
},
|
|
765
728
|
|
|
766
729
|
DoWhileStatement(node, state) {
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
c(');')
|
|
773
|
-
];
|
|
730
|
+
state.commands.push('do ');
|
|
731
|
+
handle(node.body, state);
|
|
732
|
+
state.commands.push(' while (');
|
|
733
|
+
handle(node.test, state);
|
|
734
|
+
state.commands.push(');');
|
|
774
735
|
},
|
|
775
736
|
|
|
776
737
|
EmptyStatement(node, state) {
|
|
777
|
-
|
|
738
|
+
state.commands.push(';');
|
|
778
739
|
},
|
|
779
740
|
|
|
780
741
|
ExportAllDeclaration(node, state) {
|
|
781
|
-
|
|
742
|
+
state.commands.push('export * from ');
|
|
743
|
+
handle(node.source, state);
|
|
744
|
+
state.commands.push(';');
|
|
782
745
|
},
|
|
783
746
|
|
|
784
747
|
ExportDefaultDeclaration(node, state) {
|
|
785
|
-
|
|
748
|
+
state.commands.push('export default ');
|
|
749
|
+
|
|
750
|
+
handle(node.declaration, state);
|
|
786
751
|
|
|
787
752
|
if (node.declaration.type !== 'FunctionDeclaration') {
|
|
788
|
-
|
|
753
|
+
state.commands.push(';');
|
|
789
754
|
}
|
|
790
|
-
|
|
791
|
-
return chunks;
|
|
792
755
|
},
|
|
793
756
|
|
|
794
757
|
ExportNamedDeclaration(node, state) {
|
|
795
|
-
|
|
758
|
+
state.commands.push('export ');
|
|
796
759
|
|
|
797
760
|
if (node.declaration) {
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
const name = handle(specifier.local, state)[0];
|
|
802
|
-
const as = handle(specifier.exported, state)[0];
|
|
803
|
-
|
|
804
|
-
if (name.content === as.content) {
|
|
805
|
-
return [name];
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
return [name, c(' as '), as];
|
|
809
|
-
});
|
|
761
|
+
handle(node.declaration, state);
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
810
764
|
|
|
811
|
-
|
|
765
|
+
state.commands.push('{');
|
|
766
|
+
sequence(node.specifiers, state, true, (s, state) => {
|
|
767
|
+
handle(s.local, state);
|
|
812
768
|
|
|
813
|
-
if (
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
chunks.push(c('\n}'));
|
|
817
|
-
} else {
|
|
818
|
-
chunks.push(c('{ '));
|
|
819
|
-
push_array(chunks, join(specifiers, c(', ')));
|
|
820
|
-
chunks.push(c(' }'));
|
|
769
|
+
if (s.local.name !== s.exported.name) {
|
|
770
|
+
state.commands.push(' as ');
|
|
771
|
+
handle(s.exported, state);
|
|
821
772
|
}
|
|
773
|
+
});
|
|
774
|
+
state.commands.push('}');
|
|
822
775
|
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
}
|
|
776
|
+
if (node.source) {
|
|
777
|
+
state.commands.push(' from ');
|
|
778
|
+
handle(node.source, state);
|
|
827
779
|
}
|
|
828
780
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
return chunks;
|
|
781
|
+
state.commands.push(';');
|
|
832
782
|
},
|
|
833
783
|
|
|
834
784
|
ExpressionStatement(node, state) {
|
|
@@ -837,32 +787,34 @@ const handlers = {
|
|
|
837
787
|
node.expression.left.type === 'ObjectPattern'
|
|
838
788
|
) {
|
|
839
789
|
// is an AssignmentExpression to an ObjectPattern
|
|
840
|
-
|
|
790
|
+
state.commands.push('(');
|
|
791
|
+
handle(node.expression, state);
|
|
792
|
+
state.commands.push(');');
|
|
793
|
+
return;
|
|
841
794
|
}
|
|
842
795
|
|
|
843
|
-
|
|
796
|
+
handle(node.expression, state);
|
|
797
|
+
state.commands.push(';');
|
|
844
798
|
},
|
|
845
799
|
|
|
846
800
|
ForStatement: (node, state) => {
|
|
847
|
-
|
|
801
|
+
state.commands.push('for (');
|
|
848
802
|
|
|
849
803
|
if (node.init) {
|
|
850
804
|
if (node.init.type === 'VariableDeclaration') {
|
|
851
|
-
|
|
805
|
+
handle_var_declaration(node.init, state);
|
|
852
806
|
} else {
|
|
853
|
-
|
|
807
|
+
handle(node.init, state);
|
|
854
808
|
}
|
|
855
809
|
}
|
|
856
810
|
|
|
857
|
-
|
|
858
|
-
if (node.test)
|
|
859
|
-
|
|
860
|
-
if (node.update)
|
|
861
|
-
|
|
862
|
-
chunks.push(c(') '));
|
|
863
|
-
push_array(chunks, handle(node.body, state));
|
|
811
|
+
state.commands.push('; ');
|
|
812
|
+
if (node.test) handle(node.test, state);
|
|
813
|
+
state.commands.push('; ');
|
|
814
|
+
if (node.update) handle(node.update, state);
|
|
864
815
|
|
|
865
|
-
|
|
816
|
+
state.commands.push(') ');
|
|
817
|
+
handle(node.body, state);
|
|
866
818
|
},
|
|
867
819
|
|
|
868
820
|
ForInStatement: shared['ForInStatement|ForOfStatement'],
|
|
@@ -873,297 +825,196 @@ const handlers = {
|
|
|
873
825
|
|
|
874
826
|
FunctionExpression: shared['FunctionDeclaration|FunctionExpression'],
|
|
875
827
|
|
|
876
|
-
Identifier(node) {
|
|
828
|
+
Identifier(node, state) {
|
|
877
829
|
let name = node.name;
|
|
878
|
-
|
|
830
|
+
state.commands.push(c(name, node));
|
|
879
831
|
},
|
|
880
832
|
|
|
881
833
|
IfStatement(node, state) {
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
...handle(node.consequent, state)
|
|
887
|
-
];
|
|
834
|
+
state.commands.push('if (');
|
|
835
|
+
handle(node.test, state);
|
|
836
|
+
state.commands.push(') ');
|
|
837
|
+
handle(node.consequent, state);
|
|
888
838
|
|
|
889
839
|
if (node.alternate) {
|
|
890
|
-
|
|
891
|
-
|
|
840
|
+
state.commands.push(' else ');
|
|
841
|
+
handle(node.alternate, state);
|
|
892
842
|
}
|
|
893
|
-
|
|
894
|
-
return chunks;
|
|
895
843
|
},
|
|
896
844
|
|
|
897
845
|
ImportDeclaration(node, state) {
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
846
|
+
if (node.specifiers.length === 0) {
|
|
847
|
+
state.commands.push('import ');
|
|
848
|
+
handle(node.source, state);
|
|
849
|
+
state.commands.push(';');
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
902
852
|
|
|
903
|
-
|
|
904
|
-
|
|
853
|
+
/** @type {import('estree').ImportNamespaceSpecifier | null} */
|
|
854
|
+
let namespace_specifier = null;
|
|
905
855
|
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
chunks.push(c(', '));
|
|
909
|
-
}
|
|
856
|
+
/** @type {import('estree').ImportDefaultSpecifier | null} */
|
|
857
|
+
let default_specifier = null;
|
|
910
858
|
|
|
911
|
-
|
|
859
|
+
/** @type {import('estree').ImportSpecifier[]} */
|
|
860
|
+
const named_specifiers = [];
|
|
912
861
|
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
break;
|
|
921
|
-
}
|
|
862
|
+
for (const s of node.specifiers) {
|
|
863
|
+
if (s.type === 'ImportNamespaceSpecifier') {
|
|
864
|
+
namespace_specifier = s;
|
|
865
|
+
} else if (s.type === 'ImportDefaultSpecifier') {
|
|
866
|
+
default_specifier = s;
|
|
867
|
+
} else {
|
|
868
|
+
named_specifiers.push(s);
|
|
922
869
|
}
|
|
870
|
+
}
|
|
923
871
|
|
|
924
|
-
|
|
925
|
-
// we have named specifiers
|
|
926
|
-
const specifiers = /** @type {import('estree').ImportSpecifier[]} */ (node.specifiers)
|
|
927
|
-
.slice(i)
|
|
928
|
-
.map((specifier) => {
|
|
929
|
-
const name = handle(specifier.imported, state)[0];
|
|
930
|
-
const as = handle(specifier.local, state)[0];
|
|
872
|
+
state.commands.push('import ');
|
|
931
873
|
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
874
|
+
if (namespace_specifier) {
|
|
875
|
+
state.commands.push(c('* as ' + namespace_specifier.local.name, namespace_specifier));
|
|
876
|
+
}
|
|
935
877
|
|
|
936
|
-
|
|
937
|
-
|
|
878
|
+
if (default_specifier) {
|
|
879
|
+
state.commands.push(c(default_specifier.local.name, default_specifier));
|
|
880
|
+
}
|
|
938
881
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
specifiers.map(get_length).reduce(sum, 0) +
|
|
942
|
-
2 * specifiers.length +
|
|
943
|
-
6 +
|
|
944
|
-
get_length(source);
|
|
882
|
+
if (named_specifiers.length > 0) {
|
|
883
|
+
if (default_specifier) state.commands.push(', ');
|
|
945
884
|
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
chunks.push(c(`{ `));
|
|
952
|
-
push_array(chunks, join(specifiers, c(', ')));
|
|
953
|
-
chunks.push(c(' }'));
|
|
885
|
+
state.commands.push('{');
|
|
886
|
+
sequence(named_specifiers, state, true, (s, state) => {
|
|
887
|
+
if (s.local.name !== s.imported.name) {
|
|
888
|
+
handle(s.imported, state);
|
|
889
|
+
state.commands.push(' as ');
|
|
954
890
|
}
|
|
955
|
-
}
|
|
956
891
|
|
|
957
|
-
|
|
892
|
+
handle(s.local, state);
|
|
893
|
+
});
|
|
894
|
+
state.commands.push('}');
|
|
958
895
|
}
|
|
959
896
|
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
return chunks;
|
|
897
|
+
state.commands.push(' from ');
|
|
898
|
+
handle(node.source, state);
|
|
899
|
+
state.commands.push(';');
|
|
964
900
|
},
|
|
965
901
|
|
|
966
902
|
ImportExpression(node, state) {
|
|
967
|
-
|
|
903
|
+
state.commands.push('import(');
|
|
904
|
+
handle(node.source, state);
|
|
905
|
+
state.commands.push(')');
|
|
968
906
|
},
|
|
969
907
|
|
|
970
908
|
LabeledStatement(node, state) {
|
|
971
|
-
|
|
909
|
+
handle(node.label, state);
|
|
910
|
+
state.commands.push(': ');
|
|
911
|
+
handle(node.body, state);
|
|
972
912
|
},
|
|
973
913
|
|
|
974
914
|
Literal(node, state) {
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
];
|
|
981
|
-
}
|
|
915
|
+
// TODO do we need to handle weird unicode characters somehow?
|
|
916
|
+
// str.replace(/\\u(\d{4})/g, (m, n) => String.fromCharCode(+n))
|
|
917
|
+
const value =
|
|
918
|
+
node.raw ??
|
|
919
|
+
(typeof node.value === 'string' ? JSON.stringify(node.value) : String(node.value));
|
|
982
920
|
|
|
983
|
-
|
|
921
|
+
state.commands.push(c(value, node));
|
|
984
922
|
},
|
|
985
923
|
|
|
986
924
|
LogicalExpression: shared['BinaryExpression|LogicalExpression'],
|
|
987
925
|
|
|
988
926
|
MemberExpression(node, state) {
|
|
989
|
-
/**
|
|
990
|
-
* @type any[]
|
|
991
|
-
*/
|
|
992
|
-
const chunks = [];
|
|
993
|
-
|
|
994
927
|
if (EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression) {
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
928
|
+
state.commands.push('(');
|
|
929
|
+
handle(node.object, state);
|
|
930
|
+
state.commands.push(')');
|
|
998
931
|
} else {
|
|
999
|
-
|
|
932
|
+
handle(node.object, state);
|
|
1000
933
|
}
|
|
1001
934
|
|
|
1002
935
|
if (node.computed) {
|
|
1003
936
|
if (node.optional) {
|
|
1004
|
-
|
|
937
|
+
state.commands.push('?.');
|
|
1005
938
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
939
|
+
state.commands.push('[');
|
|
940
|
+
handle(node.property, state);
|
|
941
|
+
state.commands.push(']');
|
|
1009
942
|
} else {
|
|
1010
|
-
|
|
1011
|
-
|
|
943
|
+
state.commands.push(node.optional ? '?.' : '.');
|
|
944
|
+
handle(node.property, state);
|
|
1012
945
|
}
|
|
1013
|
-
|
|
1014
|
-
return chunks;
|
|
1015
946
|
},
|
|
1016
947
|
|
|
1017
948
|
MetaProperty(node, state) {
|
|
1018
|
-
|
|
949
|
+
handle(node.meta, state);
|
|
950
|
+
state.commands.push('.');
|
|
951
|
+
handle(node.property, state);
|
|
1019
952
|
},
|
|
1020
953
|
|
|
1021
954
|
MethodDefinition(node, state) {
|
|
1022
|
-
const chunks = [];
|
|
1023
|
-
|
|
1024
955
|
if (node.static) {
|
|
1025
|
-
|
|
956
|
+
state.commands.push('static ');
|
|
1026
957
|
}
|
|
1027
958
|
|
|
1028
959
|
if (node.kind === 'get' || node.kind === 'set') {
|
|
1029
960
|
// Getter or setter
|
|
1030
|
-
|
|
961
|
+
state.commands.push(node.kind + ' ');
|
|
1031
962
|
}
|
|
1032
963
|
|
|
1033
964
|
if (node.value.async) {
|
|
1034
|
-
|
|
965
|
+
state.commands.push('async ');
|
|
1035
966
|
}
|
|
1036
967
|
|
|
1037
968
|
if (node.value.generator) {
|
|
1038
|
-
|
|
969
|
+
state.commands.push('*');
|
|
1039
970
|
}
|
|
1040
971
|
|
|
1041
|
-
if (node.computed)
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
chunks.push(c(']'));
|
|
1045
|
-
} else {
|
|
1046
|
-
push_array(chunks, handle(node.key, state));
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
chunks.push(c('('));
|
|
1050
|
-
|
|
1051
|
-
const { params } = node.value;
|
|
1052
|
-
for (let i = 0; i < params.length; i += 1) {
|
|
1053
|
-
push_array(chunks, handle(params[i], state));
|
|
1054
|
-
if (i < params.length - 1) chunks.push(c(', '));
|
|
1055
|
-
}
|
|
972
|
+
if (node.computed) state.commands.push('[');
|
|
973
|
+
handle(node.key, state);
|
|
974
|
+
if (node.computed) state.commands.push(']');
|
|
1056
975
|
|
|
1057
|
-
|
|
1058
|
-
|
|
976
|
+
state.commands.push('(');
|
|
977
|
+
sequence(node.value.params, state, false, handle);
|
|
978
|
+
state.commands.push(') ');
|
|
1059
979
|
|
|
1060
|
-
|
|
980
|
+
handle(node.value.body, state);
|
|
1061
981
|
},
|
|
1062
982
|
|
|
1063
|
-
NewExpression
|
|
1064
|
-
const chunks = [c('new ')];
|
|
1065
|
-
|
|
1066
|
-
if (
|
|
1067
|
-
EXPRESSIONS_PRECEDENCE[node.callee.type] < EXPRESSIONS_PRECEDENCE.CallExpression ||
|
|
1068
|
-
has_call_expression(node.callee)
|
|
1069
|
-
) {
|
|
1070
|
-
chunks.push(c('('));
|
|
1071
|
-
push_array(chunks, handle(node.callee, state));
|
|
1072
|
-
chunks.push(c(')'));
|
|
1073
|
-
} else {
|
|
1074
|
-
push_array(chunks, handle(node.callee, state));
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
// TODO this is copied from CallExpression — DRY it out
|
|
1078
|
-
const args = node.arguments.map((arg) =>
|
|
1079
|
-
handle(arg, {
|
|
1080
|
-
...state,
|
|
1081
|
-
indent: state.indent + '\t'
|
|
1082
|
-
})
|
|
1083
|
-
);
|
|
1084
|
-
|
|
1085
|
-
const separator = args.some(has_newline) // TODO or length exceeds 80
|
|
1086
|
-
? c(',\n' + state.indent)
|
|
1087
|
-
: c(', ');
|
|
1088
|
-
|
|
1089
|
-
chunks.push(c('('));
|
|
1090
|
-
push_array(chunks, join(args, separator));
|
|
1091
|
-
chunks.push(c(')'));
|
|
1092
|
-
|
|
1093
|
-
return chunks;
|
|
1094
|
-
},
|
|
983
|
+
NewExpression: shared['CallExpression|NewExpression'],
|
|
1095
984
|
|
|
1096
985
|
ObjectExpression(node, state) {
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
let has_inline_comment = false;
|
|
986
|
+
state.commands.push('{');
|
|
987
|
+
sequence(node.properties, state, true, (p, state) => {
|
|
988
|
+
if (p.type === 'Property' && p.value.type === 'FunctionExpression') {
|
|
989
|
+
const fn = /** @type {import('estree').FunctionExpression} */ (p.value);
|
|
1102
990
|
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
chunks,
|
|
1110
|
-
handle(p, {
|
|
1111
|
-
...state,
|
|
1112
|
-
indent: state.indent + '\t'
|
|
1113
|
-
})
|
|
1114
|
-
);
|
|
1115
|
-
|
|
1116
|
-
if (state.comments.length) {
|
|
1117
|
-
// TODO generalise this, so it works with ArrayExpressions and other things.
|
|
1118
|
-
// At present, stuff will just get appended to the closest statement/declaration
|
|
1119
|
-
chunks.push(c(', '));
|
|
991
|
+
if (p.kind === 'get' || p.kind === 'set') {
|
|
992
|
+
state.commands.push(p.kind + ' ');
|
|
993
|
+
} else {
|
|
994
|
+
if (fn.async) state.commands.push('async ');
|
|
995
|
+
if (fn.generator) state.commands.push('*');
|
|
996
|
+
}
|
|
1120
997
|
|
|
1121
|
-
|
|
1122
|
-
|
|
998
|
+
if (p.computed) state.commands.push('[');
|
|
999
|
+
handle(p.key, state);
|
|
1000
|
+
if (p.computed) state.commands.push(']');
|
|
1123
1001
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
? `/*${comment.value}*/\n${state.indent}\t`
|
|
1128
|
-
: `//${comment.value}\n${state.indent}\t`
|
|
1129
|
-
)
|
|
1130
|
-
);
|
|
1002
|
+
state.commands.push('(');
|
|
1003
|
+
sequence(fn.params, state, false, handle);
|
|
1004
|
+
state.commands.push(') ');
|
|
1131
1005
|
|
|
1132
|
-
|
|
1133
|
-
has_inline_comment = true;
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1006
|
+
handle(fn.body, state);
|
|
1136
1007
|
} else {
|
|
1137
|
-
|
|
1138
|
-
chunks.push(separator);
|
|
1139
|
-
}
|
|
1008
|
+
handle(p, state);
|
|
1140
1009
|
}
|
|
1141
1010
|
});
|
|
1142
|
-
|
|
1143
|
-
const multiple_lines = has_inline_comment || has_newline(chunks) || get_length(chunks) > 40;
|
|
1144
|
-
|
|
1145
|
-
if (multiple_lines) {
|
|
1146
|
-
separator.content = `,\n${state.indent}\t`;
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
return [
|
|
1150
|
-
c(multiple_lines ? `{\n${state.indent}\t` : `{ `),
|
|
1151
|
-
...chunks,
|
|
1152
|
-
c(multiple_lines ? `\n${state.indent}}` : ` }`)
|
|
1153
|
-
];
|
|
1011
|
+
state.commands.push('}');
|
|
1154
1012
|
},
|
|
1155
1013
|
|
|
1156
1014
|
ObjectPattern(node, state) {
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
push_array(chunks, handle(node.properties[i], state));
|
|
1161
|
-
if (i < node.properties.length - 1) chunks.push(c(', '));
|
|
1162
|
-
}
|
|
1163
|
-
|
|
1164
|
-
chunks.push(c(' }'));
|
|
1165
|
-
|
|
1166
|
-
return chunks;
|
|
1015
|
+
state.commands.push('{');
|
|
1016
|
+
sequence(node.properties, state, true, handle);
|
|
1017
|
+
state.commands.push('}');
|
|
1167
1018
|
},
|
|
1168
1019
|
|
|
1169
1020
|
// @ts-expect-error this isn't a real node type, but Acorn produces it
|
|
@@ -1172,100 +1023,54 @@ const handlers = {
|
|
|
1172
1023
|
},
|
|
1173
1024
|
|
|
1174
1025
|
PrivateIdentifier(node, state) {
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
push_array(chunks, [c(node.name, node)]);
|
|
1178
|
-
|
|
1179
|
-
return chunks;
|
|
1026
|
+
state.commands.push('#', c(node.name, node));
|
|
1180
1027
|
},
|
|
1181
1028
|
|
|
1182
1029
|
Program(node, state) {
|
|
1183
|
-
|
|
1030
|
+
handle_body(node.body, state);
|
|
1184
1031
|
},
|
|
1185
1032
|
|
|
1186
1033
|
Property(node, state) {
|
|
1187
|
-
const value =
|
|
1034
|
+
const value = node.value.type === 'AssignmentPattern' ? node.value.left : node.value;
|
|
1188
1035
|
|
|
1189
|
-
|
|
1190
|
-
return value;
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
// special case
|
|
1194
|
-
if (
|
|
1036
|
+
const shorthand =
|
|
1195
1037
|
!node.computed &&
|
|
1196
|
-
node.
|
|
1197
|
-
node.value.left.type === 'Identifier' &&
|
|
1038
|
+
node.kind === 'init' &&
|
|
1198
1039
|
node.key.type === 'Identifier' &&
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
return value;
|
|
1202
|
-
}
|
|
1040
|
+
value.type === 'Identifier' &&
|
|
1041
|
+
node.key.name === value.name;
|
|
1203
1042
|
|
|
1204
|
-
if (
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
((node.key.type === 'Identifier' && node.key.name === value[0].content) ||
|
|
1208
|
-
(node.key.type === 'Literal' && node.key.value === value[0].content))
|
|
1209
|
-
) {
|
|
1210
|
-
return value;
|
|
1043
|
+
if (shorthand) {
|
|
1044
|
+
handle(node.value, state);
|
|
1045
|
+
return;
|
|
1211
1046
|
}
|
|
1212
1047
|
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
if (node.value.async) {
|
|
1219
|
-
chunks.push(c('async '));
|
|
1220
|
-
}
|
|
1221
|
-
if (node.value.generator) {
|
|
1222
|
-
chunks.push(c('*'));
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
push_array(chunks, node.computed ? [c('['), ...key, c(']')] : key);
|
|
1226
|
-
chunks.push(c('('));
|
|
1227
|
-
push_array(
|
|
1228
|
-
chunks,
|
|
1229
|
-
join(
|
|
1230
|
-
node.value.params.map((param) => handle(param, state)),
|
|
1231
|
-
c(', ')
|
|
1232
|
-
)
|
|
1233
|
-
);
|
|
1234
|
-
chunks.push(c(') '));
|
|
1235
|
-
push_array(chunks, handle(node.value.body, state));
|
|
1236
|
-
|
|
1237
|
-
return chunks;
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
if (node.computed) {
|
|
1241
|
-
return [c('['), ...key, c(']: '), ...value];
|
|
1242
|
-
}
|
|
1243
|
-
|
|
1244
|
-
return [...key, c(': '), ...value];
|
|
1048
|
+
if (node.computed) state.commands.push('[');
|
|
1049
|
+
handle(node.key, state);
|
|
1050
|
+
state.commands.push(node.computed ? ']: ' : ': ');
|
|
1051
|
+
handle(node.value, state);
|
|
1245
1052
|
},
|
|
1246
1053
|
|
|
1247
1054
|
PropertyDefinition(node, state) {
|
|
1248
|
-
const chunks = [];
|
|
1249
|
-
|
|
1250
1055
|
if (node.static) {
|
|
1251
|
-
|
|
1056
|
+
state.commands.push('static ');
|
|
1252
1057
|
}
|
|
1253
1058
|
|
|
1254
1059
|
if (node.computed) {
|
|
1255
|
-
|
|
1060
|
+
state.commands.push('[');
|
|
1061
|
+
handle(node.key, state);
|
|
1062
|
+
state.commands.push(']');
|
|
1256
1063
|
} else {
|
|
1257
|
-
|
|
1064
|
+
handle(node.key, state);
|
|
1258
1065
|
}
|
|
1259
1066
|
|
|
1260
1067
|
if (node.value) {
|
|
1261
|
-
|
|
1068
|
+
state.commands.push(' = ');
|
|
1262
1069
|
|
|
1263
|
-
|
|
1070
|
+
handle(node.value, state);
|
|
1264
1071
|
}
|
|
1265
1072
|
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
return chunks;
|
|
1073
|
+
state.commands.push(';');
|
|
1269
1074
|
},
|
|
1270
1075
|
|
|
1271
1076
|
RestElement: shared['RestElement|SpreadElement'],
|
|
@@ -1274,163 +1079,186 @@ const handlers = {
|
|
|
1274
1079
|
if (node.argument) {
|
|
1275
1080
|
const contains_comment =
|
|
1276
1081
|
node.argument.leadingComments &&
|
|
1277
|
-
node.argument.leadingComments.some(
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
...handle(node.argument, state),
|
|
1283
|
-
c(contains_comment ? ');' : ';')
|
|
1284
|
-
];
|
|
1082
|
+
node.argument.leadingComments.some((comment) => comment.type === 'Line');
|
|
1083
|
+
|
|
1084
|
+
state.commands.push(contains_comment ? 'return (' : 'return ');
|
|
1085
|
+
handle(node.argument, state);
|
|
1086
|
+
state.commands.push(contains_comment ? ');' : ';');
|
|
1285
1087
|
} else {
|
|
1286
|
-
|
|
1088
|
+
state.commands.push('return;');
|
|
1287
1089
|
}
|
|
1288
1090
|
},
|
|
1289
1091
|
|
|
1290
1092
|
SequenceExpression(node, state) {
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1093
|
+
state.commands.push('(');
|
|
1094
|
+
sequence(node.expressions, state, false, handle);
|
|
1095
|
+
state.commands.push(')');
|
|
1294
1096
|
},
|
|
1295
1097
|
|
|
1296
1098
|
SpreadElement: shared['RestElement|SpreadElement'],
|
|
1297
1099
|
|
|
1298
1100
|
StaticBlock(node, state) {
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
];
|
|
1101
|
+
state.commands.push(indent, 'static {', newline);
|
|
1102
|
+
|
|
1103
|
+
handle_body(node.body, state);
|
|
1104
|
+
|
|
1105
|
+
state.commands.push(dedent, newline, '}');
|
|
1305
1106
|
},
|
|
1306
1107
|
|
|
1307
1108
|
Super(node, state) {
|
|
1308
|
-
|
|
1109
|
+
state.commands.push(c('super', node));
|
|
1309
1110
|
},
|
|
1310
1111
|
|
|
1311
1112
|
SwitchStatement(node, state) {
|
|
1312
|
-
|
|
1113
|
+
state.commands.push('switch (');
|
|
1114
|
+
handle(node.discriminant, state);
|
|
1115
|
+
state.commands.push(') {', indent);
|
|
1116
|
+
|
|
1117
|
+
let first = true;
|
|
1118
|
+
|
|
1119
|
+
for (const block of node.cases) {
|
|
1120
|
+
if (!first) state.commands.push('\n');
|
|
1121
|
+
first = false;
|
|
1313
1122
|
|
|
1314
|
-
node.cases.forEach((block) => {
|
|
1315
1123
|
if (block.test) {
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1124
|
+
state.commands.push(newline, `case `);
|
|
1125
|
+
handle(block.test, state);
|
|
1126
|
+
state.commands.push(':');
|
|
1319
1127
|
} else {
|
|
1320
|
-
|
|
1128
|
+
state.commands.push(newline, `default:`);
|
|
1321
1129
|
}
|
|
1322
1130
|
|
|
1323
|
-
|
|
1324
|
-
chunks.push(c(`\n${state.indent}\t\t`));
|
|
1325
|
-
push_array(chunks, handle(statement, { ...state, indent: `${state.indent}\t\t` }));
|
|
1326
|
-
});
|
|
1327
|
-
});
|
|
1131
|
+
state.commands.push(indent);
|
|
1328
1132
|
|
|
1329
|
-
|
|
1133
|
+
for (const statement of block.consequent) {
|
|
1134
|
+
state.commands.push(newline);
|
|
1135
|
+
handle(statement, state);
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
state.commands.push(dedent);
|
|
1139
|
+
}
|
|
1330
1140
|
|
|
1331
|
-
|
|
1141
|
+
state.commands.push(dedent, newline, `}`);
|
|
1332
1142
|
},
|
|
1333
1143
|
|
|
1334
1144
|
TaggedTemplateExpression(node, state) {
|
|
1335
|
-
|
|
1145
|
+
handle(node.tag, state);
|
|
1146
|
+
handle(node.quasi, state);
|
|
1336
1147
|
},
|
|
1337
1148
|
|
|
1338
1149
|
TemplateLiteral(node, state) {
|
|
1339
|
-
|
|
1150
|
+
state.commands.push('`');
|
|
1340
1151
|
|
|
1341
1152
|
const { quasis, expressions } = node;
|
|
1342
1153
|
|
|
1343
1154
|
for (let i = 0; i < expressions.length; i++) {
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1155
|
+
const raw = quasis[i].value.raw;
|
|
1156
|
+
|
|
1157
|
+
state.commands.push(raw, '${');
|
|
1158
|
+
handle(expressions[i], state);
|
|
1159
|
+
state.commands.push('}');
|
|
1160
|
+
|
|
1161
|
+
if (/\n/.test(raw)) state.multiline = true;
|
|
1347
1162
|
}
|
|
1348
1163
|
|
|
1349
|
-
|
|
1164
|
+
const raw = quasis[quasis.length - 1].value.raw;
|
|
1350
1165
|
|
|
1351
|
-
|
|
1166
|
+
state.commands.push(raw, '`');
|
|
1167
|
+
if (/\n/.test(raw)) state.multiline = true;
|
|
1352
1168
|
},
|
|
1353
1169
|
|
|
1354
1170
|
ThisExpression(node, state) {
|
|
1355
|
-
|
|
1171
|
+
state.commands.push(c('this', node));
|
|
1356
1172
|
},
|
|
1357
1173
|
|
|
1358
1174
|
ThrowStatement(node, state) {
|
|
1359
|
-
|
|
1175
|
+
state.commands.push('throw ');
|
|
1176
|
+
handle(node.argument, state);
|
|
1177
|
+
state.commands.push(';');
|
|
1360
1178
|
},
|
|
1361
1179
|
|
|
1362
1180
|
TryStatement(node, state) {
|
|
1363
|
-
|
|
1181
|
+
state.commands.push('try ');
|
|
1182
|
+
handle(node.block, state);
|
|
1364
1183
|
|
|
1365
1184
|
if (node.handler) {
|
|
1366
1185
|
if (node.handler.param) {
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1186
|
+
state.commands.push(' catch(');
|
|
1187
|
+
handle(node.handler.param, state);
|
|
1188
|
+
state.commands.push(') ');
|
|
1370
1189
|
} else {
|
|
1371
|
-
|
|
1190
|
+
state.commands.push(' catch ');
|
|
1372
1191
|
}
|
|
1373
1192
|
|
|
1374
|
-
|
|
1193
|
+
handle(node.handler.body, state);
|
|
1375
1194
|
}
|
|
1376
1195
|
|
|
1377
1196
|
if (node.finalizer) {
|
|
1378
|
-
|
|
1379
|
-
|
|
1197
|
+
state.commands.push(' finally ');
|
|
1198
|
+
handle(node.finalizer, state);
|
|
1380
1199
|
}
|
|
1381
|
-
|
|
1382
|
-
return chunks;
|
|
1383
1200
|
},
|
|
1384
1201
|
|
|
1385
1202
|
UnaryExpression(node, state) {
|
|
1386
|
-
|
|
1203
|
+
state.commands.push(node.operator);
|
|
1387
1204
|
|
|
1388
1205
|
if (node.operator.length > 1) {
|
|
1389
|
-
|
|
1206
|
+
state.commands.push(' ');
|
|
1390
1207
|
}
|
|
1391
1208
|
|
|
1392
1209
|
if (EXPRESSIONS_PRECEDENCE[node.argument.type] < EXPRESSIONS_PRECEDENCE.UnaryExpression) {
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1210
|
+
state.commands.push('(');
|
|
1211
|
+
handle(node.argument, state);
|
|
1212
|
+
state.commands.push(')');
|
|
1396
1213
|
} else {
|
|
1397
|
-
|
|
1214
|
+
handle(node.argument, state);
|
|
1398
1215
|
}
|
|
1399
|
-
|
|
1400
|
-
return chunks;
|
|
1401
1216
|
},
|
|
1402
1217
|
|
|
1403
1218
|
UpdateExpression(node, state) {
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1219
|
+
if (node.prefix) {
|
|
1220
|
+
state.commands.push(node.operator);
|
|
1221
|
+
handle(node.argument, state);
|
|
1222
|
+
} else {
|
|
1223
|
+
handle(node.argument, state);
|
|
1224
|
+
state.commands.push(node.operator);
|
|
1225
|
+
}
|
|
1407
1226
|
},
|
|
1408
1227
|
|
|
1409
1228
|
VariableDeclaration(node, state) {
|
|
1410
|
-
|
|
1229
|
+
handle_var_declaration(node, state);
|
|
1230
|
+
state.commands.push(';');
|
|
1411
1231
|
},
|
|
1412
1232
|
|
|
1413
1233
|
VariableDeclarator(node, state) {
|
|
1234
|
+
handle(node.id, state);
|
|
1235
|
+
|
|
1414
1236
|
if (node.init) {
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
return handle(node.id, state);
|
|
1237
|
+
state.commands.push(' = ');
|
|
1238
|
+
handle(node.init, state);
|
|
1418
1239
|
}
|
|
1419
1240
|
},
|
|
1420
1241
|
|
|
1421
1242
|
WhileStatement(node, state) {
|
|
1422
|
-
|
|
1243
|
+
state.commands.push('while (');
|
|
1244
|
+
handle(node.test, state);
|
|
1245
|
+
state.commands.push(') ');
|
|
1246
|
+
handle(node.body, state);
|
|
1423
1247
|
},
|
|
1424
1248
|
|
|
1425
1249
|
WithStatement(node, state) {
|
|
1426
|
-
|
|
1250
|
+
state.commands.push('with (');
|
|
1251
|
+
handle(node.object, state);
|
|
1252
|
+
state.commands.push(') ');
|
|
1253
|
+
handle(node.body, state);
|
|
1427
1254
|
},
|
|
1428
1255
|
|
|
1429
1256
|
YieldExpression(node, state) {
|
|
1430
1257
|
if (node.argument) {
|
|
1431
|
-
|
|
1258
|
+
state.commands.push(node.delegate ? `yield* ` : `yield `);
|
|
1259
|
+
handle(node.argument, state);
|
|
1260
|
+
} else {
|
|
1261
|
+
state.commands.push(node.delegate ? `yield*` : `yield`);
|
|
1432
1262
|
}
|
|
1433
|
-
|
|
1434
|
-
return [c(node.delegate ? `yield*` : `yield`)];
|
|
1435
1263
|
}
|
|
1436
1264
|
};
|