Skip to content

Commit

Permalink
Merge pull request #19309 from emberjs/update/bump-vm-enable-dynamic-…
Browse files Browse the repository at this point in the history
…helpers-components

[FEATURE dynamic-helper-and-modifier] Add dynamic helper usage
  • Loading branch information
rwjblue committed Dec 16, 2020
2 parents 1fa40fb + f8339c3 commit e464c73
Show file tree
Hide file tree
Showing 26 changed files with 384 additions and 1,228 deletions.
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

0 comments on commit e464c73

Please sign in to comment.