@stencil/core 5.0.0-beta.0 → 5.0.0-beta.10

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.
@@ -1069,6 +1069,32 @@ declare const Fragment: FunctionalComponent;
1069
1069
  //#region src/runtime/host-listener.d.ts
1070
1070
  declare const addHostEventListeners: (elm: HostElement, hostRef: HostRef, listeners?: ComponentRuntimeHostListener[]) => void;
1071
1071
  //#endregion
1072
+ //#region src/runtime/inject-side-effect-style.d.ts
1073
+ /**
1074
+ * Registers a root (a shadow root, or `document`) to receive every side-effect CSS import
1075
+ * (a plain, non-component `import './foo.css'`), now and in future. Call in `connectedCallback`,
1076
+ * paired with `unregisterSideEffectStyleTarget` in `disconnectedCallback` so the registry doesn't
1077
+ * hold disconnected roots forever.
1078
+ * @param root the root to register
1079
+ */
1080
+ declare function registerSideEffectStyleTarget(root: DocumentOrShadowRoot): void;
1081
+ /**
1082
+ * Removes a root registered via `registerSideEffectStyleTarget` - call in `disconnectedCallback`.
1083
+ * @param root the root to unregister
1084
+ */
1085
+ declare function unregisterSideEffectStyleTarget(root: DocumentOrShadowRoot): void;
1086
+ /**
1087
+ * Applies plain (non-component) CSS text to every registered root - respects shadow DOM
1088
+ * encapsulation instead of always reaching for the top-level document. Not meant to be called
1089
+ * directly: this is what the compiler's CSS-to-ESM output calls for CSS with no Stencil `tag`
1090
+ * (i.e. not a component's own `styleUrl`), typically a third-party dependency's CSS import.
1091
+ *
1092
+ * `@font-face` rules are pulled out and adopted onto top-level `document` not per-root
1093
+ * (Chromium (https://issues.chromium.org/issues/41085401) per-root never loads).
1094
+ * @param cssText the CSS text to apply
1095
+ */
1096
+ declare function injectSideEffectStyle(cssText: string): void;
1097
+ //#endregion
1072
1098
  //#region src/runtime/mixin.d.ts
1073
1099
  type Ctor<T = {}> = new (...args: any[]) => T;
1074
1100
  declare function Mixin(...mixins: ((base: Ctor) => Ctor)[]): Ctor<{}>;
@@ -1248,4 +1274,4 @@ declare const setAssetPath: (path: string) => string;
1248
1274
  declare const setScopedSsr: (opts: SsrFactoryOptions) => void;
1249
1275
  declare const needsScopedSSR: () => boolean;
1250
1276
  //#endregion
1251
- export { BUILD, Build, Env, Fragment, Host, Mixin, NAMESPACE, addHostEventListeners, bootstrapLazy, cmpModules, connectedCallback, consoleDevError, consoleDevInfo, consoleDevWarn, consoleError, createEvent, defineCustomElement, disconnectedCallback, forceModeUpdate, forceUpdate, getAssetPath, getElement, getHostRef, getMode, getRenderingRef, getShadowRoot, getValue, hAsync as h, insertVdomAnnotations, isMemberInElement, jsx, jsxs, loadModule, modeResolutionChain, needsScopedSSR, nextTick, parsePropertyValue, plt, postUpdateComponent, proxyComponent, proxyCustomElement, readTask, registerComponents, registerHost, registerInstance, renderVdom, setAssetPath, setErrorHandler, setMode, setNonce, setPlatformHelpers, setScopedSsr, setTagTransformer, setValue, ssrApp, styles, supportsConstructableStylesheets, supportsListenerOptions, supportsMutableAdoptedStyleSheets, transformTag, win, writeTask };
1277
+ export { BUILD, Build, Env, Fragment, Host, Mixin, NAMESPACE, addHostEventListeners, bootstrapLazy, cmpModules, connectedCallback, consoleDevError, consoleDevInfo, consoleDevWarn, consoleError, createEvent, defineCustomElement, disconnectedCallback, forceModeUpdate, forceUpdate, getAssetPath, getElement, getHostRef, getMode, getRenderingRef, getShadowRoot, getValue, hAsync as h, injectSideEffectStyle, insertVdomAnnotations, isMemberInElement, jsx, jsxs, loadModule, modeResolutionChain, needsScopedSSR, nextTick, parsePropertyValue, plt, postUpdateComponent, proxyComponent, proxyCustomElement, readTask, registerComponents, registerHost, registerInstance, registerSideEffectStyleTarget, renderVdom, setAssetPath, setErrorHandler, setMode, setNonce, setPlatformHelpers, setScopedSsr, setTagTransformer, setValue, ssrApp, styles, supportsConstructableStylesheets, supportsListenerOptions, supportsMutableAdoptedStyleSheets, transformTag, unregisterSideEffectStyleTarget, win, writeTask };
@@ -1597,16 +1597,33 @@ const signalNodeDisposers = /* @__PURE__ */ new WeakMap();
1597
1597
  const disposeSignalVNode = (vnode) => {
1598
1598
  const elm = vnode.$elm$;
1599
1599
  if (elm) {
1600
- const dispose = signalNodeDisposers.get(elm);
1601
- if (dispose) {
1602
- dispose();
1603
- signalNodeDisposers.delete(elm);
1604
- }
1600
+ disposeTextSignal(elm);
1605
1601
  disposeAllSignalAttrs(elm);
1606
1602
  }
1607
1603
  vnode.$children$?.forEach(disposeSignalVNode);
1608
1604
  };
