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

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.
@@ -1,9 +1,9 @@
1
1
  import { n as __require } from "./rolldown-runtime-BhDjJH2R.mjs";
2
- import { S as HYDRATED_CSS } from "./client-Db2rdxUM.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-BKtLn2R9.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";
@@ -461,9 +461,9 @@ const scopeCss = (cssText, scopeId, commentOriginalSelector) => {
461
461
  };
462
462
  //#endregion
463
463
  //#region src/version.ts
464
- const version = "5.0.0-beta.10";
465
- const buildId = "1789054824";
466
- const vermoji = "🚘";
464
+ const version = "5.0.0-beta.12";
465
+ const buildId = "1789547794";
466
+ const vermoji = "🏇";
467
467
  /**
468
468
  * Get the installed version of a tool/dependency.
469
469
  * Handles packages with exports maps that point to subdirectories.
@@ -2854,6 +2854,7 @@ const setPackageVersionByContent = (pkgVersions, pkgContent) => {
2854
2854
  if (pkg.name && pkg.version) setPackageVersion(pkgVersions, pkg.name, pkg.version);
2855
2855
  } catch {}
2856
2856
  };
2857
+ const isLocalModule = (p) => p.startsWith(".") || p.startsWith("/");
2857
2858
  const isNodeModulePath = (p) => normalizePath(p).split("/").includes("node_modules");
2858
2859
  const getModuleId = (orgImport) => {
2859
2860
  if (orgImport.startsWith("~")) orgImport = orgImport.substring(1);
@@ -6024,7 +6025,8 @@ const addTagTransform$2 = (compilerCtx, buildCtx) => {
6024
6025
  const expression = node.expression;
6025
6026
  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")) {
6026
6027
  const [firstArg, ...restArgs] = node.arguments;
6027
- if (firstArg) {
6028
+ const alreadyTransformed = firstArg && ts.isCallExpression(firstArg) && ts.isIdentifier(firstArg.expression) && (firstArg.expression.text === "__stencil_transformTag" || firstArg.expression.text === "transformTag");
6029
+ if (firstArg && !alreadyTransformed) {
6028
6030
  const newFirstArg = ts.factory.createCallExpression(ts.factory.createIdentifier(TRANSFORM_TAG), void 0, [firstArg]);
6029
6031
  newNode = ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [newFirstArg, ...restArgs]);
6030
6032
  }
@@ -11230,10 +11232,13 @@ const MODE_RESOLUTION_CHAIN_DECLARATION = `modeResolutionChain = [];`;
11230
11232
  const SSR_FACTORY_INTRO = `
11231
11233
  //! let ${MODE_RESOLUTION_CHAIN_DECLARATION}
11232
11234
 
11233
- // Capture native setTimeout/clearTimeout at module scope (before globalThis can be shadowed inside the factory).
11235
+ // Capture native at module scope (before globalThis can be shadowed inside the factory).
11236
+
11234
11237
  // Used for the hydrate timeout timer to avoid being affected by constrainTimeouts.
11235
11238
  var $nativeSetTimeout = (typeof globalThis !== 'undefined' ? globalThis : global).setTimeout;
11236
11239
  var $nativeClearTimeout = (typeof globalThis !== 'undefined' ? globalThis : global).clearTimeout;
11240
+ // Used to abort in-flight fetch() calls and to call any user defined AbortControllers when ssr times out.
11241
+ var $stencilNativeAbortController = AbortController;
11237
11242
 
11238
11243
  export function ssrFactory($stencilWindow, $stencilHydrateOpts, $stencilHydrateResults, $stencilAfterHydrate, $stencilHydrateResolve) {
11239
11244
  var globalThis = $stencilWindow;
@@ -11326,8 +11331,46 @@ export function ssrFactory($stencilWindow, $stencilHydrateOpts, $stencilHydrateR
11326
11331
 
11327
11332
  var fetch, FetchError, Headers, Request, Response;
11328
11333
 
11334
+ // Aborted when the render times out or errors, so in-flight fetch() calls
11335
+ // made by component code stop holding the render's window/results alive
11336
+ // instead of running to completion against a torn-down window. See #6864.
11337
+ var $stencilAbortController = new $stencilNativeAbortController();
11338
+
11339
+ // Any AbortController a component creates itself is transparently wired to
11340
+ // cascade-abort when the render times out too, so component code using the
11341
+ // standard AbortController convention for its own cancellable work (axios,
11342
+ // aws-sdk v3, the mongodb driver, etc.) gets cancelled automatically.
11343
+ var AbortController = function () {
11344
+ var controller = new $stencilNativeAbortController();
11345
+ $stencilAbortController.signal.addEventListener(
11346
+ 'abort',
11347
+ function () {
11348
+ controller.abort();
11349
+ },
11350
+ { once: true },
11351
+ );
11352
+ return controller;
11353
+ };
11354
+
11355
+ function $stencilFetchSignal(callerSignal) {
11356
+ if (!callerSignal) {
11357
+ return $stencilAbortController.signal;
11358
+ }
11359
+ if (callerSignal.aborted || $stencilAbortController.signal.aborted) {
11360
+ return callerSignal.aborted ? callerSignal : $stencilAbortController.signal;
11361
+ }
11362
+ var merged = new $stencilNativeAbortController();
11363
+ var onAbort = function () { merged.abort(); };
11364
+ callerSignal.addEventListener('abort', onAbort, { once: true });
11365
+ $stencilAbortController.signal.addEventListener('abort', onAbort, { once: true });
11366
+ return merged.signal;
11367
+ }
11368
+
11329
11369
  if (typeof $stencilWindow.fetch === 'function') {
11330
- fetch = $stencilWindow.fetch;
11370
+ var $stencilRawFetch = $stencilWindow.fetch;
11371
+ fetch = $stencilWindow.fetch = function(input, init) {
11372
+ return $stencilRawFetch(input, Object.assign({}, init, { signal: $stencilFetchSignal(init && init.signal) }));
11373
+ };
11331
11374
  } else {
11332
11375
  fetch = $stencilWindow.fetch = function() { throw new Error('fetch() is not implemented'); };
11333
11376
  }
@@ -11363,7 +11406,7 @@ export function ssrFactory($stencilWindow, $stencilHydrateOpts, $stencilHydrateR
11363
11406
  `;
11364
11407
  const SSR_FACTORY_OUTRO = `
11365
11408
  /*hydrateAppClosure end*/
