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

[FEATURE dynamic-helper-and-modifier] Add dynamic helper usage #19309

Merged
merged 1 commit into from Dec 16, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 12 additions & 12 deletions package.json
Expand Up @@ -74,19 +74,19 @@
},
"devDependencies": {
"@babel/preset-env": "^7.9.5",
"@glimmer/compiler": "0.70.0",
"@glimmer/compiler": "0.71.1",
"@glimmer/env": "^0.1.7",
"@glimmer/global-context": "0.70.0",
"@glimmer/interfaces": "0.70.0",
"@glimmer/manager": "0.70.0",
"@glimmer/destroyable": "0.70.0",
"@glimmer/owner": "0.70.0",
"@glimmer/node": "0.70.0",
"@glimmer/opcode-compiler": "0.70.0",
"@glimmer/program": "0.70.0",
"@glimmer/reference": "0.70.0",
"@glimmer/runtime": "0.70.0",
"@glimmer/validator": "0.70.0",
"@glimmer/global-context": "0.71.1",
"@glimmer/interfaces": "0.71.1",
"@glimmer/manager": "0.71.1",
"@glimmer/destroyable": "0.71.1",
"@glimmer/owner": "0.71.1",
"@glimmer/node": "0.71.1",
"@glimmer/opcode-compiler": "0.71.1",
"@glimmer/program": "0.71.1",
"@glimmer/reference": "0.71.1",
"@glimmer/runtime": "0.71.1",
"@glimmer/validator": "0.71.1",
"@simple-dom/document": "^1.4.0",
"@types/qunit": "^2.9.1",
"@types/rsvp": "^4.0.3",
Expand Down
Expand Up @@ -41,10 +41,6 @@ export default class InternalManager
implements
InternalComponentManager<InternalComponentState, EmberInternalComponentConstructor>,
WithCreateInstance {
static for(definition: EmberInternalComponentConstructor, name: string): () => InternalManager {
return () => new InternalManager(definition, name);
}

constructor(private ComponentClass: EmberInternalComponentConstructor, private name: string) {}

getCapabilities(): InternalComponentCapabilities {
Expand Down
2 changes: 1 addition & 1 deletion packages/@ember/-internals/glimmer/lib/component.ts
Expand Up @@ -1128,6 +1128,6 @@ Component.reopenClass({
positionalParams: [],
});

setInternalComponentManager(() => CURLY_COMPONENT_MANAGER, Component);
setInternalComponentManager(CURLY_COMPONENT_MANAGER, Component);

export default Component;
2 changes: 1 addition & 1 deletion packages/@ember/-internals/glimmer/lib/components/input.ts
Expand Up @@ -126,7 +126,7 @@ export const InputComponent = {
},
};

setInternalComponentManager(InternalManager.for(Input, 'input'), InputComponent);
setInternalComponentManager(new InternalManager(Input, 'input'), InputComponent);
setComponentTemplate(InputTemplate, InputComponent);

Input.toString = () => '@ember/component/input';
8 changes: 4 additions & 4 deletions packages/@ember/-internals/glimmer/lib/helper.ts
Expand Up @@ -8,7 +8,7 @@ import { getDebugName, symbol } from '@ember/-internals/utils';
import { join } from '@ember/runloop';
import { DEBUG } from '@glimmer/env';
import { Arguments, Dict, HelperManager } from '@glimmer/interfaces';
import { helperCapabilities, setHelperManager } from '@glimmer/manager';
import { getInternalHelperManager, helperCapabilities, setHelperManager } from '@glimmer/manager';
import {
consumeTag,
createTag,
Expand Down Expand Up @@ -195,11 +195,11 @@ class ClassicHelperManager implements HelperManager<ClassicHelperStateBucket> {
}
}

export const CLASSIC_HELPER_MANAGER_FACTORY = (owner: Owner | undefined): ClassicHelperManager => {
setHelperManager((owner: Owner | undefined): ClassicHelperManager => {
return new ClassicHelperManager(owner);
};
}, Helper);

setHelperManager(CLASSIC_HELPER_MANAGER_FACTORY, Helper);
export const CLASSIC_HELPER_MANAGER = getInternalHelperManager(Helper);

///////////

Expand Down

This file was deleted.

Expand Up @@ -2,5 +2,5 @@ import { Helper, HelperDefinitionState } from '@glimmer/interfaces';
import { setInternalHelperManager } from '@glimmer/manager';

export function internalHelper(helper: Helper): HelperDefinitionState {
return setInternalHelperManager(() => helper, {});
return setInternalHelperManager(helper, {});
}
4 changes: 3 additions & 1 deletion packages/@ember/-internals/glimmer/lib/modifiers/action.ts
@@ -1,3 +1,4 @@
import { Owner } from '@ember/-internals/owner';
import { uuid } from '@ember/-internals/utils';
import { ActionManager, isSimpleClick } from '@ember/-internals/views';
import { assert, deprecate } from '@ember/debug';
Expand Down Expand Up @@ -204,6 +205,7 @@ export class ActionState {

class ActionModifierManager implements InternalModifierManager<ActionState, object> {
create(
_owner: Owner,
element: SimpleElement,
_state: object,
args: VMArguments,
Expand Down Expand Up @@ -312,4 +314,4 @@ class ActionModifierManager implements InternalModifierManager<ActionState, obje

const ACTION_MODIFIER_MANAGER = new ActionModifierManager();

export default setInternalModifierManager(() => ACTION_MODIFIER_MANAGER, {});
export default setInternalModifierManager(ACTION_MODIFIER_MANAGER, {});
12 changes: 4 additions & 8 deletions packages/@ember/-internals/glimmer/lib/modifiers/internal.ts
Expand Up @@ -63,23 +63,19 @@ class InternalModifierState implements Destroyable {

class InternalModifierManager
implements ModifierManager<InternalModifierState, typeof InternalModifier> {
constructor(private readonly owner: Owner) {}

create(
owner: Owner,
element: SimpleElement,
factory: typeof InternalModifier,
args: VMArguments
): InternalModifierState {
assert('element must be an HTMLElement', element instanceof HTMLElement);

let instance = new factory(this.owner, element, args.capture());
let instance = new factory(owner, element, args.capture());

registerDestructor(instance, (modifier) => modifier.remove());

return new InternalModifierState(
factory.name,
new factory(this.owner, element, args.capture())
);
return new InternalModifierState(factory.name, instance);
}

// not needed for now, but feel free to implement this
Expand All @@ -105,4 +101,4 @@ class InternalModifierManager
}
}

setInternalModifierManager((owner: Owner) => new InternalModifierManager(owner), InternalModifier);
setInternalModifierManager(new InternalModifierManager(), InternalModifier);
4 changes: 3 additions & 1 deletion packages/@ember/-internals/glimmer/lib/modifiers/on.ts
@@ -1,3 +1,4 @@
import { Owner } from '@ember/-internals/owner';
import { assert } from '@ember/debug';
import { registerDestructor } from '@glimmer/destroyable';
import { DEBUG } from '@glimmer/env';
Expand Down Expand Up @@ -322,6 +323,7 @@ class OnModifierManager implements InternalModifierManager<OnModifierState | nul
}

create(
_owner: Owner,
element: SimpleElement | Element,
_state: object,
args: VMArguments
Expand Down Expand Up @@ -387,6 +389,6 @@ const ON_MODIFIER_MANAGER = new OnModifierManager();

const on = {};

setInternalModifierManager(() => ON_MODIFIER_MANAGER, on);
setInternalModifierManager(ON_MODIFIER_MANAGER, on);

export default on;
12 changes: 5 additions & 7 deletions packages/@ember/-internals/glimmer/lib/resolver.ts
Expand Up @@ -31,13 +31,12 @@ import {
import { _WeakSet } from '@glimmer/util';
import { isCurlyManager } from './component-managers/curly';
import {
CLASSIC_HELPER_MANAGER_FACTORY,
CLASSIC_HELPER_MANAGER,
HelperFactory,
HelperInstance,
isClassicHelper,
SimpleHelper,
} from './helper';
import { default as componentAssertionHelper } from './helpers/-assert-implicit-component-helper-argument';
import { default as inElementNullCheckHelper } from './helpers/-in-element-null-check';
import { default as normalizeClassHelper } from './helpers/-normalize-class';
import { default as trackArray } from './helpers/-track-array';
Expand Down Expand Up @@ -193,7 +192,6 @@ const BUILTIN_KEYWORD_HELPERS = {
'-get-dynamic-var': internalHelper(getDynamicVar),
'-mount': mountHelper,
'-outlet': outletHelper,
'-assert-implicit-component-helper-argument': componentAssertionHelper,
'-in-el-null': inElementNullCheckHelper,
};

Expand Down Expand Up @@ -267,10 +265,10 @@ export default class ResolverImpl implements RuntimeResolver<Owner>, CompileTime
// we'll trigger an assertion
if (!CLASSIC_HELPER_MANAGER_ASSOCIATED.has(factory)) {
CLASSIC_HELPER_MANAGER_ASSOCIATED.add(factory);
setInternalHelperManager(CLASSIC_HELPER_MANAGER_FACTORY, factory);
setInternalHelperManager(CLASSIC_HELPER_MANAGER, factory);
}
} else {
setInternalHelperManager(CLASSIC_HELPER_MANAGER_FACTORY, factory);
setInternalHelperManager(CLASSIC_HELPER_MANAGER, factory);
}

return factory;
Expand Down Expand Up @@ -345,7 +343,7 @@ export default class ResolverImpl implements RuntimeResolver<Owner>, CompileTime
};
} else {
let factory = owner.factoryFor(P`component:-default`)!;
let manager = getInternalComponentManager(owner, factory.class as object);
let manager = getInternalComponentManager(factory.class as object);

definition = {
state: factory,
Expand All @@ -358,7 +356,7 @@ export default class ResolverImpl implements RuntimeResolver<Owner>, CompileTime

let factory = pair.component;
let ComponentClass = factory.class!;
let manager = getInternalComponentManager(owner, ComponentClass);
let manager = getInternalComponentManager(ComponentClass);

definition = {
state: isCurlyManager(manager) ? factory : ComponentClass,
Expand Down
Expand Up @@ -1319,20 +1319,6 @@ moduleFor(
this.assertStableRerender();
}

['@test GH#17121 implicit component invocations should not perform string lookup']() {
this.registerComponent('foo-bar', { template: 'foo-bar component' });

expectAssertion(
() =>
this.render(strip`
{{#let 'foo-bar' as |foo|}}
{{foo 1 2 3}}
{{/let}}
`),
"expected `foo` to be a contextual component but found a string. Did you mean `(component foo)`? ('-top-level' @ L1:C29) "
);
}

['@test RFC#311 invoking named args (without arguments)']() {
this.registerComponent('x-outer', { template: '{{@inner}}' });
this.registerComponent('x-inner', { template: 'inner' });
Expand Down
Expand Up @@ -19,6 +19,7 @@ import {
on,
fn,
} from '@ember/-internals/glimmer';
import GlimmerishComponent from '../../utils/glimmerish-component';

if (EMBER_STRICT_MODE) {
moduleFor(
Expand Down Expand Up @@ -89,6 +90,69 @@ if (EMBER_STRICT_MODE) {
this.assertHTML('foobar');
this.assertStableRerender();
}

'@test Can use a dynamic component definition'() {
let Foo = defineComponent({}, 'Hello, world!');
let Bar = defineComponent(
{},
'<this.Foo/>',
class extends GlimmerishComponent {
Foo = Foo;
}
);

this.registerComponent('bar', { ComponentClass: Bar });

this.render('<Bar/>');
this.assertHTML('Hello, world!');
this.assertStableRerender();
}

'@test Can use a dynamic component definition (curly)'() {
let Foo = defineComponent({}, 'Hello, world!');
let Bar = defineComponent(
{},
'{{this.Foo}}',
class extends GlimmerishComponent {
Foo = Foo;
}
);

this.registerComponent('bar', { ComponentClass: Bar });

this.render('<Bar/>');
this.assertHTML('Hello, world!');
this.assertStableRerender();
}

'@test Can use a dynamic helper definition'() {
let foo = defineSimpleHelper(() => 'Hello, world!');
let Bar = defineComponent(
{},
'{{this.foo}}',
class extends GlimmerishComponent {
foo = foo;
}
);

this.registerComponent('bar', { ComponentClass: Bar });

this.render('<Bar/>');
this.assertHTML('Hello, world!');
this.assertStableRerender();
}

'@feature(EMBER_DYNAMIC_HELPERS_AND_MODIFIERS) Can use a curried dynamic helper'() {
let foo = defineSimpleHelper((value) => value);
let Foo = defineComponent({}, '{{@value}}');
let Bar = defineComponent({ Foo, foo }, '<Foo @value={{foo "Hello, world!"}}/>');

this.registerComponent('bar', { ComponentClass: Bar });

this.render('<Bar/>');
this.assertHTML('Hello, world!');
this.assertStableRerender();
}
}
);

Expand Down
@@ -1,7 +1,13 @@
import { DEBUG } from '@glimmer/env';

import { RenderingTestCase, moduleFor, runDestroy, runTask } from 'internal-test-helpers';
import { Helper } from '@ember/-internals/glimmer';
import {
RenderingTestCase,
moduleFor,
runDestroy,
runTask,
defineSimpleHelper,
} from 'internal-test-helpers';
import { Helper, Component } from '@ember/-internals/glimmer';
import { set, tracked } from '@ember/-internals/metal';
import { backtrackingMessageFor } from '../../utils/debug-stack';

Expand Down Expand Up @@ -769,6 +775,31 @@ moduleFor(
this.render('{{hello-world}}');
}, expectedMessage);
}

'@feature(EMBER_DYNAMIC_HELPERS_AND_MODIFIERS) Can use a curried dynamic helper'() {
let val = defineSimpleHelper((value) => value);

this.registerComponent('foo', {
template: '{{@value}}',
});

this.registerComponent('bar', {
template: '<Foo @value={{helper this.val "Hello, world!"}}/>',
ComponentClass: Component.extend({ val }),
});

this.render('<Bar/>');
this.assertText('Hello, world!');
this.assertStableRerender();
}

'@feature(!EMBER_DYNAMIC_HELPERS_AND_MODIFIERS) Can use a curried dynamic helper'() {
expectAssertion(() => {
this.registerComponent('bar', {
template: '<Foo @value={{helper this.val "Hello, world!"}}/>',
});
}, /Cannot use the \(helper\) keyword yet, as it has not been implemented/);
}
}
);

Expand Down