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 ember-htmlbars-local-lookup] #12673

Merged
merged 1 commit into from
Dec 4, 2015
Merged

Conversation

rwjblue
Copy link
Member

@rwjblue rwjblue commented Dec 3, 2015

Implements local lookup concepts. This new concept is primarily used from the template layer in this initial implementation, but the source option is usable generally.

There are a couple main concepts being added here:

  • Expanding a type:name relative to a given source type:name into a fully qualified type:name (that includes the source info).
  • Expose the currently rendering template's meta information on the RenderEnv.
  • Adding a second layer of lookups in all places that components or helpers are resolved.

expandLocalLookup

We use the expandLocalLookup function on the resolver (when present) to take both the source and target full names and return a new fully qualified full name. By default the resolver will not have an expandLocalLookup function, but an example implementation exists in the ember-htmlbars/tests/integration/local-lookup-test module here.

meta

As of Ember 1.12, metadata has been appended to every template to allow better customization of things like deprecation messages and template compilation errors.

With the changes in this commit that metadata is exposed on the RenderEnv which is present through the various internal glimmer engine hooks (and provides us the source information needed for the local lookups added here).

local + global lookups

The various places that are responsible for looking helpers and components up have been updated to do two layers of lookups. Once for the current global style lookups, and a second for lookups relative to the invocation template.


I have created a small demo twiddle: here

The builds from this PR can also be located here and available from bower at:

"ember": "rwjblue/ember#local-lookup",

@Gaurav0
Copy link
Contributor

Gaurav0 commented Dec 3, 2015

Is there an RFC for this feature? Also, how would you access a nested component from outside local context?

Awesome twiddle, btw!

@rwjblue
Copy link
Member Author

rwjblue commented Dec 3, 2015

@Gaurav0:

Is there an RFC for this feature?

No there is no corresponding RFC for this.

How would you access a nested component from outside local context?

This isn't really changed here, you could invoke {{local-only/x-local}} in a template (for current Ember.Component's), but there is no way to access nested components (other than this PR if/when it lands) via angle bracket invocation (because we do not intend to support <local-only/x-local /> invocation).

@@ -232,12 +245,23 @@ function buildInjections(/* container, ...injections */) {
return hash;
}