11366
- ssrApp(window, $stencilHydrateOpts, $stencilHydrateResults, $stencilAfterHydrate, $stencilHydrateResolve);
11409
+ ssrApp(window, $stencilHydrateOpts, $stencilHydrateResults, $stencilAfterHydrate, $stencilHydrateResolve, $stencilAbortController);
11367
11410
  }
11368
11411
 
11369
11412
  hydrateAppClosure($stencilWindow);
@@ -11637,6 +11680,40 @@ if (typeof globalThis !== "undefined") {
11637
11680
  if (typeof globalThis.clearInterval !== "function") globalThis.clearInterval = function() {};
11638
11681
  }
11639
11682
  `;
11683
+ const SSR_WASM_ABORT_CONTROLLER_POLYFILL = `
11684
+ if (typeof globalThis !== "undefined" && typeof globalThis.AbortController !== "function") {
11685
+ function StencilPolyfillAbortSignal() {
11686
+ this.aborted = false;
11687
+ this.reason = undefined;
11688
+ this._listeners = [];
11689
+ }
11690
+ StencilPolyfillAbortSignal.prototype.addEventListener = function(type, listener, options) {
11691
+ if (type !== "abort" || typeof listener !== "function") return;
11692
+ this._listeners.push({ listener: listener, once: !!(options && options.once) });
11693
+ };
11694
+ StencilPolyfillAbortSignal.prototype.removeEventListener = function(type, listener) {
11695
+ if (type !== "abort") return;
11696
+ this._listeners = this._listeners.filter(function(entry) { return entry.listener !== listener; });
11697
+ };
11698
+ StencilPolyfillAbortSignal.prototype.dispatchEvent = function(event) {
11699
+ var signal = this;
11700
+ signal._listeners.slice().forEach(function(entry) { entry.listener.call(signal, event); });
11701
+ signal._listeners = signal._listeners.filter(function(entry) { return !entry.once; });
11702
+ return true;
11703
+ };
11704
+ function StencilPolyfillAbortController() {
11705
+ this.signal = new StencilPolyfillAbortSignal();
11706
+ }
11707
+ StencilPolyfillAbortController.prototype.abort = function(reason) {
11708
+ if (this.signal.aborted) return;
11709
+ this.signal.aborted = true;
11710
+ this.signal.reason = reason;
11711
+ this.signal.dispatchEvent({ type: "abort" });
11712
+ };
11713
+ globalThis.AbortController = StencilPolyfillAbortController;
11714
+ globalThis.AbortSignal = StencilPolyfillAbortSignal;
11715
+ }
11716
+ `;
11640
11717
  const SSR_WASM_INTERFACE = `declare module "main" {
11641
11718
  export function renderToString(): void;
11642
11719
  export function setTagTransformer(): void;
@@ -11651,6 +11728,12 @@ module.exports = {
11651
11728
  return;
11652
11729
  }
11653
11730
  var inp = JSON.parse(Host.inputString());
11731
+ // QuickJS-ng has no timers, so if hydration never settles on its own (a Promise
11732
+ // nothing will ever resolve), the call doesn't hang - it just runs out of scheduled
11733
+ // work and returns whatever was last written here. Write a diagnostic up front so
11734
+ // that's a real error instead of silence, then overwrite it once renderToString()
11735
+ // actually resolves.
11736
+ Host.outputString(JSON.stringify({ __error: 'renderToString did not complete - a component may be waiting on work that never resolves' }));
11654
11737
  var result = await renderToString(inp.html, inp.options);
11655
11738
  Host.outputString(JSON.stringify(result));
11656
11739
  } catch(e) {
@@ -11707,7 +11790,7 @@ const generateSsrWasmApp = async (config, compilerCtx, buildCtx, outputTargets)
11707
11790
  checks: { pluginTimings: config.logLevel === "debug" }
11708
11791
  };
