@mintlify/common 1.0.1268 → 1.0.1270

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.
Files changed (26) hide show
  1. package/dist/mdx/estreeReferences.d.ts +39 -0
  2. package/dist/mdx/estreeReferences.js +963 -0
  3. package/dist/mdx/plugins/remark/firstPartyMarkdownComponents.d.ts +3 -0
  4. package/dist/mdx/plugins/remark/firstPartyMarkdownComponents.js +29 -0
  5. package/dist/mdx/plugins/remark/remarkMdxRemoveUnknownJsx/index.d.ts +1 -1
  6. package/dist/mdx/plugins/remark/remarkVisibilityForMarkdown.d.ts +7 -1
  7. package/dist/mdx/plugins/remark/remarkVisibilityForMarkdown.js +581 -177
  8. package/dist/mdx/plugins/remark/staticEvaluator.d.ts +55 -0
  9. package/dist/mdx/plugins/remark/staticEvaluator.js +639 -0
  10. package/dist/mdx/plugins/remark/unfoldComponentsForMarkdown.d.ts +71 -0
  11. package/dist/mdx/plugins/remark/unfoldComponentsForMarkdown.js +1414 -0
  12. package/dist/mdx/remark-core.d.ts +7 -0
  13. package/dist/mdx/remark-core.js +32 -0
  14. package/dist/mdx/remark.d.ts +1 -7
  15. package/dist/mdx/remark.js +2 -32
  16. package/dist/mdx/snippets/getExportMap.js +33 -5
  17. package/dist/mdx/snippets/resolveAllImports.js +3 -2
  18. package/dist/mdx/snippets/resolveImport/exportCollision.d.ts +1 -0
  19. package/dist/mdx/snippets/resolveImport/exportCollision.js +2 -1
  20. package/dist/mdx/snippets/resolveImport/index.d.ts +11 -1
  21. package/dist/mdx/snippets/resolveImport/index.js +129 -16
  22. package/dist/mdx/snippets/resolveImport/resolveComponentWithContent.js +38 -5
  23. package/dist/mdx/snippets/resolveImport/snippetDeclarations.d.ts +56 -0
  24. package/dist/mdx/snippets/resolveImport/snippetDeclarations.js +655 -0
  25. package/dist/tsconfig.build.tsbuildinfo +1 -1
  26. package/package.json +6 -5
