esrap 1.1.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +3 -2
- package/src/handlers.js +621 -794
- 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,195 @@ 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
|
-
|
|
935
|
-
|
|
936
|
-
return [name, c(' as '), as];
|
|
937
|
-
});
|
|
874
|
+
if (default_specifier) {
|
|
875
|
+
state.commands.push(c(default_specifier.local.name, default_specifier));
|
|
876
|
+
if (namespace_specifier || named_specifiers.length > 0) state.commands.push(', ');
|
|
877
|
+
}
|
|
938
878
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
2 * specifiers.length +
|
|
943
|
-
6 +
|
|
944
|
-
get_length(source);
|
|
879
|
+
if (namespace_specifier) {
|
|
880
|
+
state.commands.push(c('* as ' + namespace_specifier.local.name, namespace_specifier));
|
|
881
|
+
}
|
|
945
882
|
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
push_array(chunks, join(specifiers, c(', ')));
|
|
953
|
-
chunks.push(c(' }'));
|
|
883
|
+
if (named_specifiers.length > 0) {
|
|
884
|
+
state.commands.push('{');
|
|
885
|
+
sequence(named_specifiers, state, true, (s, state) => {
|
|
886
|
+
if (s.local.name !== s.imported.name) {
|
|
887
|
+
handle(s.imported, state);
|
|
888
|
+
state.commands.push(' as ');
|
|
954
889
|
}
|
|
955
|
-
}
|
|
956
890
|
|
|
957
|
-
|
|
891
|
+
handle(s.local, state);
|
|
892
|
+
});
|
|
893
|
+
state.commands.push('}');
|
|
958
894
|
}
|
|
959
895
|
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
return chunks;
|
|
896
|
+
state.commands.push(' from ');
|
|
897
|
+
handle(node.source, state);
|
|
898
|
+
state.commands.push(';');
|
|
964
899
|
},
|
|
965
900
|
|
|
966
901
|
ImportExpression(node, state) {
|
|
967
|
-
|
|
902
|
+
state.commands.push('import(');
|
|
903
|
+
handle(node.source, state);
|
|
904
|
+
state.commands.push(')');
|
|
968
905
|
},
|
|
969
906
|
|
|
970
907
|
LabeledStatement(node, state) {
|
|
971
|
-
|
|
908
|
+
handle(node.label, state);
|
|
909
|
+
state.commands.push(': ');
|
|
910
|
+
handle(node.body, state);
|
|
972
911
|
},
|
|
973
912
|
|
|
974
913
|
Literal(node, state) {
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
];
|
|
981
|
-
}
|
|
914
|
+
// TODO do we need to handle weird unicode characters somehow?
|
|
915
|
+
// str.replace(/\\u(\d{4})/g, (m, n) => String.fromCharCode(+n))
|
|
916
|
+
const value =
|
|
917
|
+
node.raw ??
|
|
918
|
+
(typeof node.value === 'string' ? JSON.stringify(node.value) : String(node.value));
|
|
982
919
|
|
|
983
|
-
|
|
920
|
+
state.commands.push(c(value, node));
|
|
984
921
|
},
|
|
985
922
|
|
|
986
923
|
LogicalExpression: shared['BinaryExpression|LogicalExpression'],
|
|
987
924
|
|
|
988
925
|
MemberExpression(node, state) {
|
|
989
|
-
/**
|
|
990
|
-
* @type any[]
|
|
991
|
-
*/
|
|
992
|
-
const chunks = [];
|
|
993
|
-
|
|
994
926
|
if (EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression) {
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
927
|
+
state.commands.push('(');
|
|
928
|
+
handle(node.object, state);
|
|
929
|
+
state.commands.push(')');
|
|
998
930
|
} else {
|
|
999
|
-
|
|
931
|
+
handle(node.object, state);
|
|
1000
932
|
}
|
|
1001
933
|
|
|
1002
934
|
if (node.computed) {
|
|
1003
935
|
if (node.optional) {
|
|
1004
|
-
|
|
936
|
+
state.commands.push('?.');
|
|
1005
937
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
938
|
+
state.commands.push('[');
|
|
939
|
+
handle(node.property, state);
|
|
940
|
+
state.commands.push(']');
|
|
1009
941
|
} else {
|
|
1010
|
-
|
|
1011
|
-
|
|
942
|
+
state.commands.push(node.optional ? '?.' : '.');
|
|
943
|
+
handle(node.property, state);
|
|
1012
944
|
}
|
|
1013
|
-
|
|
1014
|
-
return chunks;
|
|
1015
945
|
},
|
|
1016
946
|
|
|
1017
947
|
MetaProperty(node, state) {
|
|
1018
|
-
|
|
948
|
+
handle(node.meta, state);
|
|
949
|
+
state.commands.push('.');
|
|
950
|
+
handle(node.property, state);
|
|
1019
951
|
},
|
|
1020
952
|
|
|
1021
953
|
MethodDefinition(node, state) {
|
|
1022
|
-
const chunks = [];
|
|
1023
|
-
|
|
1024
954
|
if (node.static) {
|
|
1025
|
-
|
|
955
|
+
state.commands.push('static ');
|
|
1026
956
|
}
|
|
1027
957
|
|
|
1028
958
|
if (node.kind === 'get' || node.kind === 'set') {
|
|
1029
959
|
// Getter or setter
|
|
1030
|
-
|
|
960
|
+
state.commands.push(node.kind + ' ');
|
|
1031
961
|
}
|
|
1032
962
|
|
|
1033
963
|
if (node.value.async) {
|
|
1034
|
-
|
|
964
|
+
state.commands.push('async ');
|
|
1035
965
|
}
|
|
1036
966
|
|
|
1037
967
|
if (node.value.generator) {
|
|
1038
|
-
|
|
968
|
+
state.commands.push('*');
|
|
1039
969
|
}
|
|
1040
970
|
|
|
1041
|
-
if (node.computed)
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
chunks.push(c(']'));
|
|
1045
|
-
} else {
|
|
1046
|
-
push_array(chunks, handle(node.key, state));
|
|
1047
|
-
}
|
|
971
|
+
if (node.computed) state.commands.push('[');
|
|
972
|
+
handle(node.key, state);
|
|
973
|
+
if (node.computed) state.commands.push(']');
|
|
1048
974
|
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
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
|
-
}
|
|
975
|
+
state.commands.push('(');
|
|
976
|
+
sequence(node.value.params, state, false, handle);
|
|
977
|
+
state.commands.push(') ');
|
|
1056
978
|
|
|
1057
|
-
|
|
1058
|
-
push_array(chunks, handle(node.value.body, state));
|
|
1059
|
-
|
|
1060
|
-
return chunks;
|
|
979
|
+
handle(node.value.body, state);
|
|
1061
980
|
},
|
|
1062
981
|
|
|
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
|
-
},
|
|
982
|
+
NewExpression: shared['CallExpression|NewExpression'],
|
|
1095
983
|
|
|
1096
984
|
ObjectExpression(node, state) {
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
let has_inline_comment = false;
|
|
985
|
+
state.commands.push('{');
|
|
986
|
+
sequence(node.properties, state, true, (p, state) => {
|
|
987
|
+
if (p.type === 'Property' && p.value.type === 'FunctionExpression') {
|
|
988
|
+
const fn = /** @type {import('estree').FunctionExpression} */ (p.value);
|
|
1102
989
|
|
|
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(', '));
|
|
990
|
+
if (p.kind === 'get' || p.kind === 'set') {
|
|
991
|
+
state.commands.push(p.kind + ' ');
|
|
992
|
+
} else {
|
|
993
|
+
if (fn.async) state.commands.push('async ');
|
|
994
|
+
if (fn.generator) state.commands.push('*');
|
|
995
|
+
}
|
|
1120
996
|
|
|
1121
|
-
|
|
1122
|
-
|
|
997
|
+
if (p.computed) state.commands.push('[');
|
|
998
|
+
handle(p.key, state);
|
|
999
|
+
if (p.computed) state.commands.push(']');
|
|
1123
1000
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
? `/*${comment.value}*/\n${state.indent}\t`
|
|
1128
|
-
: `//${comment.value}\n${state.indent}\t`
|
|
1129
|
-
)
|
|
1130
|
-
);
|
|
1001
|
+
state.commands.push('(');
|
|
1002
|
+
sequence(fn.params, state, false, handle);
|
|
1003
|
+
state.commands.push(') ');
|
|
1131
1004
|
|
|
1132
|
-
|
|
1133
|
-
has_inline_comment = true;
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1005
|
+
handle(fn.body, state);
|
|
1136
1006
|
} else {
|
|
1137
|
-
|
|
1138
|
-
chunks.push(separator);
|
|
1139
|
-
}
|
|
1007
|
+
handle(p, state);
|
|
1140
1008
|
}
|
|
1141
1009
|
});
|
|
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
|
-
];
|
|
1010
|
+
state.commands.push('}');
|
|
1154
1011
|
},
|
|
1155
1012
|
|
|
1156
1013
|
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;
|
|
1014
|
+
state.commands.push('{');
|
|
1015
|
+
sequence(node.properties, state, true, handle);
|
|
1016
|
+
state.commands.push('}');
|
|
1167
1017
|
},
|
|
1168
1018
|
|
|
1169
1019
|
// @ts-expect-error this isn't a real node type, but Acorn produces it
|
|
@@ -1172,100 +1022,54 @@ const handlers = {
|
|
|
1172
1022
|
},
|
|
1173
1023
|
|
|
1174
1024
|
PrivateIdentifier(node, state) {
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
push_array(chunks, [c(node.name, node)]);
|
|
1178
|
-
|
|
1179
|
-
return chunks;
|
|
1025
|
+
state.commands.push('#', c(node.name, node));
|
|
1180
1026
|
},
|
|
1181
1027
|
|
|
1182
1028
|
Program(node, state) {
|
|
1183
|
-
|
|
1029
|
+
handle_body(node.body, state);
|
|
1184
1030
|
},
|
|
1185
1031
|
|
|
1186
1032
|
Property(node, state) {
|
|
1187
|
-
const value =
|
|
1033
|
+
const value = node.value.type === 'AssignmentPattern' ? node.value.left : node.value;
|
|
1188
1034
|
|
|
1189
|
-
|
|
1190
|
-
return value;
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
// special case
|
|
1194
|
-
if (
|
|
1035
|
+
const shorthand =
|
|
1195
1036
|
!node.computed &&
|
|
1196
|
-
node.
|
|
1197
|
-
node.value.left.type === 'Identifier' &&
|
|
1037
|
+
node.kind === 'init' &&
|
|
1198
1038
|
node.key.type === 'Identifier' &&
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
return value;
|
|
1202
|
-
}
|
|
1039
|
+
value.type === 'Identifier' &&
|
|
1040
|
+
node.key.name === value.name;
|
|
1203
1041
|
|
|
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;
|
|
1042
|
+
if (shorthand) {
|
|
1043
|
+
handle(node.value, state);
|
|
1044
|
+
return;
|
|
1211
1045
|
}
|
|
1212
1046
|
|
|
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];
|
|
1047
|
+
if (node.computed) state.commands.push('[');
|
|
1048
|
+
handle(node.key, state);
|
|
1049
|
+
state.commands.push(node.computed ? ']: ' : ': ');
|
|
1050
|
+
handle(node.value, state);
|
|
1245
1051
|
},
|
|
1246
1052
|
|
|
1247
1053
|
PropertyDefinition(node, state) {
|
|
1248
|
-
const chunks = [];
|
|
1249
|
-
|
|
1250
1054
|
if (node.static) {
|
|
1251
|
-
|
|
1055
|
+
state.commands.push('static ');
|
|
1252
1056
|
}
|
|
1253
1057
|
|
|
1254
1058
|
if (node.computed) {
|
|
1255
|
-
|
|
1059
|
+
state.commands.push('[');
|
|
1060
|
+
handle(node.key, state);
|
|
1061
|
+
state.commands.push(']');
|
|
1256
1062
|
} else {
|
|
1257
|
-
|
|
1063
|
+
handle(node.key, state);
|
|
1258
1064
|
}
|
|
1259
1065
|
|
|
1260
1066
|
if (node.value) {
|
|
1261
|
-
|
|
1067
|
+
state.commands.push(' = ');
|
|
1262
1068
|
|
|
1263
|
-
|
|
1069
|
+
handle(node.value, state);
|
|
1264
1070
|
}
|
|
1265
1071
|
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
return chunks;
|
|
1072
|
+
state.commands.push(';');
|
|
1269
1073
|
},
|
|
1270
1074
|
|
|
1271
1075
|
RestElement: shared['RestElement|SpreadElement'],
|
|
@@ -1274,163 +1078,186 @@ const handlers = {
|
|
|
1274
1078
|
if (node.argument) {
|
|
1275
1079
|
const contains_comment =
|
|
1276
1080
|
node.argument.leadingComments &&
|
|
1277
|
-
node.argument.leadingComments.some(
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
...handle(node.argument, state),
|
|
1283
|
-
c(contains_comment ? ');' : ';')
|
|
1284
|
-
];
|
|
1081
|
+
node.argument.leadingComments.some((comment) => comment.type === 'Line');
|
|
1082
|
+
|
|
1083
|
+
state.commands.push(contains_comment ? 'return (' : 'return ');
|
|
1084
|
+
handle(node.argument, state);
|
|
1085
|
+
state.commands.push(contains_comment ? ');' : ';');
|
|
1285
1086
|
} else {
|
|
1286
|
-
|
|
1087
|
+
state.commands.push('return;');
|
|
1287
1088
|
}
|
|
1288
1089
|
},
|
|
1289
1090
|
|
|
1290
1091
|
SequenceExpression(node, state) {
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1092
|
+
state.commands.push('(');
|
|
1093
|
+
sequence(node.expressions, state, false, handle);
|
|
1094
|
+
state.commands.push(')');
|
|
1294
1095
|
},
|
|
1295
1096
|
|
|
1296
1097
|
SpreadElement: shared['RestElement|SpreadElement'],
|
|
1297
1098
|
|
|
1298
1099
|
StaticBlock(node, state) {
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
];
|
|
1100
|
+
state.commands.push(indent, 'static {', newline);
|
|
1101
|
+
|
|
1102
|
+
handle_body(node.body, state);
|
|
1103
|
+
|
|
1104
|
+
state.commands.push(dedent, newline, '}');
|
|
1305
1105
|
},
|
|
1306
1106
|
|
|
1307
1107
|
Super(node, state) {
|
|
1308
|
-
|
|
1108
|
+
state.commands.push(c('super', node));
|
|
1309
1109
|
},
|
|
1310
1110
|
|
|
1311
1111
|
SwitchStatement(node, state) {
|
|
1312
|
-
|
|
1112
|
+
state.commands.push('switch (');
|
|
1113
|
+
handle(node.discriminant, state);
|
|
1114
|
+
state.commands.push(') {', indent);
|
|
1115
|
+
|
|
1116
|
+
let first = true;
|
|
1117
|
+
|
|
1118
|
+
for (const block of node.cases) {
|
|
1119
|
+
if (!first) state.commands.push('\n');
|
|
1120
|
+
first = false;
|
|
1313
1121
|
|
|
1314
|
-
node.cases.forEach((block) => {
|
|
1315
1122
|
if (block.test) {
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1123
|
+
state.commands.push(newline, `case `);
|
|
1124
|
+
handle(block.test, state);
|
|
1125
|
+
state.commands.push(':');
|
|
1319
1126
|
} else {
|
|
1320
|
-
|
|
1127
|
+
state.commands.push(newline, `default:`);
|
|
1321
1128
|
}
|
|
1322
1129
|
|
|
1323
|
-
|
|
1324
|
-
chunks.push(c(`\n${state.indent}\t\t`));
|
|
1325
|
-
push_array(chunks, handle(statement, { ...state, indent: `${state.indent}\t\t` }));
|
|
1326
|
-
});
|
|
1327
|
-
});
|
|
1130
|
+
state.commands.push(indent);
|
|
1328
1131
|
|
|
1329
|
-
|
|
1132
|
+
for (const statement of block.consequent) {
|
|
1133
|
+
state.commands.push(newline);
|
|
1134
|
+
handle(statement, state);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
state.commands.push(dedent);
|
|
1138
|
+
}
|
|
1330
1139
|
|
|
1331
|
-
|
|
1140
|
+
state.commands.push(dedent, newline, `}`);
|
|
1332
1141
|
},
|
|
1333
1142
|
|
|
1334
1143
|
TaggedTemplateExpression(node, state) {
|
|
1335
|
-
|
|
1144
|
+
handle(node.tag, state);
|
|
1145
|
+
handle(node.quasi, state);
|
|
1336
1146
|
},
|
|
1337
1147
|
|
|
1338
1148
|
TemplateLiteral(node, state) {
|
|
1339
|
-
|
|
1149
|
+
state.commands.push('`');
|
|
1340
1150
|
|
|
1341
1151
|
const { quasis, expressions } = node;
|
|
1342
1152
|
|
|
1343
1153
|
for (let i = 0; i < expressions.length; i++) {
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1154
|
+
const raw = quasis[i].value.raw;
|
|
1155
|
+
|
|
1156
|
+
state.commands.push(raw, '${');
|
|
1157
|
+
handle(expressions[i], state);
|
|
1158
|
+
state.commands.push('}');
|
|
1159
|
+
|
|
1160
|
+
if (/\n/.test(raw)) state.multiline = true;
|
|
1347
1161
|
}
|
|
1348
1162
|
|
|
1349
|
-
|
|
1163
|
+
const raw = quasis[quasis.length - 1].value.raw;
|
|
1350
1164
|
|
|
1351
|
-
|
|
1165
|
+
state.commands.push(raw, '`');
|
|
1166
|
+
if (/\n/.test(raw)) state.multiline = true;
|
|
1352
1167
|
},
|
|
1353
1168
|
|
|
1354
1169
|
ThisExpression(node, state) {
|
|
1355
|
-
|
|
1170
|
+
state.commands.push(c('this', node));
|
|
1356
1171
|
},
|
|
1357
1172
|
|
|
1358
1173
|
ThrowStatement(node, state) {
|
|
1359
|
-
|
|
1174
|
+
state.commands.push('throw ');
|
|
1175
|
+
handle(node.argument, state);
|
|
1176
|
+
state.commands.push(';');
|
|
1360
1177
|
},
|
|
1361
1178
|
|
|
1362
1179
|
TryStatement(node, state) {
|
|
1363
|
-
|
|
1180
|
+
state.commands.push('try ');
|
|
1181
|
+
handle(node.block, state);
|
|
1364
1182
|
|
|
1365
1183
|
if (node.handler) {
|
|
1366
1184
|
if (node.handler.param) {
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1185
|
+
state.commands.push(' catch(');
|
|
1186
|
+
handle(node.handler.param, state);
|
|
1187
|
+
state.commands.push(') ');
|
|
1370
1188
|
} else {
|
|
1371
|
-
|
|
1189
|
+
state.commands.push(' catch ');
|
|
1372
1190
|
}
|
|
1373
1191
|
|
|
1374
|
-
|
|
1192
|
+
handle(node.handler.body, state);
|
|
1375
1193
|
}
|
|
1376
1194
|
|
|
1377
1195
|
if (node.finalizer) {
|
|
1378
|
-
|
|
1379
|
-
|
|
1196
|
+
state.commands.push(' finally ');
|
|
1197
|
+
handle(node.finalizer, state);
|
|
1380
1198
|
}
|
|
1381
|
-
|
|
1382
|
-
return chunks;
|
|
1383
1199
|
},
|
|
1384
1200
|
|
|
1385
1201
|
UnaryExpression(node, state) {
|
|
1386
|
-
|
|
1202
|
+
state.commands.push(node.operator);
|
|
1387
1203
|
|
|
1388
1204
|
if (node.operator.length > 1) {
|
|
1389
|
-
|
|
1205
|
+
state.commands.push(' ');
|
|
1390
1206
|
}
|
|
1391
1207
|
|
|
1392
1208
|
if (EXPRESSIONS_PRECEDENCE[node.argument.type] < EXPRESSIONS_PRECEDENCE.UnaryExpression) {
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1209
|
+
state.commands.push('(');
|
|
1210
|
+
handle(node.argument, state);
|
|
1211
|
+
state.commands.push(')');
|
|
1396
1212
|
} else {
|
|
1397
|
-
|
|
1213
|
+
handle(node.argument, state);
|
|
1398
1214
|
}
|
|
1399
|
-
|
|
1400
|
-
return chunks;
|
|
1401
1215
|
},
|
|
1402
1216
|
|
|
1403
1217
|
UpdateExpression(node, state) {
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1218
|
+
if (node.prefix) {
|
|
1219
|
+
state.commands.push(node.operator);
|
|
1220
|
+
handle(node.argument, state);
|
|
1221
|
+
} else {
|
|
1222
|
+
handle(node.argument, state);
|
|
1223
|
+
state.commands.push(node.operator);
|
|
1224
|
+
}
|
|
1407
1225
|
},
|
|
1408
1226
|
|
|
1409
1227
|
VariableDeclaration(node, state) {
|
|
1410
|
-
|
|
1228
|
+
handle_var_declaration(node, state);
|
|
1229
|
+
state.commands.push(';');
|
|
1411
1230
|
},
|
|
1412
1231
|
|
|
1413
1232
|
VariableDeclarator(node, state) {
|
|
1233
|
+
handle(node.id, state);
|
|
1234
|
+
|
|
1414
1235
|
if (node.init) {
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
return handle(node.id, state);
|
|
1236
|
+
state.commands.push(' = ');
|
|
1237
|
+
handle(node.init, state);
|
|
1418
1238
|
}
|
|
1419
1239
|
},
|
|
1420
1240
|
|
|
1421
1241
|
WhileStatement(node, state) {
|
|
1422
|
-
|
|
1242
|
+
state.commands.push('while (');
|
|
1243
|
+
handle(node.test, state);
|
|
1244
|
+
state.commands.push(') ');
|
|
1245
|
+
handle(node.body, state);
|
|
1423
1246
|
},
|
|
1424
1247
|
|
|
1425
1248
|
WithStatement(node, state) {
|
|
1426
|
-
|
|
1249
|
+
state.commands.push('with (');
|
|
1250
|
+
handle(node.object, state);
|
|
1251
|
+
state.commands.push(') ');
|
|
1252
|
+
handle(node.body, state);
|
|
1427
1253
|
},
|
|
1428
1254
|
|
|
1429
1255
|
YieldExpression(node, state) {
|
|
1430
1256
|
if (node.argument) {
|
|
1431
|
-
|
|
1257
|
+
state.commands.push(node.delegate ? `yield* ` : `yield `);
|
|
1258
|
+
handle(node.argument, state);
|
|
1259
|
+
} else {
|
|
1260
|
+
state.commands.push(node.delegate ? `yield*` : `yield`);
|
|
1432
1261
|
}
|
|
1433
|
-
|
|
1434
|
-
return [c(node.delegate ? `yield*` : `yield`)];
|
|
1435
1262
|
}
|
|
1436
1263
|
};
|