[FEATURE ember-module-unification] Initial implementation#15368
[FEATURE ember-module-unification] Initial implementation#15368mixonic merged 1 commit intoemberjs:masterfrom
Conversation
mixonic
left a comment
There was a problem hiding this comment.
Left comments for a few minor items. The testing and feature flag stuff can be improved but the functionality here looks good at a glance. Please do cross-link to the PRs and issues elsewhere.
packages/container/lib/container.js
Outdated
| @@ -1,5 +1,5 @@ | |||
| /* globals Proxy */ | |||
| import { assert } from 'ember-debug'; | |||
| import { assert, isFeatureEnabled } from 'ember-debug'; | |||
There was a problem hiding this comment.
@rwjblue am I correct in suggesting this should be using ember/features now? Like so:
import { EMBER_MODULE_UNIFICATION } from 'ember/features';Hm I don't think we have any docs on this in CONTRIBUTING.md.
packages/container/lib/container.js
Outdated
| // with ember-module-unification, if expandLocalLookup returns something, | ||
| // pass it to the resolve without the source | ||
| fullName = expandedFullName; | ||
| delete options.source; |
There was a problem hiding this comment.
I wonder if here and at the other delete call further down we should not be mutating the passed-in object? Instead allocate a new one.
packages/container/lib/registry.js
Outdated
| return name; | ||
| } | ||
|
|
||
| return options && options.source ? `${options.source}:${name}` : name; |
There was a problem hiding this comment.
Can you wrap the test here in parens just for legibility?
return (options && options.source) ? `${options.source}:${name}` : name;|
|
||
| let container = registry.container(); | ||
|
|
||
| strictEqual(container.factoryFor('component:my-input', { source: src }).class, PrivateComponent, 'The correct factory was provided'); |
There was a problem hiding this comment.
Tests are passed assert as an argument and should use that over the global assertion methods. For example:
QUnit.test('The container can pass a source to factoryFor', function(assert) {
/* ... */
assert.strictEqual(
container.factoryFor('component:my-input', {source: src}).class, PrivateComponent,
'The correct factory was provided'
);
/* ... */In fact re-using the string 'component:my-input' instead of re-typing it would clean things up as well, as would using source instead of src as the source string variable name (then this can be {source}).
| let container = registry.container(); | ||
|
|
||
| strictEqual(container.factoryFor('component:my-input', { source: src }).class, PrivateComponent, 'The correct factory was provided'); | ||
| strictEqual(container.factoryManagerCache[`template:routes/application:component:my-input`].class, |
There was a problem hiding this comment.
Instead of asserting the contents of the private cache, can the cache be make _ private and here you can assert resolve or the method on the resolver isn't called a second time? or that it is called with a different source? Test the behavior, not the state of the cache?
7288544 to
1f40d58
Compare
packages/container/lib/container.js
Outdated
| // pass it to the resolve without the source | ||
| normalizedName = expandedFullName; | ||
| options = copy(options, true); | ||
| delete options.source; |
There was a problem hiding this comment.
Copying all properties then deleting one is not ideal. It likely causes the object to go into hash table mode which is a slower data structure.
It would be ideal to create an object with only the data we want to pass forward. Kind of silly that we are doing all this work since I think there are no other properties on options :-p
But please just make an object. Even options = {} would be better if there are no other options to copy.
There was a problem hiding this comment.
This is scenario that will never get hit in practice because it would only be executed if expandedLocalLookup is implemented and returns something. Are you suggesting that I do options = {};? I'm concerned that some upstream caller might add an addition property to options and expect it to be passed to the resolver.
There was a problem hiding this comment.
@iezer Right, options as an argument to lookup is only a contract with the lookup method. We don't document the argument as resolverOptions where it is implied the object is passed transparently.
A patch that build the object up by iterating Object.keys but skipping source would be ok, but really IMO just building the new object (in this case passing an empty object) is fine. Building a whole new object by iterating would be slow, calling the delete after copying is slow, and this is fairly performance sensitive code. Doing the fast and API-conservative thing is ok.
There was a problem hiding this comment.
Ok I'll make that change
There was a problem hiding this comment.
Talked with @dgeb, and I think this psuedo code would be correct for us to ensure we get the higher precedence for local/private lookups over global when resolving a pair of things:
`
a:/my-app/widgets/x-mark
b:/my-app/widgets/top-level/x-mark
`
let source = 'b:/my-app/widgets/top-level';
let a = di.lookup('a:x-mark', {source})
let pairedB;
if (a) {
pairedB = di.lookup('b', {source: a})
}
let b;
if (pairedB) {
b = pairedB;
} else {
b = di.lookup('b:x-mark', {source})
if (b) {
let pairedA = di.lookup('a', {source: b})
a = pairedA;
}
}
let paired = [a,b]
return paired;
1f40d58 to
bd5ad81
Compare
|
@mixonic I'm not sure I follow that example. When you call |
e7cdb3f to
14b5e36
Compare
* Pass `source` to the resolver's `resolve` method as a second argument * Update the logic for component pairs to ensure local/private resolution of a component/template are only matched with another local/private resolution.
14b5e36 to
5e0a1fd
Compare
|
I've added the commit prefix and an entry to |
To support module unification, we must modify the container and registry to pass the source as second parameter to the resolver. This PR introduces a new feature flag called
ember-module-unificationwhich does just that.I'll follow up with some PRs in the
ember-resolverandglimmer-resolverrepos, and an end-to-end example of an Ember app using module unification and private components.When the feature flag is on, this change breaks two tests related to
expandLocalLookup. I'm looking at a way to support the new functionality and make those tests pass. While I'm doing that, I'd appreciate some feedback on the overall design here.EDIT
Related PRs:
@mixonic @rwjblue