Skip to content

Commit

Permalink
fix(di): use official metadata instead of weakmap (#1977)
Browse files Browse the repository at this point in the history
[skip ci]
  • Loading branch information
Sayan751 committed May 20, 2024
1 parent 7d44ed1 commit 9aeeffa
Show file tree
Hide file tree
Showing 18 changed files with 357 additions and 302 deletions.
26 changes: 26 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,32 @@
"cwd": "${workspaceRoot}",
"internalConsoleOptions": "openOnSessionStart"
},
{
"type": "node",
"request": "launch",
"name": "Launch mocha i18n tests",
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
"env": {
"TS_NODE_PROJECT": "${workspaceRoot}/packages/__tests__/tsconfig.json"
},
"args": [
"--ui",
"bdd",
"--reporter",
"min",
"--colors",
"--recursive",
"--timeout",
"0",
"--watch-extensions",
"js",
"--bail",
"${workspaceRoot}/packages/__tests__/dist/setup-node.js",
"${workspaceRoot}/packages/__tests__/dist/i18n/**/*.spec.js",
],
"cwd": "${workspaceRoot}",
"internalConsoleOptions": "openOnSessionStart"
},
{
"type": "node",
"request": "launch",
Expand Down
10 changes: 4 additions & 6 deletions packages/__tests__/src/3-runtime-html/attribute-pattern.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { DI, Constructable } from '@aurelia/kernel';
import { DI } from '@aurelia/kernel';
import {
attributePattern,
AttributePatternDefinition,
IAttributePattern,
ISyntaxInterpreter,
AttributePattern
} from '@aurelia/template-compiler';
import { assert } from '@aurelia/testing';

Expand Down Expand Up @@ -251,14 +250,13 @@ describe('3-runtime-html/attribute-pattern.spec.ts', function () {
container.register(ThePattern as any);
const interpreter = container.get(ISyntaxInterpreter);
const attrPattern = container.get(IAttributePattern);
const patternDefs = AttributePattern.getPatternDefinitions(attrPattern.constructor as Constructable);
interpreter.add(patternDefs);
interpreter.add(defs);

const result = interpreter.interpret(value);
if (match != null) {
assert.strictEqual(result.pattern, match);
assert.strictEqual(
patternDefs.map(d => d.pattern).includes(result.pattern),
defs.map(d => d.pattern).includes(result.pattern),
true,
`patternDefs.map(d => d.pattern).indexOf(result.pattern) >= 0\n result: ${result.pattern}`
);
Expand All @@ -268,7 +266,7 @@ describe('3-runtime-html/attribute-pattern.spec.ts', function () {
assert.deepStrictEqual(receivedParts, result.parts, `receivedParts`);
} else {
assert.strictEqual(
!patternDefs.map(d => d.pattern).includes(result.pattern),
!defs.map(d => d.pattern).includes(result.pattern),
true,
`patternDefs.map(d => d.pattern).indexOf(result.pattern) === -1`
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
CustomElement,
CustomElementDefinition,
CustomElementType,
DefaultBindingSyntax,
} from '@aurelia/runtime-html';
import {
HydrateElementInstruction,
Expand Down Expand Up @@ -367,7 +366,7 @@ describe('3-runtime-html/template-compiler.au-slot.spec.ts', function () {

function compileTemplate(template: string, ...registrations: unknown[]) {
const { container, sut } = createFixture();
container.register(DefaultBindingSyntax, ...registrations);
container.register(...registrations);

const templateDefinition = CustomElementDefinition.create({
name: 'ano',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import {
PartialCustomElementDefinition,
CustomElementDefinition,
CustomAttributeDefinition,
DefaultBindingSyntax,
} from '@aurelia/runtime-html';
import {
TemplateCompilerHooks,
Expand Down Expand Up @@ -331,7 +330,7 @@ describe('3-runtime-html/template-compiler.spec.ts', function () {
it('enables binding commands to override custom attribute', function () {
const { template, instructions } = compileWith(
`<el foo.trigger="1">`,
[DefaultBindingSyntax, CustomAttribute.define('foo', class {})]
[CustomAttribute.define('foo', class {})]
);

assertTemplateHtml(template, '<!--au*--><el></el>');
Expand Down
98 changes: 98 additions & 0 deletions packages/__tests__/src/i18n/t/translation-integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1637,4 +1637,102 @@ describe('i18n/t/translation-integration.spec.ts', function () {
}

});

// This test doubles down as the containerization of the attribute patterns; that is not global registry of patterns other than the container.
it('different aliases can be used for different apps', async function () {
@customElement({ name: 'app-one', template: `<span t="\${key11}"></span><span t.bind="key12"></span>` })
class AppOne {
public key11: string = 'key11';
public key12: string = 'key12';
}

@customElement({ name: 'app-two', template: `<span i18n="\${key21}"></span><span i18n.bind="key22"></span>` })
class AppTwo {
public key21: string = 'key21';
public key22: string = 'key22';
}

const translation = {
key11: 'a',
key12: 'b',
key21: 'c',
key22: 'd',

key13: 'e',
key14: 'f',
key23: 'g',
key24: 'h',
};

const i18nInitOptions = {
fallbackLng: 'en',
fallbackNS: 'translation',
resources: { en: { translation } },
};
let checkPoint1 = false;
let checkPoint2 = false;
async function createAppOne() {
const ctx = TestContext.create();
const host = PLATFORM.document.createElement('app-one');
const au = new Aurelia(ctx.container);
au.register(
I18nConfiguration.customize((opt) => {
opt.translationAttributeAliases = ['t'];
opt.initOptions = i18nInitOptions;
})
);
checkPoint1 = true;

while (!checkPoint2) {
await new Promise((res) => setTimeout(res, 1));
}

au.app({ host, component: AppOne });
await au.start();

return { au, host, vm: au.root.controller.viewModel as AppOne, queue: ctx.platform.domQueue };
}

async function createAppTwo() {
while (!checkPoint1) {
await new Promise((res) => setTimeout(res, 1));
}

const ctx = TestContext.create();
const host = PLATFORM.document.createElement('app-two');
const au = new Aurelia(ctx.container);
au.register(
I18nConfiguration.customize((opt) => {
opt.translationAttributeAliases = ['i18n'];
opt.initOptions = i18nInitOptions;
})
);
checkPoint2 = true;

au.app({ host, component: AppTwo });
await au.start();
return { au, host, vm: au.root.controller.viewModel as AppTwo, queue: ctx.platform.domQueue };
}

const [
{ au: au1, host: host1, vm: appOne, queue: q1 },
{ au: au2, host: host2, vm: appTwo, queue: q2 },
] = await Promise.all([createAppOne(), createAppTwo()]);

assert.html.textContent(host1, 'ab');
assert.html.textContent(host2, 'cd');

appOne.key11 = 'key13';
appOne.key12 = 'key14';
q1.flush();

appTwo.key21 = 'key23';
appTwo.key22 = 'key24';
q2.flush();

assert.html.textContent(host1, 'ef');
assert.html.textContent(host2, 'gh');

await Promise.all([au1.stop(), au2.stop()]);
});
});
90 changes: 1 addition & 89 deletions packages/__tests__/src/i18n/t/translation-renderer.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {
I18nConfiguration,
TranslationAttributePattern,
TranslationBindAttributePattern,
TranslationBindBindingCommand,
TranslationBindBindingInstruction,
TranslationBindBindingRenderer,
Expand All @@ -12,7 +10,7 @@ import {
TranslationBindInstructionType,
TranslationInstructionType,
} from '@aurelia/i18n';
import { Constructable, Registration } from '@aurelia/kernel';
import { Registration } from '@aurelia/kernel';
import { IExpressionParser } from '@aurelia/expression-parser';
import {
IObserverLocator,
Expand All @@ -27,11 +25,8 @@ import {
AttrMapper,
} from '@aurelia/runtime-html';
import {
AttributePattern,
AttributePatternDefinition,
AttrSyntax,
BindingCommand,
IAttributePattern,
IAttrMapper,
PropertyBindingInstruction,
InstructionType,
Expand All @@ -41,44 +36,6 @@ import { assert, PLATFORM, createContainer } from '@aurelia/testing';
const noopLocator = {} as unknown as IObserverLocator;

describe('i18n/t/translation-renderer.spec.ts', function () {
describe('TranslationAttributePattern', function () {
function createFixture(aliases: string[] = ['t']) {
const patterns: AttributePatternDefinition[] = [];
for (const pattern of aliases) {
patterns.push({ pattern, symbols: '' });
TranslationAttributePattern.registerAlias(pattern);
}
const container = createContainer().register(AttributePattern.define(patterns, TranslationAttributePattern));
return container.get(IAttributePattern);
}

it('registers alias attribute patterns when provided', function () {
const aliases = ['t', 'i18n'];
const sut = createFixture(aliases);

assert.instanceOf(sut, TranslationAttributePattern);

const patternDefs = [];
for (const alias of aliases) {
assert.typeOf(sut[alias], 'function');
patternDefs.push({ pattern: alias, symbols: '' });
}

assert.deepEqual(AttributePattern.getPatternDefinitions(sut.constructor as Constructable), patternDefs);
});

it('creates attribute syntax without `to` part when `T="expr"` is used', function () {
const sut = createFixture();
const pattern = 't';
const value = 'simple.key';

const actual: AttrSyntax = sut[pattern](pattern, value, []);
assert.equal(actual.command, pattern);
assert.equal(actual.rawName, pattern);
assert.equal(actual.rawValue, value);
assert.equal(actual.target, '');
});
});

describe('TranslationBindingCommand', function () {
function createFixture(aliases?: string[]) {
Expand Down Expand Up @@ -177,51 +134,6 @@ describe('i18n/t/translation-renderer.spec.ts', function () {
});
});

describe('TranslationBindAttributePattern', function () {
function createFixture(aliases: string[] = ['t']) {
const patterns: AttributePatternDefinition[] = [];
for (const pattern of aliases) {
patterns.push({ pattern: `${pattern}.bind`, symbols: '.' });
TranslationBindAttributePattern.registerAlias(pattern);
}
const container = createContainer().register(
AttributePattern.define(patterns, TranslationBindAttributePattern)
);
return container.get(IAttributePattern);
}

it('registers alias attribute patterns when provided', function () {
const aliases = ['t', 'i18n'];
const sut = createFixture(aliases);

assert.instanceOf(sut, TranslationBindAttributePattern);
assert.deepEqual(
AttributePattern.getPatternDefinitions(sut.constructor as Constructable),
aliases.reduce(
(acc, alias) => {
acc.push({ pattern: `${alias}.bind`, symbols: '.' });
return acc;
},
[]));

aliases.forEach((alias) => {
assert.typeOf(sut[`${alias}.bind`], 'function', `${alias}.bind`);
});
});

it('creates attribute syntax with `to` part when `T.bind="expr"` is used', function () {
const sut = createFixture();
const pattern = 't.bind';
const value = 'simple.key';

const actual: AttrSyntax = sut[pattern](pattern, value, ['t', 'bind']);
assert.equal(actual.command, pattern);
assert.equal(actual.rawName, pattern);
assert.equal(actual.rawValue, value);
assert.equal(actual.target, 'bind');
});
});

describe('TranslationBindBindingCommand', function () {
function createFixture(aliases?: string[]) {
aliases = aliases || [];
Expand Down
24 changes: 16 additions & 8 deletions packages/i18n/src/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IContainer, Registration } from '@aurelia/kernel';
import { AppTask } from '@aurelia/runtime-html';
import { AttributePatternDefinition, BindingCommand, AttributePattern } from '@aurelia/template-compiler';
import { AttributePatternDefinition, BindingCommand, AttributePattern, AttrSyntax } from '@aurelia/template-compiler';
import { DateFormatBindingBehavior } from './df/date-format-binding-behavior';
import { DateFormatValueConverter } from './df/date-format-value-converter';
import { I18N, I18nService } from './i18n';
Expand All @@ -17,8 +17,6 @@ import {
TranslationParametersBindingRenderer
} from './t/translation-parameters-renderer';
import {
TranslationAttributePattern,
TranslationBindAttributePattern,
TranslationBindBindingCommand,
TranslationBindBindingRenderer,
TranslationBindingCommand,
Expand All @@ -41,25 +39,35 @@ function coreComponents(options: I18nConfigurationOptions) {
const bindPatterns: AttributePatternDefinition[] = [];
const commandAliases: string[] = [];
const bindCommandAliases: string[] = [];
class TranslationAttributePattern {
[key: string]: ((rawName: string, rawValue: string, parts: readonly string[]) => AttrSyntax);
}
class TranslationBindAttributePattern {
[key: string]: ((rawName: string, rawValue: string, parts: readonly string[]) => AttrSyntax);
}
for (const alias of aliases) {
const bindAlias = `${alias}.bind`;

patterns.push({ pattern: alias, symbols: '' });
TranslationAttributePattern.registerAlias(alias);
TranslationAttributePattern.prototype[alias] = function (rawName: string, rawValue: string, _parts: readonly string[]): AttrSyntax {
return new AttrSyntax(rawName, rawValue, '', alias);
};

const bindAlias = `${alias}.bind`;
bindPatterns.push({ pattern: bindAlias, symbols: '.' });
TranslationBindAttributePattern.registerAlias(alias);
TranslationBindAttributePattern.prototype[bindAlias] = function (rawName: string, rawValue: string, parts: readonly string[]): AttrSyntax {
return new AttrSyntax(rawName, rawValue, parts[1], bindAlias);
};

if (alias !== 't') {
commandAliases.push(alias);
bindCommandAliases.push(bindAlias);
}
}
const renderers = [
AttributePattern.define(patterns, TranslationAttributePattern),
AttributePattern.create(patterns, TranslationAttributePattern),
BindingCommand.define({name:'t', aliases: commandAliases}, TranslationBindingCommand),
TranslationBindingRenderer,
AttributePattern.define(bindPatterns, TranslationBindAttributePattern),
AttributePattern.create(bindPatterns, TranslationBindAttributePattern),
BindingCommand.define({name:'t.bind', aliases: bindCommandAliases}, TranslationBindBindingCommand),
TranslationBindBindingRenderer,
TranslationParametersAttributePattern,
Expand Down
Loading

0 comments on commit 9aeeffa

Please sign in to comment.