@@ -0,0 +1,55 @@
1
+ import type { Root } from 'mdast';
2
+ export declare function nodeType(value: unknown): string | undefined;
3
+ export type StaticValue = string | number | boolean | null | undefined | {
4
+ readonly [key: string]: StaticValue;
5
+ } | readonly StaticValue[];
6
+ export type StaticScope = Map<string, StaticValue>;
7
+ export declare function isStaticObject(value: StaticValue): value is {
8
+ readonly [key: string]: StaticValue;
9
+ };
10
+ /**
11
+ * Caps a value's expanded size: its node count with shared references counted each time they
12
+ * appear, plus the length of every string and object key. Without it, `[a, a]` chains and string doubling stay
13
+ * cheap to evaluate but explode when serialized or inlined.
14
+ */
15
+ export declare const MAX_STATIC_VALUE_WEIGHT = 100000;
16
+ export declare function isNoOpSpreadValue(value: StaticValue): boolean;
17
+ export declare function serializeStaticValue(value: StaticValue): string;
18
+ export declare function identifierName(node: unknown): string | undefined;
19
+ export type ComponentDef = {
20
+ params: unknown[];
21
+ body: unknown;
22
+ };
23
+ export type MarkdownComponentContext = {
24
+ defs: Map<string, ComponentDef>;
25
+ moduleScope: StaticScope;
26
+ /**
27
+ * Primitive `const` values built only from literals and other such values. No object is read to
28
+ * produce them, so no write the evaluator cannot see can make them stale.
29
+ */
30
+ literalScope: StaticScope;
31
+ };
32
+ export type EvalResult = {
33
+ ok: true;
34
+ value: StaticValue;
35
+ } | {
36
+ ok: false;
37
+ };
38
+ export declare const EVAL_FAILED: EvalResult;
39
+ export type EvalEnv = {
40
+ scope: StaticScope;
41
+ propsObjectName?: string;
42
+ failedProps?: ReadonlySet<string>;
43
+ restName?: string;
44
+ restFailedProps?: ReadonlySet<string>;
45
+ };
46
+ export declare function unbindPattern(pattern: unknown, env: EvalEnv): void;
47
+ export declare function bindPattern(pattern: unknown, value: StaticValue, env: EvalEnv): void;
48
+ export declare function evaluateStatic(node: unknown, env: EvalEnv): EvalResult;
49
+ /**
50
+ * Collects a module's component definitions and its statically known values. Objects are only
51
+ * bound when the module never writes through any object: tracking which objects a write can reach
52
+ * is not worth the risk of publishing a stale value, while primitives are copied on read and stay
53
+ * known. A top-level write also invalidates the objects it may change for every later initializer.
54
+ */
55
+ export declare function collectContextFromTree(tree: Root): MarkdownComponentContext;
@@ -0,0 +1,639 @@
1
+ import { isObject } from '../../../types/guards.js';
2
+ import { collectModuleWrites, collectPatternNames, hasEagerCall, } from '../../estreeReferences.js';
3
+ export function nodeType(value) {
4
+ return isObject(value) && typeof value.type === 'string' ? value.type : undefined;
5
+ }
6
+ export function isStaticObject(value) {
7
+ return isObject(value);
8
+ }
9
+ /**
10
+ * Caps a value's expanded size: its node count with shared references counted each time they
11
+ * appear, plus the length of every string and object key. Without it, `[a, a]` chains and string doubling stay
12
+ * cheap to evaluate but explode when serialized or inlined.
13
+ */
14
+ export const MAX_STATIC_VALUE_WEIGHT = 100000;
15
+ const weights = new WeakMap();
16
+ function weightOf(value) {
17
+ if (typeof value === 'string')
18
+ return 1 + value.length;
19
+ if (typeof value !== 'object' || value === null)
20
+ return 1;
21
+ const cached = weights.get(value);
22
+ if (cached !== undefined)
23
+ return cached;
24
+ let total = 1;
25
+ if (Array.isArray(value)) {
26
+ for (const child of value) {
27
+ total += weightOf(child);
28
+ if (total > MAX_STATIC_VALUE_WEIGHT)
29
+ break;
30
+ }
31
+ }
32
+ else {
33
+ for (const [key, child] of Object.entries(value)) {
34
+ total += key.length + weightOf(child);
35
+ if (total > MAX_STATIC_VALUE_WEIGHT)
36
+ break;
37
+ }
38
+ }
39
+ weights.set(value, total);
40
+ return total;
41
+ }
42
+ function withinBudget(value) {
43
+ return weightOf(value) > MAX_STATIC_VALUE_WEIGHT ? EVAL_FAILED : { ok: true, value };
44
+ }
45
+ export function isNoOpSpreadValue(value) {
46
+ return (value === null || value === undefined || typeof value === 'boolean' || typeof value === 'number');
47
+ }
48
+ // Self-contained literals: `Infinity` and `NaN` are shadowable identifiers, not keywords.
49
+ function serializeNumber(value) {
50
+ if (Object.is(value, -0))
51
+ return '-0';
52
+ if (Number.isNaN(value))
53
+ return '0/0';
54
+ if (!Number.isFinite(value))
55
+ return value > 0 ? '1e999' : '-1e999';
56
+ return JSON.stringify(value);
57
+ }
58
+ export function serializeStaticValue(value) {
59
+ if (value === undefined)
60
+ return 'void 0';
61
+ if (value === null)
62
+ return 'null';
63
+ if (typeof value === 'number')
64
+ return serializeNumber(value);
65
+ if (typeof value === 'string' || typeof value === 'boolean')
66
+ return JSON.stringify(value);
67
+ if (Array.isArray(value)) {
68
+ return `[${value.map((item) => serializeStaticValue(item)).join(',')}]`;
69
+ }
70
+ return `{${Object.entries(value)
71
+ .map(([key, item]) => {
72
+ const serializedKey = key === '__proto__' ? '["__proto__"]' : JSON.stringify(key);
73
+ return `${serializedKey}:${serializeStaticValue(item)}`;
74
+ })
75
+ .join(',')}}`;
76
+ }
77
+ function defineOwn(target, key, value) {
78
+ Object.defineProperty(target, key, {
79
+ value,
80
+ enumerable: true,
81
+ writable: true,
82
+ configurable: true,
83
+ });
84
+ }
85
+ export function identifierName(node) {
86
+ if (nodeType(node) === 'Identifier' && isObject(node) && typeof node.name === 'string') {
87
+ return node.name;
88
+ }
89
+ return undefined;
90
+ }
91
+ function isPrimitiveValue(value) {
92
+ return value === null || typeof value !== 'object';
93
+ }
94
+ export const EVAL_FAILED = { ok: false };
95
+ function unknowableMembers(name, env) {
96
+ if (name === undefined)
97
+ return undefined;
98
+ if (name === env.propsObjectName)
99
+ return env.failedProps;
100
+ if (name === env.restName)
101
+ return env.restFailedProps;
102
+ return undefined;
103
+ }
104
+ function isNullish(value) {
105
+ return value === null || value === undefined;
106
+ }
107
+ function isObjectValue(value) {
108
+ return typeof value === 'object' && value !== null;
109
+ }
110
+ function isLooselyEqual(left, right) {
111
+ if (left === right)
112
+ return true;
113
+ if (isNullish(left) || isNullish(right))
114
+ return isNullish(left) && isNullish(right);
115
+ if (isObjectValue(left) || isObjectValue(right)) {
116
+ return isObjectValue(left) && isObjectValue(right) ? false : undefined;
117
+ }
118
+ if (typeof left === 'boolean' || typeof right === 'boolean') {
119
+ return Number(left) === Number(right);
120
+ }
121
+ if (typeof left === 'number' && typeof right === 'string')
122
+ return left === Number(right);
123
+ if (typeof left === 'string' && typeof right === 'number')
124
+ return Number(left) === right;
125
+ return false;
126
+ }
127
+ function readScope(name, env) {
128
+ if (!env.scope.has(name))
129
+ return EVAL_FAILED;
130
+ const bound = env.scope.get(name);
131
+ return { ok: true, value: bound === undefined ? undefined : bound };
132
+ }
133
+ function propertyKey(property, env) {
134
+ if (property.computed === true) {
135
+ const evaluatedKey = evaluateStatic(property.key, env);
136
+ return evaluatedKey.ok && typeof evaluatedKey.value === 'string'
137
+ ? evaluatedKey.value
138
+ : undefined;
139
+ }
140
+ const name = identifierName(property.key);
141
+ if (name !== undefined)
142
+ return name;
143
+ if (nodeType(property.key) === 'Literal' &&
144
+ isObject(property.key) &&
145
+ typeof property.key.value === 'string') {
146
+ return property.key.value;
147
+ }
148
+ return undefined;
149
+ }
150
+ function readMember(object, key) {
151
+ if (Array.isArray(object)) {
152
+ if (typeof key !== 'number' || !Number.isInteger(key) || key < 0)
153
+ return EVAL_FAILED;
154
+ if (key >= object.length)
155
+ return { ok: true, value: undefined };
156
+ return { ok: true, value: object[key] };
157
+ }
158
+ if (!isStaticObject(object) || typeof key !== 'string')
159
+ return EVAL_FAILED;
160
+ return { ok: true, value: Object.hasOwn(object, key) ? object[key] : undefined };
161
+ }
162
+ export function unbindPattern(pattern, env) {
163
+ const names = new Set();
164
+ collectPatternNames(pattern, names);
165
+ for (const name of names)
166
+ env.scope.delete(name);
167
+ }
168
+ export function bindPattern(pattern, value, env) {
169
+ const type = nodeType(pattern);
170
+ if (type === 'Identifier') {
171
+ const name = identifierName(pattern);
172
+ if (name !== undefined)
173
+ env.scope.set(name, value);
174
+ return;
175
+ }
176
+ if (type === 'AssignmentPattern' && isObject(pattern)) {
177
+ const resolved = value === undefined ? evaluateStatic(pattern.right, env) : { ok: true, value };
178
+ if (resolved.ok)
179
+ bindPattern(pattern.left, resolved.value, env);
180
+ else
181
+ unbindPattern(pattern.left, env);
182
+ return;
183
+ }
184
+ if (type === 'ObjectPattern' && isObject(pattern) && Array.isArray(pattern.properties)) {
185
+ if (!isStaticObject(value)) {
186
+ unbindPattern(pattern, env);
187
+ return;
188
+ }
189
+ const remaining = Object.assign({}, value);
190
+ let remainingKnown = true;
191
+ for (const property of pattern.properties) {
192
+ if (nodeType(property) === 'RestElement' && isObject(property)) {
193
+ if (remainingKnown)
194
+ bindPattern(property.argument, remaining, env);
195
+ else
196
+ unbindPattern(property.argument, env);
197
+ continue;
198
+ }
199
+ if (nodeType(property) !== 'Property' || !isObject(property))
200
+ continue;
201
+ const key = propertyKey(property, env);
202
+ if (key === undefined) {
203
+ remainingKnown = false;
204
+ unbindPattern(property.value, env);
205
+ continue;
206
+ }
207
+ delete remaining[key];
208
+ bindPattern(property.value, Object.hasOwn(value, key) ? value[key] : undefined, env);
209
+ }
210
+ return;
211
+ }
212
+ if (type === 'ArrayPattern' && isObject(pattern) && Array.isArray(pattern.elements)) {
213
+ if (!Array.isArray(value)) {
214
+ unbindPattern(pattern, env);
215
+ return;
216
+ }
217
+ for (let index = 0; index < pattern.elements.length; index++) {
218
+ const element = pattern.elements[index];
219
+ if (element === null || element === undefined)
220
+ continue;
221
+ if (nodeType(element) === 'RestElement' && isObject(element)) {
222
+ bindPattern(element.argument, value.slice(index), env);
223
+ break;
224
+ }
225
+ bindPattern(element, index < value.length ? value[index] : undefined, env);
226
+ }
227
+ }
228
+ }
229
+ export function evaluateStatic(node, env) {
230
+ var _a, _b;
231
+ if (!isObject(node))
232
+ return EVAL_FAILED;
233
+ switch (node.type) {
234
+ case 'Literal': {
235
+ const value = node.value;
236
+ if (typeof value === 'string' ||
237
+ typeof value === 'number' ||
238
+ typeof value === 'boolean' ||
239
+ value === null) {
240
+ return { ok: true, value };
241
+ }
242
+ return EVAL_FAILED;
243
+ }
244
+ case 'Identifier': {
245
+ if (typeof node.name !== 'string')
246
+ return EVAL_FAILED;
247
+ if (node.name === 'undefined' && !env.scope.has('undefined')) {
248
+ return { ok: true, value: undefined };
249
+ }
250
+ // Copying a props or rest object with unknowable keys would turn those keys
251
+ // into missing ones, so only member reads of known keys are allowed.
252
+ if (((_b = (_a = unknowableMembers(node.name, env)) === null || _a === void 0 ? void 0 : _a.size) !== null && _b !== void 0 ? _b : 0) > 0)
253
+ return EVAL_FAILED;
254
+ return readScope(node.name, env);
255
+ }
256
+ case 'ParenthesizedExpression':
257
+ return evaluateStatic(node.expression, env);
258
+ case 'MemberExpression': {
259
+ const property = node.property;
260
+ const key = node.computed === true
261
+ ? evaluateStatic(property, env)
262
+ : { ok: true, value: identifierName(property) };
263
+ if (!key.ok || key.value === undefined)
264
+ return EVAL_FAILED;
265
+ const objectName = identifierName(node.object);
266
+ const unknowable = unknowableMembers(objectName, env);
267
+ if (unknowable !== undefined && objectName !== undefined) {
268
+ if (typeof key.value === 'string' && unknowable.has(key.value))
269
+ return EVAL_FAILED;
270
+ const resolvedObject = readScope(objectName, env);
271
+ return resolvedObject.ok ? readMember(resolvedObject.value, key.value) : EVAL_FAILED;
272
+ }
273
+ const resolvedObject = evaluateStatic(node.object, env);
274
+ if (!resolvedObject.ok)
275
+ return EVAL_FAILED;
276
+ return readMember(resolvedObject.value, key.value);
277
+ }
278
+ case 'ObjectExpression': {
279
+ if (!Array.isArray(node.properties))
280
+ return EVAL_FAILED;
281
+ const result = {};
282
+ for (const property of node.properties) {
283
+ if (!isObject(property))
284
+ return EVAL_FAILED;
285
+ if (property.type === 'SpreadElement') {
286
+ const spread = evaluateStatic(property.argument, env);
287
+ if (!spread.ok)
288
+ return EVAL_FAILED;
289
+ if (isNoOpSpreadValue(spread.value))
290
+ continue;
291
+ if (!isStaticObject(spread.value))
292
+ return EVAL_FAILED;
293
+ for (const [key, value] of Object.entries(spread.value))
294
+ defineOwn(result, key, value);
295
+ continue;
296
+ }
297
+ if (property.type !== 'Property')
298
+ return EVAL_FAILED;
299
+ const key = propertyKey(property, env);
300
+ if (key === undefined)
301
+ return EVAL_FAILED;
302
+ // A literal `__proto__:` key sets the prototype rather than an own property.
303
+ if (key === '__proto__' && property.computed !== true && property.shorthand !== true) {
304
+ return EVAL_FAILED;
305
+ }
306
+ const value = evaluateStatic(property.value, env);
307
+ if (!value.ok)
308
+ return EVAL_FAILED;
309
+ defineOwn(result, key, value.value);
310
+ }
311
+ return withinBudget(result);
312
+ }
313
+ case 'ArrayExpression': {
314
+ if (!Array.isArray(node.elements))
315
+ return EVAL_FAILED;
316
+ const result = [];
317
+ for (const element of node.elements) {
318
+ // A hole is not an `undefined` entry: iteration methods skip it
319
+ if (element === null)
320
+ return EVAL_FAILED;
321
+ if (isObject(element) && element.type === 'SpreadElement') {
322
+ const spread = evaluateStatic(element.argument, env);
323
+ if (!spread.ok || !Array.isArray(spread.value))
324
+ return EVAL_FAILED;
325
+ if (result.length + spread.value.length > MAX_STATIC_VALUE_WEIGHT)
326
+ return EVAL_FAILED;
327
+ for (const item of spread.value)
328
+ result.push(item);
329
+ continue;
330
+ }
331
+ const value = evaluateStatic(element, env);
332
+ if (!value.ok)
333
+ return EVAL_FAILED;
334
+ result.push(value.value);
335
+ }
336
+ return withinBudget(result);
337
+ }
338
+ case 'TemplateLiteral': {
339
+ const quasis = Array.isArray(node.quasis) ? node.quasis : [];
340
+ const expressions = Array.isArray(node.expressions) ? node.expressions : [];
341
+ let result = '';
342
+ for (let i = 0; i < quasis.length; i++) {
343
+ const quasi = quasis[i];
344
+ const cooked = isObject(quasi) && isObject(quasi.value) && typeof quasi.value.cooked === 'string'
345
+ ? quasi.value.cooked
346
+ : '';
347
+ result += cooked;
348
+ if (i < expressions.length) {
349
+ const part = evaluateStatic(expressions[i], env);
350
+ if (!part.ok)
351
+ return EVAL_FAILED;
352
+ if (typeof part.value === 'object' && part.value !== null)
353
+ return EVAL_FAILED;
354
+ result += String(part.value);
355
+ }
356
+ if (result.length > MAX_STATIC_VALUE_WEIGHT)
357
+ return EVAL_FAILED;
358
+ }
359
+ return { ok: true, value: result };
360
+ }
361
+ case 'BinaryExpression': {
362
+ const left = evaluateStatic(node.left, env);
363
+ const right = evaluateStatic(node.right, env);
364
+ if (!left.ok || !right.ok)
365
+ return EVAL_FAILED;
366
+ switch (node.operator) {
367
+ case '+':
368
+ if (isObjectValue(left.value) || isObjectValue(right.value))
369
+ return EVAL_FAILED;
370
+ if (typeof left.value === 'string' || typeof right.value === 'string') {
371
+ const joined = `${String(left.value)}${String(right.value)}`;
372
+ return joined.length > MAX_STATIC_VALUE_WEIGHT
373
+ ? EVAL_FAILED
374
+ : { ok: true, value: joined };
375
+ }
376
+ if (typeof left.value === 'number' && typeof right.value === 'number') {
377
+ const sum = left.value + right.value;
378
+ return Number.isNaN(sum) ? EVAL_FAILED : { ok: true, value: sum };
379
+ }
380
+ return EVAL_FAILED;
381
+ case '===':
382
+ return { ok: true, value: left.value === right.value };
383
+ case '!==':
384
+ return { ok: true, value: left.value !== right.value };
385
+ case '==':
386
+ case '!=': {
387
+ const equal = isLooselyEqual(left.value, right.value);
388
+ if (equal === undefined)
389
+ return EVAL_FAILED;
390
+ return { ok: true, value: node.operator === '==' ? equal : !equal };
391
+ }
392
+ default:
393
+ return EVAL_FAILED;
394
+ }
395
+ }
396
+ case 'LogicalExpression': {
397
+ const left = evaluateStatic(node.left, env);
398
+ if (!left.ok)
399
+ return EVAL_FAILED;
400
+ const leftTruthy = Boolean(left.value);
401
+ if (node.operator === '&&')
402
+ return leftTruthy ? evaluateStatic(node.right, env) : left;
403
+ if (node.operator === '||')
404
+ return leftTruthy ? left : evaluateStatic(node.right, env);
405
+ if (node.operator === '??') {
406
+ return left.value === null || left.value === undefined
407
+ ? evaluateStatic(node.right, env)
408
+ : left;
409
+ }
410
+ return EVAL_FAILED;
411
+ }
412
+ case 'ConditionalExpression': {
413
+ const test = evaluateStatic(node.test, env);
414
+ if (!test.ok)
415
+ return EVAL_FAILED;
416
+ return evaluateStatic(test.value ? node.consequent : node.alternate, env);
417
+ }
418
+ case 'UnaryExpression': {
419
+ const argument = evaluateStatic(node.argument, env);
420
+ if (!argument.ok)
421
+ return EVAL_FAILED;
422
+ if (node.operator === 'void')
423
+ return { ok: true, value: undefined };
424
+ if (node.operator === '!')
425
+ return { ok: true, value: !argument.value };
426
+ if (node.operator === '-' || node.operator === '+') {
427
+ if (typeof argument.value === 'object' && argument.value !== null)
428
+ return EVAL_FAILED;
429
+ const numeric = node.operator === '-' ? -Number(argument.value) : Number(argument.value);
430
+ if (Number.isNaN(numeric))
431
+ return EVAL_FAILED;
432
+ return { ok: true, value: numeric };
433
+ }
434
+ return EVAL_FAILED;
435
+ }
436
+ default:
437
+ return EVAL_FAILED;
438
+ }
439
+ }
440
+ function isFunctionNode(value) {
441
+ const type = nodeType(value);
442
+ return (type === 'ArrowFunctionExpression' ||
443
+ type === 'FunctionExpression' ||
444
+ type === 'FunctionDeclaration');
445
+ }
446
+ function esmStatements(node) {
447
+ var _a;
448
+ if (node.type !== 'mdxjsEsm')
449
+ return [];
450
+ const estree = (_a = node.data) === null || _a === void 0 ? void 0 : _a.estree;
451
+ if (!isObject(estree) || !Array.isArray(estree.body))
452
+ return [];
453
+ return estree.body;
454
+ }
455
+ /** Every estree program or expression in the tree: ESM, `{expressions}`, and JSX attribute values. */
456
+ function collectEstrees(node, estrees) {
457
+ if (Array.isArray(node)) {
458
+ for (const child of node)
459
+ collectEstrees(child, estrees);
460
+ return;
461
+ }
462
+ if (!isObject(node))
463
+ return;
464
+ if (isObject(node.data) && node.data.estree !== undefined)
465
+ estrees.push(node.data.estree);
466
+ for (const [key, child] of Object.entries(node)) {
467
+ if (key !== 'data' && key !== 'position')
468
+ collectEstrees(child, estrees);
469
+ }
470
+ }
471
+ function dropObjectBindings(moduleScope) {
472
+ for (const [name, value] of moduleScope) {
473
+ if (typeof value === 'object' && value !== null)
474
+ moduleScope.delete(name);
475
+ }
476
+ }
477
+ /**
478
+ * Whether a top-level statement may write while it runs: directly, or through a call when the
479
+ * module has writes inside functions, since any call may run one of them.
480
+ */
481
+ function writesEagerly(statement, moduleWrites) {
482
+ const { reassigned, mutated } = collectModuleWrites(statement, true);
483
+ if (reassigned.size > 0 || mutated.size > 0)
484
+ return true;
485
+ return moduleWrites && hasEagerCall(statement);
486
+ }
487
+ /**
488
+ * Collects a module's component definitions and its statically known values. Objects are only
489
+ * bound when the module never writes through any object: tracking which objects a write can reach
490
+ * is not worth the risk of publishing a stale value, while primitives are copied on read and stay
491
+ * known. A top-level write also invalidates the objects it may change for every later initializer.
492
+ */
493
+ export function collectContextFromTree(tree) {
494
+ const defs = new Map();
495
+ const moduleScope = new Map();
496
+ const literalScope = new Map();
497
+ const aliases = [];
498
+ const statements = tree.children.flatMap(esmStatements);
499
+ const registerFunction = (name, fn) => {
500
+ const params = Array.isArray(fn.params) ? fn.params : [];
501
+ defs.set(name, { params, body: fn.body });
502
+ };
503
+ const registerDeclarator = (declarator, kind) => {
504
+ if (nodeType(declarator) !== 'VariableDeclarator' || !isObject(declarator))
505
+ return;
506
+ // A later declarator in the same statement runs after earlier ones, so only its own
507
+ // initializer should drop objects bound above it.
508
+ if (writesEagerly(declarator, moduleWrites))
509
+ dropObjectBindings(moduleScope);
510
+ const init = declarator.init;
511
+ const name = identifierName(declarator.id);
512
+ if (name !== undefined && isFunctionNode(init) && isObject(init)) {
513
+ registerFunction(name, init);
514
+ return;
515
+ }
516
+ if (kind !== 'const')
517
+ return;
518
+ const literal = evaluateStatic(init, { scope: literalScope });
519
+ if (literal.ok) {
520
+ // Defaults and computed keys in the pattern may read earlier literal values
521
+ const bound = new Map(literalScope);
522
+ bindPattern(declarator.id, literal.value, { scope: bound });
523
+ const declared = new Set();
524
+ collectPatternNames(declarator.id, declared);
525
+ for (const boundName of declared) {
526
+ if (!bound.has(boundName))
527
+ continue;
528
+ const stored = bound.get(boundName);
529
+ const value = stored === undefined ? undefined : stored;
530
+ if (isPrimitiveValue(value))
531
+ literalScope.set(boundName, value);
532
+ }
533
+ }
534
+ const evaluated = evaluateStatic(init, { scope: moduleScope });
535
+ if (!evaluated.ok)
536
+ return;
537
+ bindPattern(declarator.id, evaluated.value, { scope: moduleScope });
538
+ };
539
+ const estrees = [];
540
+ collectEstrees(tree, estrees);
541
+ const { reassigned, mutated } = collectModuleWrites(estrees);
542
+ const moduleWrites = reassigned.size > 0 || mutated.size > 0;
543
+ for (const statement of statements) {
544
+ if (!isObject(statement))
545
+ continue;
546
+ // A variable declaration writes from inside its declarators, which are checked one by one.
547
+ // Dropping here would hide objects from earlier declarators in the same statement.
548
+ const declaresVariables = statement.type === 'VariableDeclaration' ||
549
+ (statement.type === 'ExportNamedDeclaration' &&
550
+ isObject(statement.declaration) &&
551
+ statement.declaration.type === 'VariableDeclaration');
552
+ if (!declaresVariables && writesEagerly(statement, moduleWrites))
553
+ dropObjectBindings(moduleScope);
554
+ if (statement.type === 'VariableDeclaration') {
555
+ const declarations = Array.isArray(statement.declarations) ? statement.declarations : [];
556
+ for (const declarator of declarations)
557
+ registerDeclarator(declarator, statement.kind);
558
+ continue;
559
+ }
560
+ if (statement.type === 'FunctionDeclaration') {
561
+ const id = statement.id;
562
+ if (nodeType(id) === 'Identifier' && isObject(id) && typeof id.name === 'string') {
563
+ registerFunction(id.name, statement);
564
+ }
565
+ continue;
566
+ }
567
+ if (statement.type === 'ExportNamedDeclaration') {
568
+ const declaration = statement.declaration;
569
+ if (nodeType(declaration) === 'VariableDeclaration' && isObject(declaration)) {
570
+ const declarations = Array.isArray(declaration.declarations)
571
+ ? declaration.declarations
572
+ : [];
573
+ for (const declarator of declarations)
574
+ registerDeclarator(declarator, declaration.kind);
575
+ }
576
+ if (nodeType(declaration) === 'FunctionDeclaration' && isObject(declaration)) {
577
+ const id = declaration.id;
578
+ if (nodeType(id) === 'Identifier' && isObject(id) && typeof id.name === 'string') {
579
+ registerFunction(id.name, declaration);
580
+ }
581
+ }
582
+ // `export { a as b } from "./mod"` re-exports another module. Its local name is not a
583
+ // binding in this file, so copying a same-named local would publish the wrong value.
584
+ if (statement.source != null)
585
+ continue;
586
+ const specifiers = Array.isArray(statement.specifiers) ? statement.specifiers : [];
587
+ for (const specifier of specifiers) {
588
+ if (nodeType(specifier) !== 'ExportSpecifier' || !isObject(specifier))
589
+ continue;
590
+ const local = specifier.local;
591
+ const exported = specifier.exported;
592
+ if (isObject(local) &&
593
+ typeof local.name === 'string' &&
594
+ isObject(exported) &&
595
+ typeof exported.name === 'string') {
596
+ aliases.push([local.name, exported.name]);
597
+ }
598
+ }
599
+ }
600
+ if (statement.type === 'ExportDefaultDeclaration') {
601
+ const declaration = statement.declaration;
602
+ if (isFunctionNode(declaration) && isObject(declaration)) {
603
+ const id = declaration.id;
604
+ if (nodeType(id) === 'Identifier' && isObject(id) && typeof id.name === 'string') {
605
+ registerFunction(id.name, declaration);
606
+ }
607
+ }
608
+ }
609
+ }
610
+ for (const name of reassigned) {
611
+ moduleScope.delete(name);
612
+ literalScope.delete(name);
613
+ defs.delete(name);
614
+ }
615
+ if (mutated.size > 0)
616
+ dropObjectBindings(moduleScope);
617
+ let aliasChanged = true;
618
+ while (aliasChanged) {
619
+ aliasChanged = false;
620
+ for (const [local, exported] of aliases) {
621
+ const def = defs.get(local);
622
+ if (def && !defs.has(exported)) {
623
+ defs.set(exported, def);
624
+ aliasChanged = true;
625
+ }
626
+ if (moduleScope.has(local) && !moduleScope.has(exported)) {
627
+ const bound = moduleScope.get(local);
628
+ moduleScope.set(exported, bound === undefined ? undefined : bound);
629
+ aliasChanged = true;
630
+ }
631
+ if (literalScope.has(local) && !literalScope.has(exported)) {
632
+ const bound = literalScope.get(local);
633
+ literalScope.set(exported, bound === undefined ? undefined : bound);
634
+ aliasChanged = true;
635
+ }
636
+ }
637
+ }
638
+ return { defs, moduleScope, literalScope };
639
+ }