@cplieger/deadset-ts 3.12.0 → 3.12.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/src/graph.js CHANGED
@@ -32,15 +32,15 @@ const SWEPT = {
32
32
  };
33
33
  /**
34
34
  * Whether a root of each kind names a caller, which holds it live under both relations: a
35
- * tool reads the configuration it loads, a runtime runs a test file, a setup file and a
36
- * worker, and a configured root asserts a caller. The other kinds only suppose a consumer
37
- * that imports what a manifest entry, a binary or an entry file exports, or names a
38
- * library's published API, so such a root is live under reachability alone.
35
+ * tool reads the configuration it loads, a runtime runs a test file, a setup file, a
36
+ * worker and a command, the manifest names what enters the package, and an entry file, a
37
+ * configured root and a pattern assert a caller. A library's published API only supposes
38
+ * a consumer the run may not see, so it is live under reachability alone.
39
39
  */
40
40
  const NAMES_A_CALLER = {
41
- "entry-file": false,
42
- "manifest-entry": false,
43
- "manifest-binary": false,
41
+ "entry-file": true,
42
+ "manifest-entry": true,
43
+ "manifest-binary": true,
44
44
  "published-api": false,
45
45
  configured: true,
46
46
  pattern: true,
package/dist/src/roots.js CHANGED
@@ -4,9 +4,8 @@
4
4
  *
5
5
  * Every root seeds REACHABILITY, and no root counts as a reference. A root of a kind
6
6
  * that names a caller is live under reference counting as well, which the sweep
7
- * decides; a root that only supposes a consumer is not, so an exported declaration
8
- * something outside the program reaches is live under reachability and still a
9
- * candidate under reference counting.
7
+ * decides; the published API only supposes a consumer, so a published export is live
8
+ * under reachability and still a candidate under reference counting.
10
9
  */
11
10
  import { aliasChains } from "./alias-chain.js";
12
11
  import { entryPoints } from "./entry-points.js";
@@ -94,6 +93,7 @@ function childrenOf(held) {
94
93
  * is a root with everything its module exports: each name of the module's export
95
94
  * table, and where a name is a re-export, every link of the chain to the declaration
96
95
  * it carries, so a re-exported declaration is a root of the file that publishes it.
96
+ * In a library, what a published file exports is rooted by the published API alone.
97
97
  * A file a runtime executes without reading its exports, a test file or a worker, is
98
98
  * a root by itself.
99
99
  */
@@ -116,14 +116,19 @@ export function roots(project, held, targetRoot, options) {
116
116
  entered.push({ file, kind, source, exports });
117
117
  };
118
118
  const published = [];
119
- const publishes = (entry) => entry.published &&
119
+ const publishes = (entry) => options.publishedAPI &&
120
+ entry.published &&
120
121
  (options.manifest.declaresExports ? entry.member.startsWith("exports") : true);
122
+ for (const entry of options.manifest.entries) {
123
+ if (publishes(entry)) {
124
+ published.push(...files.named(entry.path));
125
+ }
126
+ }
127
+ const publishedNames = new Set(published.map((file) => file.fileName));
121
128
  for (const entry of options.manifest.entries) {
122
129
  for (const file of files.named(entry.path)) {
123
- enter(file, entry.role === "run" ? "manifest-binary" : "manifest-entry", entry.member, true);
124
- if (options.publishedAPI && publishes(entry)) {
125
- published.push(file);
126
- }
130
+ const kind = entry.role === "run" ? "manifest-binary" : "manifest-entry";
131
+ enter(file, kind, entry.member, !publishedNames.has(file.fileName));
127
132
  }
128
133
  }
129
134
  for (const pattern of options.entryFiles) {
package/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cplieger/deadset-ts",
3
- "version": "3.12.0",
3
+ "version": "3.12.1",
4
4
  "license": "GPL-3.0-or-later",
5
5
  "exports": {
6
6
  ".": "./src/index.ts"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cplieger/deadset-ts",
3
- "version": "3.12.0",
3
+ "version": "3.12.1",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Deterministic dead-code analysis for TypeScript, class and type members included",
package/src/graph.ts CHANGED
@@ -39,15 +39,15 @@ const SWEPT: Readonly<Record<SymbolKind, boolean>> = {
39
39
 
40
40
  /**
41
41
  * Whether a root of each kind names a caller, which holds it live under both relations: a
42
- * tool reads the configuration it loads, a runtime runs a test file, a setup file and a
43
- * worker, and a configured root asserts a caller. The other kinds only suppose a consumer
44
- * that imports what a manifest entry, a binary or an entry file exports, or names a
45
- * library's published API, so such a root is live under reachability alone.
42
+ * tool reads the configuration it loads, a runtime runs a test file, a setup file, a
43
+ * worker and a command, the manifest names what enters the package, and an entry file, a
44
+ * configured root and a pattern assert a caller. A library's published API only supposes
45
+ * a consumer the run may not see, so it is live under reachability alone.
46
46
  */
47
47
  const NAMES_A_CALLER: Readonly<Record<RootKind, boolean>> = {
48
- "entry-file": false,
49
- "manifest-entry": false,
50
- "manifest-binary": false,
48
+ "entry-file": true,
49
+ "manifest-entry": true,
50
+ "manifest-binary": true,
51
51
  "published-api": false,
52
52
  configured: true,
53
53
  pattern: true,
package/src/roots.ts CHANGED
@@ -4,9 +4,8 @@
4
4
  *
5
5
  * Every root seeds REACHABILITY, and no root counts as a reference. A root of a kind
6
6
  * that names a caller is live under reference counting as well, which the sweep
7
- * decides; a root that only supposes a consumer is not, so an exported declaration
8
- * something outside the program reaches is live under reachability and still a
9
- * candidate under reference counting.
7
+ * decides; the published API only supposes a consumer, so a published export is live
8
+ * under reachability and still a candidate under reference counting.
10
9
  */
11
10
 
12
11
  import type { SourceFile } from "@typescript/native/unstable/ast";
@@ -23,9 +22,9 @@ import { sourceFilesOf } from "./source-files.ts";
23
22
  export type RootKind =
24
23
  /** A file `ts.entry_files` names, and what it exports. */
25
24
  | "entry-file"
26
- /** A file the manifest names as an importable entry point, and what it exports. */
25
+ /** A file the manifest names as an importable entry point, and what it exports outside the published API. */
27
26
  | "manifest-entry"
28
- /** A file the manifest names as a command, and what it exports. */
27
+ /** A file the manifest names as a command, and what it exports outside the published API. */
29
28
  | "manifest-binary"
30
29
  /** A declaration a consumer of a library target can name. */
31
30
  | "published-api"
@@ -168,6 +167,7 @@ function childrenOf(held: Inventory): ReadonlyMap<string, readonly InventorySymb
168
167
  * is a root with everything its module exports: each name of the module's export
169
168
  * table, and where a name is a re-export, every link of the chain to the declaration
170
169
  * it carries, so a re-exported declaration is a root of the file that publishes it.
170
+ * In a library, what a published file exports is rooted by the published API alone.
171
171
  * A file a runtime executes without reading its exports, a test file or a worker, is
172
172
  * a root by itself.
173
173
  */
@@ -198,14 +198,19 @@ export function roots<Brand>(
198
198
 
199
199
  const published: SourceFile[] = [];
200
200
  const publishes = (entry: ManifestEntry): boolean =>
201
+ options.publishedAPI &&
201
202
  entry.published &&
202
203
  (options.manifest.declaresExports ? entry.member.startsWith("exports") : true);
204
+ for (const entry of options.manifest.entries) {
205
+ if (publishes(entry)) {
206
+ published.push(...files.named(entry.path));
207
+ }
208
+ }
209
+ const publishedNames = new Set(published.map((file) => file.fileName));
203
210
  for (const entry of options.manifest.entries) {
204
211
  for (const file of files.named(entry.path)) {
205
- enter(file, entry.role === "run" ? "manifest-binary" : "manifest-entry", entry.member, true);
206
- if (options.publishedAPI && publishes(entry)) {
207
- published.push(file);
208
- }
212
+ const kind = entry.role === "run" ? "manifest-binary" : "manifest-entry";
213
+ enter(file, kind, entry.member, !publishedNames.has(file.fileName));
209
214
  }
210
215
  }
211
216
  for (const pattern of options.entryFiles) {