11709
11792
  const rolldownOutput = await (await rolldown(rolldownOptions)).generate({
11710
- banner: generatePreamble(config) + SSR_WASM_TIMER_POLYFILL,
11793
+ banner: generatePreamble(config) + SSR_WASM_TIMER_POLYFILL + SSR_WASM_ABORT_CONTROLLER_POLYFILL,
11711
11794
  outro: SSR_WASM_OUTRO,
11712
11795
  format: "iife",
11713
11796
  name: "StencilSsrWasm",
@@ -15609,23 +15692,159 @@ function matchesNamedDeclaration(name) {
15609
15692
  };
15610
15693
  }
15611
15694
  /**
15612
- * Finds a re-export of `className` in `sourceFile` - `export { X } from './y'` or
15613
- * `export { X as Y } from './y'` - as used by barrel entry points (e.g. `@stencil/core`'s own
15614
- * public `index.d.mts`, which re-exports its runtime API from `./declarations/stencil-public-runtime`
15615
- * rather than declaring it directly).
15695
+ * Finds a re-export of `className` in `sourceFile`: `export { X } from './y'`, or the
15696
+ * bundler-split shape `import { X as name } from './y'; export { name };` (no `from` clause).
15616
15697
  * @param sourceFile the (barrel) source file to scan
15617
15698
  * @param className the exported name to look for
15618
- * @returns the module specifier and the name to look for in that module (the local name, before
15619
- * any `as` aliasing), or `undefined` if no matching re-export is found
15699
+ * @returns the module specifier and name to look for there (before any `as` aliasing), or
15700
+ * `undefined` if not found
15620
15701
  */
15621
15702
  function findReExport(sourceFile, className) {
15622
15703
  for (const stmt of sourceFile.statements) {
15623
- if (!ts.isExportDeclaration(stmt) || !stmt.moduleSpecifier || !ts.isStringLiteral(stmt.moduleSpecifier) || !stmt.exportClause || !ts.isNamedExports(stmt.exportClause)) continue;
15624
- for (const element of stmt.exportClause.elements) if (element.name.text === className) return {
15704
+ if (!ts.isExportDeclaration(stmt) || !stmt.exportClause || !ts.isNamedExports(stmt.exportClause)) continue;
15705
+ const element = stmt.exportClause.elements.find((el) => el.name.text === className);
15706
+ if (!element) continue;
15707
+ if (stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier)) return {
15625
15708
  moduleSpecifier: stmt.moduleSpecifier.text,
15626
15709
  localName: element.propertyName?.text ?? element.name.text
15627
15710
  };
15711
+ const importOrigin = findImportOrigin(sourceFile, element.propertyName?.text ?? element.name.text);
15712
+ if (importOrigin) return importOrigin;
15713
+ }
15714
+ }
15715
+ /**
15716
+ * Finds `name`'s import in `sourceFile` and returns its module and origin name (before any `as`
15717
+ * aliasing; `'default'` for a default import).
15718
+ * @param sourceFile the source file to scan for a matching import
15719
+ * @param name the local (post-aliasing) name an import bound
15720
+ * @returns the import's module specifier and origin name, or `undefined` if `name` isn't imported
15721
+ */
15722
+ function findImportOrigin(sourceFile, name) {
15723
+ for (const stmt of sourceFile.statements) {
15724
+ if (!ts.isImportDeclaration(stmt) || !stmt.importClause || !ts.isStringLiteral(stmt.moduleSpecifier)) continue;
15725
+ const moduleSpecifier = stmt.moduleSpecifier.text;
15726
+ if (stmt.importClause.name?.text === name) return {
15727
+ moduleSpecifier,
15728
+ localName: "default"
15729
+ };
15730
+ const bindings = stmt.importClause.namedBindings;
15731
+ if (!bindings || !ts.isNamedImports(bindings)) continue;
15732
+ const element = bindings.elements.find((el) => el.name.text === name);
15733
+ if (element) return {
15734
+ moduleSpecifier,
15735
+ localName: element.propertyName?.text ?? element.name.text
15736
+ };
15737
+ }
15738
+ }
15739
+ /**
15740
+ * Finds `name` as a top-level declaration in `sf` (see `matchesNamedDeclaration`), following a
15741
+ * same-file export alias if `name` is only ever the public side of a local rename
15742
+ * (`export { RealName as name }`, no `from` clause).
15743
+ * @param sf the source file to search
15744
+ * @param name the declaration name to look for, which may only exist as an export alias
15745
+ * @returns the matched statement, or `undefined`
15746
+ */
15747
+ function findStatementByName(sf, name) {
15748
+ const direct = sf.statements.find(matchesNamedDeclaration(name));
15749
+ if (direct) return direct;
15750
+ for (const stmt of sf.statements) {
15751
+ if (!ts.isExportDeclaration(stmt) || stmt.moduleSpecifier || !stmt.exportClause || !ts.isNamedExports(stmt.exportClause)) continue;
15752
+ const aliasedName = stmt.exportClause.elements.find((el) => el.name.text === name)?.propertyName?.text;
15753
+ if (aliasedName && aliasedName !== name) return sf.statements.find(matchesNamedDeclaration(aliasedName));
15754
+ }
15755
+ }
15756
+ /**
15757
+ * Picks the runtime target out of a `package.json` `exports` condition entry - prefers `import`
15758
+ * over `require`/`node`/`default`, recursing into nested condition objects.
15759
+ * @param entry an `exports` map value: a path string, or nested conditions
15760
+ * @returns the resolved relative path, or `undefined` if no usable condition was found
15761
+ */
15762
+ function pickJsCondition(entry) {
15763
+ if (typeof entry === "string") return entry;
15764
+ if (typeof entry !== "object" || entry === null) return;
15765
+ const conditions = entry;
15766
+ for (const key of [
15767
+ "import",
15768
+ "require",
15769
+ "node",
15770
+ "default"
15771
+ ]) if (key in conditions) {
15772
+ const picked = pickJsCondition(conditions[key]);
15773
+ if (picked) return picked;
15774
+ }
15775
+ }
15776
+ /**
15777
+ * Reads and parses `filePath` as JS, with parent nodes set - unlike `tsGetSourceFile`, which
15778
+ * never triggers binding, so `.parent` stays unset and `node.getSourceFile()` returns `undefined`.
15779
+ * @param config the current Stencil validated config
15780
+ * @param filePath the absolute path of the JS file to read and parse
15781
+ * @returns the parsed source file, or `undefined` if it couldn't be read
15782
+ */
15783
+ function readJsSourceFile(config, filePath) {
15784
+ try {
15785
+ const text = config.sys.readFileSync(filePath);
15786
+ if (typeof text !== "string") return;
15787
+ return ts.createSourceFile(filePath, text, ts.ScriptTarget.ESNext, true, ts.ScriptKind.JS);
15788
+ } catch {
15789
+ return;
15790
+ }
15791
+ }
15792
+ /**
15793
+ * Resolves the runtime JS entry for a bare (non-relative) module specifier by reading its
15794
+ * package's own `package.json` `exports` map, instead of `tsResolveModuleName` - which always
15795
+ * resolves to the package's `types` entry, an ambient signature with no body a mixin factory's
15796
+ * class can never be found inside.
15797
+ * @param config the current Stencil validated config
15798
+ * @param compilerCtx the current compiler context
15799
+ * @param moduleSpecifier the bare package specifier to resolve
15800
+ * @param containingFile the file the specifier was imported from
15801
+ * @returns the resolved JS source file, or `undefined` if it couldn't be resolved this way
15802
+ */
15803
+ function resolveModuleJsEntry(config, compilerCtx, moduleSpecifier, containingFile) {
15804
+ if (isLocalModule(moduleSpecifier)) return;
15805
+ const pkgJsonPath = tsResolveModuleNamePackageJsonPath(config, compilerCtx, moduleSpecifier, containingFile);
15806
+ if (!pkgJsonPath) return;
15807
+ let pkgJson;
15808
+ try {
15809
+ pkgJson = JSON.parse(config.sys.readFileSync(pkgJsonPath));
15810
+ } catch {
15811
+ return;
15812
+ }
15813
+ const pkgName = pkgJson.name;
15814
+ if (!pkgName || !moduleSpecifier.startsWith(pkgName) || !pkgJson.exports) return;
15815
+ const subpath = moduleSpecifier === pkgName ? "." : `.${moduleSpecifier.slice(pkgName.length)}`;
15816
+ const exportsMap = pkgJson.exports;
15817
+ const conditionEntry = typeof exportsMap === "string" ? subpath === "." ? exportsMap : void 0 : exportsMap[subpath] ?? (subpath === "." ? exportsMap : void 0);
15818
+ const target = conditionEntry && pickJsCondition(conditionEntry);
15819
+ if (!target) return;
15820
+ return readJsSourceFile(config, normalizePath(join$2(dirname$1(pkgJsonPath), target)));
15821
+ }
15822
+ /**
15823
+ * Finds `className`'s class inside a resolved JS entry (see `resolveModuleJsEntry`), following
15824
+ * re-export hops the same way `resolveAndProcessExtendedClass` walks a `.d.ts`/`.ts` source.
15825
+ * @param config the current Stencil validated config
15826
+ * @param compilerCtx the current compiler context
15827
+ * @param source the JS source file to search
15828
+ * @param className the class (or mixin factory) name to look for
15829
+ * @param hopsRemaining re-export hops still allowed before giving up
15830
+ * @returns the found class and the source file it's declared in, or `undefined`
15831
+ */
15832
+ function findClassInJsModule(config, compilerCtx, source, className, hopsRemaining = 3) {
15833
+ const matchedStatement = findStatementByName(source, className);
15834
+ if (matchedStatement) {
15835
+ const classNode = ts.isClassDeclaration(matchedStatement) ? matchedStatement : findClassWalk(matchedStatement);
15836
+ return classNode && {
15837
+ classNode,
15838
+ sourceFile: source
15839
+ };
15628
15840
  }
15841
+ if (hopsRemaining <= 0) return;
15842
+ const reExport = findReExport(source, className);
15843
+ if (!reExport) return;
15844
+ const resolvedFileName = tsResolveModuleName(config, compilerCtx, reExport.moduleSpecifier, source.fileName)?.resolvedModule?.resolvedFileName;
15845
+ const nextSource = resolvedFileName && readJsSourceFile(config, resolvedFileName);
15846
+ if (!nextSource) return;
15847
+ return findClassInJsModule(config, compilerCtx, nextSource, reExport.localName, hopsRemaining - 1);
15629
15848
  }
15630
15849
  /**
15631
15850
  * Filters `dedupeMembers` down to entries not already present in `staticMembers`
@@ -15733,9 +15952,11 @@ function convertDiskSourceFileDecorators(sourceFile, config, target = ts.ScriptT
15733
15952
  * @param ogModule the original module file of the class declaration
15734
15953
  * @param targetScriptTarget the script target to convert decorators with, if needed
15735
15954
  * @param barrelHopsRemaining re-export hops still allowed before giving up
15955
+ * @param originalModuleSpecifier the specifier this lookup started from, before any barrel hops
15956
+ * @param originalContainingFile the file `originalModuleSpecifier` was imported from
15736
15957
  * @returns the found class declaration, or `undefined`
15737
15958
  */
15738
- function resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration, currentSource, moduleSpecifier, className, dependentClasses, typeChecker, ogModule, targetScriptTarget = ts.ScriptTarget.ESNext, barrelHopsRemaining = 1) {
15959
+ function resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration, currentSource, moduleSpecifier, className, dependentClasses, typeChecker, ogModule, targetScriptTarget = ts.ScriptTarget.ESNext, barrelHopsRemaining = 1, originalModuleSpecifier = moduleSpecifier, originalContainingFile = currentSource.fileName) {
15739
15960
  let keepLooking = true;
15740
15961
  const foundFile = tsResolveModuleName(buildCtx.config, compilerCtx, moduleSpecifier, currentSource.fileName);
15741
15962
  if (!foundFile?.resolvedModule || !className) return;
@@ -15751,10 +15972,10 @@ function resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration,
15751
15972
  }
