@stencil/core 5.0.0-beta.1 → 5.0.0-beta.11

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 (32) hide show
  1. package/dist/app-data/index.d.ts +1 -1
  2. package/dist/{client-BRu0GtRn.mjs → client-CdFmjaQa.mjs} +40 -15
  3. package/dist/compiler/browser.d.ts +1 -1
  4. package/dist/compiler/browser.js +77 -41
  5. package/dist/compiler/index.d.mts +1 -1
  6. package/dist/compiler/index.mjs +2 -2
  7. package/dist/compiler/utils/index.d.mts +1 -1
  8. package/dist/{compiler-CJG6qvQt.mjs → compiler-2EypBn_Y.mjs} +346 -122
  9. package/dist/declarations/stencil-public-compiler.d.ts +6 -1
  10. package/dist/declarations/stencil-public-runtime.d.ts +57 -55
  11. package/dist/{index-BXAcVN2j.d.ts → index-BHciXst1.d.ts} +57 -55
  12. package/dist/{index-DmHmu3y0.d.mts → index-CKnzMkZC.d.mts} +1 -1
  13. package/dist/{index-BopBfjPu.d.mts → index-Cw1NW9FW.d.mts} +6 -1
  14. package/dist/index.mjs +1 -1
  15. package/dist/jsx-runtime.mjs +1 -1
  16. package/dist/{node-75gQKkFz.mjs → node-HKfDhPR3.mjs} +1 -1
  17. package/dist/runtime/client/lazy.js +63 -31
  18. package/dist/runtime/client/runtime.d.ts +57 -55
  19. package/dist/runtime/client/runtime.js +63 -31
  20. package/dist/runtime/index.d.ts +1 -1
  21. package/dist/runtime/index.js +63 -31
  22. package/dist/runtime/server/index.d.mts +2 -1
  23. package/dist/runtime/server/index.mjs +83 -44
  24. package/dist/runtime/server/runner.mjs +8 -5
  25. package/dist/signals/index.d.ts +11 -2
  26. package/dist/signals/index.js +11 -1
  27. package/dist/sys/node/index.d.mts +1 -1
  28. package/dist/sys/node/index.mjs +1 -1
  29. package/dist/sys/node/worker.mjs +2 -2
  30. package/dist/testing/index.d.mts +6 -1
  31. package/dist/testing/index.mjs +64 -32
  32. package/package.json +4 -4
@@ -1,9 +1,9 @@
1
1
  import { n as __require } from "./rolldown-runtime-BhDjJH2R.mjs";
2
- import { S as HYDRATED_CSS } from "./client-BRu0GtRn.mjs";
2
+ import { S as HYDRATED_CSS } from "./client-CdFmjaQa.mjs";
3
3
  import { $ as VALID_CONFIG_OUTPUT_TARGETS, A as DIST_LAZY, D as COPY, E as COLLECTION_MANIFEST_FILE_NAME, J as STANDALONE, L as EVENT_FLAGS, P as DOCS_JSON, Q as TYPES, R as GENERATED_DTS, S as ASSETS, T as COLLECTION_APP_DATA_FILE_NAME, U as LOADER_BUNDLE, X as STYLE_EXT, Y as STATS, a as isBoolean$1, b as unique, c as isFunction, d as isObject, et as WATCH_FLAGS, f as isString$1, g as sortBy, i as fromEntries, l as isIterable, m as noop, p as mergeIntoWith, r as flatOne, t as dashToPascalCase, u as isNumber$1, v as toDashCase, w as COLLECTION, y as toTitleCase, z as GLOBAL_STYLE } from "./helpers-Cpp3qc3u.mjs";
4
4
  import { E as escapeRegExpSpecialCharacters, S as formatComponentRuntimeMeta, T as byteSize, _ as loadRolldownDiagnostics, a as getSourceMappingUrlForEndOfFile, b as splitLineBreaks, c as err, f as augmentDiagnosticWithNode, g as isRolldownError, h as createOnWarnFn, i as getInlineSourceMappingUrlLinker, l as map, m as loadTypeScriptDiagnostics, n as validateComponentTag, p as loadTypeScriptDiagnostic, r as isRemoteUrl, s as rolldownToStencilSourceMap, t as validateComponentModes, u as ok, w as stringifyRuntimeData, x as isRootPath, y as normalizeDiagnostics } from "./validation-DAdGTrys.mjs";
5
5
  import { $ as catchError, A as isOutputTargetDocsVscode, B as relativeImport, C as isOutputTargetDistLazy, D as isOutputTargetDocsCustomElementsManifest, E as isOutputTargetDocsCustom, F as isOutputTargetStandalone, G as normalizeFsPathQuery, H as join$2, I as isOutputTargetStats, J as resolve$2, K as normalizePath, L as isOutputTargetTypes, M as isOutputTargetLoaderBundle, N as isOutputTargetSsr, O as isOutputTargetDocsJson, P as isOutputTargetSsrWasm, Q as buildWarn, R as isOutputTargetWww, S as isOutputTargetCustom, T as isOutputTargetDocsAgentSkill, W as normalizeFsPath, X as buildError, Z as buildJsonFileError, a as hasDependency, b as isOutputTargetCollection, d as parsePackageJson, et as hasError, f as readOnlyArrayHasStringMember, g as getComponentsDtsSrcFilePath, h as filterExcludedComponents, i as getTextDocs, j as isOutputTargetGlobalStyle, k as isOutputTargetDocsReadme, l as isTsFile, m as filterActiveTargets, n as createJsVarName, o as isDtsFile, p as readPackageJson, q as relative$1, r as generatePreamble, rt as isGlob, t as addDocBlock, tt as hasWarning, u as isTsxFile, v as getComponentsFromModules, w as isOutputTargetDocs, x as isOutputTargetCopy, y as isOutputTargetAssets, z as isValidConfigOutputTarget } from "./util-IKfWWLJo.mjs";
6
- import { i as CustomElementsExportBehaviorOptions, o as buildEvents, r as createNodeLogger, t as createNodeSys } from "./node-75gQKkFz.mjs";
6
+ import { i as CustomElementsExportBehaviorOptions, o as buildEvents, r as createNodeLogger, t as createNodeSys } from "./node-HKfDhPR3.mjs";
7
7
  import ts, { default as ts$1 } from "typescript";
8
8
  import { readFileSync } from "node:fs";
9
9
  import { basename, dirname, isAbsolute, join, resolve } from "node:path";
@@ -342,12 +342,13 @@ const scopeSelector = (selector, scopeSelectorText, hostSelector, slotSelector)
342
342
  else return shallowPart.trim();
343
343
  }).join(", ");
344
344
  };
