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