15752
15973
  foundSource = convertDiskSourceFileDecorators(foundSource, buildCtx.config, targetScriptTarget);
15753
15974
  }
15754
- const matchedStatement = foundSource.statements.find(matchesNamedDeclaration(className));
15975
+ const matchedStatement = findStatementByName(foundSource, className);
15755
15976
  if (!matchedStatement) {
15756
15977
  const reExport = barrelHopsRemaining > 0 ? findReExport(foundSource, className) : void 0;
15757
- if (reExport) return resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration, foundSource, reExport.moduleSpecifier, reExport.localName, dependentClasses, typeChecker, ogModule, targetScriptTarget, barrelHopsRemaining - 1);
15978
+ if (reExport) return resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration, foundSource, reExport.moduleSpecifier, reExport.localName, dependentClasses, typeChecker, ogModule, targetScriptTarget, barrelHopsRemaining - 1, originalModuleSpecifier, originalContainingFile);
15758
15979
  const err = buildWarn(buildCtx.diagnostics);
15759
15980
  err.messageText = `Unable to find "${className}" in the imported module "${moduleSpecifier}".
15760
15981
  Please import class / mixin-factory declarations directly and not via barrel files.`;
@@ -15762,16 +15983,25 @@ function resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration,
15762
15983
  return;
