diff --git a/lib/ast-nested-transform.js b/lib/ast-nested-transform.js
index e51ac63..3b97f1a 100644
--- a/lib/ast-nested-transform.js
+++ b/lib/ast-nested-transform.js
@@ -12,6 +12,9 @@ class AngleBracketPolyfill {
transform(ast) {
let b = this.syntax.builders;
+ // in order to debug in https://https://astexplorer.net/#/gist/0590eb883edfcd163b183514df4cc717
+ // **** copy from here ****
+
function dasherize(string) {
return string.replace(/[A-Z]/g, function(char, index) {
if (index === 0 || !ALPHA.test(string[index - 1])) {
@@ -22,58 +25,57 @@ class AngleBracketPolyfill {
});
}
- function replaceNestedComponents(string) {
- return string.replace('::', '/');
- }
+ let rootProgram;
+ let letBlock;
+ let yieldedComponents = new Map();
- function getBlockParamName(node) {
- let unnestedName = node.tag.replace('::', '');
- let possibleName = unnestedName;
-
- const nestedNames = node.children
- .map(child => {
- switch (child.type) {
- case 'ElementNode':
- return child.tag;
- case 'MustacheStatement':
- return child.path.original;
- default:
- break;
- }
- })
- .filter(child => child);
-
- let adder = 0;
- while (nestedNames.indexOf(possibleName) !== -1) {
- adder++;
- possibleName = `${unnestedName}${adder}`;
+ function ensureLetWrapper() {
+ if (!letBlock) {
+ letBlock = b.block('let', [], b.hash([]), b.program(rootProgram.body), null, null);
+ rootProgram.body = [letBlock];
}
-
- return possibleName;
}
- function wrapAngeBrackedComponentWithLetHelper(node) {
- let tag = node.tag;
+ let counter = 0;
+ function localNameForYieldedComponent(tag) {
+ let localName = yieldedComponents.get(tag);
+ if (!localName) {
+ localName = tag.replace(/::/g, '') + '_ANGLE_' + counter++;
+ let transformedPath = dasherize(tag.replace(/::/g, '/'));
- let params = [
- b.sexpr(b.path('component'), [b.string(dasherize(replaceNestedComponents(tag)))]),
- ];
+ let positionalArg = b.sexpr(b.path('component'), [b.string(transformedPath)]);
+ letBlock.params.push(positionalArg);
+ letBlock.program.blockParams.push(localName);
- node.tag = getBlockParamName(node);
- let program = b.program([node], [getBlockParamName(node)]);
- program.__ignore = true;
+ yieldedComponents.set(tag, localName);
+ }
- return b.block('let', params, b.hash([]), program, null, null);
+ return localName;
}
let visitor = {
+ // supports glimmer-vm@0.39
+ Template(node) {
+ rootProgram = node;
+ },
+
+ // supports glimmer-vm < 0.39
+ Program(node) {
+ // on older ember versions `Program` is used for both the "wrapping
+ // template" and for each block
+ if (!rootProgram) {
+ rootProgram = node;
+ }
+ },
+
ElementNode(node) {
let tag = node.tag;
- if (tag.indexOf('::') !== -1 && tag.charAt(0) === tag.charAt(0).toUpperCase()) {
- let newNode = wrapAngeBrackedComponentWithLetHelper(node);
+ if (tag.indexOf('::') !== -1) {
+ ensureLetWrapper();
- return newNode;
+ let localName = localNameForYieldedComponent(tag);
+ node.tag = localName;
}
},
};
diff --git a/lib/ast-transform.js b/lib/ast-transform.js
index f50676f..4d32caa 100644
--- a/lib/ast-transform.js
+++ b/lib/ast-transform.js
@@ -28,7 +28,7 @@ class AngleBracketPolyfill {
}
function replaceNestedComponents(string) {
- return string.replace('::', '/');
+ return string.replace(/::/g, '/');
}
function isSimple(mustache) {
diff --git a/tests/integration/components/angle-bracket-invocation-test.js b/tests/integration/components/angle-bracket-invocation-test.js
index 0385b1c..ed64924 100644
--- a/tests/integration/components/angle-bracket-invocation-test.js
+++ b/tests/integration/components/angle-bracket-invocation-test.js
@@ -192,6 +192,19 @@ module('Integration | Component | angle-bracket-invocation', function(hooks) {
assert.dom('[data-foo="bar"]').exists();
});
+ test('nested paths do not conflict with non-nested paths with similar names', async function(assert) {
+ this.owner.register('template:components/foo/bar', hbs`hi rwjblue!`);
+ this.owner.register('template:components/foo-bar', hbs`hi rtablada!`);
+
+ await render(hbs`
+
+
+ `);
+
+ assert.dom('[data-foo="bar"]').hasText('hi rwjblue!');
+ assert.dom('[data-foo="baz"]').hasText('hi rtablada!');
+ });
+
test('invoke nested path', async function(assert) {
this.owner.register('template:components/foo/bar', hbs`hi rwjblue!`);
@@ -202,6 +215,16 @@ module('Integration | Component | angle-bracket-invocation', function(hooks) {
assert.dom('[data-foo="bar"]').exists();
});
+ test('invoke deeply nested path', async function(assert) {
+ this.owner.register('template:components/foo/bar/baz/qux', hbs`hi rwjblue!`);
+
+ await render(hbs`
+
+ `);
+
+ assert.dom('[data-foo="bar"]').exists();
+ });
+
test('invoke dynamic - path', async function(assert) {
this.owner.register('service:elsewhere', Service.extend());
this.owner.register(