Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DEBUG } from '@glimmer/env';
import { moduleFor, RenderingTestCase, strip, runTask } from 'internal-test-helpers';
import { moduleFor, RenderingTestCase, strip, runTask, runAppend } from 'internal-test-helpers';

import { set, computed } from '@ember/object';
import { precompileTemplate } from '@ember/template-compilation';
Expand Down Expand Up @@ -87,6 +87,50 @@ moduleFor(
});
}

['@test it throws a useful assertion for an invalid dynamic component value in non-strict mode'](
assert
) {
if (!DEBUG) {
assert.expect(0);
return;
}

assert.throws(() => {
this.render('{{component this.componentName}}', {
componentName: { name: 'not-a-component' },
});
}, /The `{{component}}` helper received an invalid value\. It expects a component definition or a string component name\./);
}

['@test it throws a useful assertion for an invalid dynamic component value in strict mode'](
assert
) {
if (!DEBUG) {
assert.expect(0);
return;
}

assert.throws(() => {
this.owner.register(
'template:-top-level',
this.compile('{{component this.componentName}}', {
moduleName: '-top-level',
strictMode: true,
})
);

let attrs = {
componentName: { name: 'not-a-component' },
tagName: '',
layoutName: '-top-level',
};

this.owner.register('component:-top-level', Component.extend(attrs));
this.component = this.owner.lookup('component:-top-level');
runAppend(this.component);
}, /The `{{component}}` helper received an invalid value\. In strict mode, it expects a component definition\./);
}

['@test it has an element']() {
let instance;

Expand Down
15 changes: 15 additions & 0 deletions packages/@glimmer/runtime/lib/compiled/opcodes/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import { expect, unwrap } from '@glimmer/debug-util/lib/platform-utils';
import assert from '@glimmer/debug-util/lib/assert';
import { unwrapTemplate } from '@glimmer/debug-util/lib/template';
import { registerDestructor } from '@glimmer/destroyable';
import { hasInternalComponentManager } from '@glimmer/manager/lib/internal/api';
import { managerHasCapability } from '@glimmer/manager/lib/util/capabilities';
import { isConstRef, valueForRef } from '@glimmer/reference/lib/reference';
import { assign } from '@glimmer/util/lib/object-utils';
Expand Down Expand Up @@ -168,6 +169,20 @@ APPEND_OPCODES.add(VM_RESOLVE_DYNAMIC_COMPONENT_OP, (vm, { op1: _isStrict }) =>

vm.loadValue($t1, null); // Clear the temp register

if (DEBUG) {
assert(
component === null ||
component === undefined ||
typeof component === 'string' ||
isCurriedValue(component) ||
((typeof component === 'object' || typeof component === 'function') &&
hasInternalComponentManager(component)),
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.

I had to double check this because hasInternalComponentManager is misleadingly named -- this is what we want and would work with 3rd-party component managers

isStrict
? 'The `{{component}}` helper received an invalid value. In strict mode, it expects a component definition.'
: 'The `{{component}}` helper received an invalid value. It expects a component definition or a string component name.'
);
}

let definition: ComponentDefinition | CurriedValue;

if (typeof component === 'string') {
Expand Down
Loading