1609
1605
  /**
1606
+ * Tear down a text node's signal subscription, if it has one.
1607
+ * @param textNode the text node to unsubscribe
1608
+ */
1609
+ const disposeTextSignal = (textNode) => {
1610
+ const dispose = signalNodeDisposers.get(textNode);
1611
+ if (dispose) {
1612
+ dispose();
1613
+ signalNodeDisposers.delete(textNode);
1614
+ }
1615
+ };
1616
+ /**
1617
+ * Subscribe a text node to a signal, keeping its `data` in sync on every change.
1618
+ * @param textNode the text node to keep in sync
1619
+ * @param textSig the signal to subscribe to
1620
+ */
1621
+ const wireTextSignal = (textNode, textSig) => {
1622
+ signalNodeDisposers.set(textNode, effect$1(() => {
1623
+ textNode.data = String(textSig.value);
1624
+ }));
1625
+ };
1626
+ /**
1610
1627
  * Create a DOM Node corresponding to one of the children of a given VNode.
1611
1628
  *
1612
1629
  * @param oldParentVNode the parent VNode from the previous render
@@ -1628,13 +1645,7 @@ const createElm = (oldParentVNode, newParentVNode, childIndex) => {
1628
1645
  if (BUILD$1.isDev && newVNode.$elm$) newVNode.$text$ !== null ? `${newVNode.$text$}` : `${String(newVNode.$tag$)}`;
1629
1646
  if (BUILD$1.vdomText && newVNode.$text$ != null) {
1630
1647
  elm = newVNode.$elm$ = win.document.createTextNode(newVNode.$text$);
1631
- if (BUILD$1.vdomSignals && newVNode.$signal$) {
1632
- const textSig = newVNode.$signal$;
1633
- const textNode = elm;
1634
- signalNodeDisposers.set(textNode, effect$1(() => {
1635
- textNode.data = String(textSig.value);
1636
- }));
1637
- }
1648
+ if (BUILD$1.vdomSignals && newVNode.$signal$) wireTextSignal(elm, newVNode.$signal$);
1638
1649
  } else if (BUILD$1.slotRelocation && newVNode.$flags$ & VNODE_FLAGS.isSlotReference) {
1639
1650
  elm = newVNode.$elm$ = BUILD$1.isDebug || BUILD$1.hydrateServerSide ? slotReferenceDebugNode(newVNode) : win.document.createTextNode("");
1640
1651
  if (typeof newVNode.$attrs$?.slot === "string") elm["s-sa"] = newVNode.$attrs$.slot;
@@ -1995,7 +2006,17 @@ const patch = (oldVNode, newVNode, isInitialRender = false) => {
1995
2006
  else if (BUILD$1.hydrateClientSide && isInitialRender && BUILD$1.updatable && oldChildren !== null && newChildren === null) newVNode.$children$ = oldChildren;
1996
2007
  if (BUILD$1.svg && isSvgMode && tag === "svg") isSvgMode = false;
1997
2008
  } else if (BUILD$1.vdomText && BUILD$1.slotRelocation && (defaultHolder = elm["s-cr"])) defaultHolder.parentNode.textContent = text;
1998
- else if (BUILD$1.vdomText && oldVNode.$text$ !== text) elm.data = text;
2009
+ else if (BUILD$1.vdomText) {
2010
+ if (BUILD$1.vdomSignals && newVNode.$signal$) {
2011
+ if (newVNode.$signal$ !== oldVNode.$signal$) {
2012
+ disposeTextSignal(elm);
2013
+ wireTextSignal(elm, newVNode.$signal$);
2014
+ }
2015
+ } else {
2016
+ if (BUILD$1.vdomSignals && oldVNode.$signal$) disposeTextSignal(elm);
2017
+ if (oldVNode.$text$ !== text) elm.data = text;
2018
+ }
2019
+ }
1999
2020
  };
2000
2021
  /**
2001
2022
  * Component-global information about nodes which are either currently being
@@ -3329,12 +3350,13 @@ const restoreSafeSelector = (placeholders, content) => {
3329
3350
  const _polyfillHost = "-shadowcsshost";
3330
3351
  const _polyfillSlotted = "-shadowcssslotted";
3331
3352
  const _polyfillHostContext = "-shadowcsscontext";
3353
+ const _parenSuffix = ")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)";
3332
3354
  let _cssColonHostRe;
3333
3355
  let _cssColonHostContextRe;
3334
3356
  let _cssColonSlottedRe;
3335
- const getCssColonHostRe = () => _cssColonHostRe ??= /* @__PURE__ */ new RegExp("(-shadowcsshost)(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)", "gim");
3336
- const getCssColonHostContextRe = () => _cssColonHostContextRe ??= /* @__PURE__ */ new RegExp("(-shadowcsscontext)(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)", "gim");
3337
- const getCssColonSlottedRe = () => _cssColonSlottedRe ??= /* @__PURE__ */ new RegExp("(-shadowcssslotted)(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)", "gim");
3357
+ const getCssColonHostRe = () => _cssColonHostRe ??= new RegExp("(-shadowcsshost" + _parenSuffix, "gim");
3358
+ const getCssColonHostContextRe = () => _cssColonHostContextRe ??= new RegExp("(-shadowcsscontext" + _parenSuffix, "gim");
3359
+ const getCssColonSlottedRe = () => _cssColonSlottedRe ??= new RegExp("(-shadowcssslotted" + _parenSuffix, "gim");
3338
3360
  const _polyfillHostNoCombinator = "-shadowcsshost-no-combinator";
3339
3361
  const _polyfillHostNoCombinatorRe = /-shadowcsshost-no-combinator([^\s]*)/;
3340
3362
  const _shadowDOMSelectorsRe = [/::shadow/g, /::content/g];