15763
15984
  }
15764
15985
  let foundClassDeclaration = matchedStatement ? ts.isClassDeclaration(matchedStatement) ? matchedStatement : void 0 : void 0;
15986
+ let foundClassSource = foundSource;
15765
15987
  if (!foundClassDeclaration && matchedStatement) {
15766
15988
  foundClassDeclaration = findClassWalk(matchedStatement);
15767
15989
  keepLooking = false;
15990
+ if (!foundClassDeclaration && isDtsFile(foundSource.fileName) && !isLocalModule(originalModuleSpecifier)) {
15991
+ const jsSource = resolveModuleJsEntry(buildCtx.config, compilerCtx, originalModuleSpecifier, originalContainingFile);
15992
+ const foundInJs = jsSource && findClassInJsModule(buildCtx.config, compilerCtx, jsSource, className);
15993
+ if (foundInJs) {
15994
+ foundClassDeclaration = foundInJs.classNode;
15995
+ foundClassSource = foundInJs.sourceFile;
15996
+ }
15997
+ }
15768
15998
  if (!foundClassDeclaration) warnMixinFactoryClassNotFound(buildCtx, className, classDeclaration);
15769
15999
  }
15770
16000
  if (foundClassDeclaration && !dependentClasses.some((dc) => dc.classNode === foundClassDeclaration)) {
15771
16001
  dependentClasses.push({
15772
16002
  classNode: foundClassDeclaration,
15773
- sourceFile: foundSource,
15774
- fileName: foundFile.resolvedModule.resolvedFileName
16003
+ sourceFile: foundClassSource,
16004
+ fileName: foundClassSource.fileName
15775
16005
  });
15776
16006
  if (keepLooking) buildExtendsTree(compilerCtx, foundClassDeclaration, dependentClasses, typeChecker, buildCtx, ogModule);
15777
16007
  }
