diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68355b9c1..7a6328483 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,3 +54,5 @@ jobs: - name: suite run: ${{ matrix.command }} working-directory: ${{ matrix.dir }} + env: + NODE_OPTIONS: "--max-old-space-size=8192" diff --git a/packages/compat/package.json b/packages/compat/package.json index 33e141aa7..bba0453c9 100644 --- a/packages/compat/package.json +++ b/packages/compat/package.json @@ -49,7 +49,6 @@ "broccoli-source": "^3.0.1", "chalk": "^4.1.1", "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", "fast-sourcemap-concat": "^2.1.1", "fs-extra": "^9.1.0", "fs-tree-diff": "^2.0.1", diff --git a/packages/compat/src/compat-app-builder.ts b/packages/compat/src/compat-app-builder.ts index 290d701e7..58a94db3d 100644 --- a/packages/compat/src/compat-app-builder.ts +++ b/packages/compat/src/compat-app-builder.ts @@ -1,8 +1,6 @@ -import type { Node as BroccoliNode } from 'broccoli-node-api'; -import type { OutputPaths, AddonPackage, Engine, AppMeta, TemplateColocationPluginOptions } from '@embroider/core'; +import type { AddonPackage, Engine, TemplateColocationPluginOptions } from '@embroider/core'; import { explicitRelative, - extensionsPattern, warn, jsHandlebarsCompile, templateColocationPluginPath, @@ -17,15 +15,13 @@ import type { CompatResolverOptions } from './resolver-transform'; import type { PackageRules } from './dependency-rules'; import { activePackageRules } from './dependency-rules'; import flatMap from 'lodash/flatMap'; -import mergeWith from 'lodash/mergeWith'; import cloneDeep from 'lodash/cloneDeep'; import bind from 'bind-decorator'; -import { outputJSONSync, readFileSync, readJSONSync, rmSync, writeFileSync, realpathSync } from 'fs-extra'; +import { outputJSONSync, writeFileSync, realpathSync } from 'fs-extra'; import type { Options as EtcOptions } from 'babel-plugin-ember-template-compilation'; import type { Options as ResolverTransformOptions } from './resolver-transform'; import type { Options as AdjustImportsOptions } from './babel-plugin-adjust-imports'; import { makePortable } from '@embroider/core/src/portable-babel-config'; -import { AppFiles } from '@embroider/core/src/app-files'; import type { PortableHint } from '@embroider/core/src/portable'; import { maybeNodeModuleVersion } from '@embroider/core/src/portable'; import { Memoize } from 'typescript-memoize'; @@ -33,21 +29,18 @@ import { join, dirname } from 'path'; import resolve from 'resolve'; import type ContentForConfig from './content-for-config'; import type { V1Config } from './v1-config'; -import type { Package, PackageInfo } from '@embroider/core'; -import { readdirSync, pathExistsSync } from 'fs-extra'; +import type { Package } from '@embroider/core'; +import { readdirSync } from 'fs-extra'; import type { TransformOptions } from '@babel/core'; import { MacrosConfig } from '@embroider/macros/src/node'; -import escapeRegExp from 'escape-string-regexp'; import type CompatApp from './compat-app'; -import { SyncDir } from './sync-dir'; // This exists during the actual broccoli build step. As opposed to CompatApp, // which also exists during pipeline-construction time. export class CompatAppBuilder { constructor( - private root: string, private origAppPackage: Package, private appPackageWithMovedDeps: Package, private options: Required, @@ -58,14 +51,6 @@ export class CompatAppBuilder { private synthStyles: Package ) {} - @Memoize() - private fastbootJSSrcDir() { - let target = join(this.compatApp.root, 'fastboot'); - if (pathExistsSync(target)) { - return target; - } - } - private activeAddonChildren(pkg: Package): AddonPackage[] { let result = (pkg.dependencies.filter(this.isActiveAddon) as AddonPackage[]).filter( // When looking for child addons, we want to ignore 'peerDependencies' of @@ -127,16 +112,6 @@ export class CompatAppBuilder { return ['.wasm', '.mjs', '.js', '.json', '.ts', '.hbs', '.hbs.js', '.gjs', '.gts']; } - private addEmberEntrypoints(): string[] { - let classicEntrypoints = ['index.html']; - for (let entrypoint of classicEntrypoints) { - let sourcePath = join(this.compatApp.root, entrypoint); - let rewrittenAppPath = join(this.root, entrypoint); - writeFileSync(rewrittenAppPath, readFileSync(sourcePath)); - } - return classicEntrypoints; - } - private modulePrefix(): string { return this.configTree.readConfig().modulePrefix; } @@ -145,19 +120,15 @@ export class CompatAppBuilder { return this.configTree.readConfig().podModulePrefix; } - private rootURL(): string { - return this.configTree.readConfig().rootURL; - } - @Memoize() private activeRules() { return activePackageRules(this.options.packageRules.concat(defaultAddonPackageRules()), [ - { name: this.origAppPackage.name, version: this.origAppPackage.version, root: this.root }, + { name: this.origAppPackage.name, version: this.origAppPackage.version, root: this.origAppPackage.root }, ...this.allActiveAddons.filter(p => p.meta['auto-upgraded']), ]); } - private resolverConfig(engines: AppFiles[]): CompatResolverOptions { + private resolverConfig(engines: Engine[]): CompatResolverOptions { let renamePackages = Object.assign({}, ...this.allActiveAddons.map(dep => dep.meta['renamed-packages'])); let renameModules = Object.assign({}, ...this.allActiveAddons.map(dep => dep.meta['renamed-modules'])); @@ -174,13 +145,12 @@ export class CompatAppBuilder { renamePackages, resolvableExtensions: this.resolvableExtensions(), appRoot: this.origAppPackage.root, - engines: engines.map((appFiles, index) => ({ - packageName: appFiles.engine.package.name, - // first engine is the app, which has been relocated to this.root + engines: engines.map(engine => ({ + packageName: engine.package.name, // we need to use the real path here because webpack requests always use the real path i.e. follow symlinks - root: realpathSync(index === 0 ? this.root : appFiles.engine.package.root), - fastbootFiles: appFiles.fastbootFiles, - activeAddons: [...appFiles.engine.addons] + root: realpathSync(engine.package.root), + fastbootFiles: {}, + activeAddons: [...engine.addons] .map(([addon, canResolveFromFile]) => ({ name: addon.name, root: addon.root, @@ -190,7 +160,7 @@ export class CompatAppBuilder { // that the last one wins. Our resolver's order is the order to // search, so first one wins. .reverse(), - isLazy: appFiles.engine.package.isLazyEngine(), + isLazy: engine.package.isLazyEngine(), })), amdCompatibility: this.options.amdCompatibility, @@ -208,11 +178,6 @@ export class CompatAppBuilder { return config; } - @Memoize() - private get resolvableExtensionsPattern(): RegExp { - return extensionsPattern(this.resolvableExtensions()); - } - @Memoize() private async babelConfig(resolverConfig: CompatResolverOptions) { let babel = cloneDeep(this.compatApp.babelConfig()); @@ -286,7 +251,7 @@ export class CompatAppBuilder { { absoluteRuntime: __dirname, useESModules: true, regenerator: false }, ]); - const portable = makePortable(babel, { basedir: this.root }, this.portableHints); + const portable = makePortable(babel, { basedir: this.origAppPackage.root }, this.portableHints); addCachablePlugin(portable.config); return portable; } @@ -300,15 +265,7 @@ export class CompatAppBuilder { if (!child.isEngine()) { this.findActiveAddons(child, engine, true); } - let canResolveFrom: string; - if (pkg === this.appPackageWithMovedDeps) { - // we want canResolveFrom to always be a rewritten package path, and our - // app's package is not rewritten yet here. - canResolveFrom = resolvePath(this.root, 'package.json'); - } else { - // whereas our addons are already moved - canResolveFrom = resolvePath(pkg.root, 'package.json'); - } + let canResolveFrom = resolvePath(pkg.root, 'package.json'); engine.addons.set(child, canResolveFrom); } // ensure addons are applied in the correct order, if set (via @embroider/compat/v1-addon) @@ -347,7 +304,7 @@ export class CompatAppBuilder { addons: new Map(), isApp: !current, modulePrefix: addon.name, - appRelativePath: explicitRelative(this.root, addon.root), + appRelativePath: explicitRelative(this.origAppPackage.root, addon.root), }); } } @@ -356,11 +313,6 @@ export class CompatAppBuilder { return done; } - @Memoize() - private get activeFastboot() { - return this.activeAddonChildren(this.appPackageWithMovedDeps).find(a => a.name === 'ember-cli-fastboot'); - } - private emberVersion() { let pkg = this.activeAddonChildren(this.appPackageWithMovedDeps).find(a => a.name === 'ember-source'); if (!pkg) { @@ -369,108 +321,18 @@ export class CompatAppBuilder { return pkg.version; } - @Memoize() - private get fastbootConfig(): - | { packageJSON: PackageInfo; extraAppFiles: string[]; extraVendorFiles: string[] } - | undefined { - if (this.activeFastboot) { - // this is relying on work done in stage1 by @embroider/compat/src/compat-adapters/ember-cli-fastboot.ts - let packageJSON = readJSONSync(join(this.activeFastboot.root, '_fastboot_', 'package.json')); - let { extraAppFiles, extraVendorFiles } = packageJSON['embroider-fastboot']; - delete packageJSON['embroider-fastboot']; - extraVendorFiles.push('assets/embroider_macros_fastboot_init.js'); - return { packageJSON, extraAppFiles, extraVendorFiles }; - } - } - - private engines: { engine: Engine; appSync: SyncDir; fastbootSync: SyncDir | undefined }[] | undefined; - - private updateAppJS(appJSPath: string): AppFiles[] { - if (!this.engines) { - this.engines = this.partitionEngines().map(engine => { - if (engine.isApp) { - // this is the app. We have more to do for the app than for other - // engines. - let fastbootSync: SyncDir | undefined; - if (this.activeFastboot) { - let fastbootDir = this.fastbootJSSrcDir(); - if (fastbootDir) { - fastbootSync = new SyncDir(fastbootDir, resolvePath(this.root, '_fastboot_')); - } - } - return { - engine, - appSync: new SyncDir(appJSPath, this.root), - fastbootSync, - }; - } else { - // this is not the app, so it's some other engine. Engines are already - // built by stage1 like all other addons, so we only need to observe - // their files, not doing any actual copying or building. - return { - engine, - appSync: new SyncDir(engine.package.root, undefined), - - // AFAIK, we've never supported a fastboot overlay directory in an - // engine. But if we do need that, it would go here. - fastbootSync: undefined, - }; - } - }); - } - - for (let engine of this.engines) { - engine.appSync.update(); - engine.fastbootSync?.update(); - } - - return this.engines.map( - ({ engine, appSync, fastbootSync }) => - new AppFiles( - engine, - appSync.files, - fastbootSync?.files ?? new Set(), - this.resolvableExtensionsPattern, - this.staticAppPathsPattern, - this.podModulePrefix() - ) - ); - } - - @Memoize() - private get staticAppPathsPattern(): RegExp | undefined { - if (this.options.staticAppPaths.length > 0) { - return new RegExp( - '^(?:' + this.options.staticAppPaths.map(staticAppPath => escapeRegExp(staticAppPath)).join('|') + ')(?:$|/)' - ); - } - } - - private firstBuild = true; + private engines: Engine[] | undefined; - async build(inputPaths: OutputPaths) { + async build() { // on the first build, we lock down the macros config. on subsequent builds, // this doesn't do anything anyway because it's idempotent. this.compatApp.macrosConfig.finalize(); - // on first build, clear the output directory completely - if (this.firstBuild) { - rmSync(this.root, { recursive: true, force: true }); - this.firstBuild = false; - } - - let appFiles = this.updateAppJS(inputPaths.appJS); - let assetPaths = this.addEmberEntrypoints(); - - if (this.activeFastboot) { - // when using fastboot, our own package.json needs to be in the output so fastboot can read it. - assetPaths.push('package.json'); + if (!this.engines) { + this.engines = this.partitionEngines(); } - let pkg = this.combinePackageJSON(assetPaths); - writeFileSync(join(this.root, 'package.json'), JSON.stringify(pkg, null, 2), 'utf8'); - - let resolverConfig = this.resolverConfig(appFiles); + let resolverConfig = this.resolverConfig(this.engines); let config = this.configTree.readConfig(); let contentForConfig = this.contentForTree.readContents(); @@ -483,43 +345,6 @@ export class CompatAppBuilder { this.addMacrosConfig(this.compatApp.macrosConfig.babelPluginConfig()[0]); } - private combinePackageJSON(assetPaths: string[]): object { - let pkgLayers: any[] = [this.origAppPackage.packageJSON]; - let fastbootConfig = this.fastbootConfig; - if (fastbootConfig) { - // fastboot-specific package.json output is allowed to add to our original package.json - pkgLayers.push(fastbootConfig.packageJSON); - } - - let meta: AppMeta = { - type: 'app', - version: 2, - assets: assetPaths, - babel: { - filename: '_babel_config_.js', - isParallelSafe: true, // TODO - majorVersion: this.compatApp.babelMajorVersion(), - fileFilter: '_babel_filter_.js', - }, - 'root-url': this.rootURL(), - }; - - if ((this.origAppPackage.packageJSON['ember-addon']?.version ?? 0) < 2) { - meta['auto-upgraded'] = true; - // our rewriting keeps app in app directory, etc. - pkgLayers.push({ - exports: { - './*': './app/*', - './tests/*': './tests/*', - }, - }); - } - - pkgLayers.push({ 'ember-addon': meta }); - - return combinePackageJSON(...pkgLayers); - } - private async etcOptions(resolverConfig: CompatResolverOptions): Promise { let transforms = this.compatApp.htmlbarsPlugins; @@ -545,10 +370,10 @@ export class CompatAppBuilder { let resolver = new Resolver(resolverConfig); let resolution = await resolver.nodeResolve( 'ember-source/vendor/ember/ember-template-compiler', - resolvePath(this.root, 'package.json') + resolvePath(this.origAppPackage.root, 'package.json') ); if (resolution.type !== 'real') { - throw new Error(`bug: unable to resolve ember-template-compiler from ${this.root}`); + throw new Error(`bug: unable to resolve ember-template-compiler from ${this.origAppPackage.root}`); } return { @@ -698,17 +523,6 @@ const { babelFilter } = require(${JSON.stringify(require.resolve('@embroider/cor module.exports = babelFilter({{json-stringify skipBabel}}, "{{js-string-escape appRoot}}"); `) as (params: { skipBabel: Options['skipBabel']; appRoot: string }) => string; -function combinePackageJSON(...layers: object[]) { - function custom(objValue: any, srcValue: any, key: string, _object: any, _source: any, stack: { size: number }) { - if (key === 'keywords' && stack.size === 0) { - if (Array.isArray(objValue)) { - return objValue.concat(srcValue); - } - } - } - return mergeWith({}, ...layers, custom); -} - function addCachablePlugin(babelConfig: TransformOptions) { if (Array.isArray(babelConfig.plugins) && babelConfig.plugins.length > 0) { const plugins = Object.create(null); @@ -735,9 +549,3 @@ function addCachablePlugin(babelConfig: TransformOptions) { ]); } } - -interface TreeNames { - appJS: BroccoliNode; - publicTree: BroccoliNode | undefined; - configTree: BroccoliNode; -} diff --git a/packages/compat/src/compat-app.ts b/packages/compat/src/compat-app.ts index 32459e261..7b01dda28 100644 --- a/packages/compat/src/compat-app.ts +++ b/packages/compat/src/compat-app.ts @@ -542,25 +542,6 @@ export default class CompatApp { return './' + asset; } - private preprocessJS(tree: BroccoliNode): BroccoliNode { - // we're saving all our babel compilation for the final stage packager - this.legacyEmberAppInstance.registry.remove('js', 'ember-cli-babel'); - - // auto-import is supported natively so we don't need it here - this.legacyEmberAppInstance.registry.remove('js', 'ember-auto-import-analyzer'); - - tree = buildFunnel(tree, { destDir: this.name }); - - tree = this.preprocessors.preprocessJs(tree, `/`, '/', { - annotation: 'v1-app-preprocess-js', - registry: this.legacyEmberAppInstance.registry, - }); - - tree = buildFunnel(tree, { srcDir: this.name }); - - return tree; - } - get htmlbarsPlugins(): Transform[] { let plugins = loadAstPlugins(this.legacyEmberAppInstance.registry); // even if the app was using @embroider/macros, we drop it from the config @@ -569,33 +550,6 @@ export default class CompatApp { return plugins; } - // our own appTree. Not to be confused with the one that combines the app js - // from all addons too. - private get appTree(): BroccoliNode { - return this.preprocessJS( - buildFunnel(this.legacyEmberAppInstance.trees.app, { - exclude: ['styles/**', '*.html'], - destDir: 'app', - }) - ); - } - - private get testsTree(): BroccoliNode | undefined { - if (this.shouldBuildTests && this.legacyEmberAppInstance.trees.tests) { - return this.preprocessJS( - buildFunnel(this.legacyEmberAppInstance.trees.tests, { - destDir: 'tests', - }) - ); - } - } - - private get lintTree(): BroccoliNode | undefined { - if (this.shouldBuildTests) { - return this.legacyEmberAppInstance.getLintTests(); - } - } - private get vendorTree(): BroccoliNode | undefined { return this.ensureTree(this.legacyEmberAppInstance.trees.vendor); } @@ -622,29 +576,6 @@ export default class CompatApp { return this.requireFromEmberCLI('ember-cli-preprocess-registry/preprocessors'); } - private get publicTree(): BroccoliNode | undefined { - return this.ensureTree(this.legacyEmberAppInstance.trees.public); - } - - private processAppJS(): { appJS: BroccoliNode } { - let appTree = this.appTree; - let testsTree = this.testsTree; - let lintTree = this.lintTree; - - let trees: BroccoliNode[] = []; - trees.push(appTree); - - if (testsTree) { - trees.push(testsTree); - } - if (lintTree) { - trees.push(lintTree); - } - return { - appJS: mergeTrees(trees, { overwrite: true }), - }; - } - readonly macrosConfig: MacrosConfig; constructor(readonly legacyEmberAppInstance: EmberAppInstance, _options?: Options) { @@ -674,17 +605,10 @@ export default class CompatApp { } private inTrees(prevStageTree: BroccoliNode) { - let publicTree = this.publicTree; let configTree = this.config; let contentForTree = this.contentFor; - if (this.options.extraPublicTrees.length > 0) { - publicTree = mergeTrees([publicTree, ...this.options.extraPublicTrees].filter(Boolean) as BroccoliNode[]); - } - return { - appJS: this.processAppJS().appJS, - publicTree, configTree, contentForTree, prevStageTree, @@ -708,7 +632,6 @@ export default class CompatApp { } private async instantiate( - root: string, packageCache: RewrittenPackageCache, configTree: V1Config, contentForTree: ContentForConfig @@ -717,7 +640,6 @@ export default class CompatApp { let movedAppPkg = packageCache.withRewrittenDeps(origAppPkg); let workingDir = locateEmbroiderWorkingDir(this.root); return new CompatAppBuilder( - root, origAppPkg, movedAppPkg, this.options, @@ -735,14 +657,14 @@ export default class CompatApp { let tree = () => { let inTrees = this.inTrees(prevStage.tree); - return new WaitForTrees(inTrees, this.annotation, async treePaths => { + return new WaitForTrees(inTrees, this.annotation, async _treePaths => { if (!this.active) { let { outputPath } = await prevStage.ready(); let packageCache = RewrittenPackageCache.shared('embroider', this.root); - this.active = await this.instantiate(outputPath, packageCache, inTrees.configTree, inTrees.contentForTree); + this.active = await this.instantiate(packageCache, inTrees.configTree, inTrees.contentForTree); resolve({ outputPath }); } - await this.active.build(treePaths); + await this.active.build(); }); }; diff --git a/packages/compat/src/http-audit.ts b/packages/compat/src/http-audit.ts index 062503c54..417986182 100644 --- a/packages/compat/src/http-audit.ts +++ b/packages/compat/src/http-audit.ts @@ -17,8 +17,24 @@ export async function httpAudit( return new URL(specifier, fromFile).href; } + async function fetchWithRetry(id: string, options: HTTPAuditOptions) { + let remainingTries = 5; + let backoffMS = 666; + + for (;;) { + try { + return await (options.fetch ?? globalThis.fetch)(id); + } catch (err) { + if (remainingTries-- > 0) { + backoffMS *= 1.5; + await new Promise(r => setTimeout(r, backoffMS)); + } + } + } + } + async function load(id: string): Promise<{ content: string | Buffer; type: ContentType }> { - let response = await (options.fetch ?? globalThis.fetch)(id); + let response = await fetchWithRetry(id, options); let content = await response.text(); let type: ContentType; if (response.status !== 200) { diff --git a/packages/compat/src/options.ts b/packages/compat/src/options.ts index afb86ce8c..3590b0599 100644 --- a/packages/compat/src/options.ts +++ b/packages/compat/src/options.ts @@ -1,5 +1,4 @@ import type { V1AddonConstructor } from './v1-addon'; -import type { Node } from 'broccoli-node-api'; import type { Options as CoreOptions } from '@embroider/core'; import { optionsWithDefaults as coreWithDefaults } from '@embroider/core'; import type { PackageRules } from './dependency-rules'; @@ -71,11 +70,6 @@ export default interface Options extends CoreOptions { // setting your own value here (including null to completely disable it). compatAdapters?: Map; - // optional list of additional broccoli trees that should be incorporated into - // the final build. This exists because the classic `app.toTree()` method - // accepts an optional tree argument that has the same purpose. - extraPublicTrees?: Node[]; - // Allows you to tell Embroider about otherwise dynamic dependencies within // your app and addons that it can't figure out on its own. These are combined // with the default rules that ship with Embroider. Your own rules take diff --git a/packages/compat/src/standalone-addon-build.ts b/packages/compat/src/standalone-addon-build.ts index e58ac564d..d6a2ca089 100644 --- a/packages/compat/src/standalone-addon-build.ts +++ b/packages/compat/src/standalone-addon-build.ts @@ -42,7 +42,7 @@ ${summarizePeerDepViolations(violations)} } let v1Addons = findV1Addons(appPackage); - let index = buildAddonIndex(compatApp, appPackage, v1Addons); + let index = buildAddonIndex(appPackage, v1Addons); let interiorTrees: Node[] = []; let exteriorTrees = [...v1Addons].map(pkg => { @@ -73,7 +73,7 @@ ${summarizePeerDepViolations(violations)} ]); } -function buildAddonIndex(compatApp: CompatApp, appPackage: Package, packages: Set): RewrittenPackageIndex { +function buildAddonIndex(appPackage: Package, packages: Set): RewrittenPackageIndex { let content: RewrittenPackageIndex = { packages: {}, extraResolutions: {}, @@ -87,23 +87,11 @@ function buildAddonIndex(compatApp: CompatApp, appPackage: Package, packages: Se } } - // adding an entry for the app itself to have a place in the - // rewritten-packages, even though this stage hasn't actually put it there - // yet. This directory lives outside our rewritten-pacakges directory because - // it's produced by a separate build stage, and it's easier to have them - // writing into separate directories. - content.packages[compatApp.root] = join('..', '..', '..', 'tmp', 'rewritten-app'); - let nonResolvableDeps = appPackage.nonResolvableDeps; if (nonResolvableDeps) { let extraRoots = [...nonResolvableDeps.values()].map(v => v.root); - - // the app gets extraResolutions support just like every addon does - content.extraResolutions[join('..', '..', '..', 'tmp', 'rewritten-app')] = extraRoots; - - // but it also gets extraResolutions registered against its *original* - // location, because the app is unique because stage2 needs a Package - // representing the *unmoved* app but seeing *moved* deps. + // the app gets extraResolutions registered against its *original* + // location content.extraResolutions[appPackage.root] = extraRoots; } diff --git a/packages/compat/src/sync-dir.ts b/packages/compat/src/sync-dir.ts deleted file mode 100644 index d33a5bb50..000000000 --- a/packages/compat/src/sync-dir.ts +++ /dev/null @@ -1,60 +0,0 @@ -import assertNever from 'assert-never'; -import FSTree from 'fs-tree-diff'; -import walkSync from 'walk-sync'; -import { resolve } from 'path'; -import { copySync, mkdirpSync, removeSync, rmdirSync, unlinkSync } from 'fs-extra'; - -// mirrors the changes in the src dir to the dest dir, while tracking the -// current set of files present. If dest is undefined, it only tracks the set of -// files without mirroring the changes to anywhere -export class SyncDir { - private prev: FSTree = new FSTree(); - readonly files: Set = new Set(); - - constructor(private src: string, private dest: string | undefined) {} - - update(): void { - let next = new FSTree({ - entries: walkSync.entries(this.src), - }); - for (let [operation, relativePath] of this.prev.calculatePatch(next)) { - let outputPath: string | undefined; - if (this.dest) { - outputPath = resolve(this.dest, relativePath); - } - switch (operation) { - case 'unlink': - if (outputPath) { - unlinkSync(outputPath); - } - this.files.delete(relativePath); - break; - case 'rmdir': - if (outputPath) { - rmdirSync(outputPath); - } - break; - case 'mkdir': - if (outputPath) { - mkdirpSync(outputPath); - } - break; - case 'change': - if (outputPath) { - removeSync(outputPath); - copySync(resolve(this.src, relativePath), outputPath, { dereference: true }); - } - break; - case 'create': - if (outputPath) { - copySync(resolve(this.src, relativePath), outputPath, { dereference: true }); - } - this.files.add(relativePath); - break; - default: - assertNever(operation); - } - this.prev = next; - } - } -} diff --git a/packages/test-setup/src/index.ts b/packages/test-setup/src/index.ts index a88ee633c..ac75e2f18 100644 --- a/packages/test-setup/src/index.ts +++ b/packages/test-setup/src/index.ts @@ -25,7 +25,7 @@ const embroiderDevDeps = { */ export function maybeEmbroider(app: any, opts: PipelineOptions = {}) { if (!shouldUseEmbroider(app)) { - return app.toTree(opts?.extraPublicTrees); + return app.toTree(); } // we're using `require` here on purpose because diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1a3a9a596..fc1cc294f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -250,9 +250,6 @@ importers: debug: specifier: ^4.3.2 version: 4.3.6(supports-color@8.1.1) - escape-string-regexp: - specifier: ^4.0.0 - version: 4.0.0 fast-sourcemap-concat: specifier: ^2.1.1 version: 2.1.1 @@ -1664,8 +1661,8 @@ importers: specifier: ^3.23.0 version: 3.29.4 scenario-tester: - specifier: ^4.1.0 - version: 4.1.0 + specifier: ^4.1.1 + version: 4.1.1 semver: specifier: ^7.3.8 version: 7.6.3 @@ -23187,8 +23184,8 @@ packages: yargs: 16.2.0 dev: true - /scenario-tester@4.1.0: - resolution: {integrity: sha512-kaEL+iG3snSoXRnxUNXmyoKMpcGinnmqjacy44qNFKKoJSAkrb3QbgpgUcBu/DjuA5DH9dZeEQvSq6wDa5Ql2g==} + /scenario-tester@4.1.1: + resolution: {integrity: sha512-wJ6u1TqnvRsPgLKOA8RRAePKFrduxuynE2uZo98PPuWc9BzqQuEMQmNPKS2sFbhHwgY88VstqpDSjWoxdtkONw==} hasBin: true dependencies: fixturify-project: 7.1.2 diff --git a/tests/addon-template/vite.config.mjs b/tests/addon-template/vite.config.mjs index e0d1511f4..4121500ba 100644 --- a/tests/addon-template/vite.config.mjs +++ b/tests/addon-template/vite.config.mjs @@ -12,13 +12,8 @@ import { import { resolve } from "path"; import { babel } from "@rollup/plugin-babel"; -const root = "tmp/rewritten-app"; - export default defineConfig(({ mode }) => { return { - root, - // esbuild in vite does not support decorators - esbuild: false, cacheDir: resolve("node_modules", ".vite"), resolve: { extensions: [ @@ -61,14 +56,14 @@ export default defineConfig(({ mode }) => { // If the "app" is a classic addon dummy app, the public directory is tests/dummy/public, // any public directory at the root would rather contain the assets provided by the addon, // which are managed by the assets plugin. - publicDir: resolve(process.cwd(), "tests/dummy/public"), + publicDir: "tests/dummy/public", build: { - outDir: resolve(process.cwd(), "dist"), + outDir: "dist", rollupOptions: { input: { - main: resolve(root, "index.html"), + main: "index.html", ...(shouldBuildTests(mode) - ? { tests: resolve(root, "tests/index.html") } + ? { tests: "tests/index.html" } : undefined), }, }, diff --git a/tests/app-template/ember-cli-build.js b/tests/app-template/ember-cli-build.js index ab01aed3e..ebb76e53a 100644 --- a/tests/app-template/ember-cli-build.js +++ b/tests/app-template/ember-cli-build.js @@ -6,11 +6,5 @@ const { maybeEmbroider } = require('@embroider/test-setup'); module.exports = function (defaults) { let app = new EmberApp(defaults, {}); - return maybeEmbroider(app, { - skipBabel: [ - { - package: 'qunit', - }, - ], - }); + return maybeEmbroider(app); }; diff --git a/tests/app-template/testem.js b/tests/app-template/testem.js index ed2f37124..b4b6691fd 100644 --- a/tests/app-template/testem.js +++ b/tests/app-template/testem.js @@ -1,23 +1,25 @@ 'use strict'; -module.exports = { - test_page: 'tests/index.html?hidepassed', - disable_watching: true, - launch_in_ci: ['Chrome'], - launch_in_dev: ['Chrome'], - browser_start_timeout: 120, - browser_args: { - Chrome: { - ci: [ - // --no-sandbox is needed when running Chrome inside a container - process.env.CI ? '--no-sandbox' : null, - '--headless', - '--disable-dev-shm-usage', - '--disable-software-rasterizer', - '--mute-audio', - '--remote-debugging-port=0', - '--window-size=1440,900', - ].filter(Boolean), +if (typeof module !== 'undefined') { + module.exports = { + test_page: 'tests/index.html?hidepassed', + disable_watching: true, + launch_in_ci: ['Chrome'], + launch_in_dev: ['Chrome'], + browser_start_timeout: 120, + browser_args: { + Chrome: { + ci: [ + // --no-sandbox is needed when running Chrome inside a container + process.env.CI ? '--no-sandbox' : null, + '--headless', + '--disable-dev-shm-usage', + '--disable-software-rasterizer', + '--mute-audio', + '--remote-debugging-port=0', + '--window-size=1440,900', + ].filter(Boolean), + }, }, - }, -}; + }; +} diff --git a/tests/app-template/vite.config.mjs b/tests/app-template/vite.config.mjs index 9298c30e8..283be3c43 100644 --- a/tests/app-template/vite.config.mjs +++ b/tests/app-template/vite.config.mjs @@ -12,11 +12,8 @@ import { import { resolve } from "path"; import { babel } from "@rollup/plugin-babel"; -const root = "tmp/rewritten-app"; - export default defineConfig(({ mode }) => { return { - root, cacheDir: resolve("node_modules", ".vite"), resolve: { extensions: [ @@ -50,20 +47,16 @@ export default defineConfig(({ mode }) => { }), ], optimizeDeps: optimizeDeps(), - publicDir: resolve(process.cwd(), "public"), server: { port: 4200, - watch: { - ignored: ["!**/tmp/**"], - }, }, build: { - outDir: resolve(process.cwd(), "dist"), + outDir: "dist", rollupOptions: { input: { - main: resolve(root, "index.html"), + main: "index.html", ...(shouldBuildTests(mode) - ? { tests: resolve(root, "tests/index.html") } + ? { tests: "tests/index.html" } : undefined), }, }, diff --git a/tests/scenarios/compat-app-html-attributes-test.ts b/tests/scenarios/compat-app-html-attributes-test.ts deleted file mode 100644 index ec04b0a28..000000000 --- a/tests/scenarios/compat-app-html-attributes-test.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { ExpectFile } from '@embroider/test-support/file-assertions/qunit'; -import { expectFilesAt } from '@embroider/test-support/file-assertions/qunit'; -import { appScenarios } from './scenarios'; -import QUnit from 'qunit'; -import { join } from 'path'; - -const { module: Qmodule, test } = QUnit; - -appScenarios - .map('compat-app-script-attributes', app => { - let indexHtml = app.files['index.html']; - - if (typeof indexHtml !== 'string') { - throw new Error('index.html unexpectedly missing'); - } - - // => - indexHtml = indexHtml.replace('vendor.css">', 'vendor.css" data-original-filename="vendor.css">'); - indexHtml = indexHtml.replace('app-template.css">', 'app-template.css" data-original-filename="app-template.css">'); - - // =>