hermes-transform 0.11.1 → 0.12.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.
@@ -1,41 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- */
9
-
10
- 'use strict';
11
-
12
- const {isNonEmptyArray} = require('../common/util.js');
13
-
14
- /**
15
- * @typedef {import("./types/estree").Node} Node
16
- */
17
-
18
- function locStart(node, opts) {
19
- const {ignoreDecorators} = opts || {};
20
-
21
- // Handle nodes with decorators. They should start at the first decorator
22
- if (!ignoreDecorators) {
23
- const decorators =
24
- (node.declaration && node.declaration.decorators) || node.decorators;
25
-
26
- if (isNonEmptyArray(decorators)) {
27
- return locStart(decorators[0]);
28
- }
29
- }
30
-
31
- return node.range ? node.range[0] : node.start;
32
- }
33
-
34
- function locEnd(node) {
35
- return node.range ? node.range[1] : node.end;
36
- }
37
-
38
- module.exports = {
39
- locStart,
40
- locEnd,
41
- };
@@ -1,37 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- */
9
-
10
- 'use strict';
11
-
12
- const handleComments = require('./comments.js');
13
- const {isBlockComment, isLineComment} = require('./utils.js');
14
-
15
- function canAttachComment(node) {
16
- return (
17
- node.type &&
18
- !isBlockComment(node) &&
19
- !isLineComment(node) &&
20
- node.type !== 'EmptyStatement' &&
21
- node.type !== 'TemplateElement' &&
22
- node.type !== 'Import' &&
23
- // `babel-ts` don't have similar node for `class Foo { bar() /* bat */; }`
24
- node.type !== 'TSEmptyBodyFunctionExpression'
25
- );
26
- }
27
-
28
- module.exports = {
29
- canAttachComment,
30
- handleComments: {
31
- avoidAstMutation: true,
32
- ownLine: handleComments.handleOwnLineComment,
33
- endOfLine: handleComments.handleEndOfLineComment,
34
- remaining: handleComments.handleRemainingComment,
35
- },
36
- getCommentChildNodes: handleComments.getCommentChildNodes,
37
- };
@@ -1,135 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- */
9
-
10
- 'use strict';
11
-
12
- /**
13
- * @param {Comment} comment
14
- * @returns {boolean}
15
- */
16
- function isBlockComment(comment) {
17
- return (
18
- comment.type === 'Block' ||
19
- comment.type === 'CommentBlock' ||
20
- // `meriyah`
21
- comment.type === 'MultiLine'
22
- );
23
- }
24
-
25
- /**
26
- * @param {Comment} comment
27
- * @returns {boolean}
28
- */
29
- function isLineComment(comment) {
30
- return (
31
- comment.type === 'Line' ||
32
- comment.type === 'CommentLine' ||
33
- // `meriyah` has `SingleLine`, `HashbangComment`, `HTMLOpen`, and `HTMLClose`
34
- comment.type === 'SingleLine' ||
35
- comment.type === 'HashbangComment' ||
36
- comment.type === 'HTMLOpen' ||
37
- comment.type === 'HTMLClose'
38
- );
39
- }
40
-
41
- /**
42
- * @param {Node} node
43
- * @returns {boolean}
44
- */
45
- function isCallExpression(node) {
46
- return (
47
- node &&
48
- (node.type === 'CallExpression' || node.type === 'OptionalCallExpression')
49
- );
50
- }
51
-
52
- /**
53
- * @param {Node} node
54
- * @returns {boolean}
55
- */
56
- function isMemberExpression(node) {
57
- return (
58
- node &&
59
- (node.type === 'MemberExpression' ||
60
- node.type === 'OptionalMemberExpression')
61
- );
62
- }
63
-
64
- const functionParametersCache = new WeakMap();
65
- function getFunctionParameters(node) {
66
- if (functionParametersCache.has(node)) {
67
- return functionParametersCache.get(node);
68
- }
69
- const parameters = [];
70
- if (node.this) {
71
- parameters.push(node.this);
72
- }
73
- // `params` vs `parameters` - see https://github.com/babel/babel/issues/9231
74
- if (Array.isArray(node.parameters)) {
75
- parameters.push(...node.parameters);
76
- } else if (Array.isArray(node.params)) {
77
- parameters.push(...node.params);
78
- }
79
- if (node.rest) {
80
- parameters.push(node.rest);
81
- }
82
- functionParametersCache.set(node, parameters);
83
- return parameters;
84
- }
85
-
86
- const callArgumentsCache = new WeakMap();
87
- function getCallArguments(node) {
88
- if (callArgumentsCache.has(node)) {
89
- return callArgumentsCache.get(node);
90
- }
91
-
92
- let args = node.arguments;
93
- if (node.type === 'ImportExpression') {
94
- args = [node.source];
95
-
96
- if (node.attributes) {
97
- args.push(node.attributes);
98
- }
99
- }
100
-
101
- callArgumentsCache.set(node, args);
102
- return args;
103
- }
104
-
105
- function isPrettierIgnoreComment(comment) {
106
- return comment.value.trim() === 'prettier-ignore' && !comment.unignore;
107
- }
108
-
109
- function isCallLikeExpression(node) {
110
- return (
111
- isCallExpression(node) ||
112
- node.type === 'NewExpression' ||
113
- node.type === 'ImportExpression'
114
- );
115
- }
116
-
117
- function isObjectProperty(node) {
118
- return (
119
- node &&
120
- (node.type === 'ObjectProperty' ||
121
- (node.type === 'Property' && !node.method && node.kind === 'init'))
122
- );
123
- }
124
-
125
- module.exports = {
126
- getFunctionParameters,
127
- getCallArguments,
128
- isBlockComment,
129
- isCallLikeExpression,
130
- isLineComment,
131
- isPrettierIgnoreComment,
132
- isCallExpression,
133
- isMemberExpression,
134
- isObjectProperty,
135
- };
@@ -1,437 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- */
9
-
10
- 'use strict';
11
-
12
- const assert = require('assert');
13
-
14
- const {
15
- hasNewline,
16
- addLeadingComment,
17
- addDanglingComment,
18
- addTrailingComment,
19
- } = require('../common/util.js');
20
-
21
- const childNodesCache = new WeakMap();
22
- function getSortedChildNodes(node, options, resultArray) {
23
- if (!node) {
24
- return;
25
- }
26
- const {printer, locStart, locEnd} = options;
27
-
28
- if (resultArray) {
29
- if (printer.canAttachComment && printer.canAttachComment(node)) {
30
- // This reverse insertion sort almost always takes constant
31
- // time because we almost always (maybe always?) append the
32
- // nodes in order anyway.
33
- let i;
34
- for (i = resultArray.length - 1; i >= 0; --i) {
35
- if (
36
- locStart(resultArray[i]) <= locStart(node) &&
37
- locEnd(resultArray[i]) <= locEnd(node)
38
- ) {
39
- break;
40
- }
41
- }
42
- resultArray.splice(i + 1, 0, node);
43
- return;
44
- }
45
- } else if (childNodesCache.has(node)) {
46
- return childNodesCache.get(node);
47
- }
48
-
49
- const childNodes =
50
- (printer.getCommentChildNodes &&
51
- printer.getCommentChildNodes(node, options)) ||
52
- (typeof node === 'object' &&
53
- Object.entries(node)
54
- .filter(
55
- ([key]) =>
56
- key !== 'enclosingNode' &&
57
- key !== 'precedingNode' &&
58
- key !== 'followingNode' &&
59
- key !== 'tokens' &&
60
- key !== 'comments' &&
61
- key !== 'parent',
62
- )
63
- .map(([, value]) => value));
64
-
65
- if (!childNodes) {
66
- return;
67
- }
68
-
69
- if (!resultArray) {
70
- resultArray = [];
71
- childNodesCache.set(node, resultArray);
72
- }
73
-
74
- for (const childNode of childNodes) {
75
- getSortedChildNodes(childNode, options, resultArray);
76
- }
77
-
78
- return resultArray;
79
- }
80
-
81
- // As efficiently as possible, decorate the comment object with
82
- // .precedingNode, .enclosingNode, and/or .followingNode properties, at
83
- // least one of which is guaranteed to be defined.
84
- function decorateComment(node, comment, options, enclosingNode) {
85
- const {locStart, locEnd} = options;
86
- const commentStart = locStart(comment);
87
- const commentEnd = locEnd(comment);
88
-
89
- const childNodes = getSortedChildNodes(node, options);
90
- let precedingNode;
91
- let followingNode;
92
- // Time to dust off the old binary search robes and wizard hat.
93
- let left = 0;
94
- let right = childNodes.length;
95
- while (left < right) {
96
- const middle = (left + right) >> 1;
97
- const child = childNodes[middle];
98
- const start = locStart(child);
99
- const end = locEnd(child);
100
-
101
- // The comment is completely contained by this child node.
102
- if (start <= commentStart && commentEnd <= end) {
103
- // Abandon the binary search at this level.
104
- return decorateComment(child, comment, options, child);
105
- }
106
-
107
- if (end <= commentStart) {
108
- // This child node falls completely before the comment.
109
- // Because we will never consider this node or any nodes
110
- // before it again, this node must be the closest preceding
111
- // node we have encountered so far.
112
- precedingNode = child;
113
- left = middle + 1;
114
- continue;
115
- }
116
-
117
- if (commentEnd <= start) {
118
- // This child node falls completely after the comment.
119
- // Because we will never consider this node or any nodes after
120
- // it again, this node must be the closest following node we
121
- // have encountered so far.
122
- followingNode = child;
123
- right = middle;
124
- continue;
125
- }
126
-
127
- /* istanbul ignore next */
128
- throw new Error('Comment location overlaps with node location');
129
- }
130
-
131
- // We don't want comments inside of different expressions inside of the same
132
- // template literal to move to another expression.
133
- if (enclosingNode && enclosingNode.type === 'TemplateLiteral') {
134
- const {quasis} = enclosingNode;
135
- const commentIndex = findExpressionIndexForComment(
136
- quasis,
137
- comment,
138
- options,
139
- );
140
-
141
- if (
142
- precedingNode &&
143
- findExpressionIndexForComment(quasis, precedingNode, options) !==
144
- commentIndex
145
- ) {
146
- precedingNode = null;
147
- }
148
- if (
149
- followingNode &&
150
- findExpressionIndexForComment(quasis, followingNode, options) !==
151
- commentIndex
152
- ) {
153
- followingNode = null;
154
- }
155
- }
156
-
157
- return {enclosingNode, precedingNode, followingNode};
158
- }
159
-
160
- const returnFalse = () => false;
161
- function attach(comments, ast, text, options) {
162
- if (!Array.isArray(comments)) {
163
- return;
164
- }
165
-
166
- const tiesToBreak = [];
167
- const {
168
- locStart,
169
- locEnd,
170
- printer: {handleComments = {}},
171
- } = options;
172
- // TODO: Make this as default behavior
173
- const {
174
- avoidAstMutation,
175
- ownLine: handleOwnLineComment = returnFalse,
176
- endOfLine: handleEndOfLineComment = returnFalse,
177
- remaining: handleRemainingComment = returnFalse,
178
- } = handleComments;
179
-
180
- const decoratedComments = comments.map((comment, index) => ({
181
- ...decorateComment(ast, comment, options),
182
- comment,
183
- text,
184
- options,
185
- ast,
186
- isLastComment: comments.length - 1 === index,
187
- }));
188
-
189
- for (const [index, context] of decoratedComments.entries()) {
190
- const {
191
- comment,
192
- precedingNode,
193
- enclosingNode,
194
- followingNode,
195
- text,
196
- options,
197
- ast,
198
- isLastComment,
199
- } = context;
200
-
201
- if (
202
- options.parser === 'json' ||
203
- options.parser === 'json5' ||
204
- options.parser === '__js_expression' ||
205
- options.parser === '__vue_expression'
206
- ) {
207
- if (locStart(comment) - locStart(ast) <= 0) {
208
- addLeadingComment(ast, comment);
209
- continue;
210
- }
211
- if (locEnd(comment) - locEnd(ast) >= 0) {
212
- addTrailingComment(ast, comment);
213
- continue;
214
- }
215
- }
216
-
217
- let args;
218
- if (avoidAstMutation) {
219
- args = [context];
220
- } else {
221
- comment.enclosingNode = enclosingNode;
222
- comment.precedingNode = precedingNode;
223
- comment.followingNode = followingNode;
224
- args = [comment, text, options, ast, isLastComment];
225
- }
226
-
227
- if (isOwnLineComment(text, options, decoratedComments, index)) {
228
- comment.placement = 'ownLine';
229
- // If a comment exists on its own line, prefer a leading comment.
230
- // We also need to check if it's the first line of the file.
231
- if (handleOwnLineComment(...args)) {
232
- // We're good
233
- } else if (followingNode) {
234
- // Always a leading comment.
235
- addLeadingComment(followingNode, comment);
236
- } else if (precedingNode) {
237
- addTrailingComment(precedingNode, comment);
238
- } else if (enclosingNode) {
239
- addDanglingComment(enclosingNode, comment);
240
- } else {
241
- // There are no nodes, let's attach it to the root of the ast
242
- /* istanbul ignore next */
243
- addDanglingComment(ast, comment);
244
- }
245
- } else if (isEndOfLineComment(text, options, decoratedComments, index)) {
246
- comment.placement = 'endOfLine';
247
- if (handleEndOfLineComment(...args)) {
248
- // We're good
249
- } else if (precedingNode) {
250
- // There is content before this comment on the same line, but
251
- // none after it, so prefer a trailing comment of the previous node.
252
- addTrailingComment(precedingNode, comment);
253
- } else if (followingNode) {
254
- addLeadingComment(followingNode, comment);
255
- } else if (enclosingNode) {
256
- addDanglingComment(enclosingNode, comment);
257
- } else {
258
- // There are no nodes, let's attach it to the root of the ast
259
- /* istanbul ignore next */
260
- addDanglingComment(ast, comment);
261
- }
262
- } else {
263
- comment.placement = 'remaining';
264
- if (handleRemainingComment(...args)) {
265
- // We're good
266
- } else if (precedingNode && followingNode) {
267
- // Otherwise, text exists both before and after the comment on
268
- // the same line. If there is both a preceding and following
269
- // node, use a tie-breaking algorithm to determine if it should
270
- // be attached to the next or previous node. In the last case,
271
- // simply attach the right node;
272
- const tieCount = tiesToBreak.length;
273
- if (tieCount > 0) {
274
- const lastTie = tiesToBreak[tieCount - 1];
275
- if (lastTie.followingNode !== followingNode) {
276
- breakTies(tiesToBreak, text, options);
277
- }
278
- }
279
- tiesToBreak.push(context);
280
- } else if (precedingNode) {
281
- addTrailingComment(precedingNode, comment);
282
- } else if (followingNode) {
283
- addLeadingComment(followingNode, comment);
284
- } else if (enclosingNode) {
285
- addDanglingComment(enclosingNode, comment);
286
- } else {
287
- // There are no nodes, let's attach it to the root of the ast
288
- /* istanbul ignore next */
289
- addDanglingComment(ast, comment);
290
- }
291
- }
292
- }
293
-
294
- breakTies(tiesToBreak, text, options);
295
-
296
- if (!avoidAstMutation) {
297
- for (const comment of comments) {
298
- // These node references were useful for breaking ties, but we
299
- // don't need them anymore, and they create cycles in the AST that
300
- // may lead to infinite recursion if we don't delete them here.
301
- delete comment.precedingNode;
302
- delete comment.enclosingNode;
303
- delete comment.followingNode;
304
- }
305
- }
306
- }
307
-
308
- const isAllEmptyAndNoLineBreak = text => !/[\S\n\u2028\u2029]/.test(text);
309
- function isOwnLineComment(text, options, decoratedComments, commentIndex) {
310
- const {comment, precedingNode} = decoratedComments[commentIndex];
311
- const {locStart, locEnd} = options;
312
- let start = locStart(comment);
313
-
314
- if (precedingNode) {
315
- // Find first comment on the same line
316
- for (let index = commentIndex - 1; index >= 0; index--) {
317
- const {comment, precedingNode: currentCommentPrecedingNode} =
318
- decoratedComments[index];
319
- if (
320
- currentCommentPrecedingNode !== precedingNode ||
321
- !isAllEmptyAndNoLineBreak(text.slice(locEnd(comment), start))
322
- ) {
323
- break;
324
- }
325
- start = locStart(comment);
326
- }
327
- }
328
-
329
- return hasNewline(text, start, {backwards: true});
330
- }
331
-
332
- function isEndOfLineComment(text, options, decoratedComments, commentIndex) {
333
- const {comment, followingNode} = decoratedComments[commentIndex];
334
- const {locStart, locEnd} = options;
335
- let end = locEnd(comment);
336
-
337
- if (followingNode) {
338
- // Find last comment on the same line
339
- for (
340
- let index = commentIndex + 1;
341
- index < decoratedComments.length;
342
- index++
343
- ) {
344
- const {comment, followingNode: currentCommentFollowingNode} =
345
- decoratedComments[index];
346
- if (
347
- currentCommentFollowingNode !== followingNode ||
348
- !isAllEmptyAndNoLineBreak(text.slice(end, locStart(comment)))
349
- ) {
350
- break;
351
- }
352
- end = locEnd(comment);
353
- }
354
- }
355
-
356
- return hasNewline(text, end);
357
- }
358
-
359
- function breakTies(tiesToBreak, text, options) {
360
- const tieCount = tiesToBreak.length;
361
- if (tieCount === 0) {
362
- return;
363
- }
364
- const {precedingNode, followingNode, enclosingNode} = tiesToBreak[0];
365
-
366
- const gapRegExp =
367
- (options.printer.getGapRegex &&
368
- options.printer.getGapRegex(enclosingNode)) ||
369
- /^[\s(]*$/;
370
-
371
- let gapEndPos = options.locStart(followingNode);
372
-
373
- // Iterate backwards through tiesToBreak, examining the gaps
374
- // between the tied comments. In order to qualify as leading, a
375
- // comment must be separated from followingNode by an unbroken series of
376
- // gaps (or other comments). Gaps should only contain whitespace or open
377
- // parentheses.
378
- let indexOfFirstLeadingComment;
379
- for (
380
- indexOfFirstLeadingComment = tieCount;
381
- indexOfFirstLeadingComment > 0;
382
- --indexOfFirstLeadingComment
383
- ) {
384
- const {
385
- comment,
386
- precedingNode: currentCommentPrecedingNode,
387
- followingNode: currentCommentFollowingNode,
388
- } = tiesToBreak[indexOfFirstLeadingComment - 1];
389
- assert.strictEqual(currentCommentPrecedingNode, precedingNode);
390
- assert.strictEqual(currentCommentFollowingNode, followingNode);
391
-
392
- const gap = text.slice(options.locEnd(comment), gapEndPos);
393
-
394
- if (gapRegExp.test(gap)) {
395
- gapEndPos = options.locStart(comment);
396
- } else {
397
- // The gap string contained something other than whitespace or open
398
- // parentheses.
399
- break;
400
- }
401
- }
402
-
403
- for (const [i, {comment}] of tiesToBreak.entries()) {
404
- if (i < indexOfFirstLeadingComment) {
405
- addTrailingComment(precedingNode, comment);
406
- } else {
407
- addLeadingComment(followingNode, comment);
408
- }
409
- }
410
-
411
- for (const node of [precedingNode, followingNode]) {
412
- if (node.comments && node.comments.length > 1) {
413
- node.comments.sort((a, b) => options.locStart(a) - options.locStart(b));
414
- }
415
- }
416
-
417
- tiesToBreak.length = 0;
418
- }
419
-
420
- function findExpressionIndexForComment(quasis, comment, options) {
421
- const startPos = options.locStart(comment) - 1;
422
-
423
- for (let i = 1; i < quasis.length; ++i) {
424
- if (startPos < options.locStart(quasis[i])) {
425
- return i - 1;
426
- }
427
- }
428
-
429
- // We haven't found it, it probably means that some of the locations are off.
430
- // Let's just return the first one.
431
- /* istanbul ignore next */
432
- return 0;
433
- }
434
-
435
- module.exports = {
436
- attach,
437
- };
@@ -1,14 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- */
9
-
10
- 'use strict';
11
-
12
- const getLast = arr => arr[arr.length - 1];
13
-
14
- module.exports = getLast;