@@ -16178,19 +16408,6 @@ function getExtendsClassNames(node) {
16178
16408
  if (ts.isCallExpression(expr) && expr.expression.getText() === "Mixin") return expr.arguments.filter(ts.isIdentifier).map((id) => id.text);
16179
16409
  return [];
16180
16410
  }
16181
- function findImportSpecifier(sf, localName) {
16182
- for (const stmt of sf.statements) {
16183
- if (!ts.isImportDeclaration(stmt) || !ts.isStringLiteral(stmt.moduleSpecifier)) continue;
16184
- const clause = stmt.importClause;
16185
- if (!clause) continue;
16186
- if (clause.name?.text === localName) return stmt.moduleSpecifier.text;
16187
- const bindings = clause.namedBindings;
16188
- if (bindings && ts.isNamedImports(bindings)) {
16189
- for (const el of bindings.elements) if (el.name.text === localName) return stmt.moduleSpecifier.text;
16190
- }
16191
- }
16192
- return null;
16193
- }
16194
16411
  /**
16195
16412
  * A single-file mini-program (see `convertInMemorySourceDecorators`) can
16196
16413
  * never load an imported module's own `SourceFile`, so a type that's
@@ -16214,7 +16431,7 @@ function reclassifyGlobalTypeReferences(members, declaringSf, declaringPath, res
16214
16431
  if (!references) return;
16215
16432
  Object.entries(references).forEach(([typeName, reference]) => {
16216
16433
  if (reference.location !== "global") return;
16217
- const specifier = findImportSpecifier(declaringSf, typeName);
16434
+ const specifier = findImportOrigin(declaringSf, typeName)?.moduleSpecifier;
16218
16435
  if (!specifier) return;
16219
16436
  const resolved = resolveImport(specifier, declaringPath);
16220
16437
  reference.location = "import";
@@ -16237,7 +16454,7 @@ function reclassifyGlobalTypeReferences(members, declaringSf, declaringPath, res
16237
16454
  * differ from `sf`/`path` if resolved through a re-export), or `undefined`
16238
16455
  */
