Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@
"@ember/engine/instance.js": "ember-source/@ember/engine/instance.js",
"@ember/engine/lib/engine-parent.js": "ember-source/@ember/engine/lib/engine-parent.js",
"@ember/engine/lib/strict-resolver.js": "ember-source/@ember/engine/lib/strict-resolver.js",
"@ember/engine/lib/strict-resolver/cache.js": "ember-source/@ember/engine/lib/strict-resolver/cache.js",
"@ember/engine/lib/strict-resolver/string.js": "ember-source/@ember/engine/lib/strict-resolver/string.js",
"@ember/engine/parent.js": "ember-source/@ember/engine/parent.js",
"@ember/enumerable/index.js": "ember-source/@ember/enumerable/index.js",
Expand Down
32 changes: 1 addition & 31 deletions packages/@ember/engine/lib/strict-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class StrictResolver implements Resolver {
}

#plural(s: string) {
return this.#plurals.get(s) ?? pluralize(s);
return this.#plurals.get(s) ?? s + 's';
}

resolve(fullName: string): Factory<object> | object | undefined {
Expand Down Expand Up @@ -128,36 +128,6 @@ export class StrictResolver implements Resolver {
}
}

// Handle the common irregular English plurals plus the standard -s / -es
// suffix rules. Users can override any type via the `plurals` constructor
// option (including overriding these defaults).
const IRREGULAR_PLURALS: Record<string, string> = Object.freeze({
child: 'children',
man: 'men',
woman: 'women',
person: 'people',
mouse: 'mice',
tooth: 'teeth',
foot: 'feet',
});

const NEEDS_ES_SUFFIX = /(s|ss|sh|ch|x|z)$/;
const ENDS_IN_CONSONANT_Y = /([^aeiou])y$/;

function pluralize(singular: string): string {
let irregular = IRREGULAR_PLURALS[singular];
if (irregular) {
return irregular;
}
if (ENDS_IN_CONSONANT_Y.test(singular)) {
return singular.replace(ENDS_IN_CONSONANT_Y, '$1ies');
}
if (NEEDS_ES_SUFFIX.test(singular)) {
return singular + 'es';
}
return singular + 's';
}

const fileExtension = /\.\w{1,4}$/;
const leadingDotSlash = /^\.\//;

Expand Down
35 changes: 0 additions & 35 deletions packages/@ember/engine/lib/strict-resolver/cache.js

This file was deleted.

15 changes: 4 additions & 11 deletions packages/@ember/engine/lib/strict-resolver/string.js
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this now just go in the strict-resolver file?

Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
import Cache from './cache';

const STRING_DASHERIZE_REGEXP = /[ _]/g;
const STRING_DECAMELIZE_REGEXP = /([a-z\d])([A-Z])/g;

const DECAMELIZE_CACHE = new Cache(1000, (str) =>
str.replace(STRING_DECAMELIZE_REGEXP, '$1_$2').toLowerCase()
);

const STRING_DASHERIZE_CACHE = new Cache(1000, (key) =>
DECAMELIZE_CACHE.get(key).replace(STRING_DASHERIZE_REGEXP, '-')
);

export function dasherize(str) {
return STRING_DASHERIZE_CACHE.get(str);
return str
.replace(STRING_DECAMELIZE_REGEXP, '$1_$2')
.toLowerCase()
.replace(STRING_DASHERIZE_REGEXP, '-');
}
9 changes: 0 additions & 9 deletions packages/@ember/engine/tests/resolver/-setup-resolver.js

This file was deleted.

52 changes: 7 additions & 45 deletions packages/@ember/engine/tests/resolver/basic-test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { module, test } from 'qunit';
import { StrictResolver } from '@ember/engine/lib/strict-resolver';
import { setupResolver } from './-setup-resolver';

