svelte-shaker 0.17.0 → 0.18.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.
- package/README.md +24 -34
- package/dist/analyze.d.ts +11 -261
- package/dist/analyze.js +48 -1533
- package/dist/call-site.d.ts +76 -0
- package/dist/call-site.js +300 -0
- package/dist/crawl.d.ts +67 -0
- package/dist/crawl.js +305 -0
- package/dist/css.d.ts +2 -2
- package/dist/css.js +4 -4
- package/dist/drop-props.d.ts +3 -0
- package/dist/drop-props.js +109 -0
- package/dist/engine.d.ts +1 -1
- package/dist/engine.js +2 -1
- package/dist/escape-scan.d.ts +1 -1
- package/dist/escape-scan.js +24 -34
- package/dist/index.d.ts +5 -7
- package/dist/index.js +7 -6
- package/dist/ir.d.ts +1 -1
- package/dist/model.d.ts +144 -0
- package/dist/model.js +800 -0
- package/dist/mono-rewrite.d.ts +24 -0
- package/dist/mono-rewrite.js +116 -0
- package/dist/mono.d.ts +1 -1
- package/dist/mono.js +53 -3
- package/dist/native-engine.d.ts +4 -4
- package/dist/native-engine.js +6 -7
- package/dist/parse.d.ts +15 -0
- package/dist/parse.js +29 -0
- package/dist/reverse.d.ts +7 -2
- package/dist/reverse.js +10 -8
- package/dist/revert-cascade.d.ts +3 -3
- package/dist/revert-cascade.js +2 -2
- package/dist/rsvelte-parse.js +0 -1
- package/dist/scan.d.ts +1 -1
- package/dist/scan.js +2 -23
- package/dist/substitute.d.ts +57 -0
- package/dist/substitute.js +232 -0
- package/dist/transform.d.ts +11 -24
- package/dist/transform.js +38 -610
- package/dist/unread.d.ts +1 -1
- package/dist/unread.js +2 -2
- package/dist/vite.d.ts +20 -30
- package/dist/vite.js +62 -101
- package/dist/walk-dir.d.ts +10 -0
- package/dist/walk-dir.js +39 -0
- package/dist/whitespace.d.ts +41 -0
- package/dist/whitespace.js +154 -0
- package/package.json +2 -3
- package/dist/svelte_shaker_engine.js +0 -265
- package/dist/svelte_shaker_engine_bg.wasm +0 -0
- package/dist/wasm-engine.d.ts +0 -56
- package/dist/wasm-engine.js +0 -97
package/README.md
CHANGED
|
@@ -49,19 +49,17 @@ npm i -D svelte-shaker # requires svelte@^5
|
|
|
49
49
|
|
|
50
50
|
Nothing else to install. The plugin picks its engine automatically (see
|
|
51
51
|
[Options](#options)): if a **native (napi) Rust** binary loads it runs there —
|
|
52
|
-
parsing with rsvelte in process,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
`parser` let you pin the choice.
|
|
52
|
+
parsing with rsvelte in process, by far the fastest; otherwise the shake runs on the
|
|
53
|
+
**JS engine** with **svelte/compiler**, which needs no prebuilt binary and always
|
|
54
|
+
works. Both shake **byte-identically**, so the fallback costs only build time.
|
|
55
|
+
`engine` and `parser` let you pin the choice.
|
|
57
56
|
|
|
58
57
|
## Usage (Vite)
|
|
59
58
|
|
|
60
59
|
Add the plugin **before** `svelte()`. By default it runs only in `vite build` —
|
|
61
60
|
dev/HMR is a pass-through (opt into dev shaking with the `dev` option, see
|
|
62
61
|
[Options](#options)). The engine is chosen automatically (native Rust if a binary
|
|
63
|
-
loads, else
|
|
64
|
-
cleanly (see [Options](#options)).
|
|
62
|
+
loads, else JS), and every path falls back cleanly (see [Options](#options)).
|
|
65
63
|
|
|
66
64
|
```ts
|
|
67
65
|
// vite.config.ts
|
|
@@ -87,7 +85,7 @@ through your plugin's `resolveId`/`load` hooks; the unused-prop fold / constant
|
|
|
87
85
|
fold / value-set narrowing shake only needs the `transform` swap. The
|
|
88
86
|
environment-free engine and the in-browser playground parse with svelte/compiler
|
|
89
87
|
— the Vite plugin's rsvelte selection is a plugin concern (it loads a Node-only
|
|
90
|
-
|
|
88
|
+
module); the engine takes an optional `parse` argument if you want to swap it.
|
|
91
89
|
|
|
92
90
|
### Options
|
|
93
91
|
|
|
@@ -107,9 +105,9 @@ shaker({
|
|
|
107
105
|
verbose: false, // true = per-file size breakdown after the build
|
|
108
106
|
|
|
109
107
|
// Engine is auto-selected; set these only to pin.
|
|
110
|
-
engine: 'auto', // 'auto' (native Rust if it loads, else
|
|
111
|
-
parser: undefined, // JS
|
|
112
|
-
//
|
|
108
|
+
engine: 'auto', // 'auto' (native Rust if it loads, else JS) | 'js' | 'rust'
|
|
109
|
+
parser: undefined, // JS engine only (native always uses in-process rsvelte);
|
|
110
|
+
// defaults to svelte/compiler; set 'rsvelte' to pin rsvelte instead
|
|
113
111
|
|
|
114
112
|
dev: false, // default off: dev is a pass-through. 'incremental' (re-parse only
|
|
115
113
|
// changed files) | 'coarse' (re-analyze everything) opts in; never monomorphizes
|
|
@@ -120,33 +118,25 @@ That list is exhaustive: any other key **fails the build**, naming the key and t
|
|
|
120
118
|
options that do exist. A typo would otherwise be ignored — and a misspelled
|
|
121
119
|
`preserve` ships the component you meant to protect, over-shaken.
|
|
122
120
|
|
|
123
|
-
- **`engine`** — which engine runs the shake. There are two
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
engine
|
|
129
|
-
|
|
130
|
-
small/medium apps; the **JS** engine needs no boundary crossing, so it wins for a
|
|
131
|
-
large app when the native binary isn't available. **`'auto'`** (default) uses the
|
|
132
|
-
native engine if a binary loads (no size gate), else the WASM engine for a
|
|
133
|
-
small/medium app or the JS engine for a large one. **`'rust'`** forces a Rust
|
|
134
|
-
engine — native if it loads, else WASM (throwing if `@rsvelte/compiler` can't load
|
|
135
|
-
for the WASM fallback); **`'js'`** forces the JS engine. All three are
|
|
121
|
+
- **`engine`** — which engine runs the shake. There are two. The **native (napi
|
|
122
|
+
Rust)** engine parses with rsvelte **in process** and keeps the ASTs Rust-side, so
|
|
123
|
+
no whole-program AST crosses a boundary — by far the fastest — but it ships as a
|
|
124
|
+
per-platform prebuilt binary that may not exist for every install. The **JS**
|
|
125
|
+
engine needs no prebuilt binary and always works. **`'auto'`** (default) uses the
|
|
126
|
+
native engine if a binary loads, else the JS engine. **`'rust'`** forces the native
|
|
127
|
+
engine, throwing if it can't be loaded; **`'js'`** forces the JS engine. Both are
|
|
136
128
|
differentially tested to shake **byte-identically**, so this is **speed-only** — it
|
|
137
129
|
never changes what ships.
|
|
138
|
-
- **`parser`** — how the **JS
|
|
139
|
-
|
|
140
|
-
**
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
only UTF-16 `start`/`end`, so both parsers are differentially tested to produce
|
|
130
|
+
- **`parser`** — how the **JS** engine parses `.svelte`. It does **not** apply to the
|
|
131
|
+
native engine, which always parses with rsvelte in process. It defaults to
|
|
132
|
+
**svelte/compiler**, because on the JS engine rsvelte's parse is ~2× slower with no
|
|
133
|
+
downstream benefit. The choice is **soundness-neutral** — the engine reads only
|
|
134
|
+
UTF-16 `start`/`end`, so both parsers are differentially tested to produce
|
|
144
135
|
**byte-identical** output, never changing what renders. `parser: 'svelte'` also
|
|
145
136
|
forces the native engine **off** (it can't honor svelte/compiler), so the shake uses
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
shake differently on another machine); `parser: 'svelte'` is the explicit opt-out.
|
|
137
|
+
the JS engine. With an explicit `parser: 'rsvelte'` that `@rsvelte/compiler` can't
|
|
138
|
+
satisfy, the plugin **throws** rather than silently swapping (so the same source
|
|
139
|
+
can't shake differently on another machine); `parser: 'svelte'` is the opt-out.
|
|
150
140
|
- **`monomorphize`** — the one shaking knob, **on** by default. A measured
|
|
151
141
|
net-win gate only specializes a component when that strictly shrinks the whole
|
|
152
142
|
program, so monomorphization **never bloats**: whatever the knobs are set to,
|
package/dist/analyze.d.ts
CHANGED
|
@@ -1,191 +1,16 @@
|
|
|
1
|
-
import { type AnyNode, type Parse, type ParseCache, type Root } from './parse.js';
|
|
2
|
-
import { type AnalyzeInput, type ComponentId, type ComponentPlan, type Literal } from './ir.js';
|
|
3
|
-
import { type Span } from './dead.js';
|
|
4
|
-
export type Resolve = (source: string, importer: ComponentId) => Promise<ComponentId | null> | ComponentId | null;
|
|
5
|
-
export type ReadFile = (id: ComponentId) => Promise<string> | string;
|
|
6
|
-
/** Synchronous variants of {@link Resolve}/{@link ReadFile} for callers that
|
|
7
|
-
* cannot await — e.g. an ESLint rule, which runs synchronously. Used by
|
|
8
|
-
* {@link buildAnalyzeInputSync}. */
|
|
9
|
-
export type ResolveSync = (source: string, importer: ComponentId) => ComponentId | null;
|
|
10
|
-
export type ReadFileSync = (id: ComponentId) => string;
|
|
11
|
-
/**
|
|
12
|
-
* The set of input names a child component can ever OBSERVE at runtime (docs
|
|
13
|
-
* §PR4 reverse analysis). In runes there is no `$$props`/`$$restProps`, so a
|
|
14
|
-
* component reads an input only through its `$props()` destructure:
|
|
15
|
-
* - `{ kind: 'names' }` — a clean, rest-free ObjectPattern `$props()` (or no
|
|
16
|
-
* `$props()` at all, giving the empty set): the child can observe EXACTLY
|
|
17
|
-
* these declared external names, so a call-site input NOT in the set can
|
|
18
|
-
* never be seen and is safe to drop;
|
|
19
|
-
* - `{ kind: 'all' }` — anything we cannot pin down: a `...rest` (captures
|
|
20
|
-
* undeclared inputs), an Identifier/Array binding (`let p = $props()`),
|
|
21
|
-
* more than one `$props()` call, `$props()` outside a `let <pat> = …`
|
|
22
|
-
* declarator, or a component that observes slotted content outside `$props()`
|
|
23
|
-
* — a legacy `<slot>` element or a `$$slots` read (both legal in runes mode).
|
|
24
|
-
* Then any input might be observed, so nothing is dropped.
|
|
25
|
-
*/
|
|
26
|
-
export type ReachableInputs = {
|
|
27
|
-
kind: 'all';
|
|
28
|
-
} | {
|
|
29
|
-
kind: 'names';
|
|
30
|
-
names: Set<string>;
|
|
31
|
-
};
|
|
32
|
-
/** One declared prop in a `$props()` destructuring. */
|
|
33
|
-
export interface PropDecl {
|
|
34
|
-
/** The EXTERNAL prop name — the destructure KEY (`prop` in `prop: alias`).
|
|
35
|
-
* Call sites pass this name, so value sets / dropping key off it. */
|
|
36
|
-
name: string;
|
|
37
|
-
/**
|
|
38
|
-
* The LOCAL binding name the entry introduces in the body — the destructure
|
|
39
|
-
* VALUE (`alias` in `prop: alias`, or the bare name for a shorthand `prop`),
|
|
40
|
-
* or `null` when the entry binds a NESTED pattern (`prop: { x }`) rather than a
|
|
41
|
-
* single identifier. Body and template references use THIS name, not {@link
|
|
42
|
-
* name}, so folding/substitution must look props up by it (`prop` and its alias
|
|
43
|
-
* `alias` can even be different entities — e.g. a same-named import). A `null`
|
|
44
|
-
* local is never foldable: there is no single identifier to substitute or drop.
|
|
45
|
-
*/
|
|
46
|
-
local: string | null;
|
|
47
|
-
/** The `Property` node inside the `ObjectPattern` (for surgical removal). */
|
|
48
|
-
property: AnyNode;
|
|
49
|
-
/** Default value expression, if `name = <default>`. */
|
|
50
|
-
defaultExpr?: AnyNode | undefined;
|
|
51
|
-
}
|
|
52
|
-
/** Everything we learn from parsing one component, reused by the transform. */
|
|
53
|
-
export interface FileModel {
|
|
54
|
-
id: ComponentId;
|
|
55
|
-
code: string;
|
|
56
|
-
ast: Root;
|
|
57
|
-
/**
|
|
58
|
-
* Tag name a call site renders -> resolved child component id. Holds every
|
|
59
|
-
* attributable edge into this file: a bare local for a direct `.svelte`
|
|
60
|
-
* default or a simple barrel/named import (`Sub`), and a dotted member for a
|
|
61
|
-
* namespace render (`ns.Sub`). {@link collectChildCalls} keys `<Tag .../>`
|
|
62
|
-
* sites off this map, so every kind feeds the child's value set.
|
|
63
|
-
*/
|
|
64
|
-
imports: Map<string, ComponentId>;
|
|
65
|
-
/** Declared props, or `null` if the component has no `$props()` pattern. */
|
|
66
|
-
props: PropDecl[] | null;
|
|
67
|
-
/** The `let { ... } = $props()` declaration + its pattern, for editing. */
|
|
68
|
-
propsDeclaration?: AnyNode | undefined;
|
|
69
|
-
propsPattern?: AnyNode | undefined;
|
|
70
|
-
hasRestProp: boolean;
|
|
71
|
-
/**
|
|
72
|
-
* The inputs this component can observe (docs §PR4). Drives the reverse pass:
|
|
73
|
-
* a call site of THIS component may drop an input outside {@link
|
|
74
|
-
* ReachableInputs}. Computed syntactically from the `$props()` shape.
|
|
75
|
-
*/
|
|
76
|
-
reachableInputs: ReachableInputs;
|
|
77
|
-
/**
|
|
78
|
-
* EXTERNAL names of props this component DECLARES but never READS (docs §PR7):
|
|
79
|
-
* destructured out of a clean `$props()` yet with zero value-position reference
|
|
80
|
-
* to their local binding anywhere in the instance script or template. Such a
|
|
81
|
-
* prop is invisible to the child, so its call-site attribute is dead and — when
|
|
82
|
-
* safe — the declaration can be dropped. Source-only (independent of the call
|
|
83
|
-
* sites), so it is computed ONCE here, never inside the fixpoint; the transform
|
|
84
|
-
* gates its use on the component's plan not being bailed.
|
|
85
|
-
*/
|
|
86
|
-
unreadDeclaredProps: Set<string>;
|
|
87
|
-
/**
|
|
88
|
-
* Every `<Child .../>` instance THIS component renders, with the child it
|
|
89
|
-
* resolves to and the AST node (so the fixpoint can test whether the site
|
|
90
|
-
* falls inside a dead `{#if}` span of this component — docs §2.1).
|
|
91
|
-
*/
|
|
92
|
-
childCalls: ChildCall[];
|
|
93
|
-
/**
|
|
94
|
-
* Names this component binds OUTSIDE the `$props()` pattern — local `let` /
|
|
95
|
-
* `function` declarations in the instance script, and every template-scope
|
|
96
|
-
* binder (`{#each … as ctx, i}`, destructure patterns, `{#snippet name(p)}`,
|
|
97
|
-
* `{#await … then v}` / `{:catch e}`, `let:` directives). A declared prop
|
|
98
|
-
* whose name collides with any of these is a DIFFERENT entity inside that
|
|
99
|
-
* scope, so folding/substituting/dropping it would corrupt the binding (and
|
|
100
|
-
* often produce invalid Svelte). We therefore never fold such a prop.
|
|
101
|
-
*/
|
|
102
|
-
shadowedNames: Set<string>;
|
|
103
|
-
/**
|
|
104
|
-
* Names that appear as a `{@debug …}` argument. Svelte requires those to be
|
|
105
|
-
* bare identifiers, so substituting a folded literal there is invalid and
|
|
106
|
-
* dropping the prop dangles the reference — we never fold a prop named here.
|
|
107
|
-
*/
|
|
108
|
-
debugNames: Set<string>;
|
|
109
|
-
/**
|
|
110
|
-
* Names the component WRITES TO — reassigns (`p = …`, `p += …`), mutates with
|
|
111
|
-
* `++`/`--`, destructure-assigns (`({ p } = obj)`), or two-way `bind:`s. A
|
|
112
|
-
* written prop is not a constant even when every call site passes the same
|
|
113
|
-
* literal: the write changes it at runtime, so folding it would substitute the
|
|
114
|
-
* literal into the write's target (`"a" = …`, `0++`, `bind:value={"a"}`) —
|
|
115
|
-
* invalid Svelte — and, more importantly, silently change what renders after
|
|
116
|
-
* the write. We never fold such a prop, exactly like a shadowed one.
|
|
117
|
-
*/
|
|
118
|
-
writtenNames: Set<string>;
|
|
119
|
-
/**
|
|
120
|
-
* Owner-local bindings that are provably a single primitive CONSTANT, keyed by
|
|
121
|
-
* the LOCAL name a forwarded call-site expression references (docs §13.1
|
|
122
|
-
* interprocedural pass-through). Merged into the owner's fold env so that
|
|
123
|
-
* `<Child {count}/>` — where `count` is an unmutated `let count = $state(0)` or
|
|
124
|
-
* a `const count = 0` — folds in the child exactly as a call-site literal would,
|
|
125
|
-
* feeding BOTH constant fold and value-set narrowing. A static property of the
|
|
126
|
-
* source (independent of the fixpoint's plans), so it is computed ONCE here.
|
|
127
|
-
* See {@link computeScriptConstEnv} for the (conservative) admission rules.
|
|
128
|
-
*/
|
|
129
|
-
scriptConstEnv: ReadonlyMap<string, Literal>;
|
|
130
|
-
/**
|
|
131
|
-
* Resolved ids of CHILD components this file leaks as a value (escape, docs
|
|
132
|
-
* §4.1) — e.g. `<svelte:component this={Child}>`. `analyze` unions these
|
|
133
|
-
* across the program and bails every escaped component completely, since its
|
|
134
|
-
* prop profile can no longer be observed from `<Child .../>` sites alone.
|
|
135
|
-
*/
|
|
136
|
-
escapedComponents: Set<ComponentId>;
|
|
137
|
-
/** Reasons this whole component must be left untouched. */
|
|
138
|
-
bailReasons: string[];
|
|
139
|
-
}
|
|
140
|
-
/** One `<Child .../>` instance rendered by a component. */
|
|
141
|
-
export interface ChildCall {
|
|
142
|
-
childId: ComponentId;
|
|
143
|
-
node: AnyNode;
|
|
144
|
-
}
|
|
145
1
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* records whether this write happened after the site's last *unknown* spread (one
|
|
153
|
-
* we could not expand) — only then can no spread silently override it (docs §4.1,
|
|
154
|
-
* "後勝ち順序で救う"). A known object-literal spread is expanded, not opaque, so
|
|
155
|
-
* it never counts as an "unknown spread" here.
|
|
2
|
+
* Whole-program fixpoint core (docs ARCHITECTURE §2.1): build a model per file, then
|
|
3
|
+
* alternate collecting live call-site usage and recomputing plans until they stop
|
|
4
|
+
* changing. The environment-free engine entry ({@link analyzeInput}) and the
|
|
5
|
+
* lint-oriented {@link findNeverPassedProps} live here; resolution/IO is
|
|
6
|
+
* {@link buildAnalyzeInput} (crawl.ts), per-file facts are model.ts, call-site
|
|
7
|
+
* reading is call-site.ts.
|
|
156
8
|
*/
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
* For a `dynamic` write whose value is a single expression (`prop={expr}`, or a
|
|
163
|
-
* known-spread key `{...{prop: expr}}`), the raw expression node — kept so the
|
|
164
|
-
* fixpoint can try to fold it against the OWNING component's constFold env
|
|
165
|
-
* (interprocedural pass-through, docs §13.1). Absent for a literal write, a
|
|
166
|
-
* `bind:` (a two-way write that must never fold), or a multi-part value.
|
|
167
|
-
*/
|
|
168
|
-
expr?: AnyNode | undefined;
|
|
169
|
-
}
|
|
170
|
-
/** How a child component is called at one `<Child .../>` site. */
|
|
171
|
-
export interface CallSite {
|
|
172
|
-
/**
|
|
173
|
-
* Did this site have at least one spread we could NOT statically expand (an
|
|
174
|
-
* identifier / call / `{...{…computed/nested…}}`)? A fully-known object-literal
|
|
175
|
-
* spread is expanded into {@link ExplicitProp} writes instead, so it does not
|
|
176
|
-
* set this — only an opaque spread, which may set any prop, does (docs §4.1).
|
|
177
|
-
*/
|
|
178
|
-
hadSpread: boolean;
|
|
179
|
-
/** Last-write-wins explicit props at this site, keyed by prop name. */
|
|
180
|
-
explicit: Map<string, ExplicitProp>;
|
|
181
|
-
/**
|
|
182
|
-
* The component that OWNS this call site (renders the `<Child .../>`). The
|
|
183
|
-
* fixpoint uses it to evaluate a forwarded expression (`prop={ownerProp}`)
|
|
184
|
-
* against the owner's fold env — interprocedural pass-through (docs §13.1).
|
|
185
|
-
* `undefined` for callers that read a site outside the graph fixpoint (mono).
|
|
186
|
-
*/
|
|
187
|
-
owner?: ComponentId | undefined;
|
|
188
|
-
}
|
|
9
|
+
import { type ParseCache } from './parse.js';
|
|
10
|
+
import { type AnalyzeInput, type ComponentId, type ComponentPlan } from './ir.js';
|
|
11
|
+
import { type Span } from './dead.js';
|
|
12
|
+
import { type FileModel } from './model.js';
|
|
13
|
+
import { type ReadFile, type Resolve } from './crawl.js';
|
|
189
14
|
export interface AnalyzeResult {
|
|
190
15
|
models: Map<ComponentId, FileModel>;
|
|
191
16
|
plans: Map<ComponentId, ComponentPlan>;
|
|
@@ -224,45 +49,6 @@ export declare function analyzeInput(input: AnalyzeInput, parseCache?: ParseCach
|
|
|
224
49
|
* stamping `forceBail` onto the models.
|
|
225
50
|
*/
|
|
226
51
|
export declare function planFixpoint(models: Map<ComponentId, FileModel>): Map<ComponentId, ComponentPlan>;
|
|
227
|
-
/**
|
|
228
|
-
* The Shell-side resolution + IO layer (docs/RUST-MIGRATION.md §2.1): BFS-crawl
|
|
229
|
-
* the component graph from `entries`, resolving every import edge and reading
|
|
230
|
-
* every reachable `.svelte` file up front, into a batched {@link AnalyzeInput}.
|
|
231
|
-
*
|
|
232
|
-
* This is the half that STAYS in JS — it owns `this.resolve` / file IO for Vite
|
|
233
|
-
* ecosystem compat (docs ARCHITECTURE §5/§9) — so the engine ({@link
|
|
234
|
-
* analyzeInput}) consumes its output with no callback across the boundary. The
|
|
235
|
-
* traversal mirrors the old crawl exactly: direct default-`.svelte` children and
|
|
236
|
-
* the barrel children a file actually RENDERS are followed (an unrendered barrel
|
|
237
|
-
* import is never crawled — its `<Comp/>` site cannot exist, so it cannot taint a
|
|
238
|
-
* value set), keeping the produced model set — and thus the output — identical.
|
|
239
|
-
*/
|
|
240
|
-
/**
|
|
241
|
-
* The three per-file facts the crawl needs to resolve edges — import specifiers,
|
|
242
|
-
* rendered `<Local>` tag names, and `<ns.X>` member tag names. `null` when the file
|
|
243
|
-
* has no instance script (nothing to attribute), matching the crawl's skip.
|
|
244
|
-
*/
|
|
245
|
-
export interface CrawlFacts {
|
|
246
|
-
imports: ImportInfo[];
|
|
247
|
-
renderedTags: Set<string>;
|
|
248
|
-
memberTags: Set<string>;
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Source of {@link CrawlFacts} for one `(id, code)`. The default is a JS parse +
|
|
252
|
-
* extraction ({@link jsCrawlFacts}); the native engine passes a provider backed by
|
|
253
|
-
* `ShakeSession` facts, so the crawl resolves the SAME edges without the JS parse.
|
|
254
|
-
*/
|
|
255
|
-
export type FactsProvider = (id: ComponentId, code: string) => CrawlFacts | null;
|
|
256
|
-
/** The default facts provider: parse (svelte/compiler or rsvelte) and extract. */
|
|
257
|
-
export declare function jsCrawlFacts(id: ComponentId, code: string, parseCache?: ParseCache, parse?: Parse): CrawlFacts | null;
|
|
258
|
-
export declare function buildAnalyzeInput(entries: ComponentId | ComponentId[], resolve: Resolve, readFile: ReadFile, parseCache?: ParseCache, parse?: Parse, escaped?: ComponentId[], factsProvider?: FactsProvider): Promise<AnalyzeInput>;
|
|
259
|
-
/**
|
|
260
|
-
* Synchronous twin of {@link buildAnalyzeInput} for callers that cannot await
|
|
261
|
-
* (an ESLint rule runs synchronously). Byte-for-byte the same crawl with sync
|
|
262
|
-
* `resolve`/`readFile`; the `tests/build-analyze-input-sync` differential test
|
|
263
|
-
* pins it identical to the async path, so keep the two bodies in lockstep.
|
|
264
|
-
*/
|
|
265
|
-
export declare function buildAnalyzeInputSync(entries: ComponentId | ComponentId[], resolve: ResolveSync, readFile: ReadFileSync, parseCache?: ParseCache, parse?: Parse, escaped?: ComponentId[], factsProvider?: FactsProvider): AnalyzeInput;
|
|
266
52
|
/**
|
|
267
53
|
* Dead `{#if}` spans per component implied by `plans`, via the SAME shared
|
|
268
54
|
* predicate the transform uses ({@link computeDeadSpans}). A bailed component
|
|
@@ -317,34 +103,6 @@ export declare function findNeverPassedProps(input: AnalyzeInput): Map<Component
|
|
|
317
103
|
* maps cleanly; an external name with no matching declared local is dropped.
|
|
318
104
|
*/
|
|
319
105
|
export declare function remapToLocalNames<V>(map: Map<string, V>, model: FileModel): Map<string, V>;
|
|
320
|
-
/**
|
|
321
|
-
* The bare component tag names this file RENDERS (`<Local/>`, excluding dotted
|
|
322
|
-
* `<ns.X/>` member tags). The Shell crawl uses this to resolve a barrel (a
|
|
323
|
-
* `.js`/`.ts` re-export, which costs a module read+parse) only for named imports
|
|
324
|
-
* actually rendered as a component — a value-only named import (a helper / type)
|
|
325
|
-
* is never a `<Local>` call site, so following it would read+parse a module for
|
|
326
|
-
* nothing. Skipping it only ever drops a non-call-site, so attribution (and the
|
|
327
|
-
* resulting models) are unchanged.
|
|
328
|
-
*/
|
|
329
|
-
export declare function renderedComponentTagNames(ast: Root): Set<string>;
|
|
330
|
-
/**
|
|
331
|
-
* Every dotted component tag a file renders (`<ns.Child/>` -> `"ns.Child"`). The
|
|
332
|
-
* Shell resolves each through its namespace import's barrel; bare `<Child/>` tags
|
|
333
|
-
* have no dot and are bound by the plain import maps instead.
|
|
334
|
-
*/
|
|
335
|
-
export declare function memberComponentTags(ast: Root): Set<string>;
|
|
336
|
-
/**
|
|
337
|
-
* Read one `<Child .../>` into a {@link CallSite}. Attributes are in source
|
|
338
|
-
* order, so we resolve last-write-wins (a later `a={…}` overrides an earlier
|
|
339
|
-
* one) and record, per prop, whether its winning write came *after* the last
|
|
340
|
-
* *unknown* spread — the only case a spread cannot silently override it (docs
|
|
341
|
-
* §4.1). A statically-known object-literal spread (`{...{a:1, b:2}}`) is not
|
|
342
|
-
* opaque: we expand its keys into explicit writes at the spread's position, so it
|
|
343
|
-
* both contributes those literals AND does not poison props it cannot set (docs
|
|
344
|
-
* §4.1, "{...obj} が object literal ならキー展開").
|
|
345
|
-
*/
|
|
346
|
-
export declare function readCallSite(component: AnyNode, owner?: ComponentId): CallSite;
|
|
347
|
-
/** Decide what to fold for one component from its global usage. */
|
|
348
106
|
/**
|
|
349
107
|
* Whether a declared prop name is unsafe to fold/narrow/drop because it is also
|
|
350
108
|
* bound elsewhere: shadowed by a local `let`/`function` or a template binder
|
|
@@ -357,11 +115,3 @@ export declare function readCallSite(component: AnyNode, owner?: ComponentId): C
|
|
|
357
115
|
* monomorphization specialization (mono.ts) must honor this identically.
|
|
358
116
|
*/
|
|
359
117
|
export declare function isFoldBlockedName(model: FileModel, name: string): boolean;
|
|
360
|
-
export interface ImportInfo {
|
|
361
|
-
value: string;
|
|
362
|
-
local: string;
|
|
363
|
-
/** `default` for a default import, the exported name for a named import, or
|
|
364
|
-
* `*` for a namespace import. */
|
|
365
|
-
imported: string;
|
|
366
|
-
}
|
|
367
|
-
export declare function importSources(instance: AnyNode): Generator<ImportInfo>;
|