rolldown-plugin-dts 0.25.2 → 0.27.0-beta.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/dist/index.mjs CHANGED
@@ -2,13 +2,14 @@ import { a as RE_JSON, c as RE_TS, d as filename_js_to_dts, f as filename_to_dts
2
2
  import { createContext, globalContext, invalidateContextFile } from "./tsc-context.mjs";
3
3
  import { createDebug } from "obug";
4
4
  import { importerId, include } from "rolldown/filter";
5
- import { generate } from "@babel/generator";
6
- import { isIdentifierName } from "@babel/helper-validator-identifier";
7
- import { parse } from "@babel/parser";
8
- import { isDeclarationType, isIdentifierOf, isTypeOf, resolveString, walkAST, walkASTAsync } from "ast-kit";
5
+ import { b, is } from "yuku-ast";
6
+ import { isIdentifierName } from "yuku-ast/identifier";
7
+ import { nameOf } from "yuku-ast/utils";
8
+ import { print } from "yuku-codegen";
9
+ import { parse, walk } from "yuku-parser";
9
10
  import { fork, spawn } from "node:child_process";
10
11
  import { existsSync } from "node:fs";
11
- import { mkdtemp, readFile, rm } from "node:fs/promises";
12
+ import { access, mkdtemp, readFile, rm } from "node:fs/promises";
12
13
  import path from "node:path";
13
14
  import { ResolverFactory, isolatedDeclarationSync } from "rolldown/experimental";
14
15
  import { tmpdir } from "node:os";
@@ -97,39 +98,36 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
97
98
  let file;
98
99
  try {
99
100
  file = parse(code, {
100
- plugins: [["typescript", { dts: true }], "decoratorAutoAccessors"],
101
+ lang: "dts",
101
102
  sourceType: "module",
102
- errorRecovery: true,
103
- createParenthesizedExpressions: true
103
+ attachComments: true
104
104
  });
105
105
  } catch (error) {
106
106
  throw new Error(`Failed to parse ${id}. This may be caused by a syntax error in the declaration file or a bug in the plugin. Please report this issue to https://github.com/sxzz/rolldown-plugin-dts\n${error}`, { cause: error });
107
107
  }
108
- const { program, comments } = file;
108
+ const { program } = file;
109
109
  moduleExportsMap.set(id, await collectModuleExports(this, program.body, id));
110
110
  const identifierMap = Object.create(null);
111
111
  if (!warnedCjsDtsInputs.has(id) && program.body.some(isCjsDtsInputSyntax)) {
112
112
  warnedCjsDtsInputs.add(id);
113
- this.warn(RE_NODE_MODULES.test(id) ? `${id} uses CommonJS dts syntax. CommonJS dts modules cannot be reliably bundled by rolldown-plugin-dts. Please mark this module as external in your Rolldown config.` : `${id} uses CommonJS dts syntax. rolldown-plugin-dts does not support reliably bundling CommonJS dts input.`);
114
- }
115
- if (comments) {
116
- const directives = collectReferenceDirectives(comments);
117
- commentsMap.set(id, directives);
113
+ this.warn(`${id} uses CommonJS dts syntax. ${RE_NODE_MODULES.test(id) ? `CommonJS dts modules cannot be bundled by rolldown-plugin-dts. Please mark this module as external in your Rolldown config.` : `rolldown-plugin-dts does not support bundling CommonJS dts input.`}`);
118
114
  }
115
+ const directives = collectReferenceDirectives(file.comments);
116
+ if (directives.length) commentsMap.set(id, directives);
119
117
  const appendStmts = [];
120
118
  const namespaceStmts = /* @__PURE__ */ new Map();
121
119
  for (const [i, stmt] of program.body.entries()) {
122
120
  const setStmt = (stmt) => program.body[i] = stmt;
123
121
  if (rewriteImportExport(stmt, setStmt)) continue;
124
122
  const sideEffect = stmt.type === "TSModuleDeclaration" && stmt.kind !== "namespace";
125
- if (sideEffect && stmt.id.type === "StringLiteral" && stmt.id.value[0] === ".") this.warn(`\`declare module ${JSON.stringify(stmt.id.value)}\` will be kept as-is in the output. Relative module declaration may cause unexpected issues. Found in ${id}.`);
123
+ if (sideEffect && stmt.type === "TSModuleDeclaration" && is.StringLiteral(stmt.id) && stmt.id.value[0] === ".") this.warn(`\`declare module ${JSON.stringify(stmt.id.value)}\` will be kept as-is in the output. Relative module declaration may cause unexpected issues. Found in ${id}.`);
126
124
  if (sideEffect && id.endsWith(".vue.d.ts") && code.slice(stmt.start, stmt.end).includes("__VLS_")) continue;
127
125
  const isDefaultExport = stmt.type === "ExportDefaultDeclaration";
128
- const isExportDecl = isTypeOf(stmt, ["ExportNamedDeclaration", "ExportDefaultDeclaration"]) && !!stmt.declaration;
126
+ const isExportDecl = is.oneOf(stmt, ["ExportNamedDeclaration", "ExportDefaultDeclaration"]) && !!stmt.declaration;
129
127
  const decl = isExportDecl ? stmt.declaration : stmt;
130
128
  const setDecl = isExportDecl ? (decl) => stmt.declaration = decl : setStmt;
131
- if (decl.type !== "TSDeclareFunction" && !isDeclarationType(decl)) continue;
132
- if (isTypeOf(decl, [
129
+ if (decl.type !== "TSDeclareFunction" && !is.Declaration(decl)) continue;
130
+ if (is.oneOf(decl, [
133
131
  "TSEnumDeclaration",
134
132
  "ClassDeclaration",
135
133
  "FunctionDeclaration",
@@ -142,17 +140,11 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
142
140
  else if ("id" in decl && decl.id) {
143
141
  let binding = decl.id;
144
142
  if (binding.type === "TSQualifiedName") binding = getIdFromTSEntityName(binding);
145
- binding = sideEffect ? {
146
- type: "Identifier",
147
- name: `_${getIdentifierIndex(identifierMap, "")}`
148
- } : binding;
143
+ if (sideEffect) binding = b.identifier(`_${getIdentifierIndex(identifierMap, "")}`);
149
144
  if (binding.type !== "Identifier") throw new Error(`Unexpected ${binding.type} declaration id`);
150
145
  bindings.push(binding);
151
146
  } else {
152
- const binding = {
153
- type: "Identifier",
154
- name: "export_default"
155
- };
147
+ const binding = b.identifier("export_default");
156
148
  bindings.push(binding);
157
149
  decl.id = binding;
158
150
  }
@@ -160,115 +152,58 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
160
152
  const childrenSet = /* @__PURE__ */ new Set();
161
153
  const deps = await collectDependencies(this, decl, id, namespaceStmts, childrenSet, identifierMap);
162
154
  const children = Array.from(childrenSet).filter((child) => bindings.every((b) => child !== b));
163
- if (decl !== stmt) decl.leadingComments = stmt.leadingComments;
164
- const declarationIdNode = {
165
- type: "NumericLiteral",
166
- value: registerDeclaration({
167
- decl,
168
- deps,
169
- bindings,
170
- params,
171
- children
172
- })
173
- };
174
- const depsBody = {
175
- type: "ArrayExpression",
176
- elements: deps
177
- };
178
- const depsNode = {
179
- type: "ArrowFunctionExpression",
180
- params: params.map(({ name }) => ({
181
- type: "Identifier",
182
- name
183
- })),
184
- body: depsBody,
185
- async: false,
186
- expression: true
187
- };
188
- const childrenNode = {
189
- type: "ArrayExpression",
190
- elements: children.map((node) => ({
191
- type: "StringLiteral",
192
- value: "",
193
- start: node.start,
194
- end: node.end,
195
- loc: node.loc
196
- }))
197
- };
198
- const sideEffectNode = sideEffect && {
199
- type: "CallExpression",
200
- callee: {
201
- type: "Identifier",
202
- name: "sideEffect"
203
- },
204
- arguments: [bindings[0]]
205
- };
155
+ if (decl !== stmt) decl.comments = stmt.comments;
156
+ const declarationId = registerDeclaration({
157
+ decl,
158
+ deps,
159
+ bindings,
160
+ params,
161
+ children
162
+ });
163
+ const declarationIdNode = b.numericLiteral(declarationId);
164
+ const depsBody = b.arrayExpression(deps);
165
+ const depsNode = b.arrowFunctionExpression(params.map(({ name }) => b.identifier(name)), depsBody);
166
+ const childrenNode = b.arrayExpression(children.map((node) => {
167
+ const placeholder = b.stringLiteral("");
168
+ placeholder.start = node.start;
169
+ placeholder.end = node.end;
170
+ return placeholder;
171
+ }));
172
+ const sideEffectNode = sideEffect && b.callExpression(b.identifier("sideEffect"), [bindings[0]]);
206
173
  const runtimeArrayNode = runtimeBindingArrayExpression([
207
174
  declarationIdNode,
208
175
  depsNode,
209
176
  childrenNode,
210
177
  ...sideEffectNode ? [sideEffectNode] : []
211
178
  ]);
212
- const runtimeAssignment = {
213
- type: "VariableDeclaration",
214
- kind: "var",
215
- declarations: [{
216
- type: "VariableDeclarator",
217
- id: {
218
- ...bindings[0],
219
- typeAnnotation: null
220
- },
221
- init: runtimeArrayNode
222
- }, ...bindings.slice(1).map((binding) => ({
223
- type: "VariableDeclarator",
224
- id: {
225
- ...binding,
226
- typeAnnotation: null
227
- }
228
- }))]
229
- };
179
+ const runtimeAssignment = b.variableDeclaration("var", [b.variableDeclarator({
180
+ ...bindings[0],
181
+ typeAnnotation: null
182
+ }, runtimeArrayNode), ...bindings.slice(1).map((binding) => b.variableDeclarator({
183
+ ...binding,
184
+ typeAnnotation: null
185
+ }))]);
230
186
  if (isDefaultExport) {
231
- appendStmts.push({
232
- type: "ExportNamedDeclaration",
233
- declaration: null,
234
- specifiers: [{
235
- type: "ExportSpecifier",
236
- local: bindings[0],
237
- exported: {
238
- type: "Identifier",
239
- name: "default"
240
- }
241
- }],
242
- source: null,
243
- attributes: null
244
- });
187
+ appendStmts.push(b.exportNamedDeclaration(null, [b.exportSpecifier(bindings[0], b.identifier("default"))]));
245
188
  setStmt(runtimeAssignment);
246
189
  } else setDecl(runtimeAssignment);
247
190
  }
248
- if (sideEffects) appendStmts.push({
249
- type: "ExpressionStatement",
250
- expression: {
251
- type: "CallExpression",
252
- callee: {
253
- type: "Identifier",
254
- name: "sideEffect"
255
- },
256
- arguments: []
257
- }
258
- });
191
+ if (sideEffects) appendStmts.push(b.expressionStatement(b.callExpression(b.identifier("sideEffect"), [])));
259
192
  program.body = [
260
193
  ...Array.from(namespaceStmts.values()).map(({ stmt }) => stmt),
261
194
  ...program.body,
262
195
  ...appendStmts
263
196
  ];
264
- const result = generate(file, {
197
+ const result = print(program, {
265
198
  comments: false,
266
- sourceMaps: sourcemap,
267
- sourceFileName: id
199
+ ...sourcemap && { sourceMaps: {
200
+ source: code,
201
+ sourceFileName: id
202
+ } }
268
203
  });
269
204
  return {
270
205
  code: result.code,
271
- map: result.map
206
+ map: result.map ?? null
272
207
  };
273
208
  }
274
209
  function renderChunk(code, chunk) {
@@ -276,7 +211,11 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
276
211
  const exportInfo = collectChunkExportInfo(chunk, moduleExportsMap);
277
212
  let file;
278
213
  try {
279
- file = parse(code, { sourceType: "module" });
214
+ file = parse(code, {
215
+ lang: "ts",
216
+ sourceType: "module",
217
+ attachComments: true
218
+ });
280
219
  } catch (error) {
281
220
  throw new Error(`Failed to parse generated code for chunk ${chunk.fileName}. This may be caused by a bug in the plugin. Please report this issue to https://github.com/sxzz/rolldown-plugin-dts\n${error}`, { cause: error });
282
221
  }
@@ -293,9 +232,9 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
293
232
  const [declarationIdNode, depsFn, children] = node.declarations[0].init.elements;
294
233
  const declarationId = declarationIdNode.value;
295
234
  const declaration = getDeclaration(declarationId);
296
- walkAST(declaration.decl, { enter(node) {
297
- if (node.type === "CommentBlock") return;
298
- delete node.loc;
235
+ if (sourcemap) walk(declaration.decl, { enter(node) {
236
+ node.start = void 0;
237
+ node.end = void 0;
299
238
  } });
300
239
  for (const [i, decl] of node.declarations.entries()) {
301
240
  const transformedBinding = {
@@ -304,7 +243,10 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
304
243
  };
305
244
  overwriteNode(declaration.bindings[i], transformedBinding);
306
245
  }
307
- for (const [i, child] of children.elements.entries()) Object.assign(declaration.children[i], { loc: child.loc });
246
+ if (sourcemap) for (const [i, child] of children.elements.entries()) Object.assign(declaration.children[i], {
247
+ start: child.start,
248
+ end: child.end
249
+ });
308
250
  const transformedParams = depsFn.params;
309
251
  for (const [i, transformedParam] of transformedParams.entries()) {
310
252
  const transformedName = transformedParam.name;
@@ -313,20 +255,21 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
313
255
  const transformedDeps = depsFn.body.elements;
314
256
  for (const [i, originalDep] of declaration.deps.entries()) {
315
257
  let transformedDep = transformedDeps[i];
316
- if (transformedDep.type === "UnaryExpression" && transformedDep.operator === "void") transformedDep = {
317
- type: "Identifier",
318
- name: "undefined",
319
- loc: transformedDep.loc,
320
- start: transformedDep.start,
321
- end: transformedDep.end
322
- };
323
- else if (isInfer(transformedDep)) transformedDep.name = "__Infer";
258
+ if (transformedDep.type === "UnaryExpression" && transformedDep.operator === "void") {
259
+ const undefinedDep = b.identifier("undefined");
260
+ undefinedDep.start = transformedDep.start;
261
+ undefinedDep.end = transformedDep.end;
262
+ transformedDep = undefinedDep;
263
+ } else if (isInfer(transformedDep)) transformedDep.name = "__Infer";
324
264
  if (originalDep.replace) originalDep.replace(transformedDep);
325
265
  else Object.assign(originalDep, transformedDep);
326
266
  }
327
267
  return inheritNodeComments(node, declaration.decl);
328
268
  }).filter((node) => !!node);
329
- if (program.body.length === 0) return "export { };";
269
+ if (program.body.length === 0) return {
270
+ code: "export { };",
271
+ map: null
272
+ };
330
273
  const comments = /* @__PURE__ */ new Set();
331
274
  const commentsValue = /* @__PURE__ */ new Set();
332
275
  for (const id of chunk.moduleIds) {
@@ -342,16 +285,24 @@ function createFakeJsPlugin({ sourcemap, cjsDefault, sideEffects }) {
342
285
  }
343
286
  }
344
287
  if (comments.size) {
345
- program.body[0].leadingComments ||= [];
346
- program.body[0].leadingComments.unshift(...comments);
288
+ program.body[0].comments ||= [];
289
+ program.body[0].comments.unshift(...Array.from(comments, (c) => ({
290
+ type: c.type,
291
+ value: c.value,
292
+ position: "before",
293
+ sameLine: false
294
+ })));
347
295
  }
348
- const result = generate(file, {
349
- sourceMaps: sourcemap,
350
- sourceFileName: chunk.fileName
296
+ const result = print(program, {
297
+ comments: true,
298
+ ...sourcemap && { sourceMaps: {
299
+ source: code,
300
+ sourceFileName: chunk.fileName
301
+ } }
351
302
  });
352
303
  return {
353
304
  code: result.code,
354
- map: result.map
305
+ map: result.map ?? null
355
306
  };
356
307
  }
357
308
  function registerDeclaration(info) {
@@ -400,7 +351,7 @@ function collectPatternNames(node) {
400
351
  return [];
401
352
  }
402
353
  function isTypeOnlyExport(node, specifier) {
403
- return node.exportKind === "type" || "exportKind" in specifier && specifier.exportKind === "type";
354
+ return node.exportKind === "type" || specifier.exportKind === "type";
404
355
  }
405
356
  async function collectExportInfo(context, node, id, info) {
406
357
  if (node.type === "ExportNamedDeclaration") {
@@ -411,20 +362,15 @@ async function collectExportInfo(context, node, id, info) {
411
362
  const source = await resolveExportSource(context, node.source, id);
412
363
  for (const specifier of node.specifiers) {
413
364
  const typeOnly = isTypeOnlyExport(node, specifier);
414
- if (specifier.type === "ExportSpecifier") {
415
- const exported = resolveString(specifier.exported);
416
- const local = resolveString(specifier.local);
417
- if (source) info.reExports.push({
418
- source,
419
- local,
420
- exported,
421
- typeOnly
422
- });
423
- else info.exports.set(exported, typeOnly || info.typeOnlyLocals.has(local));
424
- } else {
425
- const exported = resolveString(specifier.exported);
426
- info.exports.set(exported, typeOnly);
427
- }
365
+ const exported = nameOf(specifier.exported);
366
+ const local = nameOf(specifier.local);
367
+ if (source) info.reExports.push({
368
+ source,
369
+ local,
370
+ exported,
371
+ typeOnly
372
+ });
373
+ else info.exports.set(exported, typeOnly || info.typeOnlyLocals.has(local));
428
374
  }
429
375
  return;
430
376
  }
@@ -432,11 +378,17 @@ async function collectExportInfo(context, node, id, info) {
432
378
  info.exports.set("default", false);
433
379
  return;
434
380
  }
435
- if (node.type === "ExportAllDeclaration") info.exportAlls.push({
436
- source: await resolveExportSource(context, node.source, id),
437
- rawSource: node.source.value,
438
- typeOnly: node.exportKind === "type"
439
- });
381
+ if (node.type === "ExportAllDeclaration") {
382
+ if (node.exported) {
383
+ info.exports.set(nameOf(node.exported), node.exportKind === "type");
384
+ return;
385
+ }
386
+ info.exportAlls.push({
387
+ source: await resolveExportSource(context, node.source, id),
388
+ rawSource: node.source.value,
389
+ typeOnly: node.exportKind === "type"
390
+ });
391
+ }
440
392
  }
441
393
  async function resolveExportSource(context, source, importer) {
442
394
  if (!source) return;
@@ -508,11 +460,8 @@ function setExportTypeOnly(exports, name, typeOnly) {
508
460
  */
509
461
  function collectParams(node) {
510
462
  const typeParams = [];
511
- walkAST(node, { leave(node) {
512
- if ("typeParameters" in node && node.typeParameters?.type === "TSTypeParameterDeclaration") typeParams.push(...node.typeParameters.params.map(({ name }) => typeof name === "string" ? {
513
- type: "Identifier",
514
- name
515
- } : name));
463
+ walk(node, { leave(node) {
464
+ if ("typeParameters" in node && node.typeParameters?.type === "TSTypeParameterDeclaration") typeParams.push(...node.typeParameters.params.map(({ name }) => name));
516
465
  } });
517
466
  const paramMap = /* @__PURE__ */ new Map();
518
467
  for (const typeParam of typeParams) {
@@ -530,20 +479,28 @@ async function collectDependencies(context, node, importer, namespaceStmts, chil
530
479
  const deps = /* @__PURE__ */ new Set();
531
480
  const seen = /* @__PURE__ */ new Set();
532
481
  const preserveImportTypeCache = /* @__PURE__ */ new Map();
482
+ const importSources = /* @__PURE__ */ new Set();
483
+ walk(node, { TSImportType(node) {
484
+ importSources.add(node.source.value);
485
+ } });
486
+ if (importSources.size) await Promise.all(Array.from(importSources, async (source) => {
487
+ const resolved = await context.resolve(source, importer);
488
+ preserveImportTypeCache.set(source, !resolved || !!resolved.external);
489
+ }));
533
490
  const inferredStack = [];
534
491
  let currentInferred = /* @__PURE__ */ new Set();
535
492
  function isInferred(node) {
536
493
  return node.type === "Identifier" && currentInferred.has(node.name);
537
494
  }
538
- await walkASTAsync(node, {
495
+ walk(node, {
539
496
  enter(node) {
540
497
  if (node.type === "TSConditionalType") {
541
498
  const inferred = collectInferredNames(node.extendsType);
542
499
  inferredStack.push(inferred);
543
500
  }
544
- return Promise.resolve();
545
501
  },
546
- async leave(node, parent) {
502
+ leave(node, path) {
503
+ const { parent } = path;
547
504
  if (node.type === "TSConditionalType") inferredStack.pop();
548
505
  else if (parent?.type === "TSConditionalType") {
549
506
  const trueBranch = parent.trueType === node;
@@ -554,16 +511,14 @@ async function collectDependencies(context, node, importer, namespaceStmts, chil
554
511
  } else if (node.type === "TSInterfaceDeclaration" && node.extends) for (const heritage of node.extends || []) addDependency(heritage.expression);
555
512
  else if (node.type === "ClassDeclaration") {
556
513
  if (node.superClass) addDependency(node.superClass);
557
- if (node.implements) for (const implement of node.implements) {
558
- if (implement.type === "ClassImplements") throw new Error("Unexpected Flow syntax");
559
- addDependency(implement.expression);
560
- }
561
- } else if (isTypeOf(node, [
562
- "ObjectMethod",
563
- "ObjectProperty",
564
- "ClassProperty",
514
+ if (node.implements) for (const implement of node.implements) addDependency(implement.expression);
515
+ } else if (is.oneOf(node, [
516
+ "Property",
517
+ "PropertyDefinition",
518
+ "TSAbstractPropertyDefinition",
519
+ "MethodDefinition",
520
+ "TSAbstractMethodDefinition",
565
521
  "TSPropertySignature",
566
- "TSDeclareMethod",
567
522
  "TSMethodSignature"
568
523
  ])) {
569
524
  if (node.computed && isReferenceId(node.key)) addDependency(node.key);
@@ -580,7 +535,7 @@ async function collectDependencies(context, node, importer, namespaceStmts, chil
580
535
  case "TSImportType": {
581
536
  seen.add(node);
582
537
  const { source, qualifier } = node;
583
- const dep = await importNamespace(context, importer, node, qualifier, source, namespaceStmts, identifierMap, preserveImportTypeCache);
538
+ const dep = importNamespace(node, qualifier, source, namespaceStmts, identifierMap, preserveImportTypeCache);
584
539
  if (dep) addDependency(dep);
585
540
  break;
586
541
  }
@@ -594,49 +549,25 @@ async function collectDependencies(context, node, importer, namespaceStmts, chil
594
549
  deps.add(node);
595
550
  }
596
551
  }
597
- async function importNamespace(context, importer, node, imported, source, namespaceStmts, identifierMap, preserveCache) {
598
- let preserve = preserveCache.get(source.value);
599
- if (preserve === void 0) {
600
- const resolved = await context.resolve(source.value, importer);
601
- preserve = !resolved || !!resolved.external;
602
- preserveCache.set(source.value, preserve);
603
- }
604
- if (preserve) return;
552
+ function importNamespace(node, imported, source, namespaceStmts, identifierMap, preserveCache) {
553
+ if (preserveCache.get(source.value) ?? true) return;
605
554
  const sourceText = source.value.replaceAll(/\W/g, "_");
606
- let local = {
607
- type: "Identifier",
608
- name: `_$${isIdentifierName(source.value) ? source.value : `${sourceText}${getIdentifierIndex(identifierMap, sourceText)}`}`
609
- };
555
+ const localName = `_$${isIdentifierName(source.value) ? source.value : `${sourceText}${getIdentifierIndex(identifierMap, sourceText)}`}`;
556
+ let local = b.identifier(localName);
610
557
  if (namespaceStmts.has(source.value)) local = namespaceStmts.get(source.value).local;
611
558
  else namespaceStmts.set(source.value, {
612
- stmt: {
613
- type: "ImportDeclaration",
614
- specifiers: [{
615
- type: "ImportNamespaceSpecifier",
616
- local
617
- }],
618
- source,
619
- attributes: null
620
- },
559
+ stmt: b.importDeclaration([b.importNamespaceSpecifier(local)], source),
621
560
  local
622
561
  });
623
562
  if (imported) {
624
563
  const importedLeft = getIdFromTSEntityName(imported);
625
564
  if (imported.type === "ThisExpression" || importedLeft.type === "ThisExpression") throw new Error("Cannot import `this` from module.");
626
- overwriteNode(importedLeft, {
627
- type: "TSQualifiedName",
628
- left: local,
629
- right: { ...importedLeft }
630
- });
565
+ overwriteNode(importedLeft, b.tsQualifiedName(local, { ...importedLeft }));
631
566
  local = imported;
632
567
  }
633
568
  let replacement = node;
634
569
  if (node.typeArguments) {
635
- overwriteNode(node, {
636
- type: "TSTypeReference",
637
- typeName: local,
638
- typeArguments: node.typeArguments
639
- });
570
+ overwriteNode(node, b.tsTypeReference(local, node.typeArguments));
640
571
  replacement = local;
641
572
  } else overwriteNode(node, local);
642
573
  return {
@@ -648,12 +579,12 @@ async function importNamespace(context, importer, node, imported, source, namesp
648
579
  }
649
580
  function isChildSymbol(node, parent) {
650
581
  if (node.type === "Identifier") return true;
651
- if (isTypeOf(parent, ["TSPropertySignature", "TSMethodSignature"]) && parent.key === node) return true;
582
+ if (is.oneOf(parent, ["TSPropertySignature", "TSMethodSignature"]) && parent.key === node) return true;
652
583
  return false;
653
584
  }
654
585
  function collectInferredNames(node) {
655
586
  const inferred = [];
656
- walkAST(node, { enter(node) {
587
+ walk(node, { enter(node) {
657
588
  if (node.type === "TSInferType" && node.typeParameter) inferred.push(node.typeParameter.name.name);
658
589
  } });
659
590
  return inferred;
@@ -662,6 +593,10 @@ const REFERENCE_RE = /\/\s*<reference\s+(?:path|types)=/;
662
593
  function collectReferenceDirectives(comment, negative = false) {
663
594
  return comment.filter((c) => REFERENCE_RE.test(c.value) !== negative);
664
595
  }
596
+ const SOURCE_MAP_PRAGMA_RE = /^#\s*source(?:Mapping)?URL=/;
597
+ function isSourceMapPragma(comment) {
598
+ return SOURCE_MAP_PRAGMA_RE.test(comment.value);
599
+ }
665
600
  function isCjsDtsInputSyntax(node) {
666
601
  return node.type === "TSExportAssignment" || node.type === "TSImportEqualsDeclaration" && node.moduleReference.type === "TSExternalModuleReference";
667
602
  }
@@ -682,19 +617,16 @@ function isRuntimeBindingArrayExpression(node) {
682
617
  */
683
618
  function isRuntimeBindingArrayElements(elements) {
684
619
  const [declarationId, deps, children, effect] = elements;
685
- return declarationId?.type === "NumericLiteral" && deps?.type === "ArrowFunctionExpression" && children?.type === "ArrayExpression" && (!effect || effect.type === "CallExpression");
620
+ return is.NumericLiteral(declarationId) && deps?.type === "ArrowFunctionExpression" && children?.type === "ArrayExpression" && (!effect || effect.type === "CallExpression");
686
621
  }
687
622
  function runtimeBindingArrayExpression(elements) {
688
- return {
689
- type: "ArrayExpression",
690
- elements
691
- };
623
+ return b.arrayExpression([...elements]);
692
624
  }
693
625
  function isThisExpression(node) {
694
- return isIdentifierOf(node, "this") || node.type === "ThisExpression" || node.type === "MemberExpression" && isThisExpression(node.object);
626
+ return is.Identifier(node, "this") || node.type === "ThisExpression" || node.type === "MemberExpression" && isThisExpression(node.object);
695
627
  }
696
628
  function isInfer(node) {
697
- return isIdentifierOf(node, "infer");
629
+ return is.Identifier(node, "infer");
698
630
  }
699
631
  function TSEntityNameToRuntime(node) {
700
632
  if (node.type === "Identifier" || node.type === "ThisExpression") return node;
@@ -711,7 +643,7 @@ function getIdFromTSEntityName(node) {
711
643
  return getIdFromTSEntityName(node.left);
712
644
  }
713
645
  function isReferenceId(node) {
714
- return isTypeOf(node, ["Identifier", "MemberExpression"]);
646
+ return is.oneOf(node, ["Identifier", "MemberExpression"]);
715
647
  }
716
648
  function isHelperImport(node) {
717
649
  return node.type === "ImportDeclaration" && node.specifiers.every((spec) => spec.type === "ImportSpecifier" && spec.imported.type === "Identifier" && ["__exportAll", "__reExport"].includes(spec.local.name));
@@ -724,7 +656,7 @@ function patchImportExport(node, exportInfo, cjsDefault) {
724
656
  if (node.type === "ImportDeclaration" && node.specifiers.length) {
725
657
  for (const specifier of node.specifiers) if (isInfer(specifier.local)) specifier.local.name = "__Infer";
726
658
  }
727
- if (isTypeOf(node, [
659
+ if (is.oneOf(node, [
728
660
  "ImportDeclaration",
729
661
  "ExportAllDeclaration",
730
662
  "ExportNamedDeclaration"
@@ -732,7 +664,7 @@ function patchImportExport(node, exportInfo, cjsDefault) {
732
664
  if (node.type === "ExportAllDeclaration" && node.source && exportInfo.typeOnlyExportAllSources.has(node.source.value)) node.exportKind = "type";
733
665
  if (node.type === "ExportNamedDeclaration" && exportInfo.typeOnlyNames.size) {
734
666
  for (const spec of node.specifiers) {
735
- const name = resolveString(spec.exported);
667
+ const name = nameOf(spec.exported);
736
668
  if (exportInfo.typeOnlyNames.has(name)) if (spec.type === "ExportSpecifier") spec.exportKind = "type";
737
669
  else node.exportKind = "type";
738
670
  }
@@ -742,10 +674,10 @@ function patchImportExport(node, exportInfo, cjsDefault) {
742
674
  node.source.value = filename_dts_to(node.source.value, "js");
743
675
  return node;
744
676
  }
745
- if (cjsDefault && node.type === "ExportNamedDeclaration" && !node.source && node.specifiers.length === 1 && node.specifiers[0].type === "ExportSpecifier" && resolveString(node.specifiers[0].exported) === "default") return {
746
- type: "TSExportAssignment",
747
- expression: node.specifiers[0].local
748
- };
677
+ if (cjsDefault && node.type === "ExportNamedDeclaration" && !node.source && node.specifiers.length === 1 && node.specifiers[0].type === "ExportSpecifier" && nameOf(node.specifiers[0].exported) === "default") {
678
+ const defaultExport = node.specifiers[0];
679
+ return b.tsExportAssignment(defaultExport.local);
680
+ }
749
681
  }
750
682
  }
751
683
  function normalizeTypeOnlyExport(node) {
@@ -764,27 +696,15 @@ function patchTsNamespace(nodes) {
764
696
  if (!result) continue;
765
697
  const [binding, exports] = result;
766
698
  if (!exports.properties.length) continue;
767
- nodes[i] = {
768
- type: "TSModuleDeclaration",
769
- id: binding,
699
+ const namespaceExport = b.exportNamedDeclaration(null, exports.properties.filter((property) => property.type === "Property").map((property) => {
700
+ const local = property.value.body;
701
+ const exported = property.key;
702
+ return b.exportSpecifier(local, exported);
703
+ }));
704
+ nodes[i] = b.tsModuleDeclaration(binding, b.tsModuleBlock([namespaceExport]), {
770
705
  kind: "namespace",
771
- declare: true,
772
- body: {
773
- type: "TSModuleBlock",
774
- body: [{
775
- type: "ExportNamedDeclaration",
776
- specifiers: exports.properties.filter((property) => property.type === "ObjectProperty").map((property) => {
777
- return {
778
- type: "ExportSpecifier",
779
- local: property.value.body,
780
- exported: property.key
781
- };
782
- }),
783
- source: null,
784
- declaration: null
785
- }]
786
- }
787
- };
706
+ declare: true
707
+ });
788
708
  }
789
709
  return nodes.filter((node) => !removed.has(node));
790
710
  }
@@ -798,30 +718,10 @@ function getExportAllNamespace(node) {
798
718
  function patchReExport(nodes) {
799
719
  const exportsNames = /* @__PURE__ */ new Map();
800
720
  for (const [i, node] of nodes.entries()) if (node.type === "ImportDeclaration" && node.specifiers.length === 1 && node.specifiers[0].type === "ImportSpecifier" && node.specifiers[0].local.type === "Identifier" && node.specifiers[0].local.name.endsWith("_exports")) exportsNames.set(node.specifiers[0].local.name, node.specifiers[0].local.name);
801
- else if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && isIdentifierOf(node.expression.callee, "__reExport")) {
721
+ else if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && is.Identifier(node.expression.callee, "__reExport")) {
802
722
  const args = node.expression.arguments;
803
723
  exportsNames.set(args[0].name, args[1].name);
804
- } else if (node.type === "VariableDeclaration" && node.declarations.length === 1 && node.declarations[0].init?.type === "MemberExpression" && node.declarations[0].init.object.type === "Identifier" && exportsNames.has(node.declarations[0].init.object.name)) nodes[i] = {
805
- type: "TSTypeAliasDeclaration",
806
- id: {
807
- type: "Identifier",
808
- name: node.declarations[0].id.name
809
- },
810
- typeAnnotation: {
811
- type: "TSTypeReference",
812
- typeName: {
813
- type: "TSQualifiedName",
814
- left: {
815
- type: "Identifier",
816
- name: exportsNames.get(node.declarations[0].init.object.name)
817
- },
818
- right: {
819
- type: "Identifier",
820
- name: node.declarations[0].init.property.name
821
- }
822
- }
823
- }
824
- };
724
+ } else if (node.type === "VariableDeclaration" && node.declarations.length === 1 && node.declarations[0].init?.type === "MemberExpression" && node.declarations[0].init.object.type === "Identifier" && exportsNames.has(node.declarations[0].init.object.name)) nodes[i] = b.tsTypeAliasDeclaration(b.identifier(node.declarations[0].id.name), b.tsTypeReference(b.tsQualifiedName(b.identifier(exportsNames.get(node.declarations[0].init.object.name)), b.identifier(node.declarations[0].init.property.name))));
825
725
  else if (node.type === "ExportNamedDeclaration" && node.specifiers.length === 1 && node.specifiers[0].type === "ExportSpecifier" && node.specifiers[0].local.type === "Identifier" && exportsNames.has(node.specifiers[0].local.name)) node.specifiers[0].local.name = exportsNames.get(node.specifiers[0].local.name);
826
726
  return nodes;
827
727
  }
@@ -836,54 +736,27 @@ function rewriteImportExport(node, set) {
836
736
  node.exportKind = "value";
837
737
  return true;
838
738
  } else if (node.type === "TSImportEqualsDeclaration") {
839
- if (node.moduleReference.type === "TSExternalModuleReference") set({
840
- type: "ImportDeclaration",
841
- specifiers: [{
842
- type: "ImportDefaultSpecifier",
843
- local: node.id
844
- }],
845
- source: node.moduleReference.expression
846
- });
739
+ if (node.moduleReference.type === "TSExternalModuleReference") set(b.importDeclaration([b.importDefaultSpecifier(node.id)], node.moduleReference.expression));
847
740
  return true;
848
741
  } else if (node.type === "TSExportAssignment" && node.expression.type === "Identifier") {
849
- set({
850
- type: "ExportNamedDeclaration",
851
- specifiers: [{
852
- type: "ExportSpecifier",
853
- local: node.expression,
854
- exported: {
855
- type: "Identifier",
856
- name: "default"
857
- }
858
- }]
859
- });
742
+ set(b.exportNamedDeclaration(null, [b.exportSpecifier(node.expression, b.identifier("default"))]));
860
743
  return true;
861
744
  } else if (node.type === "ExportDefaultDeclaration" && node.declaration.type === "Identifier") {
862
- set({
863
- type: "ExportNamedDeclaration",
864
- specifiers: [{
865
- type: "ExportSpecifier",
866
- local: node.declaration,
867
- exported: {
868
- type: "Identifier",
869
- name: "default"
870
- }
871
- }]
872
- });
745
+ set(b.exportNamedDeclaration(null, [b.exportSpecifier(node.declaration, b.identifier("default"))]));
873
746
  return true;
874
747
  }
875
748
  return false;
876
749
  }
877
750
  function overwriteNode(node, newNode) {
878
- for (const key of Object.keys(node)) delete node[key];
751
+ for (const key of Object.keys(node)) Reflect.deleteProperty(node, key);
879
752
  Object.assign(node, newNode);
880
753
  return node;
881
754
  }
882
755
  function inheritNodeComments(oldNode, newNode) {
883
- newNode.leadingComments ||= [];
884
- const leadingComments = oldNode.leadingComments?.filter((comment) => comment.value.startsWith("#"));
885
- if (leadingComments) newNode.leadingComments.unshift(...leadingComments);
886
- newNode.leadingComments = collectReferenceDirectives(newNode.leadingComments, true);
756
+ newNode.comments ||= [];
757
+ const pragmas = oldNode.comments?.filter((comment) => comment.position === "before" && comment.value.startsWith("#") && !isSourceMapPragma(comment));
758
+ if (pragmas) newNode.comments.unshift(...pragmas);
759
+ newNode.comments = newNode.comments.filter((comment) => !REFERENCE_RE.test(comment.value) && !isSourceMapPragma(comment));
887
760
  return newNode;
888
761
  }
889
762
  function getIdentifierIndex(identifierMap, name) {
@@ -930,7 +803,19 @@ async function runTsgo(rootDir, tsconfig, sourcemap, tsgoPath) {
930
803
  ];
931
804
  debug$3("[tsgo] args %o", args);
932
805
  await spawnAsync(tsgo, args, { stdio: "inherit" });
933
- return tsgoDist;
806
+ return {
807
+ path: tsgoDist,
808
+ async dispose() {
809
+ if (debug$3.enabled) debug$3("[tsgo] skip cleanup of tsgoDist", tsgoDist);
810
+ else {
811
+ debug$3("[tsgo] disposing tsgoDist", tsgoDist);
812
+ await rm(tsgoDist, {
813
+ recursive: true,
814
+ force: true
815
+ }).catch(() => {});
816
+ }
817
+ }
818
+ };
934
819
  }
935
820
  //#endregion
936
821
  //#region src/generate.ts
@@ -955,12 +840,12 @@ function createGeneratePlugin({ entry, tsconfig, tsconfigRaw, build, incremental
955
840
  let rpc;
956
841
  let tscModule;
957
842
  let tscContext;
958
- let tsgoDist;
843
+ let tsgoContext;
959
844
  const rootDir = tsconfig ? path.dirname(tsconfig) : cwd;
960
845
  return {
961
846
  name: "rolldown-plugin-dts:generate",
962
847
  async buildStart(options) {
963
- if (tsgo) tsgoDist = await runTsgo(rootDir, tsconfig, sourcemap, tsgo.path);
848
+ if (tsgo) tsgoContext = await runTsgo(rootDir, tsconfig, sourcemap, tsgo.path);
964
849
  else if (!oxc) if (parallel) {
965
850
  childProcess = fork(new URL(WORKER_URL, import.meta.url), { stdio: "inherit" });
966
851
  rpc = (await import("birpc")).createBirpc({}, {
@@ -1016,14 +901,16 @@ function createGeneratePlugin({ entry, tsconfig, tsconfigRaw, build, incremental
1016
901
  ]
1017
902
  } },
1018
903
  handler(code, id) {
1019
- if (!RE_JS.test(id) || emitJs) {
904
+ const jsFile = RE_JS.test(id);
905
+ if (!jsFile || emitJs) {
1020
906
  const mod = this.getModuleInfo(id);
1021
907
  const isEntry = entryMatcher ? entryMatcher(path.relative(cwd, id)) : !!mod?.isEntry;
1022
908
  const dtsId = filename_to_dts(id);
1023
909
  dtsMap.set(dtsId, {
1024
910
  code,
1025
911
  id,
1026
- isEntry
912
+ isEntry,
913
+ jsFile
1027
914
  });
1028
915
  debug$2("register dts source: %s", id);
1029
916
  if (isEntry) {
@@ -1047,14 +934,19 @@ function createGeneratePlugin({ entry, tsconfig, tsconfigRaw, build, incremental
1047
934
  exclude: [RE_NODE_MODULES]
1048
935
  } },
1049
936
  async handler(dtsId) {
1050
- if (!dtsMap.has(dtsId)) return;
1051
- const { code, id } = dtsMap.get(dtsId);
937
+ const module = dtsMap.get(dtsId);
938
+ if (!module) return;
939
+ const { code, id, jsFile } = module;
940
+ if (jsFile && await access(dtsId).then(() => true).catch(() => false)) {
941
+ debug$2("dts file already exists for %s, skipping generation", id);
942
+ return;
943
+ }
1052
944
  let dtsCode;
1053
945
  let map;
1054
946
  debug$2("generate dts %s from %s", dtsId, id);
1055
947
  if (tsgo) {
1056
948
  if (RE_VUE.test(id)) throw new Error("tsgo does not support Vue files.");
1057
- const dtsPath = path.resolve(tsgoDist, path.relative(path.resolve(rootDir), filename_to_dts(id)));
949
+ const dtsPath = path.resolve(tsgoContext.path, path.relative(path.resolve(rootDir), filename_to_dts(id)));
1058
950
  if (!existsSync(dtsPath)) {
1059
951
  debug$2("[tsgo]", dtsPath, "is missing");
1060
952
  throw new Error(`tsgo did not generate dts file for ${id}, please check your tsconfig.`);
@@ -1132,11 +1024,8 @@ export { __json_default_export as default }`;
1132
1024
  } : void 0,
1133
1025
  async buildEnd() {
1134
1026
  childProcess?.kill();
1135
- if (!debug$2.enabled && tsgoDist) await rm(tsgoDist, {
1136
- recursive: true,
1137
- force: true
1138
- }).catch(() => {});
1139
- tsgoDist = void 0;
1027
+ await tsgoContext?.dispose();
1028
+ tsgoContext = void 0;
1140
1029
  if (newContext) tscContext = void 0;
1141
1030
  },
1142
1031
  watchChange(id) {
@@ -1148,8 +1037,7 @@ function collectJsonExportMap(code) {
1148
1037
  const exportMap = /* @__PURE__ */ new Map();
1149
1038
  const { program } = parse(code, {
1150
1039
  sourceType: "module",
1151
- plugins: [["typescript", { dts: true }]],
1152
- errorRecovery: true
1040
+ lang: "dts"
1153
1041
  });
1154
1042
  for (const decl of program.body) if (decl.type === "ExportNamedDeclaration") {
1155
1043
  if (decl.declaration) {
@@ -1167,11 +1055,11 @@ function collectJsonExports(code) {
1167
1055
  const exports = [];
1168
1056
  const { program } = parse(code, {
1169
1057
  sourceType: "module",
1170
- plugins: [["typescript", { dts: true }]]
1058
+ lang: "dts"
1171
1059
  });
1172
1060
  const members = program.body[0].declarations[0].id.typeAnnotation.typeAnnotation.members;
1173
1061
  for (const member of members) if (member.key.type === "Identifier") exports.push(member.key.name);
1174
- else if (member.key.type === "StringLiteral") exports.push(member.key.value);
1062
+ else if (is.StringLiteral(member.key)) exports.push(member.key.value);
1175
1063
  return exports;
1176
1064
  }
1177
1065
  //#endregion