@@ -3597,12 +3619,13 @@ const scopeSelector = (selector, scopeSelectorText, hostSelector, slotSelector)
3597
3619
  else return shallowPart.trim();
3598
3620
  }).join(", ");
3599
3621
  };
3622
+ const isScopableAtRule = (selector) => selector.startsWith("@media") || selector.startsWith("@supports") || selector.startsWith("@page") || selector.startsWith("@document") || selector.startsWith("@layer");
3600
3623
  const scopeSelectors = (cssText, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector) => {
3601
3624
  return processRules(cssText, (rule) => {
3602
3625
  let selector = rule.selector;
3603
3626
  let content = rule.content;
3604
3627
  if (rule.selector[0] !== "@") selector = scopeSelector(rule.selector, scopeSelectorText, hostSelector, slotSelector);
3605
- else if (rule.selector.startsWith("@media") || rule.selector.startsWith("@supports") || rule.selector.startsWith("@page") || rule.selector.startsWith("@document")) content = scopeSelectors(rule.content, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector);
3628
+ else if (isScopableAtRule(rule.selector)) content = scopeSelectors(rule.content, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector);
3606
3629
  return {
3607
3630
  selector: selector.replace(/\s{2,}/g, " ").trim(),
3608
3631
  content
@@ -3694,14 +3717,12 @@ const scopeCss = (cssText, scopeId, commentOriginalSelector) => {
3694
3717
  rule.selector = placeholder + rule.selector;
3695
3718
  return rule;
3696
3719
  };
3697
- cssText = processRules(cssText, (rule) => {
3720
+ const commentSelectors = (input) => processRules(input, (rule) => {
3698
3721
  if (rule.selector[0] !== "@") return processCommentedSelector(rule);
3699
- else if (rule.selector.startsWith("@media") || rule.selector.startsWith("@supports") || rule.selector.startsWith("@page") || rule.selector.startsWith("@document")) {
3700
- rule.content = processRules(rule.content, processCommentedSelector);
3701
- return rule;
3702
- }
3722
+ if (isScopableAtRule(rule.selector)) rule.content = commentSelectors(rule.content);
3703
3723
  return rule;
3704
3724
  });
3725
+ cssText = commentSelectors(cssText);
3705
3726
  }
3706
3727
  const scoped = scopeCssText(cssText, scopeId, hostScopeId, slotScopeId, commentOriginalSelector);
3707
3728
  cssText = [scoped.cssText, ...commentsWithHash].join("\n");
@@ -3900,6 +3921,14 @@ const setValue = (ref, propName, newVal, cmpMeta) => {
3900
3921
  //#endregion
3901
3922
  //#region src/runtime/proxy-component.ts
3902
3923
  /**
3924
+ * Serialize a prop value the way `setAccessor()` does when it reflects it, so the runtime can
3925
+ * recognize an `attributeChangedCallback` it triggered itself.
3926
+ *
3927
+ * @param propValue the current value of a reflected prop
3928
+ * @returns the string the attribute would hold, or `null` if the attribute would be removed
3929
+ */
3930
+ const reflectedAttrValue = (propValue) => propValue == null || propValue === false ? null : propValue === true ? "" : String(propValue);
3931
+ /**
3903
3932
  * Attach a series of runtime constructs to a compiled Stencil component
3904
3933
  * constructor, including getters and setters for the `@Prop` and `@State`
3905
3934
  * decorators, callbacks for when attributes change, and so on.
@@ -4047,7 +4076,9 @@ const proxyComponent = (Cstr, cmpMeta, flags) => {
4047
4076
  return;
4048
4077
  }
4049
4078
  const propFlags = members.find(([m]) => m === propName);
4050
- const isBooleanTarget = propFlags && propFlags[1][0] & MEMBER_FLAGS.Boolean;
4079
+ const propMemberFlags = propFlags ? propFlags[1][0] : 0;
4080
+ const isBooleanTarget = propMemberFlags & MEMBER_FLAGS.Boolean;
4081
+ if (BUILD$1.reflect && propMemberFlags & MEMBER_FLAGS.ReflectAttr && propMemberFlags & MEMBER_FLAGS.Any && !isComplexType(this[propName]) && reflectedAttrValue(this[propName]) === newValue) return;
4051
4082
  const isSpuriousBooleanRemoval = isBooleanTarget && newValue === null && this[propName] === void 0;
4052
4083
  if (isBooleanTarget) newValue = !(newValue === null || newValue === "false");
4053
4084
  const propDesc = Object.getOwnPropertyDescriptor(prototype, propName);
@@ -4660,6 +4691,86 @@ const getHostListenerTarget = (doc, elm, flags) => {
4660
4691
  };
4661
4692
  const hostListenerOpts = (flags) => (flags & LISTENER_FLAGS.Capture) !== 0;
4662
4693
  //#endregion
4694
+ //#region src/runtime/inject-side-effect-style.ts
4695
+ const styleSheets = /* @__PURE__ */ new Map();
4696
+ const knownRoots = /* @__PURE__ */ new Set();
4697
+ const adoptedRoots = /* @__PURE__ */ new WeakMap();
4698
+ const knownFontFaces = /* @__PURE__ */ new Set();
4699
+ const adopt = (root, sheet) => {
4700
+ let roots = adoptedRoots.get(sheet);
4701
+ if (!roots) {
4702
+ roots = /* @__PURE__ */ new WeakSet();
4703
+ adoptedRoots.set(sheet, roots);
4704
+ }
4705
+ if (!roots.has(root)) {
4706
+ roots.add(root);
4707
+ root.adoptedStyleSheets = [...root.adoptedStyleSheets, sheet];
4708
+ }
4709
+ };
4710
+ /**
4711
+ * Registers a root (a shadow root, or `document`) to receive every side-effect CSS import
4712
+ * (a plain, non-component `import './foo.css'`), now and in future. Call in `connectedCallback`,
4713
+ * paired with `unregisterSideEffectStyleTarget` in `disconnectedCallback` so the registry doesn't
4714
+ * hold disconnected roots forever.
4715
+ * @param root the root to register
4716
+ */
4717
+ function registerSideEffectStyleTarget(root) {
4718
+ knownRoots.add(root);
4719
+ for (const sheet of styleSheets.values()) adopt(root, sheet);
4720
+ }
4721
+ /**
4722
+ * Removes a root registered via `registerSideEffectStyleTarget` - call in `disconnectedCallback`.
4723
+ * @param root the root to unregister
4724
+ */
4725
+ function unregisterSideEffectStyleTarget(root) {
4726
+ knownRoots.delete(root);
4727
+ }
4728
+ const FONT_FACE_RE = /@font-face\s*\{[^{}]*\}/g;
4729
+ /**
4730
+ * Splits `@font-face` rules out of a CSS text - exported standalone (from private
4731
+ * module state - usually 3rd party node_modules) exported for testing
4732
+ * @param cssText the CSS text to split
4733
+ * @returns the font-face rules joined together (`null` if there were none) and the remaining CSS
4734
+ */
4735
+ function splitFontFaces(cssText) {
4736
+ const fontFaces = cssText.match(FONT_FACE_RE);
4737
+ if (!fontFaces) return {
4738
+ fontFaceText: null,
4739
+ rest: cssText
4740
+ };
4741
+ return {
4742
+ fontFaceText: fontFaces.join("\n"),
4743
+ rest: cssText.replace(FONT_FACE_RE, "")
4744
+ };
4745
+ }
4746
+ /**
4747
+ * Applies plain (non-component) CSS text to every registered root - respects shadow DOM
4748
+ * encapsulation instead of always reaching for the top-level document. Not meant to be called
4749
+ * directly: this is what the compiler's CSS-to-ESM output calls for CSS with no Stencil `tag`
4750
+ * (i.e. not a component's own `styleUrl`), typically a third-party dependency's CSS import.
4751
+ *
4752
+ * `@font-face` rules are pulled out and adopted onto top-level `document` not per-root
4753
+ * (Chromium (https://issues.chromium.org/issues/41085401) per-root never loads).
4754
+ * @param cssText the CSS text to apply
4755
+ */
4756
+ function injectSideEffectStyle(cssText) {
4757
+ const { fontFaceText, rest } = splitFontFaces(cssText);
4758
+ if (fontFaceText && !knownFontFaces.has(fontFaceText)) {
4759
+ knownFontFaces.add(fontFaceText);
4760
+ const fontFaceSheet = new CSSStyleSheet();
4761
+ fontFaceSheet.replaceSync(fontFaceText);
4762
+ document.adoptedStyleSheets = [...document.adoptedStyleSheets, fontFaceSheet];
4763
+ }
4764
+ if (!rest.trim()) return;
4765
+ let sheet = styleSheets.get(rest);
4766
+ if (!sheet) {
4767
+ sheet = new CSSStyleSheet();
4768
+ sheet.replaceSync(rest);
4769
+ styleSheets.set(rest, sheet);
4770
+ }
4771
+ for (const root of knownRoots) adopt(root, sheet);
4772
+ }
4773
+ //#endregion
4663
4774
  //#region src/runtime/mixin.ts
4664
4775
  const baseClass = BUILD$1.lazyLoad ? class {} : globalThis.HTMLElement || class {};
4665
4776
  function Mixin(...mixins) {
@@ -5363,4 +5474,4 @@ const setScopedSsr = (opts) => {
5363
5474
  const needsScopedSSR = () => scopedSSR;
5364
5475
  let scopedSSR = false;
5365
5476
  //#endregion
5366
- export { BUILD, Build, Env, Fragment, Host, Mixin, NAMESPACE, addHostEventListeners, bootstrapLazy, cmpModules, connectedCallback, consoleDevError, consoleDevInfo, consoleDevWarn, consoleError, createEvent, defineCustomElement, disconnectedCallback, forceModeUpdate, forceUpdate, getAssetPath, getElement, getHostRef, getMode, getRenderingRef, getShadowRoot, getValue, hAsync as h, insertVdomAnnotations, isMemberInElement, jsx, jsxs, loadModule, modeResolutionChain, needsScopedSSR, nextTick, parsePropertyValue, plt, postUpdateComponent, proxyComponent, proxyCustomElement, readTask, registerComponents, registerHost, registerInstance, renderVdom, setAssetPath, setErrorHandler, setMode, setNonce, setPlatformHelpers, setScopedSsr, setTagTransformer, setValue, ssrApp, styles, supportsConstructableStylesheets, supportsListenerOptions, supportsMutableAdoptedStyleSheets, transformTag, win, writeTask };
5477
+ export { BUILD, Build, Env, Fragment, Host, Mixin, NAMESPACE, addHostEventListeners, bootstrapLazy, cmpModules, connectedCallback, consoleDevError, consoleDevInfo, consoleDevWarn, consoleError, createEvent, defineCustomElement, disconnectedCallback, forceModeUpdate, forceUpdate, getAssetPath, getElement, getHostRef, getMode, getRenderingRef, getShadowRoot, getValue, hAsync as h, injectSideEffectStyle, insertVdomAnnotations, isMemberInElement, jsx, jsxs, loadModule, modeResolutionChain, needsScopedSSR, nextTick, parsePropertyValue, plt, postUpdateComponent, proxyComponent, proxyCustomElement, readTask, registerComponents, registerHost, registerInstance, registerSideEffectStyleTarget, renderVdom, setAssetPath, setErrorHandler, setMode, setNonce, setPlatformHelpers, setScopedSsr, setTagTransformer, setValue, ssrApp, styles, supportsConstructableStylesheets, supportsListenerOptions, supportsMutableAdoptedStyleSheets, transformTag, unregisterSideEffectStyleTarget, win, writeTask };
@@ -1,4 +1,4 @@
1
- import { J as CompilerSystem, jt as Logger } from "../../index-RrQfiPWK.mjs";
1
+ import { J as CompilerSystem, jt as Logger } from "../../index-BvF31nqP.mjs";
2
2
  //#region src/sys/node/logger/index.d.ts
3
3
  /**
4
4
  * Create a logger to run in a Node environment
@@ -1,2 +1,2 @@
1
- import { n as setupNodeProcess, r as createNodeLogger, t as createNodeSys } from "../../node-75gQKkFz.mjs";
1
+ import { n as setupNodeProcess, r as createNodeLogger, t as createNodeSys } from "../../node-BKtLn2R9.mjs";
2
2
  export { createNodeLogger, createNodeSys, setupNodeProcess };
@@ -1,5 +1,5 @@
1
- import { l as createWorkerMessageHandler } from "../../compiler-NrvbUOX1.mjs";
2
- import { t as createNodeSys } from "../../node-75gQKkFz.mjs";
1
+ import { l as createWorkerMessageHandler } from "../../compiler-PoywOlbq.mjs";
2
+ import { t as createNodeSys } from "../../node-BKtLn2R9.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
@@ -919,7 +919,8 @@ interface StencilConfig {
919
919
  * Will generate {@link https://nodejs.org/api/packages.html#packages_exports export map} entry points
920
920
  * for each component in the build when `true`.
921
921
  *
922
- * @default false
922
+ * Defaults to `true` for "no-config" projects (no `stencil.config.ts`/`.js` file), and `false`
923
+ * whenever a config file is present - set this explicitly to opt an existing project in or out.
923
924
  */
924
925
  generateExportMaps?: boolean;
925
926
  /**
@@ -973,10 +974,19 @@ interface StencilConfig {
973
974
  */
974
975
  rolldownConfig?: RolldownConfig;
975
976
  /**
976
- * Sets if the JS browser files are minified or not. Stencil uses `terser` under the hood.
977
+ * Sets if the JS browser files are minified or not.
977
978
  * Defaults to `false` in dev mode and `true` in production mode.
978
979
  */
979
980
  minifyJs?: boolean;
981
+ /**
982
+ * Which minifier to use for JS output when `minifyJs` is enabled.
983
+ *
984
+ * - `oxc`: built into rolldown. Much faster than terser. Output may be slightly larger.
985
+ * - `terser`: slower, but currently produces the smallest output.
986
+ *
987
+ * Defaults to `oxc`.
988
+ */
989
+ jsMinifier?: 'terser' | 'oxc';
980
990
  /**
981
991
  * Sets if the CSS is minified or not.
982
992
  * Defaults to `false` in dev mode and `true` in production mode.
@@ -1322,7 +1332,7 @@ type RequireFields<T, K extends keyof T> = T & { [P in K]-?: T[P]; };
1322
1332
  /**
1323
1333
  * Fields in {@link Config} to make required for {@link ValidatedConfig}
1324
1334
  */
1325
- type StrictConfigFields = keyof Pick<Config, 'cacheDir' | 'devServer' | 'compat' | 'fsNamespace' | 'hydratedFlag' | 'logLevel' | 'logger' | 'minifyCss' | 'minifyJs' | 'namespace' | 'outputTargets' | 'packageJsonFilePath' | 'rolldownConfig' | 'rootDir' | 'srcDir' | 'srcIndexHtml' | 'sys' | 'transformAliasedImportPaths'>;
1335
+ type StrictConfigFields = keyof Pick<Config, 'cacheDir' | 'devServer' | 'compat' | 'fsNamespace' | 'hydratedFlag' | 'jsMinifier' | 'logLevel' | 'logger' | 'minifyCss' | 'minifyJs' | 'namespace' | 'outputTargets' | 'packageJsonFilePath' | 'rolldownConfig' | 'rootDir' | 'srcDir' | 'srcIndexHtml' | 'sys' | 'transformAliasedImportPaths'>;
1326
1336
  /**
1327
1337
  * A version of {@link Config} that makes certain fields required. This type represents a valid configuration entity.
1328
1338
  * When a configuration is received by the user, it is a bag of unverified data. In order to make stricter guarantees
@@ -4480,6 +4490,12 @@ interface TransformCssToEsmOutput {
4480
4490
  varName: string;
4481
4491
  importPath: string;
4482
4492
  }[];
4493
+ /**
4494
+ * Whether `output` itself has an observable side effect (a plain, untagged CSS file's
4495
+ * generated module self-injects CSSStyleSheets; a Stencil component's tagged `styleUrl`
4496
+ * output doesn't)
4497
+ */
4498
+ moduleSideEffects?: boolean;
4483
4499
  }
4484
4500
  interface PackageJsonData {
4485
4501
  name?: string;
@@ -1,6 +1,6 @@
1
1
  import nodePath from "node:path";
2
2
  import { MockWindow, setupGlobal } from "@stencil/mock-doc";
3
- import ts from "typescript";
3
+ import "typescript";
4
4
  import fs from "node:fs";
5
5
  import "picomatch";
6
6
  import { effect, effect as effect$1, signal } from "@preact/signals-core";
@@ -11,6 +11,7 @@ import "postcss-selector-parser";
11
11
  import "magic-string";
12
12
  import "rolldown";
13
13
  import resolve from "resolve";
14
+ import "rolldown/utils";
14
15
  import "terser";
15
16
  import "css-what";
16
17
  import { execFile } from "node:child_process";
@@ -31,7 +32,7 @@ import "@rollup/pluginutils";
31
32
  import { createHash } from "crypto";
32
33
  import { afterAll, vi } from "vitest";
33
34
  //#region src/version.ts
34
- const version = "5.0.0-beta.0";
35
+ const version = "5.0.0-beta.10";
35
36
  const MEMBER_FLAGS = {
36
37
  String: 1,
37
38
  Number: 2,
@@ -378,10 +379,6 @@ const trimFalsy = (data) => {
378
379
  */
379
380
  const isDef = (v) => v != null && v !== void 0;
380
381
  /**
381
- * This is just a no-op, don't expect it to do anything.
382
- */
383
- const noop = () => {};
384
- /**
385
382
  * Check whether a value is a 'complex type', defined here as an object or a
386
383
  * function.
387
384
  *
@@ -534,23 +531,6 @@ function join(...paths) {
534
531
  */
535
532
  return normalizePath(nodePath.join(...paths), false);
536
533
  }
537
- /**
538
- * A wrapped version of node.js' {@link path.resolve} which adds our custom
539
- * normalization logic. This resolves a path to a given (relative or absolute)
540
- * path.
541
- *
542
- * @throws the underlying node function will throw if any argument is not a
543
- * string
544
- * @param paths a path or path fragments to resolve
545
- * @returns a resolved path!
546
- */
547
- function resolve$1(...paths) {
548
- /**
549
- * When normalizing, we should _not_ attempt to relativize the path returned by the native Node `resolve` method. When
550
- * calculating the path from each of the string-based parts, Node does not prepend './' to the calculated path.
551
- */
552
- return normalizePath(nodePath.resolve(...paths), false);
553
- }
554
534
  //#endregion
555
535
  //#region src/utils/query-nonce-meta-tag-content.ts
556
536
  /**
@@ -2391,16 +2371,33 @@ const signalNodeDisposers = /* @__PURE__ */ new WeakMap();
2391
2371
  const disposeSignalVNode = (vnode) => {
2392
2372
  const elm = vnode.$elm$;
2393
2373
  if (elm) {
2394
- const dispose = signalNodeDisposers.get(elm);
2395
- if (dispose) {
2396
- dispose();
2397
- signalNodeDisposers.delete(elm);
2398
- }
2374
+ disposeTextSignal(elm);
2399
2375
  disposeAllSignalAttrs(elm);
2400
2376
  }
2401
2377
  vnode.$children$?.forEach(disposeSignalVNode);
2402
2378
  };
2403
2379
  /**
2380
+ * Tear down a text node's signal subscription, if it has one.
2381
+ * @param textNode the text node to unsubscribe
2382
+ */
2383
+ const disposeTextSignal = (textNode) => {
2384
+ const dispose = signalNodeDisposers.get(textNode);
2385
+ if (dispose) {
2386
+ dispose();
2387
+ signalNodeDisposers.delete(textNode);
2388
+ }
2389
+ };
2390
+ /**
2391
+ * Subscribe a text node to a signal, keeping its `data` in sync on every change.
2392
+ * @param textNode the text node to keep in sync
2393
+ * @param textSig the signal to subscribe to
2394
+ */
2395
+ const wireTextSignal = (textNode, textSig) => {
2396
+ signalNodeDisposers.set(textNode, effect$1(() => {
2397
+ textNode.data = String(textSig.value);
2398
+ }));
2399
+ };
2400
+ /**
2404
2401
  * Create a DOM Node corresponding to one of the children of a given VNode.
2405
2402
  *
2406
2403
  * @param oldParentVNode the parent VNode from the previous render
@@ -2422,13 +2419,7 @@ const createElm = (oldParentVNode, newParentVNode, childIndex) => {
2422
2419
  if (BUILD.isDev && newVNode.$elm$) consoleDevError(`The JSX ${newVNode.$text$ !== null ? `"${newVNode.$text$}" text` : `"${String(newVNode.$tag$)}" element`} node should not be shared within the same renderer. The renderer caches element lookups in order to improve performance. However, a side effect from this is that the exact same JSX node should not be reused. For more information please see https://stenciljs.com/docs/templating-jsx#avoid-shared-jsx-nodes`);
2423
2420
  if (BUILD.vdomText && newVNode.$text$ != null) {
2424
2421
  elm = newVNode.$elm$ = win.document.createTextNode(newVNode.$text$);
2425
- if (BUILD.vdomSignals && newVNode.$signal$) {
2426
- const textSig = newVNode.$signal$;
2427
- const textNode = elm;
2428
- signalNodeDisposers.set(textNode, effect$1(() => {
2429
- textNode.data = String(textSig.value);
2430
- }));
2431
- }
2422
+ if (BUILD.vdomSignals && newVNode.$signal$) wireTextSignal(elm, newVNode.$signal$);
2432
2423
  } else if (BUILD.slotRelocation && newVNode.$flags$ & VNODE_FLAGS.isSlotReference) {
2433
2424
  elm = newVNode.$elm$ = BUILD.isDebug || BUILD.hydrateServerSide ? slotReferenceDebugNode(newVNode) : win.document.createTextNode("");
2434
2425
  if (typeof newVNode.$attrs$?.slot === "string") elm["s-sa"] = newVNode.$attrs$.slot;
@@ -2789,7 +2780,17 @@ const patch = (oldVNode, newVNode, isInitialRender = false) => {
2789
2780
  else if (BUILD.hydrateClientSide && isInitialRender && BUILD.updatable && oldChildren !== null && newChildren === null) newVNode.$children$ = oldChildren;
2790
2781
  if (BUILD.svg && isSvgMode && tag === "svg") isSvgMode = false;
2791
2782
  } else if (BUILD.vdomText && BUILD.slotRelocation && (defaultHolder = elm["s-cr"])) defaultHolder.parentNode.textContent = text;
2792
- else if (BUILD.vdomText && oldVNode.$text$ !== text) elm.data = text;
2783
+ else if (BUILD.vdomText) {
2784
+ if (BUILD.vdomSignals && newVNode.$signal$) {
2785
+ if (newVNode.$signal$ !== oldVNode.$signal$) {
2786
+ disposeTextSignal(elm);
2787
+ wireTextSignal(elm, newVNode.$signal$);
2788
+ }
2789
+ } else {
2790
+ if (BUILD.vdomSignals && oldVNode.$signal$) disposeTextSignal(elm);
2791
+ if (oldVNode.$text$ !== text) elm.data = text;
2792
+ }
2793
+ }
2793
2794
  };
2794
2795
  /**
2795
2796
  * Component-global information about nodes which are either currently being
@@ -4116,12 +4117,13 @@ const restoreSafeSelector = (placeholders, content) => {
4116
4117
  const _polyfillHost = "-shadowcsshost";
4117
4118
  const _polyfillSlotted = "-shadowcssslotted";
4118
4119
  const _polyfillHostContext = "-shadowcsscontext";
4120
+ const _parenSuffix = ")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)";
4119
4121
  let _cssColonHostRe;
4120
4122
  let _cssColonHostContextRe;
4121
4123
  let _cssColonSlottedRe;
4122
- const getCssColonHostRe = () => _cssColonHostRe ??= /* @__PURE__ */ new RegExp("(-shadowcsshost)(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)", "gim");
4123
- const getCssColonHostContextRe = () => _cssColonHostContextRe ??= /* @__PURE__ */ new RegExp("(-shadowcsscontext)(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)", "gim");
4124
- const getCssColonSlottedRe = () => _cssColonSlottedRe ??= /* @__PURE__ */ new RegExp("(-shadowcssslotted)(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)", "gim");
4124
+ const getCssColonHostRe = () => _cssColonHostRe ??= new RegExp("(-shadowcsshost" + _parenSuffix, "gim");
4125
+ const getCssColonHostContextRe = () => _cssColonHostContextRe ??= new RegExp("(-shadowcsscontext" + _parenSuffix, "gim");
4126
+ const getCssColonSlottedRe = () => _cssColonSlottedRe ??= new RegExp("(-shadowcssslotted" + _parenSuffix, "gim");
4125
4127
  const _polyfillHostNoCombinator = "-shadowcsshost-no-combinator";
4126
4128
  const _polyfillHostNoCombinatorRe = /-shadowcsshost-no-combinator([^\s]*)/;
4127
4129
  const _shadowDOMSelectorsRe = [/::shadow/g, /::content/g];
@@ -4384,12 +4386,13 @@ const scopeSelector = (selector, scopeSelectorText, hostSelector, slotSelector)
4384
4386
  else return shallowPart.trim();
4385
4387
  }).join(", ");
4386
4388
  };
4389
+ const isScopableAtRule = (selector) => selector.startsWith("@media") || selector.startsWith("@supports") || selector.startsWith("@page") || selector.startsWith("@document") || selector.startsWith("@layer");
4387
4390
  const scopeSelectors = (cssText, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector) => {
4388
4391
  return processRules(cssText, (rule) => {
4389
4392
  let selector = rule.selector;
4390
4393
  let content = rule.content;
4391
4394
  if (rule.selector[0] !== "@") selector = scopeSelector(rule.selector, scopeSelectorText, hostSelector, slotSelector);
4392
- else if (rule.selector.startsWith("@media") || rule.selector.startsWith("@supports") || rule.selector.startsWith("@page") || rule.selector.startsWith("@document")) content = scopeSelectors(rule.content, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector);
4395
+ else if (isScopableAtRule(rule.selector)) content = scopeSelectors(rule.content, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector);
4393
4396
  return {
4394
4397
  selector: selector.replace(/\s{2,}/g, " ").trim(),
4395
4398
  content
@@ -4481,14 +4484,12 @@ const scopeCss = (cssText, scopeId, commentOriginalSelector) => {
4481
4484
  rule.selector = placeholder + rule.selector;
4482
4485
  return rule;
4483
4486
  };
4484
- cssText = processRules(cssText, (rule) => {
4487
+ const commentSelectors = (input) => processRules(input, (rule) => {
4485
4488
  if (rule.selector[0] !== "@") return processCommentedSelector(rule);
4486
- else if (rule.selector.startsWith("@media") || rule.selector.startsWith("@supports") || rule.selector.startsWith("@page") || rule.selector.startsWith("@document")) {
4487
- rule.content = processRules(rule.content, processCommentedSelector);
4488
- return rule;
4489
- }
4489
+ if (isScopableAtRule(rule.selector)) rule.content = commentSelectors(rule.content);
4490
4490
  return rule;
4491
4491
  });
4492
+ cssText = commentSelectors(cssText);
4492
4493
  }
4493
4494
  const scoped = scopeCssText(cssText, scopeId, hostScopeId, slotScopeId, commentOriginalSelector);
4494
4495
  cssText = [scoped.cssText, ...commentsWithHash].join("\n");
@@ -4686,6 +4687,14 @@ const setValue = (ref, propName, newVal, cmpMeta) => {
4686
4687
  //#endregion
4687
4688
  //#region src/runtime/proxy-component.ts
4688
4689
  /**
4690
+ * Serialize a prop value the way `setAccessor()` does when it reflects it, so the runtime can
4691
+ * recognize an `attributeChangedCallback` it triggered itself.
4692
+ *
4693
+ * @param propValue the current value of a reflected prop
4694
+ * @returns the string the attribute would hold, or `null` if the attribute would be removed
4695
+ */
4696
+ const reflectedAttrValue = (propValue) => propValue == null || propValue === false ? null : propValue === true ? "" : String(propValue);
4697
+ /**
4689
4698
  * Attach a series of runtime constructs to a compiled Stencil component
4690
4699
  * constructor, including getters and setters for the `@Prop` and `@State`
4691
4700
  * decorators, callbacks for when attributes change, and so on.
@@ -4833,7 +4842,9 @@ const proxyComponent = (Cstr, cmpMeta, flags) => {
4833
4842
  return;
4834
4843
  }
4835
4844
  const propFlags = members.find(([m]) => m === propName);
4836
- const isBooleanTarget = propFlags && propFlags[1][0] & MEMBER_FLAGS.Boolean;
4845
+ const propMemberFlags = propFlags ? propFlags[1][0] : 0;
4846
+ const isBooleanTarget = propMemberFlags & MEMBER_FLAGS.Boolean;
4847
+ if (BUILD.reflect && propMemberFlags & MEMBER_FLAGS.ReflectAttr && propMemberFlags & MEMBER_FLAGS.Any && !isComplexType(this[propName]) && reflectedAttrValue(this[propName]) === newValue) return;
4837
4848
  const isSpuriousBooleanRemoval = isBooleanTarget && newValue === null && this[propName] === void 0;
4838
4849
  if (isBooleanTarget) newValue = !(newValue === null || newValue === "false");
4839
4850
  const propDesc = Object.getOwnPropertyDescriptor(prototype, propName);
@@ -5863,28 +5874,6 @@ new RegExp(`^(${[.../* @__PURE__ */ new Set([
5863
5874
  ])].join("|")})$`);
5864
5875
  promisify(execFile);
5865
5876
  process.platform;
5866
- //#endregion
5867
- //#region src/compiler/sys/typescript/typescript-sys.ts
5868
- const patchTypeScriptSysMinimum = () => {
5869
- if (!ts.sys) ts.sys = {
5870
- args: [],
5871
- createDirectory: noop,
5872
- directoryExists: () => false,
5873
- exit: noop,
5874
- fileExists: () => false,
5875
- getCurrentDirectory: process.cwd,
5876
- getDirectories: () => [],
5877
- getExecutingFilePath: () => "./",
5878
- readDirectory: () => [],
5879
- readFile: noop,
5880
- newLine: "\n",
5881
- resolvePath: resolve$1,
5882
- useCaseSensitiveFileNames: false,
5883
- write: noop,
5884
- writeFile: noop
5885
- };
5886
- };
5887
- patchTypeScriptSysMinimum();
5888
5877
  new Set([
5889
5878
  "CheckboxStateChange",
5890
5879
  "DOMContentLoaded",
@@ -7764,6 +7753,7 @@ function mockValidatedConfig(overrides = {}) {
7764
7753
  logger: mockLogger(),
7765
7754
  minifyCss: false,
7766
7755
  minifyJs: false,
7756
+ jsMinifier: "oxc",
7767
7757
  namespace: "Testing",
7768
7758
  outputTargets: baseConfig.outputTargets ?? [],
7769
7759
  packageJsonFilePath: nodePath.join(rootDir, "package.json"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stencil/core",
3
- "version": "5.0.0-beta.0",
3
+ "version": "5.0.0-beta.10",
4
4
  "description": "A Compiler for Web Components and Progressive Web Apps",
5
5
  "keywords": [
6
6
  "components",
@@ -43,6 +43,10 @@
43
43
  "types": "./dist/compiler/utils/index.d.mts",
44
44
  "import": "./dist/compiler/utils/index.mjs"
45
45
  },
46
+ "./compiler/browser": {
47
+ "types": "./dist/compiler/browser.d.ts",
48
+ "import": "./dist/compiler/browser.js"
49
+ },
46
50
  "./jsx-runtime": {
47
51
  "types": "./dist/jsx-runtime.d.mts",
48
52
  "import": "./dist/jsx-runtime.mjs"
@@ -116,14 +120,14 @@
116
120
  "postcss-safe-parser": "^7.0.1",
117
121
  "postcss-selector-parser": "^7.1.5",
118
122
  "resolve": "^1.22.12",
119
- "rolldown": "^1.2.4",
123
+ "rolldown": "^1.2.6",
120
124
  "semver": "^7.8.5",
121
125
  "terser": "^5.50.0",
122
126
  "tinyglobby": "^0.2.17",
123
127
  "typescript": ">5.0.0 <7.0.0",
124
- "@stencil/cli": "5.0.0-beta.0",
125
- "@stencil/dev-server": "5.0.0-beta.0",
126
- "@stencil/mock-doc": "5.0.0-beta.0"
128
+ "@stencil/dev-server": "5.0.0-beta.10",
129
+ "@stencil/cli": "5.0.0-beta.10",
130
+ "@stencil/mock-doc": "5.0.0-beta.10"
127
131
  },
128
132
  "devDependencies": {
129
133
  "@ionic/prettier-config": "^4.0.0",