345
+ const isScopableAtRule = (selector) => selector.startsWith("@media") || selector.startsWith("@supports") || selector.startsWith("@page") || selector.startsWith("@document") || selector.startsWith("@layer");
345
346
  const scopeSelectors = (cssText, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector) => {
346
347
  return processRules(cssText, (rule) => {
347
348
  let selector = rule.selector;
348
349
  let content = rule.content;
349
350
  if (rule.selector[0] !== "@") selector = scopeSelector(rule.selector, scopeSelectorText, hostSelector, slotSelector);
350
- 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);
351
+ else if (isScopableAtRule(rule.selector)) content = scopeSelectors(rule.content, scopeSelectorText, hostSelector, slotSelector, commentOriginalSelector);
351
352
  return {
352
353
  selector: selector.replace(/\s{2,}/g, " ").trim(),
353
354
  content
@@ -439,14 +440,12 @@ const scopeCss = (cssText, scopeId, commentOriginalSelector) => {
439
440
  rule.selector = placeholder + rule.selector;
440
441
  return rule;
441
442
  };
442
- cssText = processRules(cssText, (rule) => {
443
+ const commentSelectors = (input) => processRules(input, (rule) => {
443
444
  if (rule.selector[0] !== "@") return processCommentedSelector(rule);
444
- else if (rule.selector.startsWith("@media") || rule.selector.startsWith("@supports") || rule.selector.startsWith("@page") || rule.selector.startsWith("@document")) {
445
- rule.content = processRules(rule.content, processCommentedSelector);
446
- return rule;
447
- }
445
+ if (isScopableAtRule(rule.selector)) rule.content = commentSelectors(rule.content);
448
446
  return rule;
449
447
  });
448
+ cssText = commentSelectors(cssText);
450
449
  }
451
450
  const scoped = scopeCssText(cssText, scopeId, hostScopeId, slotScopeId, commentOriginalSelector);
452
451
  cssText = [scoped.cssText, ...commentsWithHash].join("\n");
@@ -462,9 +461,9 @@ const scopeCss = (cssText, scopeId, commentOriginalSelector) => {
462
461
  };
463
462
  //#endregion
464
463
  //#region src/version.ts
465
- const version = "5.0.0-beta.1";
466
- const buildId = "1788442714";
467
- const vermoji = "🚓";
464
+ const version = "5.0.0-beta.11";
465
+ const buildId = "1789429964";
466
+ const vermoji = "🍦";
468
467
  /**
469
468
  * Get the installed version of a tool/dependency.
470
469
  * Handles packages with exports maps that point to subdirectories.
@@ -6025,7 +6024,8 @@ const addTagTransform$2 = (compilerCtx, buildCtx) => {
6025
6024
  const expression = node.expression;
6026
6025
  if (ts.isPropertyAccessExpression(expression) && ((expression.name.text === "get" || expression.name.text === "define" || expression.name.text === "whenDefined") && ts.isIdentifier(expression.expression) && expression.expression.text === "customElements" || expression.name.text === "createElement" && ts.isIdentifier(expression.expression) && expression.expression.text === "document")) {
6027
6026
  const [firstArg, ...restArgs] = node.arguments;
6028
- if (firstArg) {
6027
+ const alreadyTransformed = firstArg && ts.isCallExpression(firstArg) && ts.isIdentifier(firstArg.expression) && (firstArg.expression.text === "__stencil_transformTag" || firstArg.expression.text === "transformTag");
6028
+ if (firstArg && !alreadyTransformed) {
6029
6029
  const newFirstArg = ts.factory.createCallExpression(ts.factory.createIdentifier(TRANSFORM_TAG), void 0, [firstArg]);
6030
6030
  newNode = ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [newFirstArg, ...restArgs]);
6031
6031
  }
@@ -7373,7 +7373,13 @@ function createEntryModule(cmps) {
7373
7373
  }
7374
7374
  const getLazyEntry = (isBrowser, assetPath, externalRuntime = false) => {
7375
7375
  const s = new MagicString(``);
7376
- s.append(`export { setNonce, setRegistry, setTagTransformer } from '${STENCIL_CORE_ID}';\n`);
7376
+ const platformExports = [
7377
+ "setNonce",
7378
+ "setRegistry",
7379
+ "setTagTransformer"
7380
+ ];
7381
+ if (assetPath) platformExports.push("setAssetPath");
7382
+ s.append(`export { ${platformExports.join(", ")} } from '${STENCIL_CORE_ID}';\n`);
7377
7383
  s.append(`import { bootstrapLazy } from '${STENCIL_CORE_ID}';\n`);
7378
7384
  if (isBrowser) {
7379
7385
  if (assetPath) s.append(`import { setAssetPath } from '${STENCIL_CORE_ID}';\n`);
@@ -9388,15 +9394,17 @@ const generateStandaloneTypesOutput = async (config, compilerCtx, buildCtx, type
9388
9394
  if (outputTarget.autoLoader) {
9389
9395
  const loaderFileName = typeof outputTarget.autoLoader === "object" ? outputTarget.autoLoader.fileName || "loader" : "loader";
9390
9396
  const loaderDtsPath = join$2(outputTarget.dir, `${loaderFileName}.d.ts`);
9391
- const loaderDtsCode = generateLoaderType();
9397
+ const hasAssets = buildCtx.components.some((cmp) => cmp.assetsDirs != null && cmp.assetsDirs.length > 0);
9398
+ const loaderDtsCode = generateLoaderType(hasAssets);
9392
9399
  await compilerCtx.fs.writeFile(loaderDtsPath, loaderDtsCode, { outputTargetType: outputTarget.type });
9393
9400
  }
9394
9401
  };
9395
9402
  /**
9396
9403
  * Generate a type declaration file for the auto-loader module
9404
+ * @param hasAssets whether any component declares assets, matching whether setAssetPath is actually exported
9397
9405
  * @returns the contents of the type declaration file for the loader
9398
9406
  */
9399
- const generateLoaderType = () => {
9407
+ const generateLoaderType = (hasAssets) => {
9400
9408
  return [
9401
9409
  `/**`,
9402
9410
  ` * Start the auto-loader, scanning the DOM and watching for changes.`,
@@ -9410,7 +9418,18 @@ const generateLoaderType = () => {
9410
9418
  ` * Stop the auto-loader and disconnect the MutationObserver.`,
9411
9419
  ` */`,
9412
9420
  `export declare function stop(): void;`,
9413
- ``
9421
+ ``,
9422
+ ...hasAssets ? [
9423
+ `/**`,
9424
+ ` * Used to manually set the base path where component assets can be found. The`,
9425
+ ` * default is relative to this module's own location, which may not hold once a`,
9426
+ ` * consuming bundler relocates it - call this before start() to override.`,
9427
+ ` * @param path the asset path to set`,
9428
+ ` * @returns the set path`,
9429
+ ` */`,
9430
+ `export declare function setAssetPath(path: string): string;`,
9431
+ ``
9432
+ ] : []
9414
9433
  ].join("\n");
9415
9434
  };
9416
9435
  /**
@@ -9900,7 +9919,7 @@ const FORM_ASSOCIATED_ATTRIBUTES = [
9900
9919
  * @param cmp the metadata for the component that a type definition string is generated for
9901
9920
  * @param typeImportData locally/imported/globally used type names, which may be used to prevent naming collisions
9902
9921
  * @param areTypesInternal `true` if types being generated are for a project's internal purposes, `false` otherwise
9903
- * @param signalBacking `true` if the component is using signal backing for its props; includes the signals map on the element interface
9922
+ * @param signalBacking `true` if the component is using signal backing for its props; includes the signals map on the element interface and unions JSX prop types with `ReadonlySignal<T>`
9904
9923
  * @returns the generated types string alongside additional metadata
9905
9924
  */
9906
9925
  const generateComponentTypes = (cmp, typeImportData, areTypesInternal, signalBacking = false) => {
@@ -9917,8 +9936,12 @@ const generateComponentTypes = (cmp, typeImportData, areTypesInternal, signalBac
9917
9936
  const isDep = cmp.isCollectionDependency;
9918
9937
  const propNames = new Set(propAttributes.map((p) => p.name));
9919
9938
  const formAssociatedAttrs = cmp.formAssociated ? FORM_ASSOCIATED_ATTRIBUTES.filter((attr) => !propNames.has(attr.name)) : [];
9939
+ const jsxPropAttributes = signalBacking ? propAttributes.map((attr) => ({
9940
+ ...attr,
9941
+ type: `${attr.type} | ReadonlySignal<${attr.type}>`
9942
+ })) : propAttributes;
9920
9943
  const jsxAttributes = attributesToMultiLineString([
9921
- ...propAttributes,
9944
+ ...jsxPropAttributes,
9922
9945
  ...eventAttributes,
9923
9946
  ...formAssociatedAttrs
9924
9947
  ], true, areTypesInternal);
@@ -10355,8 +10378,9 @@ const generateTypesOutput = async (config, compilerCtx, buildCtx, outputTarget)
10355
10378
  await generateAppTypes(config, compilerCtx, buildCtx, distPath);
10356
10379
  const typesDir = outputTarget.dir;
10357
10380
  if (distDtsFilePath) await generateStandaloneTypes(config, compilerCtx, buildCtx, typesDir);
10358
- if (config.outputTargets.some(isOutputTargetLoaderBundle)) await generateLoaderTypes(compilerCtx, typesDir);
10359
- if (config.outputTargets.some(isOutputTargetStandalone)) await generateStandaloneApiTypes(compilerCtx, typesDir);
10381
+ const hasAssets = buildCtx.components.some((cmp) => cmp.assetsDirs != null && cmp.assetsDirs.length > 0);
10382
+ if (config.outputTargets.some(isOutputTargetLoaderBundle)) await generateLoaderTypes(compilerCtx, typesDir, hasAssets);
10383
+ if (config.outputTargets.some(isOutputTargetStandalone)) await generateStandaloneApiTypes(compilerCtx, typesDir, hasAssets);
10360
10384
  };
10361
10385
  /**
10362
10386
  * Generate loader.d.ts file for the loader entry point.
@@ -10364,8 +10388,9 @@ const generateTypesOutput = async (config, compilerCtx, buildCtx, outputTarget)
10364
10388
  *
10365
10389
  * @param compilerCtx the current compiler context
10366
10390
  * @param typesDir the directory to write the loader.d.ts file to
10391
+ * @param hasAssets whether any component declares assets, matching whether setAssetPath is actually exported
10367
10392
  */
10368
- const generateLoaderTypes = async (compilerCtx, typesDir) => {
10393
+ const generateLoaderTypes = async (compilerCtx, typesDir, hasAssets) => {
10369
10394
  const loaderDtsContent = `export * from './components';
10370
10395
  export interface CustomElementsDefineOptions {
10371
10396
  exclude?: string[];
@@ -10401,7 +10426,17 @@ export type TagTransformer = (tag: string) => string;
10401
10426
  * Useful for namespacing (e.g. \`my-button\` → \`acme-button\`) in multi-library pages.
10402
10427
  */
10403
10428
  export declare function setTagTransformer(transformer: TagTransformer): void;
10404
- `;
10429
+ ${hasAssets ? `
10430
+ /**
10431
+ * Used to manually set the base path where component assets can be found. The
10432
+ * default is relative to this module's own location, which may not hold once a
10433
+ * bundler relocates it, or once its CDN URL diverges from the assets' own -
10434
+ * import and call this before the module's default has been used to override it.
10435
+ * @param path the asset path to set
10436
+ * @returns the set path
10437
+ */
10438
+ export declare function setAssetPath(path: string): string;
10439
+ ` : ""}`;
10405
10440
  const loaderDtsPath = join$2(typesDir, "loader.d.ts");
10406
10441
  await compilerCtx.fs.writeFile(loaderDtsPath, loaderDtsContent);
10407
10442
  };
@@ -10411,8 +10446,9 @@ export declare function setTagTransformer(transformer: TagTransformer): void;
10411
10446
  *
10412
10447
  * @param compilerCtx the current compiler context
10413
10448
  * @param typesDir the directory to write the standalone.d.ts file to
10449
+ * @param hasAssets whether any component declares assets, matching whether setAssetPath is actually exported
10414
10450
  */
10415
- const generateStandaloneApiTypes = async (compilerCtx, typesDir) => {
10451
+ const generateStandaloneApiTypes = async (compilerCtx, typesDir, hasAssets) => {
10416
10452
  const standaloneDtsContent = `/**
10417
10453
  * Used to specify a nonce value that corresponds with an application's CSP.
10418
10454
  * When set, the nonce will be added to all dynamically created script and style tags at runtime.
@@ -10445,7 +10481,16 @@ export interface SetPlatformOptions {
10445
10481
  rel?: (el: EventTarget, eventName: string, listener: EventListenerOrEventListenerObject, options: boolean | AddEventListenerOptions) => void;
10446
10482
  }
10447
10483
  export declare const setPlatformOptions: (opts: SetPlatformOptions) => void;
10448
- `;
10484
+ ${hasAssets ? `
10485
+ /**
10486
+ * Used to manually set the base path where component assets can be found. The
10487
+ * default is relative to this module's own location, which may not hold once a
10488
+ * consuming bundler relocates it - call this before any component module is imported to override.
10489
+ * @param path the asset path to set
10490
+ * @returns the set path
10491
+ */
10492
+ export declare const setAssetPath: (path: string) => string;
10493
+ ` : ""}`;
10449
10494
  const standaloneDtsPath = join$2(typesDir, "standalone.d.ts");
10450
10495
  await compilerCtx.fs.writeFile(standaloneDtsPath, standaloneDtsContent);
10451
10496
  };
@@ -11186,10 +11231,13 @@ const MODE_RESOLUTION_CHAIN_DECLARATION = `modeResolutionChain = [];`;
11186
11231
  const SSR_FACTORY_INTRO = `
11187
11232
  //! let ${MODE_RESOLUTION_CHAIN_DECLARATION}
11188
11233
 
11189
- // Capture native setTimeout/clearTimeout at module scope (before globalThis can be shadowed inside the factory).
11234
+ // Capture native at module scope (before globalThis can be shadowed inside the factory).
11235
+
11190
11236
  // Used for the hydrate timeout timer to avoid being affected by constrainTimeouts.
11191
11237
  var $nativeSetTimeout = (typeof globalThis !== 'undefined' ? globalThis : global).setTimeout;
11192
11238
  var $nativeClearTimeout = (typeof globalThis !== 'undefined' ? globalThis : global).clearTimeout;
11239
+ // Used to abort in-flight fetch() calls and to call any user defined AbortControllers when ssr times out.
11240
+ var $stencilNativeAbortController = AbortController;
11193
11241
 
11194
11242
  export function ssrFactory($stencilWindow, $stencilHydrateOpts, $stencilHydrateResults, $stencilAfterHydrate, $stencilHydrateResolve) {
11195
11243
  var globalThis = $stencilWindow;
@@ -11282,8 +11330,46 @@ export function ssrFactory($stencilWindow, $stencilHydrateOpts, $stencilHydrateR
11282
11330
 
11283
11331
  var fetch, FetchError, Headers, Request, Response;
11284
11332
 
11333
+ // Aborted when the render times out or errors, so in-flight fetch() calls
11334
+ // made by component code stop holding the render's window/results alive
11335
+ // instead of running to completion against a torn-down window. See #6864.
11336
+ var $stencilAbortController = new $stencilNativeAbortController();
11337
+
11338
+ // Any AbortController a component creates itself is transparently wired to
11339
+ // cascade-abort when the render times out too, so component code using the
11340
+ // standard AbortController convention for its own cancellable work (axios,
11341
+ // aws-sdk v3, the mongodb driver, etc.) gets cancelled automatically.
11342
+ var AbortController = function () {
11343
+ var controller = new $stencilNativeAbortController();
11344
+ $stencilAbortController.signal.addEventListener(
11345
+ 'abort',
11346
+ function () {
11347
+ controller.abort();
11348
+ },
11349
+ { once: true },
11350
+ );
11351
+ return controller;
11352
+ };
11353
+
11354
+ function $stencilFetchSignal(callerSignal) {
11355
+ if (!callerSignal) {
11356
+ return $stencilAbortController.signal;
11357
+ }
11358
+ if (callerSignal.aborted || $stencilAbortController.signal.aborted) {
11359
+ return callerSignal.aborted ? callerSignal : $stencilAbortController.signal;
11360
+ }
11361
+ var merged = new $stencilNativeAbortController();
11362
+ var onAbort = function () { merged.abort(); };
11363
+ callerSignal.addEventListener('abort', onAbort, { once: true });
11364
+ $stencilAbortController.signal.addEventListener('abort', onAbort, { once: true });
11365
+ return merged.signal;
11366
+ }
11367
+
11285
11368
  if (typeof $stencilWindow.fetch === 'function') {
11286
- fetch = $stencilWindow.fetch;
11369
+ var $stencilRawFetch = $stencilWindow.fetch;
11370
+ fetch = $stencilWindow.fetch = function(input, init) {
11371
+ return $stencilRawFetch(input, Object.assign({}, init, { signal: $stencilFetchSignal(init && init.signal) }));
11372
+ };
11287
11373
  } else {
11288
11374
  fetch = $stencilWindow.fetch = function() { throw new Error('fetch() is not implemented'); };
11289
11375
  }
@@ -11319,7 +11405,7 @@ export function ssrFactory($stencilWindow, $stencilHydrateOpts, $stencilHydrateR
11319
11405
  `;
11320
11406
  const SSR_FACTORY_OUTRO = `
11321
11407
  /*hydrateAppClosure end*/
11322
- ssrApp(window, $stencilHydrateOpts, $stencilHydrateResults, $stencilAfterHydrate, $stencilHydrateResolve);
11408
+ ssrApp(window, $stencilHydrateOpts, $stencilHydrateResults, $stencilAfterHydrate, $stencilHydrateResolve, $stencilAbortController);
11323
11409
  }
11324
11410
 
11325
11411
  hydrateAppClosure($stencilWindow);
@@ -11593,6 +11679,40 @@ if (typeof globalThis !== "undefined") {
11593
11679
  if (typeof globalThis.clearInterval !== "function") globalThis.clearInterval = function() {};
11594
11680
  }
11595
11681
  `;
11682
+ const SSR_WASM_ABORT_CONTROLLER_POLYFILL = `
11683
+ if (typeof globalThis !== "undefined" && typeof globalThis.AbortController !== "function") {
11684
+ function StencilPolyfillAbortSignal() {
11685
+ this.aborted = false;
11686
+ this.reason = undefined;
11687
+ this._listeners = [];
11688
+ }
11689
+ StencilPolyfillAbortSignal.prototype.addEventListener = function(type, listener, options) {
11690
+ if (type !== "abort" || typeof listener !== "function") return;
11691
+ this._listeners.push({ listener: listener, once: !!(options && options.once) });
11692
+ };
11693
+ StencilPolyfillAbortSignal.prototype.removeEventListener = function(type, listener) {
11694
+ if (type !== "abort") return;
11695
+ this._listeners = this._listeners.filter(function(entry) { return entry.listener !== listener; });
11696
+ };
11697
+ StencilPolyfillAbortSignal.prototype.dispatchEvent = function(event) {
11698
+ var signal = this;
11699
+ signal._listeners.slice().forEach(function(entry) { entry.listener.call(signal, event); });
11700
+ signal._listeners = signal._listeners.filter(function(entry) { return !entry.once; });
11701
+ return true;
11702
+ };
11703
+ function StencilPolyfillAbortController() {
11704
+ this.signal = new StencilPolyfillAbortSignal();
11705
+ }
11706
+ StencilPolyfillAbortController.prototype.abort = function(reason) {
11707
+ if (this.signal.aborted) return;
11708
+ this.signal.aborted = true;
11709
+ this.signal.reason = reason;
11710
+ this.signal.dispatchEvent({ type: "abort" });
11711
+ };
11712
+ globalThis.AbortController = StencilPolyfillAbortController;
11713
+ globalThis.AbortSignal = StencilPolyfillAbortSignal;
11714
+ }
11715
+ `;
11596
11716
  const SSR_WASM_INTERFACE = `declare module "main" {
11597
11717
  export function renderToString(): void;
11598
11718
  export function setTagTransformer(): void;
@@ -11607,6 +11727,12 @@ module.exports = {
11607
11727
  return;
11608
11728
  }
11609
11729
  var inp = JSON.parse(Host.inputString());
11730
+ // QuickJS-ng has no timers, so if hydration never settles on its own (a Promise
11731
+ // nothing will ever resolve), the call doesn't hang - it just runs out of scheduled
11732
+ // work and returns whatever was last written here. Write a diagnostic up front so
11733
+ // that's a real error instead of silence, then overwrite it once renderToString()
11734
+ // actually resolves.
11735
+ Host.outputString(JSON.stringify({ __error: 'renderToString did not complete - a component may be waiting on work that never resolves' }));
11610
11736
  var result = await renderToString(inp.html, inp.options);
11611
11737
  Host.outputString(JSON.stringify(result));
11612
11738
  } catch(e) {
@@ -11663,7 +11789,7 @@ const generateSsrWasmApp = async (config, compilerCtx, buildCtx, outputTargets)
11663
11789
  checks: { pluginTimings: config.logLevel === "debug" }
11664
11790
  };
11665
11791
  const rolldownOutput = await (await rolldown(rolldownOptions)).generate({
11666
- banner: generatePreamble(config) + SSR_WASM_TIMER_POLYFILL,
11792
+ banner: generatePreamble(config) + SSR_WASM_TIMER_POLYFILL + SSR_WASM_ABORT_CONTROLLER_POLYFILL,
11667
11793
  outro: SSR_WASM_OUTRO,
11668
11794
  format: "iife",
11669
11795
  name: "StencilSsrWasm",
@@ -12406,7 +12532,7 @@ const generateLoaderModule = (components, outputTarget, relativeAssetPath) => {
12406
12532
  const autoStart = typeof autoLoaderConfig === "object" ? autoLoaderConfig.autoStart !== false : true;
12407
12533
  const tagsList = components.map((cmp) => `'${cmp.tagName}'`).join(", ");
12408
12534
  const switchCases = components.map((cmp) => ` case '${cmp.tagName}': module = await import('./${cmp.tagName}.js'); break;`).join("\n");
12409
- const assetPathImport = relativeAssetPath ? `import { setAssetPath } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';\n` : "";
12535
+ const assetPathImport = relativeAssetPath ? `import { setAssetPath } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';\nexport { setAssetPath };\n` : "";
12410
12536
  const assetPathInit = relativeAssetPath ? `setAssetPath(new URL('${relativeAssetPath}', String(import.meta.url)).href);\n` : "";
12411
12537
  return `
12412
12538
  import { transformTag, getRegistry } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';
@@ -12767,12 +12893,25 @@ const addStandaloneInputs = (config, buildCtx, bundleOpts, outputTarget) => {
12767
12893
  const indexImports = [];
12768
12894
  const indexExports = [];
12769
12895
  const exportNames = [];
12896
+ let relativeAssetPath;
12897
+ if (components.some((cmp) => cmp.assetsDirs != null && cmp.assetsDirs.length > 0)) {
12898
+ const assetsTarget = config.outputTargets.find(isOutputTargetAssets);
12899
+ if (assetsTarget?.dir && outputTarget.dir) {
12900
+ const rel = relative$1(outputTarget.dir, assetsTarget.dir);
12901
+ relativeAssetPath = rel.endsWith("/") ? rel : rel + "/";
12902
+ }
12903
+ }
12770
12904
  components.forEach((cmp) => {
12771
12905
  const exp = [];
12772
12906
  const exportName = dashToPascalCase(cmp.tagName);
12773
12907
  const importName = cmp.componentClassName;
12774
12908
  const importAs = `$Cmp${exportName}`;
12775
12909
  const coreKey = `\0${exportName}`;
12910
+ if (relativeAssetPath) {
12911
+ exp.push(`import { setAssetPath } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';`);
12912
+ exp.push(`export { setAssetPath };`);
12913
+ exp.push(`setAssetPath(new URL('${relativeAssetPath}', import.meta.url).href);`);
12914
+ }
12776
12915
  if (cmp.isPlain) {
12777
12916
  exp.push(`export { ${importName} as ${exportName} } from '${cmp.sourceFilePath}';`);
12778
12917
  indexExports.push(`export { ${exportName} } from '${coreKey}';`);
@@ -12787,14 +12926,6 @@ const addStandaloneInputs = (config, buildCtx, bundleOpts, outputTarget) => {
12787
12926
  bundleOpts.inputs[cmp.tagName] = coreKey;
12788
12927
  bundleOpts.loader[coreKey] = exp.join("\n");
12789
12928
  });
12790
- let relativeAssetPath;
12791
- if (components.some((cmp) => cmp.assetsDirs != null && cmp.assetsDirs.length > 0)) {
12792
- const assetsTarget = config.outputTargets.find(isOutputTargetAssets);
12793
- if (assetsTarget?.dir && outputTarget.dir) {
12794
- const rel = relative$1(outputTarget.dir, assetsTarget.dir);
12795
- relativeAssetPath = rel.endsWith("/") ? rel : rel + "/";
12796
- }
12797
- }
12798
12929
  bundleOpts.loader["\0core"] = generateEntryPoint(outputTarget, indexImports, indexExports, exportNames, relativeAssetPath);
12799
12930
  if (outputTarget.autoLoader) {
12800
12931
  const loaderFileName = typeof outputTarget.autoLoader === "object" ? outputTarget.autoLoader.fileName || "loader" : "loader";
@@ -12818,6 +12949,7 @@ const generateEntryPoint = (outputTarget, cmpImports = [], cmpExports = [], cmpN
12818
12949
  exports.push(`export { setNonce, setRegistry, setTagTransformer, setPlatformOptions } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';`, `export * from '${USER_INDEX_ENTRY_ID}';`);
12819
12950
  if (relativeAssetPath) {
12820
12951
  imports.push(`import { setAssetPath } from '${STENCIL_INTERNAL_STANDALONE_CLIENT_PLATFORM_ID}';`);
12952
+ exports.push(`export { setAssetPath };`);
12821
12953
  body.push(`setAssetPath(new URL('${relativeAssetPath}', import.meta.url).href);`);
12822
12954
  }
12823
12955
  if (outputTarget.includeGlobalScripts !== false) {
@@ -15225,14 +15357,16 @@ const parseWatchDecorator = (typeChecker, method, decoratorName) => {
15225
15357
  * @param diagnostics for surfacing errors and warnings
15226
15358
  * @param typeChecker a TypeScript typechecker instance
15227
15359
  * @param program a {@link ts.Program} object
15360
+ * @param includeClassExpressions also convert `ts.ClassExpression` nodes (e.g. a mixin factory's
15361
+ * `(Base) => class extends Base {}`), not just named `ts.ClassDeclaration`s
15228
15362
  * @returns a TypeScript transformer factory which can be passed to
15229
15363
  * TypeScript to transform source code during the compilation process
15230
15364
  */
15231
- const convertDecoratorsToStatic = (config, diagnostics, typeChecker, program) => {
15365
+ const convertDecoratorsToStatic = (config, diagnostics, typeChecker, program, includeClassExpressions = false) => {
15232
15366
  return (transformCtx) => {
15233
15367
  let sourceFile;
15234
15368
  const visit = (node) => {
15235
- if (ts.isClassDeclaration(node)) return visitClassDeclaration(config, diagnostics, typeChecker, program, node, sourceFile);
15369
+ if (ts.isClassDeclaration(node) || includeClassExpressions && ts.isClassExpression(node)) return visitClassDeclaration(config, diagnostics, typeChecker, program, node, sourceFile);
15236
15370
  return ts.visitEachChild(node, visit, transformCtx);
15237
15371
  };
15238
15372
  return (tsSourceFile) => {
@@ -15242,10 +15376,10 @@ const convertDecoratorsToStatic = (config, diagnostics, typeChecker, program) =>
15242
15376
  };
15243
15377
  };
15244
15378
  /**
15245
- * Visit {@link ts.ClassDeclaration} nodes as part of the tree-traversal
15379
+ * Visit {@link ts.ClassDeclaration}/{@link ts.ClassExpression} nodes as part of the tree-traversal
15246
15380
  * required for {@link convertDecoratorsToStatic} to work.
15247
15381
  *
15248
- * If a given class declaration node is not decorated with `@Component` this
15382
+ * If a given class node is not decorated with `@Component` this
15249
15383
  * function will simply return it as-is. If it _is_ decorated, then it will
15250
15384
  *
15251
15385
  * 1. Convert the arguments to the `@Component` decorator to static values.
@@ -15254,7 +15388,7 @@ const convertDecoratorsToStatic = (config, diagnostics, typeChecker, program) =>
15254
15388
  * to static values.
15255
15389
  * 3. Validate that the various options selected by the component author are
15256
15390
  * valid, both individually and in combination.
15257
- * 4. Return an updated class declaration node which is ready to be used in
15391
+ * 4. Return an updated class node which is ready to be used in
15258
15392
  * the rest of the Stencil compilation pipeline (e.g. in output target
15259
15393
  * generation).
15260
15394
  *
@@ -15273,7 +15407,7 @@ const visitClassDeclaration = (config, diagnostics, typeChecker, program, classN
15273
15407
  const decoratedMembers = classMembers.filter((member) => (retrieveTsDecorators(member)?.length ?? 0) > 0);
15274
15408
  if (!decoratedMembers.length && !componentDecorator) return classNode;
15275
15409
  const filteredMethodsAndFields = removeStencilMethodDecorators(Array.from(classMembers), diagnostics, importAliasMap);
15276
- if (componentDecorator) componentDecoratorToStatic(config, typeChecker, diagnostics, classNode, filteredMethodsAndFields, componentDecorator);
15410
+ if (componentDecorator && ts.isClassDeclaration(classNode)) componentDecoratorToStatic(config, typeChecker, diagnostics, classNode, filteredMethodsAndFields, componentDecorator);
15277
15411
  if (decoratedMembers.length > 0) {
15278
15412
  const serializers = serializeDecoratorsToStatic(typeChecker, decoratedMembers, filteredMethodsAndFields, importAliasMap.get("PropSerialize"), "PropSerialize", importAliasMap.get("Prop"));
15279
15413
  const deserializers = serializeDecoratorsToStatic(typeChecker, decoratedMembers, filteredMethodsAndFields, importAliasMap.get("AttrDeserialize"), "AttrDeserialize", importAliasMap.get("Prop"));
@@ -15289,7 +15423,8 @@ const visitClassDeclaration = (config, diagnostics, typeChecker, program, classN
15289
15423
  validateMethods(diagnostics, classMembers);
15290
15424
  const currentDecorators = retrieveTsDecorators(classNode);
15291
15425
  const updatedClassFields = updateConstructor(classNode, filteredMethodsAndFields, []);
15292
- return ts.factory.updateClassDeclaration(classNode, [...filterDecorators(currentDecorators, CLASS_DECORATORS_TO_REMOVE.map((decorator) => importAliasMap.get(decorator))) ?? [], ...retrieveTsModifiers(classNode) ?? []], classNode.name, classNode.typeParameters, classNode.heritageClauses, updatedClassFields);
15426
+ const updatedModifiers = [...filterDecorators(currentDecorators, CLASS_DECORATORS_TO_REMOVE.map((decorator) => importAliasMap.get(decorator))) ?? [], ...retrieveTsModifiers(classNode) ?? []];
15427
+ return ts.isClassDeclaration(classNode) ? ts.factory.updateClassDeclaration(classNode, updatedModifiers, classNode.name, classNode.typeParameters, classNode.heritageClauses, updatedClassFields) : ts.factory.updateClassExpression(classNode, updatedModifiers, classNode.name, classNode.typeParameters, classNode.heritageClauses, updatedClassFields);
15293
15428
  };
15294
15429
  /**
15295
15430
  * Take a list of `ClassElement` AST nodes and remove any decorators from
@@ -15473,11 +15608,11 @@ const parseStaticWatchers = (staticMembers) => {
15473
15608
  //#endregion
15474
15609
  //#region src/compiler/transformers/static-to-meta/class-extension/shared.ts
15475
15610
  /**
15476
- * Warns when an `extends`/`Mixin(...)` target resolved to *something* but no class declaration
15477
- * could be found inside it - e.g. a mixin factory whose class isn't a named declaration
15478
- * (`(Base) => class extends Base {}` rather than `(Base) => { class Foo extends Base {} return
15479
- * Foo; }`). Without this, the target is silently dropped: any `@Prop`/`@State` etc. it declares
15480
- * just never appears on the extending component, with no diagnostic explaining why.
15611
+ * Warns when an `extends`/`Mixin(...)` target resolved to *something* but no class literal
15612
+ * could be found inside it - e.g. a mixin factory that returns an existing class by reference
15613
+ * (`(Base) => SomeExistingClass`) rather than a class literal. Without this, the target is
15614
+ * silently dropped: any `@Prop`/`@State` etc. it declares just never appears on the extending
15615
+ * component, with no diagnostic explaining why.
15481
15616
  * @param buildCtx used to surface the warning - omit to warn silently (e.g. from tests)
15482
15617
  * @param targetName the identifier the target was reached through
15483
15618
  * @param anchor the node to attach the warning to
@@ -15485,27 +15620,32 @@ const parseStaticWatchers = (staticMembers) => {
15485
15620
  function warnMixinFactoryClassNotFound(buildCtx, targetName, anchor) {
15486
15621
  if (!buildCtx) return;
15487
15622
  const err = buildWarn(buildCtx.diagnostics);
15488
- err.messageText = `Found "${targetName}", but couldn't find a class declaration inside it. If it's meant to be a mixin factory, make sure it declares and returns a named class, e.g. \`(Base) => { class ${targetName}Class extends Base {} return ${targetName}Class; }\` - a factory that returns a class expression directly (\`(Base) => class extends Base {}\`) isn't recognized, and any \`@Prop\`/\`@State\`/etc. it declares won't be applied.`;
15623
+ err.messageText = `Found "${targetName}", but couldn't find a class inside it. If it's meant to be a mixin factory, make sure it returns a class literal directly, e.g. \`(Base) => class extends Base {}\` or \`(Base) => { class ${targetName}Class extends Base {} return ${targetName}Class; }\` - returning an existing class by reference (\`(Base) => SomeExistingClass\`) isn't recognized, and any \`@Prop\`/\`@State\`/etc. it declares won't be applied.`;
15489
15624
  if (!buildCtx.config._isTesting) augmentDiagnosticWithNode(err, anchor);
15490
15625
  }
15491
15626
  /**
15492
- * Walks the AST looking for a class declaration, optionally by name - descends
15493
- * into a mixin factory's wrapping function (arrow function or `function`
15494
- * declaration) body too, since a mixin factory's class is always nested one
15495
- * level inside it (e.g. `const Foo = (Base) => class extends Base {}`).
15627
+ * Walks the AST looking for a class declaration or class expression, optionally by name -
15628
+ * descends into a mixin factory's wrapping function (arrow function or `function` declaration)
15629
+ * body too, since a mixin factory's class is always nested one level inside it. Recognizes all of:
15630
+ * `const Foo = (Base) => class extends Base {}` (concise arrow body), `const Foo = (Base) => {
15631
+ * return class extends Base {}; }` (block body, `return` of a class expression), and `const Foo =
15632
+ * (Base) => { class FooClass extends Base {} return FooClass; }` (block body, named declaration).
15496
15633
  * @param node the node to search from
15497
- * @param name if given, only matches a class declaration with this name
15498
- * @returns the found class declaration, or `undefined`
15634
+ * @param name if given, only matches a class with this name
15635
+ * @returns the found class, or `undefined`
15499
15636
  */
15500
15637
  function findClassWalk(node, name) {
15501
15638
  if (!node) return void 0;
15502
- if (ts.isClassDeclaration(node)) {
15639
+ if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
15503
15640
  if (!name || node.name?.text === name) return node;
15504
15641
  } else if (ts.isVariableDeclaration(node) && (!name || name === node.name?.text) && node.initializer && ts.isArrowFunction(node.initializer)) {
15642
+ const body = node.initializer.body;
15643
+ if (ts.isClassExpression(body)) return body;
15505
15644
  let found;
15506
- ts.forEachChild(node.initializer.body, (child) => {
15645
+ ts.forEachChild(body, (child) => {
15507
15646
  if (found) return;
15508
15647
  if (ts.isClassDeclaration(child)) found = child;
15648
+ else if (ts.isReturnStatement(child) && child.expression && ts.isClassExpression(child.expression)) found = child.expression;
15509
15649
  });
15510
15650
  return found;
15511
15651
  }
@@ -15518,6 +15658,22 @@ function findClassWalk(node, name) {
15518
15658
  return found;
15519
15659
  }
15520
15660
  /**
15661
+ * The declared name of a mixin-factory statement (`function Foo() {}`, or `const Foo = ...`) -
15662
+ * survives the decorator-to-static-getter transform even when the factory's inner class doesn't
15663
+ * have a name of its own, so it can anchor a post-transform re-lookup via `findClassWalk`.
15664
+ * @param node the factory statement (or its variable declaration) to read a name from
15665
+ * @returns the declared name, or `undefined` if it can't be determined
15666
+ */
15667
+ function factoryDeclaredName(node) {
15668
+ if (!node) return void 0;
15669
+ if (ts.isFunctionDeclaration(node)) return node.name?.text;
15670
+ if (ts.isVariableDeclaration(node)) return ts.isIdentifier(node.name) ? node.name.text : void 0;
15671
+ if (ts.isVariableStatement(node)) {
15672
+ const decl = node.declarationList.declarations[0];
15673
+ return decl && ts.isIdentifier(decl.name) ? decl.name.text : void 0;
15674
+ }
15675
+ }
15676
+ /**
15521
15677
  * Matches a top-level class/function/variable declaration by name - the three
15522
15678
  * shapes a mixin or base-class export can take (a plain class, a mixin
15523
15679
  * factory function declaration, or a mixin factory assigned to a `const`).
@@ -15639,7 +15795,7 @@ function convertDiskSourceFileDecorators(sourceFile, config, target = ts.ScriptT
15639
15795
  const program = ts.createProgram([sourceFile.fileName], compilerOptions, host);
15640
15796
  const typeChecker = program.getTypeChecker();
15641
15797
  const ownSourceFile = program.getSourceFile(sourceFile.fileName) ?? sourceFile;
15642
- const result = ts.transform(ownSourceFile, [convertDecoratorsToStatic(config, [], typeChecker, program)]);
15798
+ const result = ts.transform(ownSourceFile, [convertDecoratorsToStatic(config, [], typeChecker, program, true)]);
15643
15799
  const printed = ts.createPrinter({ removeComments: false }).printFile(result.transformed[0]);
15644
15800
  return ts.createSourceFile(sourceFile.fileName, printed, target, true);
15645
15801
  }
@@ -15726,6 +15882,7 @@ function buildExtendsTree(compilerCtx, classDeclaration, dependentClasses, typeC
15726
15882
  const targetScriptTarget = (ogModule?.staticSourceFile)?.languageVersion ?? ts.ScriptTarget.ESNext;
15727
15883
  let classIdentifiers = [];
15728
15884
  let foundClassDeclaration;
15885
+ let foundClassName;
15729
15886
  let keepLooking = true;
15730
15887
  extendsClause.types.forEach((type) => {
15731
15888
  if (ts.isExpressionWithTypeArguments(type) && ts.isCallExpression(type.expression) && type.expression.expression.getText() === "Mixin") classIdentifiers = type.expression.arguments.filter(ts.isIdentifier);
@@ -15742,9 +15899,11 @@ function buildExtendsTree(compilerCtx, classDeclaration, dependentClasses, typeC
15742
15899
  declarations = [...source.statements];
15743
15900
  }
15744
15901
  foundClassDeclaration = declarations?.find(ts.isClassDeclaration);
15902
+ foundClassName = foundClassDeclaration?.name?.getText();
15745
15903
  if (!foundClassDeclaration) {
15746
15904
  const node = declarations?.[0];
15747
15905
  foundClassDeclaration = findClassWalk(node);
15906
+ foundClassName = foundClassDeclaration?.name?.getText() ?? factoryDeclaredName(node);
15748
15907
  if (!node) throw "revert to sad path";
15749
15908
  keepLooking = false;
15750
15909
  if (!foundClassDeclaration) warnMixinFactoryClassNotFound(buildCtx, extendee.getText(), classDeclaration);
@@ -15753,7 +15912,7 @@ function buildExtendsTree(compilerCtx, classDeclaration, dependentClasses, typeC
15753
15912
  const foundModule = compilerCtx.moduleMap.get(foundClassDeclaration.getSourceFile().fileName);
15754
15913
  if (foundModule) {
15755
15914
  const moduleSourceFile = foundModule.staticSourceFile;
15756
- const sourceClass = findClassWalk(moduleSourceFile, foundClassDeclaration.name?.getText());
15915
+ const sourceClass = findClassWalk(moduleSourceFile, foundClassName);
15757
15916
  if (sourceClass) {
15758
15917
  dependentClasses.push({
15759
15918
  classNode: sourceClass,
@@ -15774,20 +15933,24 @@ function buildExtendsTree(compilerCtx, classDeclaration, dependentClasses, typeC
15774
15933
  if (!buildCtx.config._isTesting) augmentDiagnosticWithNode(err, classDeclaration);
15775
15934
  return;
15776
15935
  }
15777
- if (matchedStatement && ts.isClassDeclaration(matchedStatement)) foundClassDeclaration = matchedStatement;
15778
- else if (matchedStatement) {
15936
+ if (matchedStatement && ts.isClassDeclaration(matchedStatement)) {
15937
+ foundClassDeclaration = matchedStatement;
15938
+ foundClassName = foundClassDeclaration.name?.getText();
15939
+ } else if (matchedStatement) {
15779
15940
  foundClassDeclaration = findClassWalk(matchedStatement);
15941
+ foundClassName = foundClassDeclaration?.name?.getText() ?? extendee.getText();
15780
15942
  keepLooking = false;
15781
15943
  if (!foundClassDeclaration) warnMixinFactoryClassNotFound(buildCtx, extendee.getText(), classDeclaration);
15782
15944
  } else {
15783
15945
  foundClassDeclaration = findClassWalk(currentSource, extendee.getText());
15946
+ foundClassName = foundClassDeclaration?.name?.getText() ?? extendee.getText();
15784
15947
  keepLooking = false;
15785
15948
  }
15786
15949
  if (foundClassDeclaration && !dependentClasses.some((dc) => dc.classNode === foundClassDeclaration)) {
15787
15950
  const foundModule = compilerCtx.moduleMap.get(currentSource.fileName);
15788
15951
  if (foundModule?.staticSourceFile) {
15789
15952
  const transformedSource = foundModule.staticSourceFile;
15790
- const transformedClass = findClassWalk(transformedSource, foundClassDeclaration.name?.getText());
15953
+ const transformedClass = findClassWalk(transformedSource, foundClassName);
15791
15954
  if (transformedClass) {
15792
15955
  dependentClasses.push({
15793
15956
  classNode: transformedClass,
@@ -16072,7 +16235,7 @@ function convertInMemorySourceDecorators(sourceFile, config) {
16072
16235
  const program = ts.createProgram([sourceFile.fileName], compilerOptions, compilerHost);
16073
16236
  const typeChecker = program.getTypeChecker();
16074
16237
  const ownSourceFile = program.getSourceFile(sourceFile.fileName) ?? sourceFile;
16075
- const result = ts.transform(ownSourceFile, [convertDecoratorsToStatic(config, [], typeChecker, program)]);
16238
+ const result = ts.transform(ownSourceFile, [convertDecoratorsToStatic(config, [], typeChecker, program, true)]);
16076
16239
  const printed = ts.createPrinter({ removeComments: false }).printFile(result.transformed[0]);
16077
16240
  const scriptKind = sourceFile.fileName.endsWith(".tsx") || sourceFile.fileName.endsWith(".ts") ? ts.ScriptKind.TSX : ts.ScriptKind.JS;
16078
16241
  return ts.createSourceFile(sourceFile.fileName, printed, sourceFile.languageVersion, true, scriptKind);
@@ -16247,7 +16410,8 @@ function resolveAncestors(classNode, sf, path, resolveImport, visited, ancestors
16247
16410
  ancestors.push({
16248
16411
  classNode: foundClass,
16249
16412
  sourceFile: foundSf,
16250
- path: foundPath
16413
+ path: foundPath,
16414
+ factoryName: parentName
16251
16415
  });
16252
16416
  if (keepLooking) resolveAncestors(foundClass, foundSf, foundPath, resolveImport, visited, ancestors, rootClassDeclaration, buildCtx);
16253
16417
  }
@@ -16264,8 +16428,8 @@ function resolveAncestors(classNode, sf, path, resolveImport, visited, ancestors
16264
16428
  * @returns the ancestor's metadata
16265
16429
  */
16266
16430
  function extractAncestorMeta(ancestor, cmpSourceFile, resolveImport, config) {
16267
- const { classNode, sourceFile: parentSf, path: resolvedPath } = ancestor;
16268
- const className = classNode.name?.text;
16431
+ const { classNode, sourceFile: parentSf, path: resolvedPath, factoryName } = ancestor;
16432
+ const className = classNode.name?.text ?? factoryName;
16269
16433
  const parentStaticMembers = classNode.members.filter(isStaticGetter);
16270
16434
  let resolvedClassNode = classNode;
16271
16435
  let resolvedStaticMembers = parentStaticMembers;
@@ -18121,13 +18285,17 @@ const getPackageJsonRecommendations = (config, compilerCtx) => {
18121
18285
  const loaderBundle = config.outputTargets.find(isOutputTargetLoaderBundle);
18122
18286
  const standalone = config.outputTargets.find(isOutputTargetStandalone);
18123
18287
  const types = config.outputTargets.find(isOutputTargetTypes);
18288
+ const srcIndexPath = join$2(config.srcDir, "index.ts");
18289
+ const hasSrcIndex = compilerCtx.fs.accessSync(srcIndexPath);
18124
18290
  const moduleOptions = [];
18125
- if (loaderBundle?.dir) moduleOptions.push(normalizePath(relative$1(config.rootDir, join$2(loaderBundle.dir, "index.js"))));
18291
+ if (loaderBundle?.dir) {
18292
+ const loaderEntry = hasSrcIndex ? join$2(loaderBundle.dir, "index.js") : join$2(loaderBundle.dir, "esm", "loader.js");
18293
+ moduleOptions.push(normalizePath(relative$1(config.rootDir, loaderEntry)));
18294
+ }
18126
18295
  if (standalone?.dir) moduleOptions.push(normalizePath(relative$1(config.rootDir, join$2(standalone.dir, "index.js"))));
18127
18296
  const typesOptions = [];
18128
18297
  if (types?.dir) {
18129
- const srcIndexPath = join$2(config.srcDir, "index.ts");
18130
- if (compilerCtx.fs.accessSync(srcIndexPath)) typesOptions.push(normalizePath(relative$1(config.rootDir, join$2(types.dir, "index.d.ts"))));
18298
+ if (hasSrcIndex) typesOptions.push(normalizePath(relative$1(config.rootDir, join$2(types.dir, "index.d.ts"))));
18131
18299
  else {
18132
18300
  if (loaderBundle) typesOptions.push(normalizePath(relative$1(config.rootDir, join$2(types.dir, "loader.d.ts"))));
18133
18301
  if (standalone) typesOptions.push(normalizePath(relative$1(config.rootDir, join$2(types.dir, "standalone.d.ts"))));
@@ -18145,6 +18313,31 @@ const getPackageJsonRecommendations = (config, compilerCtx) => {
18145
18313
  };
18146
18314
  };
18147
18315
  /**
18316
+ * Collect the rootDir-relative directories of every configured output target that must
18317
+ * ship in the published npm package for consumers (and their tooling) to be able to use
18318
+ * it - as opposed to dev-only artifacts like `www`.
18319
+ * @param config The validated Stencil configuration
18320
+ * @param buildCtx The build context (used to check whether there are actually component
18321
+ * assets to copy - the `assets` output target is otherwise a no-op and its directory is
18322
+ * never written)
18323
+ * @returns a de-duplicated list of rootDir-relative directory paths
18324
+ */
18325
+ const getDistributableOutputDirs = (config, buildCtx) => {
18326
+ const loaderBundle = config.outputTargets.find(isOutputTargetLoaderBundle);
18327
+ const standalone = config.outputTargets.find(isOutputTargetStandalone);
18328
+ const types = config.outputTargets.find(isOutputTargetTypes);
18329
+ const collections = config.outputTargets.filter(isOutputTargetCollection);
18330
+ const assets = buildCtx.components.some((cmp) => cmp.assetsDirs != null && cmp.assetsDirs.length > 0) ? config.outputTargets.find(isOutputTargetAssets) : void 0;
18331
+ const dirs = [
18332
+ loaderBundle?.dir,
18333
+ standalone?.dir,
18334
+ types?.dir,
18335
+ assets?.dir,
18336
+ ...collections.map((c) => c.dir)
18337
+ ].filter((dir) => !!dir).map((dir) => normalizePath(relative$1(config.rootDir, dir)));
18338
+ return Array.from(new Set(dirs));
18339
+ };
18340
+ /**
18148
18341
  * Validate the package.json file for a project, checking that various fields
18149
18342
  * are set correctly for the currently-configured output targets.
18150
18343
  *
@@ -18158,8 +18351,8 @@ const getPackageJsonRecommendations = (config, compilerCtx) => {
18158
18351
  const validateBuildPackageJson = async (config, compilerCtx, buildCtx) => {
18159
18352
  if (config.watch || config.devMode || buildCtx.packageJson == null) return;
18160
18353
  validatePackageJson(config, compilerCtx, buildCtx);
18161
- const stencilCollectionOutputTargets = config.outputTargets.filter(isOutputTargetCollection);
18162
- await Promise.all(stencilCollectionOutputTargets.map((stencilCollectionOT) => validateCollectionFields(config, compilerCtx, buildCtx, stencilCollectionOT)));
18354
+ await validateFilesField(config, compilerCtx, buildCtx);
18355
+ config.outputTargets.filter(isOutputTargetCollection).forEach((stencilCollectionOT) => validateCollectionField(config, compilerCtx, buildCtx, stencilCollectionOT));
18163
18356
  };
18164
18357
  /**
18165
18358
  * Validates a project's package.json fields against recommended values
@@ -18277,40 +18470,49 @@ const validateTypeField = (config, compilerCtx, buildCtx, recommendations) => {
18277
18470
  if (recommendations.moduleOptions.length > 0 && currentType !== "module") packageJsonWarn(config, compilerCtx, buildCtx, `package.json "type" property should be set to "module".`, "\"type\"");
18278
18471
  };
18279
18472
  /**
18280
- * Validate package.json contents specific to the `collection` output target,
18281
- * checking that the `files` array and `collection` field are set correctly.
18282
- * @param config the Stencil configuration associated with the project being compiled
18283
- * @param compilerCtx the current compiler context
18284
- * @param buildCtx the context associated with the current build
18285
- * @param outputTarget the collection output target to validate against
18473
+ * Check if a rootDir-relative directory is covered by a package.json `files` array,
18474
+ * either directly or via a parent directory entry (e.g. "dist/" covers "dist/types/").
18475
+ * @param files the package.json "files" array
18476
+ * @param dir the rootDir-relative directory to check for
18477
+ * @returns true if `dir` is covered by one of the `files` entries
18286
18478
  */
18287
- const validateCollectionFields = async (config, compilerCtx, buildCtx, outputTarget) => {
18288
- await Promise.all([validatePackageFiles(config, compilerCtx, buildCtx, outputTarget), validateCollectionField(config, compilerCtx, buildCtx, outputTarget)]);
18479
+ const isDirCoveredByFiles = (files, dir) => {
18480
+ const normalizedDir = dir.replace(/\/$/, "").replace(/^\.\//, "");
18481
+ return files.some((userPath) => {
18482
+ const normalizedUserPath = normalizePath(userPath).replace(/\/$/, "").replace(/^\.\//, "");
18483
+ if (normalizedUserPath === normalizedDir) return true;
18484
+ const userPathWithSlash = normalizedUserPath + "/";
18485
+ return normalizedDir.startsWith(userPathWithSlash);
18486
+ });
18289
18487
  };
18290
18488
  /**
18291
- * Validate that the `files` field in `package.json` contains directories and
18292
- * files that are necessary for the `collection` output target.
18489
+ * Validate that the `files` field in `package.json` covers every distributable output
18490
+ * directory (loader-bundle, standalone, types, collection) - not just one of them -
18491
+ * since `npm publish` needs all of them to produce a working package for consumers.
18293
18492
  * @param config the Stencil configuration associated with the project being compiled
18294
18493
  * @param compilerCtx the current compiler context
18295
18494
  * @param buildCtx the context associated with the current build
18296
- * @param outputTarget the collection output target to validate against
18297
18495
  */
18298
- const validatePackageFiles = async (config, compilerCtx, buildCtx, outputTarget) => {
18299
- if (!Array.isArray(buildCtx.packageJson.files)) return;
18300
- const actualDistDir = normalizePath(relative$1(config.rootDir, outputTarget.dir));
18301
- if (!buildCtx.packageJson.files.some((userPath) => {
18302
- const normalizedUserPath = normalizePath(userPath).replace(/\/$/, "").replace(/^\.\//, "");
18303
- const normalizedDistDir = actualDistDir.replace(/\/$/, "").replace(/^\.\//, "");
18304
- if (normalizedUserPath === normalizedDistDir) return true;
18305
- const userPathWithSlash = normalizedUserPath + "/";
18306
- if (normalizedDistDir.startsWith(userPathWithSlash)) return true;
18307
- return false;
18308
- })) {
18309
- const msg = `package.json "files" array must contain the distribution directory "${actualDistDir}/" when generating a distribution.`;
18496
+ const validateFilesField = async (config, compilerCtx, buildCtx) => {
18497
+ const distDirs = getDistributableOutputDirs(config, buildCtx);
18498
+ if (distDirs.length === 0) return;
18499
+ const formatDirs = (dirs) => dirs.map((dir) => `"${dir}/"`).join(", ");
18500
+ if (!Array.isArray(buildCtx.packageJson.files)) {
18501
+ const npmignorePath = join$2(dirname$1(config.packageJsonFilePath), ".npmignore");
18502
+ if (!await compilerCtx.fs.access(npmignorePath)) {
18503
+ const msg = `package.json is missing a "files" array. Without one, "npm publish" falls back to ".gitignore" to decide what to include, which will likely exclude ${distDirs.length > 1 ? "the distribution directories" : "the distribution directory"} ${formatDirs(distDirs)}. Add a "files" array covering ${distDirs.length > 1 ? "them" : "it"} to package.json (or add a ".npmignore").`;
18504
+ packageJsonWarn(config, compilerCtx, buildCtx, msg, `"files"`);
18505
+ }
18506
+ return;
18507
+ }
18508
+ const files = buildCtx.packageJson.files;
18509
+ const uncoveredDirs = distDirs.filter((dir) => !isDirCoveredByFiles(files, dir));
18510
+ if (uncoveredDirs.length > 0) {
18511
+ const msg = `package.json "files" array must contain the distribution ${uncoveredDirs.length > 1 ? "directories" : "directory"} ${formatDirs(uncoveredDirs)} when generating a distribution.`;
18310
18512
  packageJsonWarn(config, compilerCtx, buildCtx, msg, `"files"`);
18311
18513
  return;
18312
18514
  }
18313
- await Promise.all(buildCtx.packageJson.files.map(async (pkgFile) => {
18515
+ await Promise.all(files.map(async (pkgFile) => {
18314
18516
  if (!isGlob(pkgFile)) {
18315
18517
  const packageJsonDir = dirname$1(config.packageJsonFilePath);
18316
18518
  const absPath = join$2(packageJsonDir, pkgFile);
@@ -18425,6 +18627,24 @@ const validateBuildFiles = (config, compilerCtx, buildCtx) => {
18425
18627
  //#endregion
18426
18628
  //#region src/compiler/build/write-export-maps.ts
18427
18629
  /**
18630
+ * Create the shared {@link NpmPkgSet} used across a single `writeExportMaps` run.
18631
+ * @param buildCtx The build context to report a warning diagnostic on if `npm` can't be run
18632
+ * @returns A function that shells out to `npm pkg set`, swallowing failure after warning once
18633
+ */
18634
+ const createNpmPkgSet = (buildCtx) => {
18635
+ let npmAvailable = true;
18636
+ return (cmd) => {
18637
+ if (!npmAvailable) return;
18638
+ try {
18639
+ execSync(`npm pkg set ${cmd}`);
18640
+ } catch (e) {
18641
+ npmAvailable = false;
18642
+ const warn = buildWarn(buildCtx.diagnostics);
18643
+ warn.messageText = `Unable to generate "exports" map in package.json: the "npm" CLI could not be run (${e.message ?? e}). Set "generateExportMaps: false" in your Stencil config to silence this warning.`;
18644
+ }
18645
+ };
18646
+ };
18647
+ /**
18428
18648
  * Create export map entry point definitions for the `package.json` file using the npm CLI.
18429
18649
  *
18430
18650
  * In v5, this uses a "smart default" approach:
@@ -18435,15 +18655,17 @@ const validateBuildFiles = (config, compilerCtx, buildCtx) => {
18435
18655
  * - Generate per-component exports for standalone output
18436
18656
  *
18437
18657
  * @param config The validated Stencil config
18658
+ * @param compilerCtx The compiler context (used to detect a user-authored src/index.ts)
18438
18659
  * @param buildCtx The build context containing the components to generate export maps for
18439
18660
  */
18440
- const writeExportMaps = (config, buildCtx) => {
18661
+ const writeExportMaps = (config, compilerCtx, buildCtx) => {
18441
18662
  const loaderBundle = config.outputTargets.find(isOutputTargetLoaderBundle);
18442
18663
  const standalone = config.outputTargets.find(isOutputTargetStandalone);
18443
18664
  const types = config.outputTargets.find(isOutputTargetTypes);
18444
- generateRootExport(config, buildCtx, loaderBundle, standalone, types);
18445
- if (loaderBundle) generateLoaderExport(config, loaderBundle, types);
18446
- if (standalone) generateComponentExports(config, buildCtx, standalone);
18665
+ const npmPkgSet = createNpmPkgSet(buildCtx);
18666
+ generateRootExport(config, compilerCtx, buildCtx, loaderBundle, standalone, types, npmPkgSet);
18667
+ if (loaderBundle) generateLoaderExport(config, loaderBundle, types, npmPkgSet);
18668
+ if (standalone) generateComponentExports(config, buildCtx, standalone, npmPkgSet);
18447
18669
  };
18448
18670
  /**
18449
18671
  * Generate the root export `exports["."]`.
@@ -18453,28 +18675,32 @@ const writeExportMaps = (config, buildCtx) => {
18453
18675
  * - If valid, leave it alone
18454
18676
  * - If missing or invalid, set default (loader-bundle > standalone priority)
18455
18677
  * @param config The validated Stencil config
18678
+ * @param compilerCtx The compiler context (used to detect a user-authored src/index.ts)
18456
18679
  * @param buildCtx The build context containing the components to generate export maps for
18457
18680
  * @param loaderBundle The loader-bundle output target, if it exists
18458
18681
  * @param standalone The standalone output target, if it exists
18459
18682
  * @param types The types output target, if it exists
18683
+ * @param npmPkgSet Function used to run `npm pkg set`, tolerating an unavailable npm CLI
18460
18684
  */
18461
- const generateRootExport = (config, buildCtx, loaderBundle, standalone, types) => {
18685
+ const generateRootExport = (config, compilerCtx, buildCtx, loaderBundle, standalone, types, npmPkgSet) => {
18462
18686
  if (!loaderBundle && !standalone) return;
18687
+ const hasSrcIndex = compilerCtx.fs.accessSync(join$2(config.srcDir, "index.ts"));
18688
+ const rootUsesEmptyLoaderIndex = !!loaderBundle && !hasSrcIndex;
18463
18689
  const currentImport = ((buildCtx.packageJson?.exports)?.["."])?.import;
18464
18690
  if (!(currentImport && isValidRootExport(config, currentImport, loaderBundle, standalone))) {
18465
18691
  const primaryDir = loaderBundle?.dir ?? standalone?.dir;
18466
18692
  if (primaryDir) {
18467
- const importPath = normalizePath(relative$1(config.rootDir, join$2(primaryDir, "index.js")));
18468
- execSync(`npm pkg set "exports[.][import]"="${importPath}"`);
18693
+ const entryFile = rootUsesEmptyLoaderIndex ? join$2("esm", "loader.js") : "index.js";
18694
+ npmPkgSet(`"exports[.][import]"="${normalizePath(relative$1(config.rootDir, join$2(primaryDir, entryFile)))}"`);
18469
18695
  if (loaderBundle?.cjs) {
18470
- const requirePath = normalizePath(relative$1(config.rootDir, join$2(loaderBundle.dir, "index.cjs")));
18471
- execSync(`npm pkg set "exports[.][require]"="${requirePath}"`);
18696
+ const cjsEntryFile = rootUsesEmptyLoaderIndex ? join$2("cjs", "loader.cjs") : "index.cjs";
18697
+ npmPkgSet(`"exports[.][require]"="${normalizePath(relative$1(config.rootDir, join$2(loaderBundle.dir, cjsEntryFile)))}"`);
18472
18698
  }
18473
18699
  }
18474
18700
  }
18475
18701
  if (types?.dir) {
18476
- const typesPath = normalizePath(relative$1(config.rootDir, join$2(types.dir, "index.d.ts")));
18477
- execSync(`npm pkg set "exports[.][types]"="${typesPath}"`);
18702
+ const typesFile = rootUsesEmptyLoaderIndex ? "loader.d.ts" : "index.d.ts";
18703
+ npmPkgSet(`"exports[.][types]"="${normalizePath(relative$1(config.rootDir, join$2(types.dir, typesFile)))}"`);
18478
18704
  }
18479
18705
  };
18480
18706
  /**
@@ -18517,20 +18743,16 @@ const ensureRelativePrefix = (path) => {
18517
18743
  * @param config The validated Stencil config
18518
18744
  * @param loaderBundle The loader-bundle output target
18519
18745
  * @param types The types output target, if it exists
18746
+ * @param npmPkgSet Function used to run `npm pkg set`, tolerating an unavailable npm CLI
18520
18747
  */
18521
- const generateLoaderExport = (config, loaderBundle, types) => {
18748
+ const generateLoaderExport = (config, loaderBundle, types, npmPkgSet) => {
18522
18749
  const esmDir = join$2(loaderBundle.dir, "esm");
18523
- const esmLoaderPath = ensureRelativePrefix(normalizePath(relative$1(config.rootDir, join$2(esmDir, "loader.js"))));
18524
- execSync(`npm pkg set "exports[./loader][import]"="${esmLoaderPath}"`);
18750
+ npmPkgSet(`"exports[./loader][import]"="${ensureRelativePrefix(normalizePath(relative$1(config.rootDir, join$2(esmDir, "loader.js"))))}"`);
18525
18751
  if (loaderBundle.cjs) {
18526
18752
  const cjsDir = join$2(loaderBundle.dir, "cjs");
18527
- const cjsLoaderPath = ensureRelativePrefix(normalizePath(relative$1(config.rootDir, join$2(cjsDir, "loader.cjs"))));
18528
- execSync(`npm pkg set "exports[./loader][require]"="${cjsLoaderPath}"`);
18529
- }
18530
- if (types?.dir) {
18531
- const typesPath = ensureRelativePrefix(normalizePath(relative$1(config.rootDir, join$2(types.dir, "loader.d.ts"))));
18532
- execSync(`npm pkg set "exports[./loader][types]"="${typesPath}"`);
18753
+ npmPkgSet(`"exports[./loader][require]"="${ensureRelativePrefix(normalizePath(relative$1(config.rootDir, join$2(cjsDir, "loader.cjs"))))}"`);
18533
18754
  }
18755
+ if (types?.dir) npmPkgSet(`"exports[./loader][types]"="${ensureRelativePrefix(normalizePath(relative$1(config.rootDir, join$2(types.dir, "loader.d.ts"))))}"`);
18534
18756
  };
18535
18757
  /**
18536
18758
  * Generate per-component exports for standalone output.
@@ -18538,13 +18760,14 @@ const generateLoaderExport = (config, loaderBundle, types) => {
18538
18760
  * @param config The validated Stencil config
18539
18761
  * @param buildCtx The build context containing the components to generate export maps for
18540
18762
  * @param standalone The standalone output target
18763
+ * @param npmPkgSet Function used to run `npm pkg set`, tolerating an unavailable npm CLI
18541
18764
  */
18542
- const generateComponentExports = (config, buildCtx, standalone) => {
18765
+ const generateComponentExports = (config, buildCtx, standalone, npmPkgSet) => {
18543
18766
  let outDir = relative$1(config.rootDir, standalone.dir);
18544
18767
  if (!outDir.startsWith(".")) outDir = "./" + outDir;
18545
18768
  buildCtx.components.forEach((cmp) => {
18546
- execSync(`npm pkg set "exports[./${cmp.tagName}][import]"="${outDir}/${cmp.tagName}.js"`);
18547
- execSync(`npm pkg set "exports[./${cmp.tagName}][types]"="${outDir}/${cmp.tagName}.d.ts"`);
18769
+ npmPkgSet(`"exports[./${cmp.tagName}][import]"="${outDir}/${cmp.tagName}.js"`);
18770
+ npmPkgSet(`"exports[./${cmp.tagName}][types]"="${outDir}/${cmp.tagName}.d.ts"`);
18548
18771
  });
18549
18772
  };
18550
18773
  //#endregion
@@ -18568,7 +18791,7 @@ const writeBuild = async (config, compilerCtx, buildCtx) => {
18568
18791
  await compilerCtx.cache.commit();
18569
18792
  buildCtx.debug(`in-memory-fs: ${compilerCtx.fs.getMemoryStats()}`);
18570
18793
  buildCtx.debug(`cache: ${compilerCtx.cache.getMemoryStats()}`);
18571
- if (config.generateExportMaps) writeExportMaps(config, buildCtx);
18794
+ if (config.generateExportMaps && !config.devMode) writeExportMaps(config, compilerCtx, buildCtx);
18572
18795
  await outputServiceWorkers(config, buildCtx);
18573
18796
  await validateBuildFiles(config, compilerCtx, buildCtx);
18574
18797
  } catch (e) {
@@ -20603,10 +20826,11 @@ const validateConfig = (userConfig = {}, bootstrapConfig) => {
20603
20826
  const devMode = isBoolean$1(config.devMode) ? config.devMode : false;
20604
20827
  config._isTesting = !!(process.env.VITEST || process.env.PLAYWRIGHT_TEST || process.env.TEST_WORKER_INDEX || process.env.TEST_PARALLEL_INDEX || process.env.NODE_ENV === "test");
20605
20828
  const sys = config.sys ?? bootstrapConfig.sys ?? createNodeSys({ logger });
20829
+ const hasExplicitGlobalStyleWithInput = (config.outputTargets || []).some((o) => isOutputTargetGlobalStyle(o) && isString$1(o.input));
20606
20830
  if ((!isString$1(config.globalStyle) || !isString$1(config.globalScript)) && typeof sys.accessSync === "function") {
20607
20831
  const preRootDir = typeof config.rootDir !== "string" ? "/" : config.rootDir;
20608
20832
  const srcDir = typeof config.srcDir === "string" ? isAbsolute$1(config.srcDir) ? config.srcDir : join$1(preRootDir, config.srcDir) : join$1(preRootDir, "src");
20609
- if (!isString$1(config.globalStyle)) for (const ext of STYLE_EXT) {
20833
+ if (!isString$1(config.globalStyle) && !hasExplicitGlobalStyleWithInput) for (const ext of STYLE_EXT) {
20610
20834
  const candidate = join$1(srcDir, `global.${ext}`);
20611
20835
  if (sys.accessSync(candidate)) {
20612
20836
  config.globalStyle = candidate;
@@ -20626,7 +20850,7 @@ const validateConfig = (userConfig = {}, bootstrapConfig) => {
20626
20850
  ...config,
20627
20851
  devMode,
20628
20852
  compat: config.compat || {},
20629
- generateExportMaps: isBoolean$1(config.generateExportMaps) ? config.generateExportMaps : false,
20853
+ generateExportMaps: isBoolean$1(config.generateExportMaps) ? config.generateExportMaps : !isString$1(config.configPath),
20630
20854
  hydratedFlag: validateHydrated(config),
20631
20855
  logLevel,
20632
20856
  logger,