@oddsquad/vite-plugin-lit 0.2.2 → 0.3.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/CHANGELOG.md +64 -0
- package/LICENSE +28 -0
- package/README.md +153 -0
- package/bin.mjs +154 -0
- package/client.d.ts +61 -0
- package/dist/client/assets/browser-agent-rpc-BXhoSh1z-BvWe4sTJ.js +69 -0
- package/dist/client/assets/browser-agent-rpc-BXhoSh1z-BvWe4sTJ.js.map +1 -0
- package/dist/client/assets/index-CFrVgNfS.js +9740 -0
- package/dist/client/assets/index-CFrVgNfS.js.map +1 -0
- package/{panel → dist/client}/index.html +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +2 -2
- package/index.js.map +1 -1
- package/lib/color-scheme.d.ts.map +1 -1
- package/lib/color-scheme.js +17 -21
- package/lib/color-scheme.js.map +1 -1
- package/lib/devframe/definition.d.ts +45 -0
- package/lib/devframe/definition.d.ts.map +1 -0
- package/lib/devframe/definition.js +547 -0
- package/lib/devframe/definition.js.map +1 -0
- package/lib/devframe/icon.d.ts +8 -0
- package/lib/devframe/icon.d.ts.map +1 -0
- package/lib/devframe/icon.js +21 -0
- package/lib/devframe/icon.js.map +1 -0
- package/lib/devframe/paths.d.ts +12 -0
- package/lib/devframe/paths.d.ts.map +1 -0
- package/lib/devframe/paths.js +38 -0
- package/lib/devframe/paths.js.map +1 -0
- package/lib/devframe/protocol.d.ts +218 -0
- package/lib/devframe/protocol.d.ts.map +1 -0
- package/lib/devframe/protocol.js +76 -0
- package/lib/devframe/protocol.js.map +1 -0
- package/lib/devframe/source.d.ts +49 -0
- package/lib/devframe/source.d.ts.map +1 -0
- package/lib/devframe/source.js +23 -0
- package/lib/devframe/source.js.map +1 -0
- package/lib/devframe/vite.d.ts +116 -0
- package/lib/devframe/vite.d.ts.map +1 -0
- package/lib/devframe/vite.js +291 -0
- package/lib/devframe/vite.js.map +1 -0
- package/lib/http.d.ts +29 -0
- package/lib/http.d.ts.map +1 -0
- package/lib/http.js +35 -0
- package/lib/http.js.map +1 -0
- package/lib/icons.d.ts +2 -0
- package/lib/icons.d.ts.map +1 -1
- package/lib/icons.js +10 -4
- package/lib/icons.js.map +1 -1
- package/lib/plugin.d.ts +15 -4
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +640 -574
- package/lib/plugin.js.map +1 -1
- package/lib/runtime/css.d.ts +2 -16
- package/lib/runtime/css.d.ts.map +1 -1
- package/lib/runtime/css.js +43 -36
- package/lib/runtime/css.js.map +1 -1
- package/lib/runtime/edge-panel.d.ts.map +1 -1
- package/lib/runtime/edge-panel.js +82 -91
- package/lib/runtime/edge-panel.js.map +1 -1
- package/lib/runtime/fonts.d.ts.map +1 -1
- package/lib/runtime/fonts.js +1 -1
- package/lib/runtime/fonts.js.map +1 -1
- package/lib/runtime/indicator.d.ts.map +1 -1
- package/lib/runtime/indicator.js +71 -74
- package/lib/runtime/indicator.js.map +1 -1
- package/lib/runtime/inspector/collect.d.ts.map +1 -1
- package/lib/runtime/inspector/collect.js +83 -90
- package/lib/runtime/inspector/collect.js.map +1 -1
- package/lib/runtime/inspector/highlight.d.ts +16 -0
- package/lib/runtime/inspector/highlight.d.ts.map +1 -0
- package/lib/runtime/inspector/highlight.js +66 -0
- package/lib/runtime/inspector/highlight.js.map +1 -0
- package/lib/runtime/inspector/install.d.ts.map +1 -1
- package/lib/runtime/inspector/install.js +180 -205
- package/lib/runtime/inspector/install.js.map +1 -1
- package/lib/runtime/inspector/serialize.d.ts.map +1 -1
- package/lib/runtime/inspector/serialize.js +86 -107
- package/lib/runtime/inspector/serialize.js.map +1 -1
- package/lib/runtime/intern.d.ts.map +1 -1
- package/lib/runtime/intern.js +31 -29
- package/lib/runtime/intern.js.map +1 -1
- package/lib/runtime/overrides.d.ts.map +1 -1
- package/lib/runtime/overrides.js +14 -13
- package/lib/runtime/overrides.js.map +1 -1
- package/lib/runtime/patch.d.ts +8 -0
- package/lib/runtime/patch.d.ts.map +1 -1
- package/lib/runtime/patch.js +321 -282
- package/lib/runtime/patch.js.map +1 -1
- package/lib/runtime/source-meta.d.ts.map +1 -1
- package/lib/runtime/source-meta.js +1 -1
- package/lib/runtime/source-meta.js.map +1 -1
- package/lib/runtime/source-overlay/editors.d.ts.map +1 -1
- package/lib/runtime/source-overlay/editors.js +27 -27
- package/lib/runtime/source-overlay/editors.js.map +1 -1
- package/lib/runtime/source-overlay/mask-path.d.ts.map +1 -1
- package/lib/runtime/source-overlay/mask-path.js +15 -15
- package/lib/runtime/source-overlay/mask-path.js.map +1 -1
- package/lib/runtime/source-overlay/overlay-element.d.ts.map +1 -1
- package/lib/runtime/source-overlay/overlay-element.js +347 -356
- package/lib/runtime/source-overlay/overlay-element.js.map +1 -1
- package/lib/runtime/source-overlay/source-host.d.ts.map +1 -1
- package/lib/runtime/source-overlay/source-host.js +64 -71
- package/lib/runtime/source-overlay/source-host.js.map +1 -1
- package/lib/runtime/source-overlay/template.d.ts.map +1 -1
- package/lib/runtime/source-overlay/template.js +3 -3
- package/lib/runtime/source-overlay/template.js.map +1 -1
- package/lib/runtime/source-overlay.d.ts.map +1 -1
- package/lib/runtime/source-overlay.js +5 -2
- package/lib/runtime/source-overlay.js.map +1 -1
- package/lib/runtime/timeline/clock.d.ts.map +1 -1
- package/lib/runtime/timeline/clock.js +2 -2
- package/lib/runtime/timeline/clock.js.map +1 -1
- package/lib/runtime/timeline/flash.d.ts +39 -0
- package/lib/runtime/timeline/flash.d.ts.map +1 -0
- package/lib/runtime/timeline/flash.js +169 -0
- package/lib/runtime/timeline/flash.js.map +1 -0
- package/lib/runtime/timeline/identity.d.ts.map +1 -1
- package/lib/runtime/timeline/identity.js +27 -27
- package/lib/runtime/timeline/identity.js.map +1 -1
- package/lib/runtime/timeline/input.d.ts.map +1 -1
- package/lib/runtime/timeline/input.js +54 -67
- package/lib/runtime/timeline/input.js.map +1 -1
- package/lib/runtime/timeline/install.d.ts.map +1 -1
- package/lib/runtime/timeline/install.js +38 -29
- package/lib/runtime/timeline/install.js.map +1 -1
- package/lib/runtime/timeline/lifecycle.d.ts +8 -0
- package/lib/runtime/timeline/lifecycle.d.ts.map +1 -1
- package/lib/runtime/timeline/lifecycle.js +149 -133
- package/lib/runtime/timeline/lifecycle.js.map +1 -1
- package/lib/runtime/timeline/public-api.d.ts.map +1 -1
- package/lib/runtime/timeline/public-api.js +9 -9
- package/lib/runtime/timeline/public-api.js.map +1 -1
- package/lib/runtime/timeline/render.d.ts.map +1 -1
- package/lib/runtime/timeline/render.js +70 -75
- package/lib/runtime/timeline/render.js.map +1 -1
- package/lib/runtime/timeline/transport.d.ts.map +1 -1
- package/lib/runtime/timeline/transport.js +39 -43
- package/lib/runtime/timeline/transport.js.map +1 -1
- package/lib/segmented-tabs.d.ts +3 -1
- package/lib/segmented-tabs.d.ts.map +1 -1
- package/lib/segmented-tabs.js +136 -107
- package/lib/segmented-tabs.js.map +1 -1
- package/lib/snapshot.d.ts +28 -0
- package/lib/snapshot.d.ts.map +1 -0
- package/lib/snapshot.js +57 -0
- package/lib/snapshot.js.map +1 -0
- package/lib/source-meta.d.ts.map +1 -1
- package/lib/source-meta.js +176 -162
- package/lib/source-meta.js.map +1 -1
- package/lib/timeline/derive.d.ts +152 -0
- package/lib/timeline/derive.d.ts.map +1 -0
- package/lib/timeline/derive.js +242 -0
- package/lib/timeline/derive.js.map +1 -0
- package/lib/timeline-plugin.d.ts.map +1 -1
- package/lib/timeline-plugin.js +304 -321
- package/lib/timeline-plugin.js.map +1 -1
- package/lib/tokens.d.ts.map +1 -1
- package/lib/tokens.js +17 -18
- package/lib/tokens.js.map +1 -1
- package/lib/transform.d.ts.map +1 -1
- package/lib/transform.js +62 -57
- package/lib/transform.js.map +1 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +1 -1
- package/lib/types.js.map +1 -1
- package/lib/wrap-table.d.ts.map +1 -1
- package/lib/wrap-table.js +19 -17
- package/lib/wrap-table.js.map +1 -1
- package/package.json +77 -13
- package/types/hmr-incompatibility.d.ts +59 -0
- package/types/hmr-incompatibility.d.ts.map +1 -0
- package/types/hmr-incompatibility.js +30 -0
- package/types/hmr-incompatibility.js.map +1 -0
- package/types/in-page.d.ts +49 -0
- package/types/in-page.d.ts.map +1 -0
- package/types/in-page.js +33 -0
- package/types/in-page.js.map +1 -0
- package/types/inspector.d.ts.map +1 -1
- package/types/inspector.js.map +1 -1
- package/types/snapshot.d.ts +44 -0
- package/types/snapshot.d.ts.map +1 -0
- package/types/snapshot.js +7 -0
- package/types/snapshot.js.map +1 -0
- package/types/timeline.d.ts +11 -0
- package/types/timeline.d.ts.map +1 -1
- package/types/timeline.js.map +1 -1
- package/panel/components-view.d.ts +0 -60
- package/panel/components-view.d.ts.map +0 -1
- package/panel/components-view.js +0 -587
- package/panel/components-view.js.map +0 -1
- package/panel/devtools-settings.d.ts +0 -41
- package/panel/devtools-settings.d.ts.map +0 -1
- package/panel/devtools-settings.js +0 -463
- package/panel/devtools-settings.js.map +0 -1
- package/panel/lit-devtools-panel.d.ts +0 -37
- package/panel/lit-devtools-panel.d.ts.map +0 -1
- package/panel/lit-devtools-panel.js +0 -185
- package/panel/lit-devtools-panel.js.map +0 -1
- package/panel/timeline-event-list.d.ts +0 -43
- package/panel/timeline-event-list.d.ts.map +0 -1
- package/panel/timeline-event-list.js +0 -416
- package/panel/timeline-event-list.js.map +0 -1
- package/panel/timeline-layers.d.ts +0 -25
- package/panel/timeline-layers.d.ts.map +0 -1
- package/panel/timeline-layers.js +0 -96
- package/panel/timeline-layers.js.map +0 -1
- package/panel/timeline-view.d.ts +0 -38
- package/panel/timeline-view.d.ts.map +0 -1
- package/panel/timeline-view.js +0 -234
- package/panel/timeline-view.js.map +0 -1
package/lib/runtime/patch.js
CHANGED
|
@@ -18,7 +18,11 @@
|
|
|
18
18
|
* it never imports lit (keeps it version-agnostic and safe for non-Lit
|
|
19
19
|
* custom elements, which get prototype/static patching only).
|
|
20
20
|
*/
|
|
21
|
-
import {
|
|
21
|
+
import {subscribeOverride} from './overrides.js';
|
|
22
|
+
import {
|
|
23
|
+
HMR_INCOMPATIBLE_CHANNEL,
|
|
24
|
+
describeHmrReason,
|
|
25
|
+
} from '../../types/hmr-incompatibility.js';
|
|
22
26
|
// Exactly one patch state per page, even if this module loads twice.
|
|
23
27
|
const STATE_KEY = Symbol.for('@lit-labs/vite-plugin-lit#patch');
|
|
24
28
|
// Brands our lifecycle wrappers so re-instrumentation is idempotent.
|
|
@@ -26,8 +30,8 @@ const RECORD_BRAND = Symbol.for('@lit-labs/vite-plugin-lit#wrapperRecord');
|
|
|
26
30
|
const PROTO_SKIP = ['constructor'];
|
|
27
31
|
const STATIC_SKIP = ['prototype', 'name', 'length'];
|
|
28
32
|
const ownKeys = (o) => [
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
...Object.getOwnPropertyNames(o),
|
|
34
|
+
...Object.getOwnPropertySymbols(o),
|
|
31
35
|
];
|
|
32
36
|
/**
|
|
33
37
|
* Syncs own members `source` → `target`: deletes own keys of `target` that
|
|
@@ -36,30 +40,32 @@ const ownKeys = (o) => [
|
|
|
36
40
|
*/
|
|
37
41
|
// Exported for unit testing; otherwise module-internal.
|
|
38
42
|
export const syncOwnMembers = (target, source, skip) => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
if (Object.getOwnPropertyDescriptor(source, key) === undefined) {
|
|
44
|
-
try {
|
|
45
|
-
delete target[key];
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
// Non-configurable; leave it.
|
|
49
|
-
}
|
|
50
|
-
}
|
|
43
|
+
for (const key of ownKeys(target)) {
|
|
44
|
+
if (skip.includes(key)) {
|
|
45
|
+
continue;
|
|
51
46
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
47
|
+
if (Object.getOwnPropertyDescriptor(source, key) === undefined) {
|
|
48
|
+
try {
|
|
49
|
+
delete target[key];
|
|
50
|
+
} catch {
|
|
51
|
+
// Non-configurable; leave it.
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
for (const key of ownKeys(source)) {
|
|
56
|
+
if (skip.includes(key)) {
|
|
57
|
+
continue;
|
|
62
58
|
}
|
|
59
|
+
try {
|
|
60
|
+
Object.defineProperty(
|
|
61
|
+
target,
|
|
62
|
+
key,
|
|
63
|
+
Object.getOwnPropertyDescriptor(source, key)
|
|
64
|
+
);
|
|
65
|
+
} catch {
|
|
66
|
+
// Non-configurable; leave it.
|
|
67
|
+
}
|
|
68
|
+
}
|
|
63
69
|
};
|
|
64
70
|
/**
|
|
65
71
|
* Defines branded `connectedCallback`/`disconnectedCallback` wrappers on the
|
|
@@ -68,44 +74,41 @@ export const syncOwnMembers = (target, source, skip) => {
|
|
|
68
74
|
* deletes the wrappers).
|
|
69
75
|
*/
|
|
70
76
|
const instrument = (state, proto, record) => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// Was detached during one or more patches; catch up.
|
|
88
|
-
this.requestUpdate?.();
|
|
89
|
-
}
|
|
90
|
-
state.generationOf.set(this, record.generation);
|
|
91
|
-
original?.call(this);
|
|
77
|
+
for (const name of ['connectedCallback', 'disconnectedCallback']) {
|
|
78
|
+
const own = Object.getOwnPropertyDescriptor(proto, name);
|
|
79
|
+
if (own?.value?.[RECORD_BRAND] === record) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
// May be an own raw function (just copied from the new class), an
|
|
83
|
+
// inherited base implementation, or absent entirely.
|
|
84
|
+
const original = proto[name];
|
|
85
|
+
const wrapper =
|
|
86
|
+
name === 'connectedCallback'
|
|
87
|
+
? function () {
|
|
88
|
+
record.instances.add(this);
|
|
89
|
+
const stamp = state.generationOf.get(this);
|
|
90
|
+
if (stamp !== undefined && stamp !== record.generation) {
|
|
91
|
+
// Was detached during one or more patches; catch up.
|
|
92
|
+
this.requestUpdate?.();
|
|
92
93
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
94
|
+
state.generationOf.set(this, record.generation);
|
|
95
|
+
original?.call(this);
|
|
96
|
+
}
|
|
97
|
+
: function () {
|
|
98
|
+
record.instances.delete(this);
|
|
99
|
+
original?.call(this);
|
|
100
|
+
};
|
|
101
|
+
wrapper[RECORD_BRAND] = record;
|
|
102
|
+
try {
|
|
103
|
+
Object.defineProperty(proto, name, {
|
|
104
|
+
value: wrapper,
|
|
105
|
+
writable: true,
|
|
106
|
+
configurable: true,
|
|
107
|
+
});
|
|
108
|
+
} catch {
|
|
109
|
+
// Non-configurable lifecycle slot; tracking degrades gracefully.
|
|
108
110
|
}
|
|
111
|
+
}
|
|
109
112
|
};
|
|
110
113
|
/**
|
|
111
114
|
* Detects standard-decorator (`accessor`) reactive properties on the new
|
|
@@ -113,26 +116,24 @@ const instrument = (state, proto, record) => {
|
|
|
113
116
|
* accessors would brand-check-throw — in-place patching is impossible.
|
|
114
117
|
*/
|
|
115
118
|
const usesStandardDecorators = (ctor) => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
119
|
+
const metadataSymbol = Symbol.metadata;
|
|
120
|
+
if (metadataSymbol === undefined) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
const metadata = Object.getOwnPropertyDescriptor(ctor, metadataSymbol)?.value;
|
|
124
|
+
if (metadata === undefined || metadata === null) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
// litPropertyMetadata is a Lit internal (not public API). Guard against
|
|
128
|
+
// rename, removal, or shape changes — a false negative here means we try
|
|
129
|
+
// to hot-patch and crash, which is handled by the outer catch in hotPatch.
|
|
130
|
+
try {
|
|
131
|
+
const litPropertyMetadata = globalThis.litPropertyMetadata;
|
|
132
|
+
const properties = litPropertyMetadata?.get(metadata);
|
|
133
|
+
return properties !== undefined && properties.size > 0;
|
|
134
|
+
} catch {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
136
137
|
};
|
|
137
138
|
/**
|
|
138
139
|
* Resolves a static `elementStyles` array to its constructed `CSSStyleSheet`s.
|
|
@@ -140,19 +141,15 @@ const usesStandardDecorators = (ctor) => {
|
|
|
140
141
|
* stylesheet support), so callers can bail rather than adopt a partial list.
|
|
141
142
|
*/
|
|
142
143
|
const stylesToSheets = (styles) => {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
return null;
|
|
153
|
-
sheets.push(sheet);
|
|
154
|
-
}
|
|
155
|
-
return sheets;
|
|
144
|
+
if (!Array.isArray(styles)) return null;
|
|
145
|
+
const sheets = [];
|
|
146
|
+
for (const style of styles) {
|
|
147
|
+
const sheet =
|
|
148
|
+
style instanceof CSSStyleSheet ? style : (style?.styleSheet ?? undefined);
|
|
149
|
+
if (!(sheet instanceof CSSStyleSheet)) return null;
|
|
150
|
+
sheets.push(sheet);
|
|
151
|
+
}
|
|
152
|
+
return sheets;
|
|
156
153
|
};
|
|
157
154
|
/**
|
|
158
155
|
* Re-adopts constructed stylesheets on an instance's shadow root from the
|
|
@@ -165,211 +162,253 @@ const stylesToSheets = (styles) => {
|
|
|
165
162
|
* whole list.
|
|
166
163
|
*/
|
|
167
164
|
const readoptStyles = (el, oldSheets) => {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
165
|
+
const root = el.renderRoot;
|
|
166
|
+
if (typeof ShadowRoot === 'undefined' || !(root instanceof ShadowRoot)) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const sheets = stylesToSheets(el.constructor.elementStyles);
|
|
170
|
+
if (sheets === null) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const drop = new Set(oldSheets);
|
|
174
|
+
const ours = new Set(sheets);
|
|
175
|
+
// Our styles go first, matching Lit's own order (extra sheets appended).
|
|
176
|
+
const preserved = [...root.adoptedStyleSheets].filter(
|
|
177
|
+
(s) => !drop.has(s) && !ours.has(s)
|
|
178
|
+
);
|
|
179
|
+
root.adoptedStyleSheets = [...sheets, ...preserved];
|
|
181
180
|
};
|
|
181
|
+
/**
|
|
182
|
+
* Builds the structured event reported over {@link HMR_INCOMPATIBLE_CHANNEL}.
|
|
183
|
+
* Exported for unit testing; otherwise module-internal. Whether the send
|
|
184
|
+
* survives the `location.reload()` that may follow it can only be checked by
|
|
185
|
+
* hand against a real dev server.
|
|
186
|
+
*/
|
|
187
|
+
export const buildHmrIncompatibleEvent = (tagName, reason, action) => ({
|
|
188
|
+
tagName,
|
|
189
|
+
time: Date.now(),
|
|
190
|
+
reason,
|
|
191
|
+
action,
|
|
192
|
+
});
|
|
182
193
|
const incompatible = (state, tagName, reason) => {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
194
|
+
const message = describeHmrReason(reason);
|
|
195
|
+
const action = state.options.onIncompatible === 'warn' ? 'warn' : 'reload';
|
|
196
|
+
state.hot?.send(
|
|
197
|
+
HMR_INCOMPATIBLE_CHANNEL,
|
|
198
|
+
buildHmrIncompatibleEvent(tagName, reason, action)
|
|
199
|
+
);
|
|
200
|
+
if (state.options.onIncompatible === 'warn') {
|
|
201
|
+
console.warn(
|
|
202
|
+
`[lit-plugin] <${tagName}> can't be hot-patched (${message}). ` +
|
|
203
|
+
`Reload the page to pick up the change.`
|
|
204
|
+
);
|
|
205
|
+
} else {
|
|
206
|
+
console.info(
|
|
207
|
+
`[lit-plugin] <${tagName}>: ${message} — performing full reload.`
|
|
208
|
+
);
|
|
209
|
+
location.reload();
|
|
210
|
+
}
|
|
191
211
|
};
|
|
192
212
|
/**
|
|
193
213
|
* Patches the originally-registered class for `record.tagName` in place
|
|
194
214
|
* from the freshly evaluated `NewClass`, then updates live instances.
|
|
195
215
|
*/
|
|
196
216
|
const hotPatch = (state, record, NewClass) => {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
217
|
+
const OldClass = record.canonical;
|
|
218
|
+
try {
|
|
219
|
+
// 1. Materialize finalized/elementProperties/elementStyles/
|
|
220
|
+
// __attributeToPropertyMap on the new class before we copy statics.
|
|
221
|
+
if (typeof NewClass.finalize === 'function') {
|
|
222
|
+
NewClass.finalize();
|
|
223
|
+
}
|
|
224
|
+
// 2. Standard-decorator `accessor` properties can't be patched in place.
|
|
225
|
+
if (usesStandardDecorators(NewClass)) {
|
|
226
|
+
incompatible(state, record.tagName, {code: 'accessor-decorators'});
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
// The platform snapshots observedAttributes at define time; new
|
|
230
|
+
// attribute observations can't take effect without a reload.
|
|
231
|
+
const oldObserved = [...(OldClass.observedAttributes ?? [])];
|
|
232
|
+
const newObserved = [...(NewClass.observedAttributes ?? [])];
|
|
233
|
+
// 3. Snapshot reactive property values per live instance through the
|
|
234
|
+
// OLD accessors. Vite serves prod lit in dev (no `development`
|
|
235
|
+
// export condition), where accessor storage keys are unique
|
|
236
|
+
// Symbol()s per class evaluation — without this, state resets.
|
|
237
|
+
const propertyKeys = new Set([
|
|
238
|
+
...(OldClass.elementProperties?.keys() ?? []),
|
|
239
|
+
...(NewClass.elementProperties?.keys() ?? []),
|
|
240
|
+
]);
|
|
241
|
+
const snapshots = new Map();
|
|
242
|
+
for (const el of record.instances) {
|
|
243
|
+
const values = new Map();
|
|
244
|
+
for (const key of propertyKeys) {
|
|
245
|
+
values.set(key, el[key]);
|
|
246
|
+
}
|
|
247
|
+
snapshots.set(el, values);
|
|
248
|
+
}
|
|
249
|
+
// 4. Re-parent prototype chains. Mixins regenerate intermediate classes
|
|
250
|
+
// on every module evaluation, so the parents usually differ.
|
|
251
|
+
const newProtoParent = Object.getPrototypeOf(NewClass.prototype);
|
|
252
|
+
if (Object.getPrototypeOf(OldClass.prototype) !== newProtoParent) {
|
|
253
|
+
Object.setPrototypeOf(OldClass.prototype, newProtoParent);
|
|
254
|
+
}
|
|
255
|
+
const newStaticParent = Object.getPrototypeOf(NewClass);
|
|
256
|
+
if (Object.getPrototypeOf(OldClass) !== newStaticParent) {
|
|
257
|
+
Object.setPrototypeOf(OldClass, newStaticParent);
|
|
258
|
+
}
|
|
259
|
+
// Capture the sheets the OLD class contributed before the static sync
|
|
260
|
+
// overwrites `elementStyles`, so readoptStyles can drop exactly those and
|
|
261
|
+
// leave imperatively-adopted sheets in place.
|
|
262
|
+
const oldSheets = stylesToSheets(OldClass.elementStyles) ?? [];
|
|
263
|
+
// 5. Sync own members new → old on the prototype and on statics.
|
|
264
|
+
syncOwnMembers(OldClass.prototype, NewClass.prototype, PROTO_SKIP);
|
|
265
|
+
syncOwnMembers(OldClass, NewClass, STATIC_SKIP);
|
|
266
|
+
// 6. The sync replaced/removed our lifecycle wrappers; re-instrument.
|
|
267
|
+
instrument(state, OldClass.prototype, record);
|
|
268
|
+
record.generation++;
|
|
269
|
+
// Module-local `instanceof NewClass` checks keep working against
|
|
270
|
+
// instances of the canonical class.
|
|
271
|
+
Object.defineProperty(NewClass, Symbol.hasInstance, {
|
|
272
|
+
value: (instance) =>
|
|
273
|
+
typeof instance === 'object' &&
|
|
274
|
+
instance !== null &&
|
|
275
|
+
OldClass.prototype.isPrototypeOf(instance),
|
|
276
|
+
configurable: true,
|
|
277
|
+
});
|
|
278
|
+
if (
|
|
279
|
+
oldObserved.length !== newObserved.length ||
|
|
280
|
+
oldObserved.some((attr, i) => attr !== newObserved[i])
|
|
281
|
+
) {
|
|
282
|
+
console.info(
|
|
283
|
+
`[lit-plugin] <${record.tagName}> changed observedAttributes; the ` +
|
|
284
|
+
`platform registry can't pick this up — reload recommended.`
|
|
285
|
+
);
|
|
286
|
+
state.hot?.send(
|
|
287
|
+
HMR_INCOMPATIBLE_CHANNEL,
|
|
288
|
+
buildHmrIncompatibleEvent(
|
|
289
|
+
record.tagName,
|
|
290
|
+
{code: 'observed-attributes-changed'},
|
|
291
|
+
'none'
|
|
292
|
+
)
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
// 7. Update live instances.
|
|
296
|
+
const newPropertyKeys = NewClass.elementProperties?.keys() ?? [];
|
|
297
|
+
// After the static sync this is the NEW class's initializer list.
|
|
298
|
+
const initializers = OldClass._initializers;
|
|
299
|
+
// Snapshot: the reconnect below mutates record.instances mid-iteration.
|
|
300
|
+
// oxlint-disable-next-line unicorn/no-useless-spread
|
|
301
|
+
for (const el of [...record.instances]) {
|
|
302
|
+
if (state.options.reconnect) {
|
|
303
|
+
el.disconnectedCallback?.();
|
|
304
|
+
el.connectedCallback?.();
|
|
305
|
+
}
|
|
306
|
+
// Decorator-created reactive controllers (e.g. @lit/context's
|
|
307
|
+
// @provide/@consume) live in per-class-evaluation closures keyed by
|
|
308
|
+
// instance via addInitializer. Re-running the initializers enrolls
|
|
309
|
+
// live instances in the new closures — without this, the first
|
|
310
|
+
// assignment through a copied accessor throws and we'd full-reload.
|
|
311
|
+
// Controllers from previous evaluations stay attached but inert
|
|
312
|
+
// (everything flows through the newest closures); that's bounded by
|
|
313
|
+
// edit count and dev-only. Runs before the value restore so e.g. a
|
|
314
|
+
// re-created ContextProvider exists when the restore pushes into it.
|
|
315
|
+
if (Array.isArray(initializers)) {
|
|
316
|
+
for (const initialize of initializers) {
|
|
317
|
+
initialize(el);
|
|
261
318
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
// Decorator-created reactive controllers (e.g. @lit/context's
|
|
272
|
-
// @provide/@consume) live in per-class-evaluation closures keyed by
|
|
273
|
-
// instance via addInitializer. Re-running the initializers enrolls
|
|
274
|
-
// live instances in the new closures — without this, the first
|
|
275
|
-
// assignment through a copied accessor throws and we'd full-reload.
|
|
276
|
-
// Controllers from previous evaluations stay attached but inert
|
|
277
|
-
// (everything flows through the newest closures); that's bounded by
|
|
278
|
-
// edit count and dev-only. Runs before the value restore so e.g. a
|
|
279
|
-
// re-created ContextProvider exists when the restore pushes into it.
|
|
280
|
-
if (Array.isArray(initializers)) {
|
|
281
|
-
for (const initialize of initializers) {
|
|
282
|
-
initialize(el);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
const values = snapshots.get(el);
|
|
286
|
-
if (values !== undefined) {
|
|
287
|
-
// Restore through the new accessors — only keys the new class
|
|
288
|
-
// still declares.
|
|
289
|
-
for (const key of newPropertyKeys) {
|
|
290
|
-
if (values.has(key)) {
|
|
291
|
-
el[key] =
|
|
292
|
-
values.get(key);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
readoptStyles(el, oldSheets);
|
|
297
|
-
state.generationOf.set(el, record.generation);
|
|
298
|
-
el.requestUpdate?.();
|
|
319
|
+
}
|
|
320
|
+
const values = snapshots.get(el);
|
|
321
|
+
if (values !== undefined) {
|
|
322
|
+
// Restore through the new accessors — only keys the new class
|
|
323
|
+
// still declares.
|
|
324
|
+
for (const key of newPropertyKeys) {
|
|
325
|
+
if (values.has(key)) {
|
|
326
|
+
el[key] = values.get(key);
|
|
327
|
+
}
|
|
299
328
|
}
|
|
329
|
+
}
|
|
330
|
+
readoptStyles(el, oldSheets);
|
|
331
|
+
state.generationOf.set(el, record.generation);
|
|
332
|
+
el.requestUpdate?.();
|
|
300
333
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
334
|
+
} catch (e) {
|
|
335
|
+
incompatible(state, record.tagName, {
|
|
336
|
+
code: 'patch-failed',
|
|
337
|
+
detail: e instanceof Error ? e.message : String(e),
|
|
338
|
+
});
|
|
339
|
+
}
|
|
304
340
|
};
|
|
305
341
|
/**
|
|
306
342
|
* Installs the `customElements.define` interceptor. Idempotent (per-page
|
|
307
343
|
* global guard); no-ops in environments without `customElements` (SSR).
|
|
308
344
|
*/
|
|
309
345
|
export const install = (options = {}) => {
|
|
310
|
-
|
|
311
|
-
|
|
346
|
+
if (typeof customElements === 'undefined') {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const g = globalThis;
|
|
350
|
+
const existing = g[STATE_KEY];
|
|
351
|
+
if (existing !== undefined) {
|
|
352
|
+
// Already installed; refresh explicitly-provided options only.
|
|
353
|
+
if (options.reconnect !== undefined) {
|
|
354
|
+
existing.options.reconnect = options.reconnect;
|
|
312
355
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
if (existing !== undefined) {
|
|
316
|
-
// Already installed; refresh explicitly-provided options only.
|
|
317
|
-
if (options.reconnect !== undefined) {
|
|
318
|
-
existing.options.reconnect = options.reconnect;
|
|
319
|
-
}
|
|
320
|
-
if (options.onIncompatible !== undefined) {
|
|
321
|
-
existing.options.onIncompatible = options.onIncompatible;
|
|
322
|
-
}
|
|
323
|
-
return;
|
|
356
|
+
if (options.onIncompatible !== undefined) {
|
|
357
|
+
existing.options.onIncompatible = options.onIncompatible;
|
|
324
358
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const hot = import.meta.hot;
|
|
362
|
+
const state = {
|
|
363
|
+
records: new Map(),
|
|
364
|
+
generationOf: new WeakMap(),
|
|
365
|
+
options: {
|
|
366
|
+
reconnect: options.reconnect ?? false,
|
|
367
|
+
onIncompatible: options.onIncompatible ?? 'reload',
|
|
368
|
+
},
|
|
369
|
+
hot,
|
|
370
|
+
};
|
|
371
|
+
g[STATE_KEY] = state;
|
|
372
|
+
// Let the DevTools panel override these behaviours live (and persist across
|
|
373
|
+
// reloads) on top of the config-time defaults above.
|
|
374
|
+
subscribeOverride(hot, (o) => {
|
|
375
|
+
if (o.hmrReconnect !== undefined) state.options.reconnect = o.hmrReconnect;
|
|
376
|
+
if (o.hmrOnIncompatible !== undefined) {
|
|
377
|
+
state.options.onIncompatible = o.hmrOnIncompatible;
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
// Captured to re-invoke below as nativeDefine.call(this, ...).
|
|
381
|
+
// oxlint-disable-next-line typescript/unbound-method
|
|
382
|
+
const nativeDefine = customElements.define;
|
|
383
|
+
customElements.define = function (name, ctor, defineOptions) {
|
|
384
|
+
let record = state.records.get(name);
|
|
385
|
+
if (record === undefined && this.get(name) !== undefined) {
|
|
386
|
+
// Defined before install() ran (shouldn't happen — the installer is
|
|
387
|
+
// import-hoisted — but recover gracefully without instance tracking).
|
|
388
|
+
record = {
|
|
389
|
+
tagName: name,
|
|
390
|
+
canonical: this.get(name),
|
|
391
|
+
instances: new Set(),
|
|
392
|
+
generation: 0,
|
|
393
|
+
};
|
|
394
|
+
state.records.set(name, record);
|
|
395
|
+
}
|
|
396
|
+
if (record === undefined) {
|
|
397
|
+
record = {
|
|
398
|
+
tagName: name,
|
|
399
|
+
canonical: ctor,
|
|
400
|
+
instances: new Set(),
|
|
401
|
+
generation: 0,
|
|
402
|
+
};
|
|
403
|
+
state.records.set(name, record);
|
|
404
|
+
instrument(state, ctor.prototype, record);
|
|
405
|
+
return nativeDefine.call(this, name, ctor, defineOptions);
|
|
406
|
+
}
|
|
407
|
+
if (ctor === record.canonical) {
|
|
408
|
+
// Same class object re-defined; nothing to patch.
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
hotPatch(state, record, ctor);
|
|
412
|
+
};
|
|
374
413
|
};
|
|
375
|
-
//# sourceMappingURL=patch.js.map
|
|
414
|
+
//# sourceMappingURL=patch.js.map
|