Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge stable into main #2008

Merged
merged 8 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Embroider Changelog

## Release (2024-06-24)

@embroider/compat 3.5.5 (patch)
@embroider/core 3.4.14 (patch)
@embroider/macros 1.16.5 (patch)
@embroider/shared-internals 2.6.2 (patch)
@embroider/webpack 4.0.4 (patch)

#### :bug: Bug Fix
* `@embroider/compat`, `@embroider/test-scenarios`
* [#2005](https://github.com/embroider-build/embroider/pull/2005) unique-id helper import based on ember-source version ([@void-mAlex](https://github.com/void-mAlex))

#### :house: Internal
* `@embroider/shared-internals`
* [#2000](https://github.com/embroider-build/embroider/pull/2000) Update typescript and fix issues with Typescript 5.5 ([@mansona](https://github.com/mansona))

#### Committers: 2
- Alex ([@void-mAlex](https://github.com/void-mAlex))
- Chris Manson ([@mansona](https://github.com/mansona))

## Release (2024-06-20)

@embroider/compat 3.5.4 (patch)
Expand Down
2 changes: 1 addition & 1 deletion packages/compat/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@embroider/compat",
"version": "3.5.4",
"version": "3.5.5",
"private": false,
"description": "Backward compatibility layer for the Embroider build system.",
"repository": {
Expand Down
9 changes: 9 additions & 0 deletions packages/compat/src/compat-app-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,14 @@ export class CompatAppBuilder {
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) {
throw new Error('no ember version!');
}
return pkg.version;
}

@Memoize()
private get fastbootConfig():
| { packageJSON: PackageInfo; extraAppFiles: string[]; extraVendorFiles: string[] }
Expand Down Expand Up @@ -523,6 +531,7 @@ export class CompatAppBuilder {
) {
let opts: ResolverTransformOptions = {
appRoot: resolverConfig.appRoot,
emberVersion: this.emberVersion(),
};
transforms.push([require.resolve('./resolver-transform'), opts]);
}
Expand Down
148 changes: 80 additions & 68 deletions packages/compat/src/resolver-transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Resolver, cleanUrl, locateEmbroiderWorkingDir } from '@embroider/core';
import type CompatOptions from './options';
import type { AuditMessage, Loc } from './audit';
import { camelCase, mergeWith } from 'lodash';
import { satisfies } from 'semver';

type Env = WithJSUtils<ASTPluginEnvironment> & {
filename: string;
Expand All @@ -41,6 +42,7 @@ export interface CompatResolverOptions extends CoreResolverOptions {

export interface Options {
appRoot: string;
emberVersion: string;
}

type BuiltIn = {
Expand All @@ -49,67 +51,73 @@ type BuiltIn = {
importableModifier?: [string, string];
};

const builtInKeywords: Record<string, BuiltIn | undefined> = {
'-get-dynamic-var': {},
'-in-element': {},
'-with-dynamic-vars': {},
action: {},
array: {
importableHelper: ['array', '@ember/helper'],
},
component: {},
concat: {
importableHelper: ['concat', '@ember/helper'],
},
debugger: {},
'each-in': {},
each: {},
fn: {
importableHelper: ['fn', '@ember/helper'],
},
get: {
importableHelper: ['get', '@ember/helper'],
},
'has-block-params': {},
'has-block': {},
hasBlock: {},
hasBlockParams: {},
hash: {
importableHelper: ['hash', '@ember/helper'],
},
helper: {},
if: {},
'in-element': {},
input: {
importableComponent: ['Input', '@ember/component'],
},
let: {},
'link-to': {
importableComponent: ['LinkTo', '@ember/routing'],
},
loc: {},
log: {},
modifier: {},
mount: {},
mut: {},
on: {
importableModifier: ['on', '@ember/modifier'],
},
outlet: {},
partial: {},
'query-params': {},
readonly: {},
textarea: {
importableComponent: ['Textarea', '@ember/component'],
},
unbound: {},
'unique-id': {
importableHelper: ['uniqueId', '@ember/helper'],
},
unless: {},
with: {},
yield: {},
};
function builtInKeywords(emberVersion: string): Record<string, BuiltIn | undefined> {
const builtInKeywords: Record<string, BuiltIn | undefined> = {
'-get-dynamic-var': {},
'-in-element': {},
'-with-dynamic-vars': {},
action: {},
array: {
importableHelper: ['array', '@ember/helper'],
},
component: {},
concat: {
importableHelper: ['concat', '@ember/helper'],
},
debugger: {},
'each-in': {},
each: {},
fn: {
importableHelper: ['fn', '@ember/helper'],
},
get: {
importableHelper: ['get', '@ember/helper'],
},
'has-block-params': {},
'has-block': {},
hasBlock: {},
hasBlockParams: {},
hash: {
importableHelper: ['hash', '@ember/helper'],
},
helper: {},
if: {},
'in-element': {},
input: {
importableComponent: ['Input', '@ember/component'],
},
let: {},
'link-to': {
importableComponent: ['LinkTo', '@ember/routing'],
},
loc: {},
log: {},
modifier: {},
mount: {},
mut: {},
on: {
importableModifier: ['on', '@ember/modifier'],
},
outlet: {},
partial: {},
'query-params': {},
readonly: {},
textarea: {
importableComponent: ['Textarea', '@ember/component'],
},
unbound: {},
'unique-id': {},
unless: {},
with: {},
yield: {},
};
if (satisfies(emberVersion, '>=5.2')) {
builtInKeywords['unique-id'] = {
importableHelper: ['uniqueId', '@ember/helper'],
};
}
return builtInKeywords;
}

interface ComponentResolution {
type: 'component';
Expand Down Expand Up @@ -167,7 +175,11 @@ class TemplateResolver implements ASTPlugin {

private moduleResolver: Resolver;

constructor(private env: Env, private config: CompatResolverOptions) {
constructor(
private env: Env,
private config: CompatResolverOptions,
private builtInsForEmberVersion: ReturnType<typeof builtInKeywords>
) {
this.moduleResolver = new Resolver(config);
if ((globalThis as any).embroider_audit) {
this.auditHandler = (globalThis as any).embroider_audit;
Expand Down Expand Up @@ -403,7 +415,7 @@ class TemplateResolver implements ASTPlugin {
return null;
}

const builtIn = builtInKeywords[name];
const builtIn = this.builtInsForEmberVersion[name];

if (builtIn?.importableComponent) {
let [importedName, specifier] = builtIn.importableComponent;
Expand Down Expand Up @@ -486,7 +498,7 @@ class TemplateResolver implements ASTPlugin {
// globally-named helpers. It throws an error. So it's fine for us to
// prioritize the builtIns here without bothering to resolve a user helper
// of the same name.
const builtIn = builtInKeywords[path];
const builtIn = this.builtInsForEmberVersion[path];

if (builtIn?.importableHelper) {
let [importedName, specifier] = builtIn.importableHelper;
Expand Down Expand Up @@ -571,7 +583,7 @@ class TemplateResolver implements ASTPlugin {
return null;
}

let builtIn = builtInKeywords[path];
let builtIn = this.builtInsForEmberVersion[path];

if (builtIn?.importableComponent) {
let [importedName, specifier] = builtIn.importableComponent;
Expand Down Expand Up @@ -660,7 +672,7 @@ class TemplateResolver implements ASTPlugin {
return null;
}

const builtIn = builtInKeywords[path];
const builtIn = this.builtInsForEmberVersion[path];
if (builtIn?.importableModifier) {
let [importedName, specifier] = builtIn.importableModifier;
return {
Expand Down Expand Up @@ -963,7 +975,7 @@ class TemplateResolver implements ASTPlugin {
}

// This is the AST transform that resolves components, helpers and modifiers at build time
export default function makeResolverTransform({ appRoot }: Options) {
export default function makeResolverTransform({ appRoot, emberVersion }: Options) {
let config: CompatResolverOptions = readJSONSync(join(locateEmbroiderWorkingDir(appRoot), 'resolver.json'));
const resolverTransform: ASTPluginBuilder<Env> = env => {
if (env.strictMode) {
Expand All @@ -972,7 +984,7 @@ export default function makeResolverTransform({ appRoot }: Options) {
visitor: {},
};
}
return new TemplateResolver(env, config);
return new TemplateResolver(env, config, builtInKeywords(emberVersion));
};
(resolverTransform as any).parallelBabel = {
requireFile: __filename,
Expand Down
1 change: 1 addition & 0 deletions packages/compat/tests/audit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ describe('audit', function () {

let transformOpts: ResolverTransformOptions = {
appRoot: resolverConfig.appRoot,
emberVersion: '*', // since no packages are declared ember version can be anything so * is valid
};
let transform: Transform = [require.resolve('../src/resolver-transform'), transformOpts];

Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@embroider/core",
"version": "3.4.13",
"version": "3.4.14",
"private": false,
"description": "A build system for EmberJS applications.",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/macros/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@embroider/macros",
"version": "1.16.4",
"version": "1.16.5",
"private": false,
"description": "Standardized build-time macros for ember apps.",
"keywords": [
Expand Down
2 changes: 1 addition & 1 deletion packages/shared-internals/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@embroider/shared-internals",
"version": "2.6.1",
"version": "2.6.2",
"private": false,
"description": "Utilities shared among the other embroider packages",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/webpack/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@embroider/webpack",
"version": "4.0.3",
"version": "4.0.4",
"private": false,
"description": "Builds EmberJS apps with Webpack",
"repository": {
Expand Down
44 changes: 41 additions & 3 deletions tests/scenarios/compat-resolver-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ Scenarios.fromProject(() => new Project())
Qmodule(scenario.name, function (hooks) {
let expectTranspiled: (file: string) => ReturnType<ReturnType<ExpectFile>['transform']>;
let givenFiles: (files: Record<string, string>) => void;
let configure: (opts?: Partial<CompatResolverOptions['options']>, extraOpts?: ConfigureOpts) => Promise<void>;
let configure: (
opts?: Partial<CompatResolverOptions['options']>,
extraOpts?: ConfigureOpts,
emberVersion?: string
) => Promise<void>;

interface ConfigureOpts {
appPackageRules?: Partial<PackageRules>;
Expand All @@ -59,13 +63,17 @@ Scenarios.fromProject(() => new Project())
outputFileSync(resolve(app.dir, filename), contents, 'utf8');
}
};
configure = async function (opts?: Partial<CompatResolverOptions['options']>, extraOpts?: ConfigureOpts) {
configure = async function (
opts?: Partial<CompatResolverOptions['options']>,
extraOpts?: ConfigureOpts,
emberVersion = '4.6.0' //based on app-template package.json
) {
let etcOptions: EtcOptions = {
compilerPath: require.resolve('ember-source-latest/dist/ember-template-compiler'),
targetFormat: 'hbs',
transforms: [
...(extraOpts?.astPlugins ?? []),
[require.resolve('@embroider/compat/src/resolver-transform'), { appRoot: app.dir }],
[require.resolve('@embroider/compat/src/resolver-transform'), { appRoot: app.dir, emberVersion }],
],
};

Expand Down Expand Up @@ -1142,6 +1150,36 @@ Scenarios.fromProject(() => new Project())
`);
});

test('built-in helper unique-id is not imported when used with ember source version <5.2', async function () {
givenFiles({
'templates/application.hbs': `{{(unique-id)}}`,
});
await configure({ staticHelpers: true }, undefined, '4.6.0');
expectTranspiled('templates/application.hbs').equalsCode(`
import { precompileTemplate } from "@ember/template-compilation";
export default precompileTemplate("{{(unique-id)}}", {
moduleName: "my-app/templates/application.hbs",
});
`);
});

test('built-in helper unique-id is imported when used with ember source version >=5.2', async function () {
givenFiles({
'templates/application.hbs': `{{(unique-id)}}`,
});
await configure({ staticHelpers: true }, undefined, '5.2.0');
expectTranspiled('templates/application.hbs').equalsCode(`
import { precompileTemplate } from "@ember/template-compilation";
import { uniqueId } from "@ember/helper";
export default precompileTemplate("{{(uniqueId)}}", {
moduleName: "my-app/templates/application.hbs",
scope: () => ({
uniqueId,
}),
});
`);
});

test('built-in modifiers are ignored when used with the modifier keyword', async function () {
givenFiles({
'templates/application.hbs': `{{modifier "on"}}{{modifier "action"}}`,
Expand Down