diff --git a/.eslintignore b/.eslintignore index d0db42742..a981add70 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,5 +1,7 @@ /packages/core/**/*.js /packages/core/**/*.d.ts +/packages/shared-internals/**/*.js +/packages/shared-internals/**/*.d.ts /packages/compat/**/*.js /packages/compat/**/*.d.ts /packages/macros/**/*.js diff --git a/packages/compat/src/compat-adapters/ember-engines.ts b/packages/compat/src/compat-adapters/ember-engines.ts index 537d7d629..1edbf33a7 100644 --- a/packages/compat/src/compat-adapters/ember-engines.ts +++ b/packages/compat/src/compat-adapters/ember-engines.ts @@ -1,6 +1,6 @@ import V1Addon from '../v1-addon'; import Filter from 'broccoli-persistent-filter'; -import { AddonMeta } from '@embroider/core/src/metadata'; +import { AddonMeta } from '@embroider/core'; class Awk extends Filter { search: string; diff --git a/packages/core/package.json b/packages/core/package.json index 67225154c..c5c1a2602 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -29,6 +29,7 @@ "@babel/traverse": "^7.12.1", "@babel/types": "^7.12.1", "@embroider/macros": "0.37.0", + "@embroider/shared-internals": "0.37.0", "assert-never": "^1.1.0", "babel-plugin-syntax-dynamic-import": "^6.18.0", "broccoli-node-api": "^1.7.0", @@ -49,7 +50,6 @@ "pkg-up": "^3.1.0", "resolve": "^1.8.1", "resolve-package-path": "^1.2.2", - "semver": "^7.3.2", "strip-bom": "^3.0.0", "typescript-memoize": "^1.0.0-alpha.3", "walk-sync": "^1.1.3", @@ -66,7 +66,6 @@ "@types/lodash": "^4.14.116", "@types/node": "^10.5.2", "@types/resolve": "^0.0.8", - "@types/semver": "^7.3.4", "@types/strip-bom": "^3.0.0", "@types/tmp": "^0.1.0", "fixturify": "^1.2.0", diff --git a/packages/core/src/app-differ.ts b/packages/core/src/app-differ.ts index 24b5df14d..1c4e01c59 100644 --- a/packages/core/src/app-differ.ts +++ b/packages/core/src/app-differ.ts @@ -1,4 +1,4 @@ -import { V2AddonPackage } from './package'; +import { AddonPackage } from '@embroider/shared-internals'; import MultiTreeDiff, { InputTree } from './multi-tree-diff'; import walkSync from 'walk-sync'; import { join, basename, dirname } from 'path'; @@ -28,7 +28,7 @@ export default class AppDiffer { constructor( private outputPath: string, private ownAppJSDir: string, - activeAddonDescendants: V2AddonPackage[], + activeAddonDescendants: AddonPackage[], // arguments below this point are only needed in fastboot mode. Fastboot // makes this pretty messy because fastboot trees all merge into the app 🤮. fastbootEnabled = false, diff --git a/packages/core/src/app-files.ts b/packages/core/src/app-files.ts index c9b4878c6..a1c32959b 100644 --- a/packages/core/src/app-files.ts +++ b/packages/core/src/app-files.ts @@ -1,5 +1,5 @@ import { sep } from 'path'; -import Package, { V2AddonPackage } from './package'; +import { Package, AddonPackage } from '@embroider/shared-internals'; import AppDiffer from './app-differ'; export interface RouteFiles { @@ -147,7 +147,7 @@ export interface EngineSummary { // the engine's own package package: Package; // the set of active addons in the engine - addons: Set; + addons: Set; // the parent engine, if any parent: EngineSummary | undefined; // where the engine's own V2 code comes from diff --git a/packages/core/src/app.ts b/packages/core/src/app.ts index f14df5031..7baf6b6e3 100644 --- a/packages/core/src/app.ts +++ b/packages/core/src/app.ts @@ -1,7 +1,13 @@ -import { AddonMeta, AppMeta } from './metadata'; +import { + AddonMeta, + AppMeta, + Package, + AddonPackage, + explicitRelative, + extensionsPattern, +} from '@embroider/shared-internals'; import { OutputPaths } from './wait-for-trees'; import { compile } from './js-handlebars'; -import Package, { V2AddonPackage } from './package'; import resolve from 'resolve'; import { Memoize } from 'typescript-memoize'; import { copySync, ensureDirSync, readJSONSync, statSync, unlinkSync, writeFileSync } from 'fs-extra'; @@ -22,7 +28,6 @@ import { TemplateCompilerPlugins } from '.'; import { templateCompilerModule, TemplateCompilerParams } from './template-compiler'; import { Resolver } from './resolver'; import { Options as AdjustImportsOptions } from './babel-plugin-adjust-imports'; -import { explicitRelative, extensionsPattern } from './paths'; import { mangledEngineRoot } from './engine-mangler'; import { AppFiles, Engine, EngineSummary, RouteFiles } from './app-files'; import partition from 'lodash/partition'; @@ -46,10 +51,10 @@ export type EmberENV = unknown; */ export interface AppAdapter { // the set of all addon packages that are active (recursive) - readonly allActiveAddons: V2AddonPackage[]; + readonly allActiveAddons: AddonPackage[]; // the direct active addon dependencies of a given package - activeAddonChildren(pkg: Package): V2AddonPackage[]; + activeAddonChildren(pkg: Package): AddonPackage[]; // path to the directory where the app's own Javascript lives. Doesn't include // any files copied out of addons, we take care of that generically in @@ -1389,7 +1394,7 @@ module.exports = babelFilter({{{json-stringify skipBabel}}}); // meta['renamed-modules'] has mapping from classic filename to real filename. // This takes that and converts it to the inverst mapping from real import path // to classic import path. -function inverseRenamedModules(meta: V2AddonPackage['meta'], extensions: RegExp) { +function inverseRenamedModules(meta: AddonPackage['meta'], extensions: RegExp) { let renamed = meta['renamed-modules']; if (renamed) { let inverted = {} as { [name: string]: string }; diff --git a/packages/core/src/babel-plugin-adjust-imports.ts b/packages/core/src/babel-plugin-adjust-imports.ts index d5de3c172..bf69c3a01 100644 --- a/packages/core/src/babel-plugin-adjust-imports.ts +++ b/packages/core/src/babel-plugin-adjust-imports.ts @@ -23,12 +23,10 @@ import { ExportAllDeclaration, importNamespaceSpecifier, } from '@babel/types'; -import PackageCache from './package-cache'; -import Package, { V2Package } from './package'; +import { PackageCache, Package, V2Package, explicitRelative } from '@embroider/shared-internals'; import { outputFileSync } from 'fs-extra'; import { Memoize } from 'typescript-memoize'; import { compile } from './js-handlebars'; -import { explicitRelative } from './paths'; interface State { emberCLIVanillaJobs: Function[]; diff --git a/packages/core/src/build-stage.ts b/packages/core/src/build-stage.ts index 045d536dc..af5c131ff 100644 --- a/packages/core/src/build-stage.ts +++ b/packages/core/src/build-stage.ts @@ -1,5 +1,5 @@ import WaitForTrees, { OutputPaths } from './wait-for-trees'; -import PackageCache from './package-cache'; +import { PackageCache } from '@embroider/shared-internals'; import Stage from './stage'; import { Node } from 'broccoli-node-api'; import { Memoize } from 'typescript-memoize'; diff --git a/packages/core/src/engine-mangler.ts b/packages/core/src/engine-mangler.ts index 073ad6bf9..2a7a1af53 100644 --- a/packages/core/src/engine-mangler.ts +++ b/packages/core/src/engine-mangler.ts @@ -1,4 +1,4 @@ -import Package from './package'; +import { Package } from '@embroider/shared-internals'; export function mangledEngineRoot(pkg: Package) { return `${pkg.root}__engine_internal__`; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 6124cbdd2..08b8ffe9f 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -6,8 +6,6 @@ export { applyVariantToTemplateCompiler, } from './packager'; export { Resolver } from './resolver'; -export { AppMeta, AddonMeta } from './metadata'; -export { default as Package, V2AddonPackage as AddonPackage, V2AppPackage as AppPackage, V2Package } from './package'; export { default as Stage } from './stage'; export { TemplateCompiler, @@ -18,14 +16,24 @@ export { export { Asset, EmberAsset, ImplicitAssetPaths } from './asset'; export { default as Options, optionsWithDefaults } from './options'; export { default as toBroccoliPlugin } from './to-broccoli-plugin'; -export { default as PackageCache } from './package-cache'; export { default as packageName } from './package-name'; export { default as WaitForTrees, OutputPaths } from './wait-for-trees'; export { default as BuildStage } from './build-stage'; -export { getOrCreate } from './get-or-create'; export { compile as jsHandlebarsCompile } from './js-handlebars'; export { AppAdapter, AppBuilder, EmberENV } from './app'; export { todo, unsupported, warn, debug, expectWarning, throwOnWarnings } from './messages'; -export { explicitRelative, extensionsPattern } from './paths'; -export { default as babelFilter } from './babel-filter'; export { mangledEngineRoot } from './engine-mangler'; + +export { + AppMeta, + AddonMeta, + explicitRelative, + extensionsPattern, + getOrCreate, + Package, + AddonPackage, + AppPackage, + V2Package, + PackageCache, + babelFilter, +} from '@embroider/shared-internals'; diff --git a/packages/core/src/stage.ts b/packages/core/src/stage.ts index d93926638..03adcae0b 100644 --- a/packages/core/src/stage.ts +++ b/packages/core/src/stage.ts @@ -1,5 +1,5 @@ -import { Node } from 'broccoli-node-api'; -import PackageCache from './package-cache'; +import type { Node } from 'broccoli-node-api'; +import { PackageCache } from '@embroider/shared-internals'; // A build Stage is _kinda_ like a Broccoli transform, and it interoperates with // Broccoli, but it takes a different approach to how stages combine. diff --git a/packages/core/src/template-colocation-plugin.ts b/packages/core/src/template-colocation-plugin.ts index 63c6013f1..2fa3c0c1c 100644 --- a/packages/core/src/template-colocation-plugin.ts +++ b/packages/core/src/template-colocation-plugin.ts @@ -21,8 +21,8 @@ import { importSpecifier, } from '@babel/types'; import { dirname } from 'path'; -import { explicitRelative } from './paths'; -import PackageCache from './package-cache'; +import { explicitRelative } from '@embroider/shared-internals'; +import { PackageCache } from '@embroider/shared-internals'; const packageCache = PackageCache.shared('embroider-stage3'); diff --git a/packages/macros/package.json b/packages/macros/package.json index 1d9b99b71..6ce40d74d 100644 --- a/packages/macros/package.json +++ b/packages/macros/package.json @@ -24,10 +24,7 @@ "test": "jest" }, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "@embroider/core": "0.37.0", + "@embroider/shared-internals": "0.37.0", "assert-never": "^1.1.0", "ember-cli-babel": "^7.23.0", "lodash": "^4.17.10", @@ -35,6 +32,10 @@ "semver": "^7.3.2" }, "devDependencies": { + "@babel/core": "^7.12.3", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1", + "@embroider/core": "0.37.0", "@embroider/test-support": "0.36.0", "@types/babel__core": "^7.1.10", "@types/babel__generator": "^7.6.2", diff --git a/packages/macros/src/babel/babel-context.ts b/packages/macros/src/babel/babel-context.ts new file mode 100644 index 000000000..58e64da2b --- /dev/null +++ b/packages/macros/src/babel/babel-context.ts @@ -0,0 +1,7 @@ +// This type probably exists somewhere in our dependencies but I couldn't find +// it. It's the object babel passes to your plugin function. +import type { types, template } from '@babel/core'; +export interface BabelContext { + template: typeof template; + types: typeof types; +} diff --git a/packages/macros/src/babel/dependency-satisfies.ts b/packages/macros/src/babel/dependency-satisfies.ts index 21c46b214..24b39509c 100644 --- a/packages/macros/src/babel/dependency-satisfies.ts +++ b/packages/macros/src/babel/dependency-satisfies.ts @@ -1,8 +1,8 @@ -import { NodePath } from '@babel/traverse'; -import { CallExpression } from '@babel/types'; +import type { NodePath } from '@babel/traverse'; +import type { CallExpression } from '@babel/types'; import State, { sourceFile } from './state'; import { satisfies } from 'semver'; -import { PackageCache } from '@embroider/core'; +import { PackageCache } from '@embroider/shared-internals'; import error from './error'; import { assertArray } from './evaluate-json'; diff --git a/packages/macros/src/babel/each.ts b/packages/macros/src/babel/each.ts index 0cc28d575..123415618 100644 --- a/packages/macros/src/babel/each.ts +++ b/packages/macros/src/babel/each.ts @@ -1,9 +1,9 @@ -import { NodePath } from '@babel/traverse'; -import { Evaluator } from './evaluate-json'; -import { parse } from '@babel/core'; -import { CallExpression, ForOfStatement, identifier, File, ExpressionStatement, Identifier } from '@babel/types'; +import type { NodePath } from '@babel/traverse'; +import { buildLiterals, Evaluator } from './evaluate-json'; +import type { CallExpression, ForOfStatement, Identifier } from '@babel/types'; import error from './error'; import State, { cloneDeep } from './state'; +import { BabelContext } from './babel-context'; type CallEachExpression = NodePath & { get(callee: 'callee'): NodePath; @@ -24,7 +24,7 @@ export function isEachPath(path: NodePath): path is EachPath { return false; } -export function insertEach(path: EachPath, state: State) { +export function insertEach(path: EachPath, state: State, context: BabelContext) { let args = path.get('right').get('arguments'); if (args.length !== 1) { throw error(path, `the each() macro accepts exactly one argument, you passed ${args.length}`); @@ -54,7 +54,7 @@ export function insertEach(path: EachPath, state: State) { state.neededRuntimeImports.set(callee.node.name, 'each'); } else { for (let element of array.value) { - let literalElement = asLiteral(element); + let literalElement = buildLiterals(element, context); for (let target of nameRefs) { target.replaceWith(literalElement); } @@ -63,13 +63,3 @@ export function insertEach(path: EachPath, state: State) { path.remove(); } } - -function asLiteral(value: unknown | undefined) { - if (typeof value === 'undefined') { - return identifier('undefined'); - } - let ast = parse(`a(${JSON.stringify(value)})`, {}) as File; - let statement = ast.program.body[0] as ExpressionStatement; - let expression = statement.expression as CallExpression; - return expression.arguments[0]; -} diff --git a/packages/macros/src/babel/error.ts b/packages/macros/src/babel/error.ts index 8b3497d90..f23e13ea4 100644 --- a/packages/macros/src/babel/error.ts +++ b/packages/macros/src/babel/error.ts @@ -1,4 +1,4 @@ -import { NodePath } from '@babel/traverse'; +import type { NodePath } from '@babel/traverse'; export default function error(path: NodePath, message: string) { return path.buildCodeFrameError(message, MacroError); diff --git a/packages/macros/src/babel/evaluate-json.ts b/packages/macros/src/babel/evaluate-json.ts index e505ec9dd..16871d061 100644 --- a/packages/macros/src/babel/evaluate-json.ts +++ b/packages/macros/src/babel/evaluate-json.ts @@ -1,20 +1,18 @@ -import { NodePath } from '@babel/traverse'; -import { +import type { NodePath } from '@babel/traverse'; +import type { Identifier, ObjectExpression, - identifier, MemberExpression, Expression, - File, ExpressionStatement, CallExpression, OptionalMemberExpression, } from '@babel/types'; -import { parse } from '@babel/core'; import State, { owningPackage } from './state'; import dependencySatisfies from './dependency-satisfies'; import moduleExists from './module-exists'; import getConfig from './get-config'; +import { BabelContext } from './babel-context'; type OpValue = string | boolean | number; @@ -423,12 +421,11 @@ export function assertArray(input: T | T[]): T[] { return input; } -export function buildLiterals(value: unknown | undefined): Identifier | ObjectExpression { +export function buildLiterals(value: unknown | undefined, babelContext: BabelContext): Identifier | ObjectExpression { if (typeof value === 'undefined') { - return identifier('undefined'); + return babelContext.types.identifier('undefined'); } - let ast = parse(`a(${JSON.stringify(value)})`, {}) as File; - let statement = ast.program.body[0] as ExpressionStatement; + let statement = babelContext.template(`a(${JSON.stringify(value)})`)() as ExpressionStatement; let expression = statement.expression as CallExpression; return expression.arguments[0] as ObjectExpression; } diff --git a/packages/macros/src/babel/fail-build.ts b/packages/macros/src/babel/fail-build.ts index a842d8468..eca148137 100644 --- a/packages/macros/src/babel/fail-build.ts +++ b/packages/macros/src/babel/fail-build.ts @@ -1,6 +1,6 @@ -import { NodePath } from '@babel/traverse'; +import type { NodePath } from '@babel/traverse'; import { Evaluator, ConfidentResult } from './evaluate-json'; -import { CallExpression } from '@babel/types'; +import type { CallExpression } from '@babel/types'; import error from './error'; import { format } from 'util'; import State from './state'; diff --git a/packages/macros/src/babel/get-config.ts b/packages/macros/src/babel/get-config.ts index c13994b8c..7ca79f245 100644 --- a/packages/macros/src/babel/get-config.ts +++ b/packages/macros/src/babel/get-config.ts @@ -1,18 +1,11 @@ -import { NodePath } from '@babel/traverse'; -import { - identifier, - CallExpression, - callExpression, - stringLiteral, - FunctionDeclaration, - returnStatement, -} from '@babel/types'; +import type { NodePath } from '@babel/traverse'; +import type { CallExpression, FunctionDeclaration } from '@babel/types'; import State, { sourceFile, unusedNameLike } from './state'; -import { PackageCache, Package } from '@embroider/core'; +import { PackageCache, Package } from '@embroider/shared-internals'; import error from './error'; import { Evaluator, assertArray, buildLiterals, ConfidentResult } from './evaluate-json'; import assertNever from 'assert-never'; -import { isIdentifier } from '@babel/types'; +import { BabelContext } from './babel-context'; const packageCache = PackageCache.shared('embroider-stage3'); export type Mode = 'own' | 'getGlobalConfig' | 'package'; @@ -55,25 +48,25 @@ export default function getConfig(path: NodePath, state: State, // this is the imperative version that's invoked directly by the babel visitor // when we encounter getConfig. It's implemented in terms of getConfig so we can // be sure we have the same semantics. -export function insertConfig(path: NodePath, state: State, mode: Mode) { +export function insertConfig(path: NodePath, state: State, mode: Mode, context: BabelContext) { if (state.opts.mode === 'compile-time') { let config = getConfig(path, state, mode); let collapsed = collapse(path, config); - let literalResult = buildLiterals(collapsed.config); + let literalResult = buildLiterals(collapsed.config, context); collapsed.path.replaceWith(literalResult); } else { if (mode === 'getGlobalConfig') { - state.neededRuntimeImports.set(calleeName(path), 'getGlobalConfig'); + state.neededRuntimeImports.set(calleeName(path, context), 'getGlobalConfig'); } else { let pkg = getPackage(path, state, mode); let pkgRoot; if (pkg) { - pkgRoot = stringLiteral(pkg.root); + pkgRoot = context.types.stringLiteral(pkg.root); } else { - pkgRoot = identifier('undefined'); + pkgRoot = context.types.identifier('undefined'); } let name = unusedNameLike('config', path); - path.replaceWith(callExpression(identifier(name), [pkgRoot])); + path.replaceWith(context.types.callExpression(context.types.identifier(name), [pkgRoot])); state.neededRuntimeImports.set(name, 'config'); } } @@ -107,15 +100,17 @@ function collapse(path: NodePath, config: any) { } } -export function inlineRuntimeConfig(path: NodePath, state: State) { +export function inlineRuntimeConfig(path: NodePath, state: State, context: BabelContext) { path.get('body').node.body = [ - returnStatement(buildLiterals({ packages: state.opts.userConfigs, global: state.opts.globalConfig })), + context.types.returnStatement( + buildLiterals({ packages: state.opts.userConfigs, global: state.opts.globalConfig }, context) + ), ]; } -function calleeName(path: NodePath): string { +function calleeName(path: NodePath, context: BabelContext): string { let callee = path.node.callee; - if (isIdentifier(callee)) { + if (context.types.isIdentifier(callee)) { return callee.name; } throw new Error(`bug: our macros should only be invoked as identifiers`); diff --git a/packages/macros/src/babel/macro-condition.ts b/packages/macros/src/babel/macro-condition.ts index 8e6af345e..1bc413b19 100644 --- a/packages/macros/src/babel/macro-condition.ts +++ b/packages/macros/src/babel/macro-condition.ts @@ -1,6 +1,6 @@ -import { NodePath } from '@babel/traverse'; +import type { NodePath } from '@babel/traverse'; import { Evaluator } from './evaluate-json'; -import { IfStatement, ConditionalExpression, CallExpression, Identifier } from '@babel/types'; +import type { IfStatement, ConditionalExpression, CallExpression, Identifier } from '@babel/types'; import error from './error'; import State from './state'; diff --git a/packages/macros/src/babel/macros-babel-plugin.ts b/packages/macros/src/babel/macros-babel-plugin.ts index ccdc941ab..919f2f1e9 100644 --- a/packages/macros/src/babel/macros-babel-plugin.ts +++ b/packages/macros/src/babel/macros-babel-plugin.ts @@ -1,20 +1,15 @@ -import { NodePath } from '@babel/traverse'; -import { +import type { NodePath } from '@babel/traverse'; +import type { CallExpression, Identifier, - memberExpression, - identifier, IfStatement, ConditionalExpression, ForOfStatement, FunctionDeclaration, OptionalMemberExpression, - importSpecifier, - importDeclaration, Program, - stringLiteral, } from '@babel/types'; -import { PackageCache } from '@embroider/core'; +import { PackageCache } from '@embroider/shared-internals'; import State, { sourceFile, pathToRuntime } from './state'; import { inlineRuntimeConfig, insertConfig, Mode as GetConfigMode } from './get-config'; import macroCondition, { isMacroConditionPath } from './macro-condition'; @@ -23,10 +18,11 @@ import { isEachPath, insertEach } from './each'; import error from './error'; import failBuild from './fail-build'; import { Evaluator, buildLiterals } from './evaluate-json'; +import { BabelContext } from './babel-context'; const packageCache = PackageCache.shared('embroider-stage3'); -export default function main(context: unknown): unknown { +export default function main(context: BabelContext): unknown { let visitor = { Program: { enter(_: NodePath, state: State) { @@ -38,7 +34,7 @@ export default function main(context: unknown): unknown { }, exit(path: NodePath, state: State) { pruneMacroImports(path); - addRuntimeImports(path, state); + addRuntimeImports(path, state, context); for (let handler of state.jobs) { handler(); } @@ -56,7 +52,7 @@ export default function main(context: unknown): unknown { enter(path: NodePath, state: State) { if (isEachPath(path)) { state.calledIdentifiers.add(path.get('right').get('callee').node); - insertEach(path, state); + insertEach(path, state, context); } }, }, @@ -66,7 +62,7 @@ export default function main(context: unknown): unknown { if (id.isIdentifier() && id.node.name === 'initializeRuntimeMacrosConfig') { let pkg = packageCache.ownerOfFile(sourceFile(path, state)); if (pkg && pkg.name === '@embroider/macros') { - inlineRuntimeConfig(path, state); + inlineRuntimeConfig(path, state, context); } } }, @@ -109,7 +105,7 @@ export default function main(context: unknown): unknown { : false; if (mode) { state.calledIdentifiers.add(callee.node); - insertConfig(path, state, mode); + insertConfig(path, state, mode, context); return; } @@ -124,7 +120,7 @@ export default function main(context: unknown): unknown { let result = new Evaluator({ state }).evaluateMacroCall(path); if (result.confident) { state.calledIdentifiers.add(callee.node); - path.replaceWith(buildLiterals(result.value)); + path.replaceWith(buildLiterals(result.value, context)); } }, exit(path: NodePath, state: State) { @@ -138,7 +134,7 @@ export default function main(context: unknown): unknown { // For example ember-auto-import needs to do some custom transforms to enable use of dynamic template strings, // so its babel plugin needs to see and handle the importSync call first! if (callee.referencesImport('@embroider/macros', 'importSync')) { - let r = identifier('require'); + let r = context.types.identifier('require'); state.generatedRequires.add(r); callee.replaceWith(r); return; @@ -196,7 +192,7 @@ export default function main(context: unknown): unknown { // Our importSync macro has been compiled to `require`. But we want to // distinguish that from any pre-existing, user-written `require` in an // Ember addon, which should retain its *runtime* meaning. - path.replaceWith(memberExpression(identifier('window'), path.node)); + path.replaceWith(context.types.memberExpression(context.types.identifier('window'), path.node)); } }, }; @@ -210,7 +206,7 @@ export default function main(context: unknown): unknown { if (state.opts.mode === 'compile-time') { let result = new Evaluator({ state }).evaluate(path); if (result.confident) { - path.replaceWith(buildLiterals(result.value)); + path.replaceWith(buildLiterals(result.value, context)); } } }, @@ -233,14 +229,15 @@ function pruneMacroImports(path: NodePath) { } } -function addRuntimeImports(path: NodePath, state: State) { +function addRuntimeImports(path: NodePath, state: State, context: BabelContext) { + let t = context.types; if (state.neededRuntimeImports.size > 0) { path.node.body.push( - importDeclaration( + t.importDeclaration( [...state.neededRuntimeImports].map(([local, imported]) => - importSpecifier(identifier(local), identifier(imported)) + t.importSpecifier(t.identifier(local), t.identifier(imported)) ), - stringLiteral(pathToRuntime(path, state)) + t.stringLiteral(pathToRuntime(path, state)) ) ); } diff --git a/packages/macros/src/babel/module-exists.ts b/packages/macros/src/babel/module-exists.ts index 679766225..2bfa05843 100644 --- a/packages/macros/src/babel/module-exists.ts +++ b/packages/macros/src/babel/module-exists.ts @@ -1,5 +1,5 @@ -import { NodePath } from '@babel/traverse'; -import { CallExpression } from '@babel/types'; +import type { NodePath } from '@babel/traverse'; +import type { CallExpression } from '@babel/types'; import State, { sourceFile } from './state'; import error from './error'; import { assertArray } from './evaluate-json'; diff --git a/packages/macros/src/babel/state.ts b/packages/macros/src/babel/state.ts index 362240fd6..1f3310f4f 100644 --- a/packages/macros/src/babel/state.ts +++ b/packages/macros/src/babel/state.ts @@ -1,8 +1,8 @@ -import { NodePath, Node } from '@babel/traverse'; +import type { NodePath, Node } from '@babel/traverse'; import cloneDeepWith from 'lodash/cloneDeepWith'; import lodashCloneDeep from 'lodash/cloneDeep'; import { join, dirname, resolve } from 'path'; -import { explicitRelative, Package, PackageCache } from '@embroider/core'; +import { explicitRelative, Package, PackageCache } from '@embroider/shared-internals'; export default interface State { generatedRequires: Set; diff --git a/packages/macros/src/glimmer/dependency-satisfies.ts b/packages/macros/src/glimmer/dependency-satisfies.ts index 283f372d7..b2683e7a4 100644 --- a/packages/macros/src/glimmer/dependency-satisfies.ts +++ b/packages/macros/src/glimmer/dependency-satisfies.ts @@ -1,5 +1,5 @@ import { satisfies } from 'semver'; -import { PackageCache } from '@embroider/core'; +import { PackageCache } from '@embroider/shared-internals'; let packageCache = PackageCache.shared('embroider-stage3'); diff --git a/packages/macros/src/glimmer/get-config.ts b/packages/macros/src/glimmer/get-config.ts index a0d9d726f..9e8fc65fc 100644 --- a/packages/macros/src/glimmer/get-config.ts +++ b/packages/macros/src/glimmer/get-config.ts @@ -1,4 +1,4 @@ -import { PackageCache } from '@embroider/core'; +import { PackageCache } from '@embroider/shared-internals'; let packageCache = PackageCache.shared('embroider-stage3'); diff --git a/packages/macros/src/macros-config.ts b/packages/macros/src/macros-config.ts index 34e43a778..0ae9cf4f5 100644 --- a/packages/macros/src/macros-config.ts +++ b/packages/macros/src/macros-config.ts @@ -1,6 +1,6 @@ import { join } from 'path'; -import { PluginItem } from '@babel/core'; -import { PackageCache, getOrCreate } from '@embroider/core'; +import type { PluginItem } from '@babel/core'; +import { PackageCache, getOrCreate } from '@embroider/shared-internals'; import { makeFirstTransform, makeSecondTransform } from './glimmer/ast-transform'; import State from './babel/state'; diff --git a/packages/macros/src/node.ts b/packages/macros/src/node.ts index da614623c..914cdbf74 100644 --- a/packages/macros/src/node.ts +++ b/packages/macros/src/node.ts @@ -5,7 +5,7 @@ export { default as MacrosConfig, Merger } from './macros-config'; // Utility for detecting our babel and AST plugins. -import { PluginItem } from '@babel/core'; +import type { PluginItem } from '@babel/core'; export function isEmbroiderMacrosPlugin(item: PluginItem) { return ( (Array.isArray(item) && diff --git a/packages/macros/tests/babel/eval.test.ts b/packages/macros/tests/babel/eval.test.ts index 175890e99..c2c1bf855 100644 --- a/packages/macros/tests/babel/eval.test.ts +++ b/packages/macros/tests/babel/eval.test.ts @@ -2,6 +2,7 @@ import { allBabelVersions } from '@embroider/test-support'; import { Evaluator, buildLiterals } from '../../src/babel/evaluate-json'; import { VariableDeclarator, isIdentifier, Expression } from '@babel/types'; import { NodePath } from '@babel/traverse'; +import { BabelContext } from '../../src/babel/babel-context'; describe('evaluation', function () { allBabelVersions({ @@ -114,7 +115,7 @@ function isNodePathPresent(path: NodePath): path return path.node != null; } -function testEval() { +function testEval(babelContext: BabelContext) { let visitor = { VariableDeclarator: { exit(path: NodePath) { @@ -129,7 +130,7 @@ function testEval() { }); let result = evaluator.evaluate(value); if (result.confident) { - value.replaceWith(buildLiterals(result.value)); + value.replaceWith(buildLiterals(result.value, babelContext)); } } }, diff --git a/packages/macros/tests/babel/helpers.ts b/packages/macros/tests/babel/helpers.ts index 6eb012cb3..38d191b26 100644 --- a/packages/macros/tests/babel/helpers.ts +++ b/packages/macros/tests/babel/helpers.ts @@ -3,7 +3,7 @@ import { join, dirname } from 'path'; import { allBabelVersions as allBabel, Project, runDefault, Transform, toCJS } from '@embroider/test-support'; import { readFileSync } from 'fs'; import { Script, createContext } from 'vm'; -import { explicitRelative } from '@embroider/core'; +import { explicitRelative } from '@embroider/shared-internals'; export { runDefault, Project }; diff --git a/packages/shared-internals/.gitignore b/packages/shared-internals/.gitignore new file mode 100644 index 000000000..ee7918ebe --- /dev/null +++ b/packages/shared-internals/.gitignore @@ -0,0 +1,7 @@ +/node_modules +/src/**/*.js +/src/**/*.d.ts +/src/**/*.map +/tests/**/*.js +/tests/**/*.d.ts +/tests/**/*.map diff --git a/packages/shared-internals/jest.config.js b/packages/shared-internals/jest.config.js new file mode 100644 index 000000000..7f4f45dca --- /dev/null +++ b/packages/shared-internals/jest.config.js @@ -0,0 +1,6 @@ +module.exports = { + testEnvironment: 'node', + testMatch: [ + '/tests/**/*.test.js', + ], +}; diff --git a/packages/shared-internals/package.json b/packages/shared-internals/package.json new file mode 100644 index 000000000..8f67fee0a --- /dev/null +++ b/packages/shared-internals/package.json @@ -0,0 +1,44 @@ +{ + "name": "@embroider/shared-internals", + "version": "0.37.0", + "private": false, + "description": "Utilities shared among the other embroider packages", + "repository": { + "type": "git", + "url": "https://github.com/embroider-build/embroider.git", + "directory": "packages/shared-internals" + }, + "license": "MIT", + "author": "Edward Faulkner", + "main": "src/index.js", + "files": [ + "src/**/*.js", + "src/**/*.d.ts", + "src/**/*.js.map" + ], + "scripts": { + "prepare": "tsc", + "test": "jest" + }, + "dependencies": { + "resolve-package-path": "^1.2.2", + "pkg-up": "^3.1.0", + "typescript-memoize": "^1.0.0-alpha.3", + "fs-extra": "^7.0.1", + "lodash": "^4.17.10", + "semver": "^7.3.2" + }, + "devDependencies": { + "@types/semver": "^7.3.4", + "@types/tmp": "^0.1.0", + "fixturify": "^1.2.0", + "tmp": "^0.1.0", + "typescript": "~4.0.0" + }, + "engines": { + "node": "10.* || 12.* || >= 14" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/packages/core/src/babel-filter.ts b/packages/shared-internals/src/babel-filter.ts similarity index 91% rename from packages/core/src/babel-filter.ts rename to packages/shared-internals/src/babel-filter.ts index 18f6fcc58..5cf4cb78b 100644 --- a/packages/core/src/babel-filter.ts +++ b/packages/shared-internals/src/babel-filter.ts @@ -1,8 +1,7 @@ import PackageCache from './package-cache'; -import Options from './options'; import semver from 'semver'; -export default function babelFilter(skipBabel: Required['skipBabel']) { +export default function babelFilter(skipBabel: { package: string; semverRange?: string }[]) { return function shouldTranspileFile(filename: string) { if (!babelCanHandle(filename)) { // quick exit for non JS extensions diff --git a/packages/core/src/get-or-create.ts b/packages/shared-internals/src/get-or-create.ts similarity index 100% rename from packages/core/src/get-or-create.ts rename to packages/shared-internals/src/get-or-create.ts diff --git a/packages/shared-internals/src/index.ts b/packages/shared-internals/src/index.ts new file mode 100644 index 000000000..3cca3b161 --- /dev/null +++ b/packages/shared-internals/src/index.ts @@ -0,0 +1,6 @@ +export { AppMeta, AddonMeta } from './metadata'; +export { explicitRelative, extensionsPattern } from './paths'; +export { getOrCreate } from './get-or-create'; +export { default as Package, V2AddonPackage as AddonPackage, V2AppPackage as AppPackage, V2Package } from './package'; +export { default as PackageCache } from './package-cache'; +export { default as babelFilter } from './babel-filter'; diff --git a/packages/core/src/metadata.ts b/packages/shared-internals/src/metadata.ts similarity index 100% rename from packages/core/src/metadata.ts rename to packages/shared-internals/src/metadata.ts diff --git a/packages/core/src/package-cache.ts b/packages/shared-internals/src/package-cache.ts similarity index 100% rename from packages/core/src/package-cache.ts rename to packages/shared-internals/src/package-cache.ts diff --git a/packages/core/src/package.ts b/packages/shared-internals/src/package.ts similarity index 100% rename from packages/core/src/package.ts rename to packages/shared-internals/src/package.ts diff --git a/packages/core/src/paths.ts b/packages/shared-internals/src/paths.ts similarity index 100% rename from packages/core/src/paths.ts rename to packages/shared-internals/src/paths.ts diff --git a/packages/core/tests/package.test.ts b/packages/shared-internals/tests/package.test.ts similarity index 100% rename from packages/core/tests/package.test.ts rename to packages/shared-internals/tests/package.test.ts diff --git a/packages/core/tests/path.test.ts b/packages/shared-internals/tests/path.test.ts similarity index 100% rename from packages/core/tests/path.test.ts rename to packages/shared-internals/tests/path.test.ts