function factoryFor(container, fullName) {
function factoryFor(container, _fullName, options) {
var registry = container.registry;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let

@rwjblue rwjblue force-pushed the local-lookup branch 2 times, most recently from 30ec32e to 423c19c Compare December 3, 2015 17:58
@rwjblue
Copy link
Member Author

rwjblue commented Dec 3, 2015

This has been updated (along with the demo twiddle, S3 assets, and bower assets) to do the following:

  • Use EmptyObject for caching local lookups (instead of dictionary) since we do not need to delete from it.
  • Ensure that local lookups "win" out over global lookups. I had previously thought this was a backwards incompatible change, but have since realized it is not (thanks @mixonic / @mmun / @dgeb for convincing me). It is not a breaking change because we do not intend to add expandLocalLookup to the existing ember-resolver/resolver, and instead we plan to make a new resolver ember-resolver/pods (or some other better name). Since the new functionality is based on a new resolver base class, it is entirely opt-in (and therefore not breaking).

let fullName = _fullName;

if (isEnabled('ember-htmlbars-local-lookup')) {
if (options && options.source) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

options should always be initialized via line 185.

@Gaurav0
Copy link
Contributor

Gaurav0 commented Dec 3, 2015

@rwjblue According to rfcs, "substantial" changes to Ember require an RFC. A substantial change is defined there as:
    

  • Any new feature that creates new API surface area, and would require a feature flag if introduced.

@rwjblue
Copy link
Member Author

rwjblue commented Dec 3, 2015

@Gaurav0 - Thanks for pointing this out and confirming that this doesn't need an RFC! There is no new public API surface area introduced by this pull request.

var registry = new Registry();

// the twitter factory is added to the module system
registry.expandLocalLookup('component:post-title', 'template:post) // => component:post/post-title
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

options should be an object in this example:

registry.expandLocalLookup('component:post-title', {source: 'template:post'}); // => component:post/post-title

@mmun
Copy link
Member

mmun commented Dec 3, 2015

@Gaurav0 This is behind a feature flag so we won't enable it before it has been discussed in an RFC. I think the work here was quite technical so Robert wanted feedback from Dan ASAP. We're confident in this feature so I expect it to go through the RFC process quickly.

@dgeb
Copy link
Member

dgeb commented Dec 3, 2015

@rwjblue LGTM except for the minor nits mentioned and the need for more unit testing of the changes to the Registry and Container.

@workmanw
Copy link

workmanw commented Dec 3, 2015

So one concern I had from a functional standpoint was ultimately losing the ability to use the component helper ({{component}}) to include a nested component. With the example that @rwjblue provided, I was/am concerned about having no way to use local-only/x-local outside of the local-only hierarchy.

So I tested with @rwjblue's example:

{{! global-only/template.hbs --}}

{{x-global}}
{{!-- both of these continue work (this is expected) --}}
{{component "local-only/x-local"}}
{{local-only/x-local}}

However, I know that with angle-brackets the later option will not be supported because it contains a slash. My question is will I still be able to do: <x-component "local-only/x-local"></x-component>?

@rwjblue
Copy link
Member Author

rwjblue commented Dec 3, 2015

My question is will I still be able to do: <x-component "local-only/x-local"></x-component>

I am unsure if there are plans to implement an angle bracket version of the component helper or if it were implemented if it would allow for nested invocation like your example. This PR does not modify the behavior of angle bracket components at all.

@workmanw
Copy link

workmanw commented Dec 3, 2015

This PR does not modify the behavior of angle bracket components at all.

Sorry, it's not always clear to me where I should give this feedback. Someone might argue this question/feedback is about how components are looked up, and others might say it's more specific to angle-bracket use case.

Anyways, this PR looks great, I'm excited to use it. It'll clean up our routable-component "shim templates" a lot. Thank you!

@rwjblue
Copy link
Member Author

rwjblue commented Dec 3, 2015

Sorry, it's not always clear to me where I should give this feedback.

No worries! I'm just not sure of the answer to your question so all I am certain of is that the behavior isn't changing from what is on master now...

@rwjblue rwjblue force-pushed the local-lookup branch 2 times, most recently from eb52993 to e29b1c9 Compare December 4, 2015 02:58
@rwjblue
Copy link
Member Author

rwjblue commented Dec 4, 2015

Just pushed an update that fixes the various inline comments here, and adds test coverage for the container/resolver parts.

});

assert.equal(result, 'foo:qux/bar');
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to verify the prioritization given to the resolver, then to the fallback registry, like in https://github.com/rwjblue/ember.js/blob/local-lookup/packages/container/tests/registry_test.js#L316-L340

Something like this (I haven't actually tried to run this):

QUnit.test('`expandLocalLookup` is handled by the resolver, then by the fallback registry, if available', function(assert) {
  assert.expect(9);

  let fallback = {
    expandLocalLookup(targetFullName, sourceFullName) {
      assert.ok(true, 'expandLocalLookup is called on the resolver');
      assert.equal(targetFullName, 'foo:bar', 'the targetFullName was passed through');
      assert.equal(sourceFullName, 'baz:qux', 'the sourceFullName was passed through');

      return 'foo:qux/bar-fallback';
    }
  };

  let resolver = {
    expandLocalLookup(targetFullName, sourceFullName) {
      assert.ok(true, 'expandLocalLookup is called on the resolver');
      assert.equal(targetFullName, 'foo:bar', 'the targetFullName was passed through');
      assert.equal(sourceFullName, 'baz:qux', 'the sourceFullName was passed through');

      return 'foo:qux/bar-resolver';
    }
  };

  let registry = new Registry({
    fallback,
    resolver
  });

  let result = registry.expandLocalLookup('foo:bar', {
    source: 'baz:qux'
  });

  assert.equal(result, 'foo:qux/bar-resolver', 'handled by the resolver');

  registry.resolver = null;

  result = registry.expandLocalLookup('foo:bar', {
    source: 'baz:qux'
  });

  assert.equal(result, 'foo:qux/bar-fallback', 'handled by the fallback registry');

  registry.fallback = null;

  result = registry.expandLocalLookup('foo:bar', {
    source: 'baz:qux'
  });

  assert.equal(result, null, 'null is returned by default when no resolver or fallback registry is present');
});

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dgeb - thank you! Updated.

Implements local lookup concepts. This new concept is primarily
used from the template layer in this initial implementation,
but the `source` option is usable generally.

There are a couple main concepts being added here:

* Expanding a `type:name` relative to a given source `type:name` into a
  fully qualified `type:name` (that includes the source info).
* Expose the currently rendering `template`'s `meta` information on the
  `RenderEnv`.
* Adding a second layer of lookups in all places that components or
  helpers are resolved.

\#### `expandLocalLookup`

We use the `expandLocalLookup` function on the resolver (when present)
to take both the source and target full names and return a new fully
qualified full name. By default the resolver will not have an
`expandLocalLookup` function, but an example implementation exists in
the `ember-htmlbars/tests/integration/local-lookup-test` module here.

\#### `meta`

As of Ember 1.12, metadata has been appended to every template to allow
better customization of things like deprecation messages and template
compilation errors.

With the changes in this commit that metadata is exposed on the
`RenderEnv` which is present through the various internal glimmer engine
hooks (and provides us the `source` information needed for the local
lookups added here).

\#### local + global lookups

The various places that are responsible for looking helpers and
components up have been updated to do two layers of lookups.  Once for
the current global style lookups, and a second for lookups relative to
the invocation template.
@dgeb
Copy link
Member

dgeb commented Dec 4, 2015

Thanks for adding that test, @rwjblue.

LGTM 👍

@mixonic
Copy link
Member

mixonic commented Dec 4, 2015

I did some cursory benchmarking with ember-performance in search of regressions, nothing alarming came up.

mixonic added a commit that referenced this pull request Dec 4, 2015
[FEATURE ember-htmlbars-local-lookup]
@mixonic mixonic merged commit f0dafd4 into emberjs:master Dec 4, 2015
@mixonic mixonic deleted the local-lookup branch December 4, 2015 16:15
@rwjblue
Copy link
Member Author

rwjblue commented Dec 4, 2015

Twiddle updated to use canary (now that this is merged).

@mikkopaderes
Copy link

@rwjblue Not sure if mentioned elsewhere but will deeply nested components look like this?

app/routes/posts/components/post-header/component.js
app/routes/posts/components/post-header/template.hbs
app/routes/posts/components/post-header/components/post-header-tabs/component.js
app/routes/posts/components/post-header/components/post-header-tabs/template.hbs

or is it like this?

app/routes/posts/components/post-header/component.js
app/routes/posts/components/post-header/template.hbs
app/routes/posts/components/post-header/post-header-tabs/component.js
app/routes/posts/components/post-header/post-header-tabs/template.hbs

@tomdale
Copy link
Member

tomdale commented Jan 16, 2016

@rmmpadres The top one is what is planned, but is orthogonal to this PR. This PR just implements the local lookup and it is up to the resolver to determine how that local lookup is resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants