@stencil/core 5.0.0-alpha.3 → 5.0.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/{client-CSm3x5ke.mjs → client-Dnio47yQ.mjs} +108 -19
  2. package/dist/compiler/index.d.mts +2 -2
  3. package/dist/compiler/index.mjs +2 -2
  4. package/dist/compiler/utils/index.d.mts +2 -2
  5. package/dist/compiler/utils/index.mjs +3 -3
  6. package/dist/{compiler-D6iP7Bzb.mjs → compiler-Dxri2g8Z.mjs} +14994 -14303
  7. package/dist/declarations/stencil-public-compiler.d.ts +342 -132
  8. package/dist/declarations/stencil-public-compiler.js +2 -3
  9. package/dist/declarations/stencil-public-runtime.d.ts +2 -0
  10. package/dist/{index-hS-KBdAP.d.ts → index-D-XN9HW_.d.ts} +1 -1
  11. package/dist/{index-tUR6pD3J.d.mts → index-D5zaocDq.d.mts} +411 -189
  12. package/dist/{index-CyrGY82h.d.ts → index-D61XZw0f.d.ts} +2 -2
  13. package/dist/{index-CXHCTQNt.d.mts → index-Dat4djoo.d.mts} +5 -1
  14. package/dist/index.mjs +1 -1
  15. package/dist/{jsx-runtime-DlDkTqps.d.ts → jsx-runtime-B3vQbWIW.d.ts} +1 -1
  16. package/dist/jsx-runtime.d.ts +1 -1
  17. package/dist/jsx-runtime.js +1 -1
  18. package/dist/{node-Bg-mO5dw.mjs → node-pj6rF4Wt.mjs} +66 -69
  19. package/dist/{regular-expression-D5pGVpCu.mjs → regular-expression-D0_N0PGa.mjs} +44 -26
  20. package/dist/runtime/app-data/index.d.ts +1 -1
  21. package/dist/runtime/client/index.d.ts +45 -8
  22. package/dist/runtime/client/index.js +132 -40
  23. package/dist/runtime/index.d.ts +33 -5
  24. package/dist/runtime/index.js +2 -2
  25. package/dist/runtime/server/index.d.mts +72 -28
  26. package/dist/runtime/server/index.mjs +146 -46
  27. package/dist/runtime/server/runner.d.mts +40 -26
  28. package/dist/runtime/server/runner.mjs +28 -22
  29. package/dist/{runtime-BBCnuprF.js → runtime-CKyUrF4i.js} +131 -39
  30. package/dist/sys/node/index.d.mts +1 -1
  31. package/dist/sys/node/index.mjs +1 -1
  32. package/dist/sys/node/worker.mjs +2 -2
  33. package/dist/testing/index.d.mts +2 -2
  34. package/dist/testing/index.mjs +17 -16
  35. package/dist/{validation-Byxie0Uk.mjs → validation-BA8nzXu_.mjs} +82 -58
  36. package/package.json +11 -12
@@ -7,7 +7,7 @@ type ResolutionHandler = (elm: HTMLElement) => string | undefined | null;
7
7
  type TagTransformer = (tag: string) => string;
8
8
  //#endregion
9
9
  //#region src/declarations/stencil-public-compiler.d.ts
10
- interface HydrateDocumentOptions {
10
+ interface SsrDocumentOptions {
11
11
  /**
12
12
  * Build ID that will be added to `<html data-stencil-build="BUILD_ID">`. By default
13
13
  * a random ID will be generated
@@ -24,7 +24,7 @@ interface HydrateDocumentOptions {
24
24
  * JavaScript to read the structure of the HTML and rebuild each
25
25
  * component. Defaults to `true`.
26
26
  */
27
- clientHydrateAnnotations?: boolean;
27
+ clientSsrAnnotations?: boolean;
28
28
  /**
29
29
  * Constrain `setTimeout()` to 1ms, but still async. Also
30
30
  * only allows `setInterval()` to fire once, also constrained to 1ms.
@@ -123,10 +123,14 @@ interface HydrateDocumentOptions {
123
123
  default: 'declarative-shadow-dom' | 'scoped';
124
124
  } | boolean;
125
125
  }
126
- interface SerializeDocumentOptions extends HydrateDocumentOptions {
126
+ interface SerializeDocumentOptions extends SsrDocumentOptions {
127
127
  /**
128
128
  * Runs after the `document` has been hydrated.
129
129
  */
130
+ afterSsr?(document: any): any | Promise<any>;
131
+ /**
132
+ * @deprecated Use `afterSsr` instead.
133
+ */
130
134
  afterHydrate?(document: any): any | Promise<any>;
131
135
  /**
132
136
  * Sets an approximate line width the HTML should attempt to stay within.
@@ -139,6 +143,10 @@ interface SerializeDocumentOptions extends HydrateDocumentOptions {
139
143
  /**
140
144
  * Runs before the `document` has been hydrated.
141
145
  */
146
+ beforeSsr?(document: any): any | Promise<any>;
147
+ /**
148
+ * @deprecated Use `beforeSsr` instead.
149
+ */
142
150
  beforeHydrate?(document: any): any | Promise<any>;
143
151
  /**
144
152
  * Format the HTML in a nicely indented format.
@@ -176,7 +184,7 @@ interface SerializeDocumentOptions extends HydrateDocumentOptions {
176
184
  */
177
185
  modes?: ResolutionHandler[];
178
186
  }
179
- interface HydrateFactoryOptions extends SerializeDocumentOptions {
187
+ interface SsrFactoryOptions extends SerializeDocumentOptions {
180
188
  serializeToHtml: boolean;
181
189
  destroyWindow: boolean;
182
190
  destroyDocument: boolean;
@@ -204,7 +212,7 @@ interface PrintLine {
204
212
  errorCharStart: number;
205
213
  errorLength?: number;
206
214
  }
207
- interface HydrateResults {
215
+ interface SsrResults {
208
216
  buildId: string;
209
217
  diagnostics: Diagnostic[];
210
218
  url: string;
@@ -216,42 +224,42 @@ interface HydrateResults {
216
224
  search: string | null;
217
225
  hash: string | null;
218
226
  html: string | null;
219
- components: HydrateComponent[];
220
- anchors: HydrateAnchorElement[];
221
- imgs: HydrateImgElement[];
222
- scripts: HydrateScriptElement[];
223
- styles: HydrateStyleElement[];
224
- staticData: HydrateStaticData[];
227
+ components: SsrComponent[];
228
+ anchors: SsrAnchorElement[];
229
+ imgs: SsrImgElement[];
230
+ scripts: SsrScriptElement[];
231
+ styles: SsrStyleElement[];
232
+ staticData: SsrStaticData[];
225
233
  title: string | null;
226
234
  hydratedCount: number;
227
235
  httpStatus: number | null;
228
236
  }
229
- interface HydrateComponent {
237
+ interface SsrComponent {
230
238
  tag: string;
231
239
  mode: string;
232
240
  count: number;
233
241
  depth: number;
234
242
  }
235
- interface HydrateElement {
243
+ interface SsrElement {
236
244
  [attrName: string]: string | undefined;
237
245
  }
238
- interface HydrateAnchorElement extends HydrateElement {
246
+ interface SsrAnchorElement extends SsrElement {
239
247
  href?: string;
240
248
  target?: string;
241
249
  }
242
- interface HydrateImgElement extends HydrateElement {
250
+ interface SsrImgElement extends SsrElement {
243
251
  src?: string;
244
252
  }
245
- interface HydrateScriptElement extends HydrateElement {
253
+ interface SsrScriptElement extends SsrElement {
246
254
  src?: string;
247
255
  type?: string;
248
256
  }
249
- interface HydrateStyleElement extends HydrateElement {
257
+ interface SsrStyleElement extends SsrElement {
250
258
  id?: string;
251
259
  href?: string;
252
260
  content?: string;
253
261
  }
254
- interface HydrateStaticData {
262
+ interface SsrStaticData {
255
263
  id: string;
256
264
  type: string;
257
265
  content: string;
@@ -265,7 +273,7 @@ interface HydrateStaticData {
265
273
  * @param options - serialization options
266
274
  * @returns the hydration results
267
275
  */
268
- declare function renderToString(html: string | any, options?: SerializeDocumentOptions): Promise<HydrateResults>;
276
+ declare function renderToString(html: string | any, options?: SerializeDocumentOptions): Promise<SsrResults>;
269
277
  /**
270
278
  * Renders HTML and returns a Node.js Readable stream.
271
279
  * This is a Node.js-specific convenience wrapper around renderToString.
@@ -276,20 +284,26 @@ declare function renderToString(html: string | any, options?: SerializeDocumentO
276
284
  */
277
285
  declare function streamToString(html: string | any, options?: SerializeDocumentOptions): Readable;
278
286
  /**
279
- * Hydrates a document or HTML string, returning the full hydration results.
287
+ * Server side renders a document or HTML string, returning the full render results.
280
288
  * This is portable (no Node.js dependencies).
281
- * @param doc - the document or HTML string to hydrate
289
+ * @param doc - the document or HTML string to render
282
290
  * @param options - hydration options
283
- * @returns the hydration results
291
+ * @returns the render results
292
+ */
293
+ declare function ssrDocument(doc: any | string, options?: SsrDocumentOptions): Promise<SsrResults>;
294
+ /**
295
+ * v4 Compat
296
+ * @alias
297
+ * @deprecated Use `ssrDocument()` instead
284
298
  */
285
- declare function hydrateDocument(doc: any | string, options?: HydrateDocumentOptions): Promise<HydrateResults>;
286
- declare function serializeDocumentToString(doc: Document, opts: HydrateFactoryOptions): string;
299
+ declare const hydrateDocument: typeof ssrDocument;
300
+ declare function serializeDocumentToString(doc: Document, opts: SsrFactoryOptions): string;
287
301
  //#endregion
288
302
  //#region src/server/runner/window-initialize.d.ts
289
303
  /**
290
304
  * Reset the docData counters. Useful for testing to ensure deterministic IDs.
291
305
  */
292
- declare function resetHydrateDocData(): void;
306
+ declare function resetSsrDocData(): void;
293
307
  //#endregion
294
308
  //#region src/runtime/tag-transform.d.ts
295
309
  /**
@@ -304,4 +318,4 @@ declare function transformTag<T extends string>(tag: T): T;
304
318
  */
305
319
  declare function setTagTransformer(transformer: TagTransformer): void;
306
320
  //#endregion
307
- export { createWindowFromHtml, hydrateDocument, renderToString, resetHydrateDocData, serializeDocumentToString, setTagTransformer, streamToString, transformTag };
321
+ export { createWindowFromHtml, hydrateDocument, renderToString, resetSsrDocData, serializeDocumentToString, setTagTransformer, ssrDocument, streamToString, transformTag };
@@ -1,5 +1,5 @@
1
1
  import { Readable } from "node:stream";
2
- import { hydrateFactory } from "@stencil/core/runtime/server/hydrate-factory";
2
+ import { ssrFactory } from "@stencil/core/runtime/server/ssr-factory";
3
3
  import { BUILD } from "@stencil/core/runtime/app-data";
4
4
  //#region ../../node_modules/.pnpm/parse5@7.2.1/node_modules/parse5/dist/common/unicode.js
5
5
  const UNDEFINED_CODE_POINTS = new Set([
@@ -8899,7 +8899,7 @@ function insertBefore(parentNode, newNode, referenceNode) {
8899
8899
  var MockHTMLElement = class extends MockElement {
8900
8900
  __namespaceURI = "http://www.w3.org/1999/xhtml";
8901
8901
  constructor(ownerDocument, nodeName) {
8902
- super(ownerDocument, typeof nodeName === "string" ? nodeName.toUpperCase() : null);
8902
+ super(ownerDocument, nodeName ? nodeName.toUpperCase() : null);
8903
8903
  }
8904
8904
  get tagName() {
8905
8905
  return this.nodeName ?? "";
@@ -13300,7 +13300,7 @@ function normalizeHydrateOptions(inputOpts) {
13300
13300
  destroyWindow: false,
13301
13301
  destroyDocument: false
13302
13302
  }, inputOpts || {});
13303
- if (typeof outputOpts.clientHydrateAnnotations !== "boolean") outputOpts.clientHydrateAnnotations = true;
13303
+ if (typeof outputOpts.clientSsrAnnotations !== "boolean") outputOpts.clientSsrAnnotations = true;
13304
13304
  if (typeof outputOpts.constrainTimeouts !== "boolean") outputOpts.constrainTimeouts = true;
13305
13305
  if (typeof outputOpts.maxHydrateCount !== "number") outputOpts.maxHydrateCount = 300;
13306
13306
  if (typeof outputOpts.runtimeLogging !== "boolean") outputOpts.runtimeLogging = false;
@@ -13319,7 +13319,7 @@ function mapValidTags(tag) {
13319
13319
  }
13320
13320
  function generateHydrateResults(opts) {
13321
13321
  if (typeof opts.url !== "string") opts.url = `https://hydrate.stenciljs.com/`;
13322
- if (typeof opts.buildId !== "string") opts.buildId = createHydrateBuildId();
13322
+ if (typeof opts.buildId !== "string") opts.buildId = createSsrBuildId();
13323
13323
  const results = {
13324
13324
  buildId: opts.buildId,
13325
13325
  diagnostics: [],
@@ -13357,7 +13357,7 @@ function generateHydrateResults(opts) {
13357
13357
  }
13358
13358
  return results;
13359
13359
  }
13360
- const createHydrateBuildId = () => {
13360
+ const createSsrBuildId = () => {
13361
13361
  let chars = "abcdefghijklmnopqrstuvwxyz";
13362
13362
  let buildId = "";
13363
13363
  while (buildId.length < 8) {
@@ -13447,7 +13447,7 @@ const docData = {
13447
13447
  /**
13448
13448
  * Reset the docData counters. Useful for testing to ensure deterministic IDs.
13449
13449
  */
13450
- function resetHydrateDocData() {
13450
+ function resetSsrDocData() {
13451
13451
  docData.hostIds = 0;
13452
13452
  docData.rootLevelIds = 0;
13453
13453
  docData.staticComponents.clear();
@@ -13510,7 +13510,7 @@ function renderToString(html, options) {
13510
13510
  * Make sure we wait for components to be hydrated.
13511
13511
  */
13512
13512
  opts.constrainTimeouts = false;
13513
- return hydrateDocument(html, opts);
13513
+ return ssrDocument(html, opts);
13514
13514
  }
13515
13515
  /**
13516
13516
  * Renders HTML and returns a Node.js Readable stream.
@@ -13527,13 +13527,13 @@ function streamToString(html, options) {
13527
13527
  return Readable.from(generateStream());
13528
13528
  }
13529
13529
  /**
13530
- * Hydrates a document or HTML string, returning the full hydration results.
13530
+ * Server side renders a document or HTML string, returning the full render results.
13531
13531
  * This is portable (no Node.js dependencies).
13532
- * @param doc - the document or HTML string to hydrate
13532
+ * @param doc - the document or HTML string to render
13533
13533
  * @param options - hydration options
13534
- * @returns the hydration results
13534
+ * @returns the render results
13535
13535
  */
13536
- function hydrateDocument(doc, options) {
13536
+ function ssrDocument(doc, options) {
13537
13537
  const opts = normalizeHydrateOptions(options);
13538
13538
  /**
13539
13539
  * Defines whether we render the shadow root as a declarative shadow root or as scoped shadow root.
@@ -13566,6 +13566,12 @@ function hydrateDocument(doc, options) {
13566
13566
  renderBuildError(results, `Invalid html or document. Must be either a valid "html" string, or DOM "document".`);
13567
13567
  return Promise.resolve(results);
13568
13568
  }
13569
+ /**
13570
+ * v4 Compat
13571
+ * @alias
13572
+ * @deprecated Use `ssrDocument()` instead
13573
+ */
13574
+ const hydrateDocument = ssrDocument;
13569
13575
  async function render(win, opts, results) {
13570
13576
  if ("process" in globalThis && typeof process.on === "function" && !process.__stencilErrors) {
13571
13577
  process.__stencilErrors = true;
@@ -13574,7 +13580,7 @@ async function render(win, opts, results) {
13574
13580
  });
13575
13581
  }
13576
13582
  initializeWindow(win, win.document, opts, results);
13577
- const beforeHydrateFn = typeof opts.beforeHydrate === "function" ? opts.beforeHydrate : NOOP;
13583
+ const beforeHydrateFn = typeof (opts.beforeSsr || opts.beforeHydrate) === "function" ? opts.beforeSsr || opts.beforeHydrate : NOOP;
13578
13584
  try {
13579
13585
  await Promise.resolve(beforeHydrateFn(win.document));
13580
13586
  return new Promise((resolve) => {
@@ -13586,24 +13592,24 @@ async function render(win, opts, results) {
13586
13592
  modeResolutionChain.length = 0;
13587
13593
  opts.modes.forEach((mode) => setMode(mode));
13588
13594
  }
13589
- return hydrateFactory(win, opts, results, afterHydrate, resolve);
13595
+ return ssrFactory(win, opts, results, afterSsr, resolve);
13590
13596
  });
13591
13597
  } catch (e) {
13592
13598
  renderCatchError(results, e);
13593
- return finalizeHydrate(win, win.document, opts, results);
13599
+ return finalizeSsr(win, win.document, opts, results);
13594
13600
  }
13595
13601
  }
13596
- async function afterHydrate(win, opts, results, resolve) {
13597
- const afterHydrateFn = typeof opts.afterHydrate === "function" ? opts.afterHydrate : NOOP;
13602
+ async function afterSsr(win, opts, results, resolve) {
13603
+ const afterSsrFn = typeof (opts.afterSsr || opts.afterHydrate) === "function" ? opts.afterSsr || opts.afterHydrate : NOOP;
13598
13604
  try {
13599
- await Promise.resolve(afterHydrateFn(win.document));
13600
- return resolve(finalizeHydrate(win, win.document, opts, results));
13605
+ await Promise.resolve(afterSsrFn(win.document));
13606
+ return resolve(finalizeSsr(win, win.document, opts, results));
13601
13607
  } catch (e) {
13602
13608
  renderCatchError(results, e);
13603
- return resolve(finalizeHydrate(win, win.document, opts, results));
13609
+ return resolve(finalizeSsr(win, win.document, opts, results));
13604
13610
  }
13605
13611
  }
13606
- function finalizeHydrate(win, doc, opts, results) {
13612
+ function finalizeSsr(win, doc, opts, results) {
13607
13613
  try {
13608
13614
  inspectElement(results, doc.documentElement, 0);
13609
13615
  if (opts.removeUnusedStyles !== false) try {
@@ -13642,7 +13648,7 @@ function finalizeHydrate(win, doc, opts, results) {
13642
13648
  } catch (e) {
13643
13649
  renderCatchError(results, e);
13644
13650
  }
13645
- if (opts.clientHydrateAnnotations) doc.documentElement.classList.add("hydrated");
13651
+ if (opts.clientSsrAnnotations) doc.documentElement.classList.add("hydrated");
13646
13652
  if (opts.serializeToHtml) results.html = serializeDocumentToString(doc, opts);
13647
13653
  } catch (e) {
13648
13654
  renderCatchError(results, e);
@@ -13687,4 +13693,4 @@ function removeScripts(elm) {
13687
13693
  }
13688
13694
  }
13689
13695
  //#endregion
13690
- export { createWindowFromHtml, hydrateDocument, renderToString, resetHydrateDocData, serializeDocumentToString, setTagTransformer, streamToString, transformTag };
13696
+ export { createWindowFromHtml, hydrateDocument, renderToString, resetSsrDocData, serializeDocumentToString, setTagTransformer, ssrDocument, streamToString, transformTag };
@@ -1309,7 +1309,8 @@ const addStyle = (styleContainerNode, cmpMeta, mode) => {
1309
1309
  styleElm.textContent = style;
1310
1310
  const nonce = plt.$nonce$ ?? queryNonceMetaTagContent(win.document);
1311
1311
  if (nonce != null) styleElm.setAttribute("nonce", nonce);
1312
- if ((BUILD.hydrateServerSide || BUILD.hotModuleReplacement) && (cmpMeta.$flags$ & CMP_FLAGS.scopedCssEncapsulation || cmpMeta.$flags$ & CMP_FLAGS.shadowNeedsScopedCss || cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation)) styleElm.setAttribute(HYDRATED_STYLE_ID, scopeId);
1312
+ if (BUILD.hydrateServerSide && (cmpMeta.$flags$ & CMP_FLAGS.scopedCssEncapsulation || cmpMeta.$flags$ & CMP_FLAGS.shadowNeedsScopedCss || cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) || BUILD.hotModuleReplacement) styleElm.setAttribute(HYDRATED_STYLE_ID, scopeId);
1313
+ if (BUILD.hotModuleReplacement && cmpMeta.$flags$ & CMP_FLAGS.hasSlotRelocation) styleElm.setAttribute("data-slot-fb", "");
1313
1314
  /**
1314
1315
  * attach styles at the end of the head tag if we render scoped components
1315
1316
  */
@@ -2420,6 +2421,46 @@ const computeMode = (elm) => modeResolutionChain.map((h) => h(elm)).find((m) =>
2420
2421
  const setMode = (handler) => modeResolutionChain.push(handler);
2421
2422
  const getMode = (ref) => getHostRef(ref)?.$modeName$;
2422
2423
  //#endregion
2424
+ //#region src/runtime/normalize-watchers.ts
2425
+ /**
2426
+ * Normalizes watcher metadata to the current `{ [methodName]: flags }[]` format.
2427
+ *
2428
+ * Prior to Stencil 4.39.x (PR #6484), the `@Watch()` compiler emitted watcher
2429
+ * handlers as a plain string array: `{ "min": ["minChanged"] }`. The new format
2430
+ * wraps each entry in an object that carries option flags (e.g. `immediate`):
2431
+ * `{ "min": [{ "minChanged": 0 }] }`.
2432
+ *
2433
+ * When a library (e.g. Ionic Framework) was compiled with an older Stencil compiler
2434
+ * but consumed by an app using a newer Stencil runtime, the runtime's
2435
+ * `Object.entries(watcher)` call receives a string and misinterprets its character
2436
+ * indices as method names, causing:
2437
+ * `TypeError: instance[watchMethodName] is not a function`
2438
+ *
2439
+ * This helper should be used at `$watchers$` assignment sites that need to
2440
+ * accept both legacy and current compiler metadata so downstream code on those
2441
+ * paths can safely assume the new object format.
2442
+ *
2443
+ * @param raw The raw watcher map from compiled metadata (new or legacy format).
2444
+ * @returns A normalized watcher map in the `{ [methodName]: flags }[]` format, or `undefined` if `raw` is `undefined` or empty.
2445
+ */
2446
+ const normalizeWatchers = (raw) => {
2447
+ if (!raw) return void 0;
2448
+ const keys = Object.keys(raw);
2449
+ if (keys.length === 0) return void 0;
2450
+ let hasLegacy = false;
2451
+ for (const propName of keys) {
2452
+ if (hasLegacy) break;
2453
+ for (const h of raw[propName]) if (typeof h === "string") {
2454
+ hasLegacy = true;
2455
+ break;
2456
+ }
2457
+ }
2458
+ if (!hasLegacy) return raw;
2459
+ const out = {};
2460
+ for (const propName of keys) out[propName] = raw[propName].map((h) => typeof h === "string" ? { [h]: 0 } : h);
2461
+ return out;
2462
+ };
2463
+ //#endregion
2423
2464
  //#region src/runtime/parse-property-value.ts
2424
2465
  /**
2425
2466
  * Parse a new property value for a given property type.
@@ -3770,7 +3811,7 @@ const proxyComponent = (Cstr, cmpMeta, flags) => {
3770
3811
  });
3771
3812
  if (BUILD.member && cmpMeta.$members$ || BUILD.propChangeCallback) {
3772
3813
  if (BUILD.propChangeCallback) {
3773
- if (Cstr.watchers && !cmpMeta.$watchers$) cmpMeta.$watchers$ = Cstr.watchers;
3814
+ if (Cstr.watchers && !cmpMeta.$watchers$) cmpMeta.$watchers$ = normalizeWatchers(Cstr.watchers);
3774
3815
  if (Cstr.deserializers && !cmpMeta.$deserializers$) cmpMeta.$deserializers$ = Cstr.deserializers;
3775
3816
  if (Cstr.serializers && !cmpMeta.$serializers$) cmpMeta.$serializers$ = Cstr.serializers;
3776
3817
  }
@@ -3875,9 +3916,11 @@ const proxyComponent = (Cstr, cmpMeta, flags) => {
3875
3916
  return;
3876
3917
  }
3877
3918
  const propFlags = members.find(([m]) => m === propName);
3878
- if (propFlags && propFlags[1][0] & MEMBER_FLAGS.Boolean) newValue = newValue !== null && newValue !== "false";
3919
+ const isBooleanTarget = propFlags && propFlags[1][0] & MEMBER_FLAGS.Boolean;
3920
+ const isSpuriousBooleanRemoval = isBooleanTarget && newValue === null && this[propName] === void 0;
3921
+ if (isBooleanTarget) newValue = !(newValue === null || newValue === "false");
3879
3922
  const propDesc = Object.getOwnPropertyDescriptor(prototype, propName);
3880
- if (newValue != this[propName] && (!propDesc.get || !!propDesc.set)) this[propName] = newValue;
3923
+ if (!isSpuriousBooleanRemoval && newValue != this[propName] && (!propDesc.get || !!propDesc.set)) this[propName] = newValue;
3881
3924
  });
3882
3925
  };
3883
3926
  Cstr.observedAttributes = Array.from(new Set([...Object.keys(cmpMeta.$watchers$ ?? {}), ...members.filter(([_, m]) => m[0] & MEMBER_FLAGS.HasAttribute).map(([propName, m]) => {
@@ -3918,7 +3961,7 @@ const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId) => {
3918
3961
  if (!Cstr) throw new Error(`Constructor for "${cmpMeta.$tagName$}#${hostRef.$modeName$}" was not found`);
3919
3962
  if (BUILD.member && !Cstr.isProxied) {
3920
3963
  if (BUILD.propChangeCallback) {
3921
- cmpMeta.$watchers$ = Cstr.watchers;
3964
+ cmpMeta.$watchers$ = normalizeWatchers(Cstr.watchers);
3922
3965
  cmpMeta.$serializers$ = Cstr.serializers;
3923
3966
  cmpMeta.$deserializers$ = Cstr.deserializers;
3924
3967
  }
@@ -4094,7 +4137,59 @@ const disconnectedCallback = async (elm) => {
4094
4137
  if (elm.shadowRoot && rootAppliedStyles.has(elm.shadowRoot)) rootAppliedStyles.delete(elm.shadowRoot);
4095
4138
  };
4096
4139
  //#endregion
4097
- //#region src/runtime/bootstrap-custom-element.ts
4140
+ //#region src/runtime/hmr-component.ts
4141
+ /**
4142
+ * Kick off hot-module-replacement for a component. In order to replace the
4143
+ * component in-place we:
4144
+ *
4145
+ * 1. get a reference to the {@link d.HostRef} for the element
4146
+ * 2. reset the element's runtime flags
4147
+ * 3. re-run the initialization logic for the element (via
4148
+ * {@link initializeComponent})
4149
+ *
4150
+ * For standalone (non-lazy) builds, we instead re-import the component module
4151
+ * and patch the prototype of the registered constructor in-place, then
4152
+ * force a re-render of all existing instances in the DOM.
4153
+ *
4154
+ * @param hostElement the host element for the component which we want to start
4155
+ * doing HMR
4156
+ * @param cmpMeta runtime metadata for the component
4157
+ * @param hmrVersionId the current HMR version ID
4158
+ */
4159
+ const hmrStart = (hostElement, cmpMeta, hmrVersionId) => {
4160
+ if (BUILD.lazyLoad) {
4161
+ const hostRef = getHostRef(hostElement);
4162
+ if (!hostRef) return;
4163
+ hostRef.$flags$ = HOST_FLAGS.hasConnected;
4164
+ initializeComponent(hostElement, hostRef, cmpMeta, hmrVersionId);
4165
+ } else hmrStandalone(hostElement, cmpMeta, hmrVersionId);
4166
+ };
4167
+ const hmrStandalone = async (hostElement, cmpMeta, hmrVersionId) => {
4168
+ const modulePath = hostElement.constructor.__stencil_module__;
4169
+ console.log(`[Stencil HMR] hmrStandalone <${cmpMeta.$tagName$}> modulePath:`, modulePath);
4170
+ if (!modulePath) {
4171
+ console.warn(`[Stencil HMR] No __stencil_module__ on <${cmpMeta.$tagName$}> constructor — was this built with devMode?`);
4172
+ return;
4173
+ }
4174
+ try {
4175
+ const newModule = await import(
4176
+ /* @vite-ignore */
4177
+ `${modulePath}?s-hmr=${hmrVersionId}`
4178
+ );
4179
+ const NewClass = Object.values(newModule).find((v) => typeof v === "function" && v.is === cmpMeta.$tagName$) ?? newModule.default;
4180
+ if (!NewClass) return;
4181
+ const ctor = customElements.get(cmpMeta.$tagName$);
4182
+ if (ctor) for (const key of Object.getOwnPropertyNames(NewClass.prototype)) {
4183
+ if (key === "constructor") continue;
4184
+ Object.defineProperty(ctor.prototype, key, Object.getOwnPropertyDescriptor(NewClass.prototype, key));
4185
+ }
4186
+ document.querySelectorAll(cmpMeta.$tagName$).forEach((el) => forceUpdate(el));
4187
+ } catch (e) {
4188
+ console.error(`[Stencil HMR] Failed to reload <${cmpMeta.$tagName$}>`, e);
4189
+ }
4190
+ };
4191
+ //#endregion
4192
+ //#region src/runtime/bootstrap-standalone.ts
4098
4193
  const defineCustomElement = (Cstr, compactMeta) => {
4099
4194
  customElements.define(transformTag(compactMeta[1]), proxyCustomElement(Cstr, compactMeta));
4100
4195
  };
@@ -4108,12 +4203,15 @@ const proxyCustomElement = (Cstr, compactMeta) => {
4108
4203
  if (BUILD.member) cmpMeta.$members$ = compactMeta[2];
4109
4204
  if (BUILD.hostListener) cmpMeta.$listeners$ = compactMeta[3];
4110
4205
  if (BUILD.propChangeCallback) {
4111
- cmpMeta.$watchers$ = Cstr.$watchers$;
4206
+ cmpMeta.$watchers$ = normalizeWatchers(Cstr.$watchers$);
4112
4207
  cmpMeta.$deserializers$ = Cstr.$deserializers$;
4113
4208
  cmpMeta.$serializers$ = Cstr.$serializers$;
4114
4209
  }
4115
4210
  if (BUILD.reflect) cmpMeta.$attrsToReflect$ = [];
4116
4211
  if (BUILD.shadowDom && !supportsShadow && cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) cmpMeta.$flags$ |= CMP_FLAGS.needsShadowDomShim;
4212
+ if (BUILD.hotModuleReplacement) Cstr.prototype["s-hmr"] = function(hmrVersionId) {
4213
+ hmrStart(this, cmpMeta, hmrVersionId);
4214
+ };
4117
4215
  if (!(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) && cmpMeta.$flags$ & CMP_FLAGS.hasSlot) if (BUILD.experimentalSlotFixes || BUILD.patchAll && cmpMeta.$flags$ & CMP_FLAGS.patchAll) patchPseudoShadowDom(Cstr.prototype);
4118
4216
  else {
4119
4217
  if (BUILD.slotChildNodesFix || BUILD.patchChildren && cmpMeta.$flags$ & CMP_FLAGS.patchChildren) patchChildSlotNodes(Cstr.prototype);
@@ -4194,29 +4292,7 @@ const forceModeUpdate = (elm) => {
4194
4292
  }
4195
4293
  };
4196
4294
  //#endregion
4197
- //#region src/runtime/hmr-component.ts
4198
- /**
4199
- * Kick off hot-module-replacement for a component. In order to replace the
4200
- * component in-place we:
4201
- *
4202
- * 1. get a reference to the {@link d.HostRef} for the element
4203
- * 2. reset the element's runtime flags
4204
- * 3. re-run the initialization logic for the element (via
4205
- * {@link initializeComponent})
4206
- *
4207
- * @param hostElement the host element for the component which we want to start
4208
- * doing HMR
4209
- * @param cmpMeta runtime metadata for the component
4210
- * @param hmrVersionId the current HMR version ID
4211
- */
4212
- const hmrStart = (hostElement, cmpMeta, hmrVersionId) => {
4213
- const hostRef = getHostRef(hostElement);
4214
- if (!hostRef) return;
4215
- hostRef.$flags$ = HOST_FLAGS.hasConnected;
4216
- initializeComponent(hostElement, hostRef, cmpMeta, hmrVersionId);
4217
- };
4218
- //#endregion
4219
- //#region src/runtime/bootstrap-lazy.ts
4295
+ //#region src/runtime/bootstrap-loader.ts
4220
4296
  const bootstrapLazy = (lazyBundles, options = {}) => {
4221
4297
  if (BUILD.profile && performance.mark) performance.mark("st:app:start");
4222
4298
  installDevTools();
@@ -4250,7 +4326,7 @@ const bootstrapLazy = (lazyBundles, options = {}) => {
4250
4326
  if (BUILD.hostListener) cmpMeta.$listeners$ = compactMeta[3];
4251
4327
  if (BUILD.reflect) cmpMeta.$attrsToReflect$ = [];
4252
4328
  if (BUILD.propChangeCallback) {
4253
- cmpMeta.$watchers$ = compactMeta[4] ?? {};
4329
+ cmpMeta.$watchers$ = normalizeWatchers(compactMeta[4]);
4254
4330
  cmpMeta.$serializers$ = compactMeta[5] ?? {};
4255
4331
  cmpMeta.$deserializers$ = compactMeta[6] ?? {};
4256
4332
  }
@@ -4406,8 +4482,19 @@ const setPlatformOptions = (opts) => Object.assign(plt, opts);
4406
4482
  //#endregion
4407
4483
  //#region src/runtime/render.ts
4408
4484
  /**
4485
+ * A WeakMap to persist HostRef objects across multiple render() calls to the
4486
+ * same container. This enables VNode diffing on re-renders — without it, each
4487
+ * call creates a fresh HostRef with no previous VNode, causing renderVdom to
4488
+ * replace the entire DOM subtree instead of patching only what changed.
4489
+ */
4490
+ const hostRefCache = /* @__PURE__ */ new WeakMap();
4491
+ /**
4409
4492
  * Method to render a virtual DOM tree to a container element.
4410
4493
  *
4494
+ * Supports efficient re-renders: calling `render()` again on the same container
4495
+ * will diff the new VNode tree against the previous one and only update what changed,
4496
+ * preserving existing DOM elements and their state.
4497
+ *
4411
4498
  * @example
4412
4499
  * ```tsx
4413
4500
  * import { render } from '@stencil/core';
@@ -4424,14 +4511,19 @@ const setPlatformOptions = (opts) => Object.assign(plt, opts);
4424
4511
  * @param container - The container element to render the virtual DOM tree to
4425
4512
  */
4426
4513
  function render(vnode, container) {
4427
- renderVdom({
4428
- $flags$: 0,
4429
- $cmpMeta$: {
4514
+ let ref = hostRefCache.get(container);
4515
+ if (!ref) {
4516
+ ref = {
4430
4517
  $flags$: 0,
4431
- $tagName$: container.tagName
4432
- },
4433
- $hostElement$: container
4434
- }, vnode);
4518
+ $cmpMeta$: {
4519
+ $flags$: 0,
4520
+ $tagName$: container.tagName
4521
+ },
4522
+ $hostElement$: container
4523
+ };
4524
+ hostRefCache.set(container, ref);
4525
+ }
4526
+ renderVdom(ref, vnode);
4435
4527
  }
4436
4528
  //#endregion
4437
4529
  //#region src/runtime/tag-transform.ts
@@ -4656,4 +4748,4 @@ const insertChildVNodeAnnotations = (doc, vnodeChild, cmpData, hostId, depth, in
4656
4748
  }
4657
4749
  };
4658
4750
  //#endregion
4659
- export { h as A, postUpdateComponent as C, getMode as D, parsePropertyValue as E, HYDRATED_STYLE_ID as F, getShadowRoot as M, getAssetPath as N, setMode as O, setAssetPath as P, getRenderingRef as S, createEvent as T, connectedCallback as _, transformTag as a, setValue as b, setNonce as c, Fragment as d, bootstrapLazy as f, disconnectedCallback as g, proxyCustomElement as h, setTagTransformer as i, getElement as j, Host as k, Mixin as l, forceModeUpdate as m, jsx as n, render as o, defineCustomElement as p, jsxs as r, setPlatformOptions as s, insertVdomAnnotations as t, addHostEventListeners as u, proxyComponent as v, renderVdom as w, forceUpdate as x, getValue as y };
4751
+ export { Host as A, postUpdateComponent as C, normalizeWatchers as D, parsePropertyValue as E, setAssetPath as F, HYDRATED_STYLE_ID as I, getElement as M, getShadowRoot as N, getMode as O, getAssetPath as P, getRenderingRef as S, createEvent as T, connectedCallback as _, transformTag as a, setValue as b, setNonce as c, Fragment as d, bootstrapLazy as f, disconnectedCallback as g, proxyCustomElement as h, setTagTransformer as i, h as j, setMode as k, Mixin as l, forceModeUpdate as m, jsx as n, render as o, defineCustomElement as p, jsxs as r, setPlatformOptions as s, insertVdomAnnotations as t, addHostEventListeners as u, proxyComponent as v, renderVdom as w, forceUpdate as x, getValue as y };
@@ -1,4 +1,4 @@
1
- import { Qr as Logger, gr as CompilerSystem } from "../../index-tUR6pD3J.mjs";
1
+ import { Qr as Logger, _r as CompilerSystem } from "../../index-D5zaocDq.mjs";
2
2
 
3
3
  //#region src/sys/node/logger/index.d.ts
4
4
  /**
@@ -1,2 +1,2 @@
1
- import { n as setupNodeProcess, r as createNodeLogger, t as createNodeSys } from "../../node-Bg-mO5dw.mjs";
1
+ import { n as setupNodeProcess, r as createNodeLogger, t as createNodeSys } from "../../node-pj6rF4Wt.mjs";
2
2
  export { createNodeLogger, createNodeSys, setupNodeProcess };
@@ -1,5 +1,5 @@
1
- import { l as createWorkerMessageHandler } from "../../compiler-D6iP7Bzb.mjs";
2
- import { t as createNodeSys } from "../../node-Bg-mO5dw.mjs";
1
+ import { l as createWorkerMessageHandler } from "../../compiler-Dxri2g8Z.mjs";
2
+ import { t as createNodeSys } from "../../node-pj6rF4Wt.mjs";
3
3
  //#region src/sys/node/node-worker-thread.ts
4
4
  /**
5
5
  * Initialize a worker thread, setting up various machinery for managing
@@ -1,5 +1,5 @@
1
- import { B as ComponentCompilerMeta, E as CompilerCtx, Qr as Logger, Rr as Diagnostic, Tt as HostRef, Wt as NewSpecPageOptions, Yr as LoadConfigInit, Zr as LogLevel, a as BuildCtx, ca as RafCallback, da as UserBuildConditionals, ei as LoggerTimeSpan, gr as CompilerSystem, mn as RuntimeRef, na as ValidatedConfig, oa as ErrorHandler, pt as ComponentRuntimeMeta, ta as UnvalidatedConfig, wt as HostElement, yn as SpecPage, zt as Module } from "../index-tUR6pD3J.mjs";
2
- import { _ as Env, c as getMode, d as Fragment, f as createEvent, g as setAssetPath, h as getAssetPath, i as getRenderingRef, n as h, p as getElement, r as forceUpdate, t as Host, u as Mixin } from "../index-CXHCTQNt.mjs";
1
+ import { B as ComponentCompilerMeta, E as CompilerCtx, Et as HostRef, Lt as NewSpecPageOptions, Mt as Module, Qr as Logger, Tt as HostElement, Yr as LoadConfigInit, Zr as LogLevel, _r as CompilerSystem, a as BuildCtx, aa as ValidatedConfig, da as RafCallback, ei as LoggerTimeSpan, fn as SpecPage, ia as UnvalidatedConfig, la as ErrorHandler, ma as UserBuildConditionals, pt as ComponentRuntimeMeta, sn as RuntimeRef, zr as Diagnostic } from "../index-D5zaocDq.mjs";
2
+ import { _ as Env, c as getMode, d as Fragment, f as createEvent, g as setAssetPath, h as getAssetPath, i as getRenderingRef, n as h, p as getElement, r as forceUpdate, t as Host, u as Mixin } from "../index-Dat4djoo.mjs";
3
3
  import { Mock } from "vitest";
4
4
 
5
5
  //#region src/testing/testing-logger.d.ts