module('strict-resolver | basic', function (hooks) {
let resolver;
let modules;

hooks.beforeEach(function () {
({ resolver, modules } = setupResolver());
modules = {};
resolver = new StrictResolver(modules);
});

test('can lookup something', function (assert) {
Expand Down Expand Up @@ -356,49 +356,11 @@ module('strict-resolver | basic', function (hooks) {
assert.strictEqual(result, 'whatever', 'super-duper-config/environment is found');
});

test('default plural handles -s / -ss / -sh / -ch / -x / -z suffixes', function (assert) {
let cases = {
'./buses/red': 'bus:red',
'./brushes/broom': 'brush:broom',
'./benches/park': 'bench:park',
'./boxes/cardboard': 'box:cardboard',
'./buzzes/loud': 'buzz:loud',
'./classes/math': 'class:math',
};

for (let [modulePath, lookup] of Object.entries(cases)) {
let r = new StrictResolver({ [modulePath]: modulePath });
assert.strictEqual(r.resolve(lookup), modulePath, `${lookup} -> ${modulePath}`);
}
});

test('default plural handles consonant + y suffix (y -> ies)', function (assert) {
let r = new StrictResolver({ './categories/widgets': 'widgets-cat' });

assert.strictEqual(r.resolve('category:widgets'), 'widgets-cat');
});

test('default plural handles common irregular nouns', function (assert) {
let cases = {
'./children/alice': 'child:alice',
'./people/bob': 'person:bob',
'./men/carl': 'man:carl',
'./women/dana': 'woman:dana',
'./mice/squeaky': 'mouse:squeaky',
'./teeth/molar': 'tooth:molar',
'./feet/left': 'foot:left',
};

for (let [modulePath, lookup] of Object.entries(cases)) {
let r = new StrictResolver({ [modulePath]: modulePath });
assert.strictEqual(r.resolve(lookup), modulePath, `${lookup} -> ${modulePath}`);
}
});

test('custom plural overrides irregular default', function (assert) {
// a user who insists on "childs" should be able to opt out of the
// built-in irregular plural
let r = new StrictResolver({ './childs/alice': 'alice' }, { child: 'childs' });
test('irregular plurals must be opted into via the plurals option', function (assert) {
// Default pluralization is naive (type + 's'), matching ember-resolver's
// behavior. A consumer that wants proper English irregulars registers
// them up-front via the plurals map.
let r = new StrictResolver({ './children/alice': 'alice' }, { child: 'children' });

assert.strictEqual(r.resolve('child:alice'), 'alice');
});
Expand Down
30 changes: 28 additions & 2 deletions smoke-tests/scenarios/scenarios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,34 @@ function embroiderWebpack(project: Project) {

function embroiderVite(project: Project) {}

// Swap the v2-app-template's default app.js for a strict-resolver variant:
// no ember-resolver, no compatModules, no modulePrefix — just a `modules =
// {...import.meta.glob(...)}` literal. Making this a variant of
// v2AppScenarios means every test that runs against v2AppScenarios also
// runs against this configuration.
function strictResolver(project: Project) {
project.mergeFiles({
app: {
'app.js': `
import Application from '@ember/application';
import Router from './router';

export default class App extends Application {
modules = {
'./router': { default: Router },
...import.meta.glob('./services/**/*.{js,ts}', { eager: true }),
...import.meta.glob('./controllers/**/*.{js,ts}', { eager: true }),
...import.meta.glob('./routes/**/*.{js,ts}', { eager: true }),
...import.meta.glob('./components/**/*.{gjs,gts,js,ts}', { eager: true }),
...import.meta.glob('./helpers/**/*.{js,ts}', { eager: true }),
...import.meta.glob('./templates/**/*.{hbs,gjs,gts}', { eager: true }),
};
}
`,
},
});
}

export const v1AppScenarios = Scenarios.fromProject(() =>
Project.fromDir(dirname(require.resolve('../app-template/package.json')), { linkDevDeps: true })
).expand({
Expand All @@ -36,8 +64,6 @@ export const v2AppScenarios = Scenarios.fromProject(() =>
embroiderVite,
});

function strictResolver(project: Project) {}

export const strictAppScenarios = Scenarios.fromProject(() =>
Project.fromDir(dirname(require.resolve('../v2-app-template/package.json')), {
linkDevDeps: true,
Expand Down
Loading