16239
16456
  function findDeclarationOrReExport(sf, path, name, resolveImport) {
16240
- const direct = sf.statements.find(matchesNamedDeclaration(name));
16457
+ const direct = findStatementByName(sf, name);
16241
16458
  if (direct) return {
16242
16459
  statement: direct,
16243
16460
  sourceFile: sf,
@@ -16250,7 +16467,7 @@ function findDeclarationOrReExport(sf, path, name, resolveImport) {
16250
16467
  const { code, path: resolvedPath } = resolved;
16251
16468
  const isTs = resolvedPath.endsWith(".tsx") || resolvedPath.endsWith(".ts");
16252
16469
  const reExportSf = ts.createSourceFile(resolvedPath, code, ts.ScriptTarget.ESNext, true, isTs ? ts.ScriptKind.TSX : ts.ScriptKind.JS);
16253
- const statement = reExportSf.statements.find(matchesNamedDeclaration(reExport.localName));
16470
+ const statement = findStatementByName(reExportSf, reExport.localName);
16254
16471
  if (!statement) return void 0;
16255
16472
  return {
16256
16473
  statement,
@@ -16287,7 +16504,7 @@ function resolveAncestors(classNode, sf, path, resolveImport, visited, ancestors
16287
16504
  let foundSf = sf;
16288
16505
  let foundPath = path;
16289
16506
  let keepLooking = true;
16290
- const sameFileStatement = sf.statements.find(matchesNamedDeclaration(parentName));
16507
+ const sameFileStatement = findStatementByName(sf, parentName);
16291
16508
  if (sameFileStatement) {
16292
16509
  if (ts.isClassDeclaration(sameFileStatement)) foundClass = sameFileStatement;
16293
16510
  else {
@@ -16296,7 +16513,7 @@ function resolveAncestors(classNode, sf, path, resolveImport, visited, ancestors
16296
16513
  if (!foundClass) warnMixinFactoryClassNotFound(buildCtx, parentName, rootClassDeclaration);
16297
16514
  }
16298
16515
  } else {
16299
- const specifier = findImportSpecifier(sf, parentName);
16516
+ const specifier = findImportOrigin(sf, parentName)?.moduleSpecifier;
16300
16517
  if (!specifier) continue;
16301
16518
  const resolved = resolveImport(specifier, path);
16302
16519
  if (!resolved) continue;
@@ -21816,6 +22033,39 @@ const DEFAULT_BROWSER_TARGETS = [
21816
22033
  //#endregion
21817
22034
  //#region src/compiler/style/css-parser/parse-css.ts
21818
22035
  /**
22036
+ * Splits a selector list on top-level commas in a single pass: a comma only
22037
+ * splits when it's outside a quoted string and at paren depth 0, so commas in
22038
+ * `:is(:a,:has(:b))` or `[title="a,b"]` aren't treated as separators.
22039
+ * Backslash escapes (inside or outside a string) are skipped so they can't shift state,
22040
+ * so e.g. `[title="a\,b"]` is treated as a single selector.
22041
+ * @param selectors The selector list to split
22042
+ * @returns An array of selectors, with whitespace trimmed from each selector
22043
+ */
22044
+ const splitSelectorList = (selectors) => {
22045
+ const parts = [];
22046
+ let depth = 0;
22047
+ let quote = null;
22048
+ let start = 0;
22049
+ for (let i = 0; i < selectors.length; i++) {
22050
+ const ch = selectors[i];
22051
+ if (quote) {
22052
+ if (ch === "\\") i++;
22053
+ else if (ch === quote) quote = null;
22054
+ continue;
22055
+ }
22056
+ if (ch === "\"" || ch === "'") quote = ch;
22057
+ else if (ch === "\\") i++;
22058
+ else if (ch === "(") depth++;
22059
+ else if (ch === ")") depth = Math.max(0, depth - 1);
22060
+ else if (ch === "," && depth === 0) {
22061
+ parts.push(selectors.slice(start, i));
22062
+ start = i + 1;
22063
+ }
22064
+ }
22065
+ parts.push(selectors.slice(start));
22066
+ return parts.map((s) => s.trim());
22067
+ };
22068
+ /**
21819
22069
  * Parses CSS string input into an AST representation.
21820
22070
  * Used for minification, finding & resolving URLs and during SSR / prerendering, removing unused selectors.
21821
22071
  *
@@ -21940,11 +22190,8 @@ const parseCss = (css, filePath) => {
21940
22190
  const selector = () => {
21941
22191
  const m = match(/^([^{]+)/);
21942
22192
  if (!m) return null;
21943
- return trim(m[0]).replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, "").replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function(str) {
21944
- return str.replace(/,/g, "‌");
21945
- }).split(/\s*(?![^(]*\)),\s*/).map(function(s) {
21946
- return s.replace(/\u200C/g, ",");
21947
- });
22193
+ const cleaned = trim(m[0]).replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, "");
22194
+ return splitSelectorList(cleaned);
21948
22195
  };
21949
22196
  const declaration = () => {
21950
22197
  const pos = position();
@@ -3732,6 +3732,10 @@ interface OutputTargetSsr extends OutputTargetBase {
3732
3732
  */
3733
3733
  cjs?: boolean;
3734
3734
  }
3735
+ /**
3736
+ * Compiles the SSR hydrate app to a WASM plugin (via `extism-js`/QuickJS-ng) that can run
3737
+ * outside of Node
3738
+ */
3735
3739
  interface OutputTargetSsrWasm extends OutputTargetBase {
3736
3740
  type: 'ssr-wasm';
3737
3741
  /** Output directory. @default 'dist/ssr-wasm' */