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

The included hook and nested addons: different application argument #3718

Closed
RSSchermer opened this issue Mar 31, 2015 · 39 comments
Closed

The included hook and nested addons: different application argument #3718

RSSchermer opened this issue Mar 31, 2015 · 39 comments

Comments

@RSSchermer
Copy link
Contributor

I'm in the process of updating 2 related component addons I maintain, ember-spin-spinner and ember-spinner-button (ember-spinner-button depends on ember-spin-spinner), to ember-cli 0.2.2 (from 0.0.46, upgrading was long overdue).

I first updated ember-spin-spinner, which was a breeze and when using it as a "top level" addon it still works as expectd. However, when updating ember-spinner-button, which uses ember-spin-spinner as a "second level" (nested) addon, its included hook starts throwing errors during ember s and ember test:

included: function(app) {
  this._super.included(app);

  var spinPath = path.join(app.bowerDirectory, 'spin.js');

  app.import(path.join(spinPath, 'spin.js'));
  app.import(path.join(spinPath, 'jquery.spin.js'));
}

The app argument is not the same when ember-spin-spinner is used as a "top level" addon as when used as a "second level" (nested) addon. The specific problems in this case are that app.bowerDirectory and app.import are undefined.

I did some digging through the issues here and came across this comment by @rwjblue, which seems to indicate that this is intended behavior.

In that comment, a distinction also seems to be made between "top level" and "second level" addons. For ember-spin-spinner the intend was not to make it either a top level or a second level addon, but both: I wanted it to be usable both a standalone addon, as well as a dependency for ember-spinner-button.

@rwjblue
Copy link
Member

rwjblue commented Mar 31, 2015

this._super.included(app); is incorrect, the first point in the comment you linked explains why.

this._super.included.apply(this, arguments); should fix the error.

@rwjblue
Copy link
Member

rwjblue commented Mar 31, 2015

Ahhh, I missed that this error was thrown from a second level addon's included hook. My comment is still correct about calling _super, it just won't fix the issue.

@RSSchermer
Copy link
Contributor Author

Thanks for the quick reply!

I found it hard to describe the problem. I'll try to summarize:

  • ember-spin-spinner's index.js is fine when using it as a top level addon in an application.
  • ember-spin-spinner's index.js throws errors when using it as a nested addon inside another addon (ember-spinner-button in this case).

I'll definately change this._super.included(app);, which I got from the addon hooks documentation (the example there might be outdated? Or is this fix specific to my case?).

@rwjblue
Copy link
Member

rwjblue commented Mar 31, 2015

the example there might be outdated

Yep, would you mind submitting a pull request to fix?

@RSSchermer
Copy link
Contributor Author

Could this perhaps be reopened? The PR was for a related issue, but this did not fix the original issue, which is that addons with included hooks such as this:

included: function(app) {
  this._super.included(app);

  var spinPath = path.join(app.bowerDirectory, 'spin.js');

  app.import(path.join(spinPath, 'spin.js'));
  app.import(path.join(spinPath, 'jquery.spin.js'));
}

cannot be used as nested addons, because of the difference in behavior of the included hook for top level addons and second level (nested) addons.

@stefanpenner
Copy link
Contributor

cannot be used as nested addons, because of the difference in behavior of the included hook for top level addons and second level (nested) addons.

the above example is incorrect, this._super.included.call(this, app) would be correct.

@stefanpenner stefanpenner reopened this Mar 31, 2015
@RSSchermer
Copy link
Contributor Author

Sorry, just copy/pasted the code from the original issue text.

I changed it to this._super.included.apply(this, arguments); as @rwjblue suggested and the problem still persists. I'll try this._super.included.call(this, app) as well.

@stefanpenner
Copy link
Contributor

as @rwjblue suggested and the problem still persists. I'll try this._super.included.call(this, app) as well.

Ya, I didn't expect it to fix it, just wanted to make sure that was also correct.

If possible, can you provide an app that demonstrates this issue? It makes me easier for me to jump it if something is already primed.

@RSSchermer
Copy link
Contributor Author

Just to confirm: this._super.included.call(this, app) does indeed not fix the problem.

If you clone/fork and install rsschermer/ember-spinner-button master and run either ember s or ember test you should run into the issue. It will say Arguments to path.join must be strings, but the deeper issue seems to be that app.bowerDirectory is undefined.

Changing app.bowerDirectory to a hard-coded 'bower_components' moves execution on a line, till it throws Object #<Class> has no method 'import' on the next line of code.

I'd be happy to make a more minimal example, but that'll be late tonight/tomorrow at the soonest, as I have to leave soon for my brother's "goodbye dinner" (he's leaving for Japan for 8 months).

@rwjblue
Copy link
Member

rwjblue commented Mar 31, 2015

Just to confirm: this._super.included.call(this, app) does indeed not fix the problem.

Yes, I did not expect it to. The included hook is called on nested addons, but they do not get access to this.app so they can't do things like app.import. That is the actual issue.

@stefanpenner
Copy link
Contributor

this was by design, and we have not yet fleshed it out further. Although we should

@ef4
Copy link
Contributor

ef4 commented Apr 8, 2015

So why is it by design that second level addons can't do import? I get that it's unfortunate that app.import has global effects, but that's inevitable when using third-party dependencies that don't expose a sane module interface.

I took notice of this issue due to ef4/ember-code-snippet#4, but it's also a showstopper for addons depending on liquid-fire. liquid-fire will want to import velocity, and will fail.

@stefanpenner
Copy link
Contributor

@ef4 dedupe compatibility in the general case, if something depends on liquid-fire, it may need to be peerDep or similar.

@janmisek
Copy link

janmisek commented Apr 8, 2015

Hello guys, I have to agree with @ef4 how important is to import 3rd party deps in nested addons.

I found out problem is related to the following lines:

# ember-cli/lib/broccoli/models/addon.js

Addon.prototype.included = function(/* app */) {
  if (!this._addonsInitialized) {
    // someone called `this._super.included` without `apply` (because of older
    // core-object issues that prevent a "real" super call from working properly)
    return;
  }
  this.eachAddonInvoke('included', [this]);
};

app argument instead of this should be passed to eachAddonInvoke to resolve the issue. Only problem with this solution is that nesting addon must have installed same (bower) dependencies as nested one.

I will do fork of ember-cli for myself with solution above. Do you want me to do pr? I would say ability to import for price of installed dependencies in nesting addon worth it

@stefanpenner
Copy link
Contributor

Do you want me to do pr?

I don't believe so.

@janmisek
Copy link

janmisek commented Apr 8, 2015

Is there any other/better solution? My usecase is need of low level utilities in utils-addon to be shared among more apps and addons. utils-addon also uses some no amd libraries.

@RSSchermer
Copy link
Contributor Author

This is the best solution I could come up with so far, figured I'd share:

I think the weird thing is that included behaves differently based on context.

I'm personally fine with the top level addon having to do all the importing for its nested addon dependencies.

A simple solution seems to be to only call the included hook for top level addons, not for second level addons, and to make sure this is clearly documented somewhere. The top level addon then needs to do all the imports for its dependencies, as well as its own imports. This way the second level "nested" addon can have its own included hook (so it can also be used as a top level addon itself), without crashing the build, because it never gets called.

Is the included hook used for other functionality besides importing? If yes, then perhaps a new hook, e.g. nested (we can probably come up with a better name), could be introduced, which is only called for second level addons and takes care of that other functionality when the addon is used as a nested addon.

This way both included and nested would be context independent and behave more predictably.

@stefanpenner
Copy link
Contributor

Is there any other/better solution?

exploring peerDep support.

@stefanpenner
Copy link
Contributor

A simple solution seems to be to only call the included hook for top level addons,

Maybe, but the whole problem is like pandoras box. It needs some thorough thought and fleshing out before we will have a good answer.

@janmisek
Copy link

whole problem is like pandoras box

For sure. At least mutual overriding dependencies in vendor.js file must be taken in consideration.

Until final solution appear Addon.prototype.included hack mentioned just works for me.

@hhff
Copy link

hhff commented Apr 11, 2015

@janmisek - could you please post an example of how you're actually doing that hack? I could use it - tried a couple things and couldn't get it to work...

@hhff
Copy link

hhff commented Apr 11, 2015

Further to that, there doesn't seem to be a intuitive way to add multiple addons to a host project when installing a master addon (via its generator). addAddonToProject works nicely, but there's no plural version of it.

I've tried passing addAddonToProject into an RSVP.all, but that chokes up and doesn't install both addons properly.

Am I missing something here? Happy to build our a pluralised addon install task if it's needed

@stefanpenner
Copy link
Contributor

Pluralized addon task sounds good.

machty added a commit to machty/ember-paper that referenced this issue Oct 12, 2016
This fixes issues with people seeing `regeneratorRuntime` is not defined when ember-concurrency / ember-maybe-import-regenerator are deeply nested dependent addons.

[This new ember app](https://github.com/v3ss0n/ember-paper-menu-error-concurrency) demonstrates the bug and is fixed with this change to ember-paper.

Prior art: ember-cli/ember-cli#3718 (comment)
miguelcobain pushed a commit to miguelcobain/ember-paper that referenced this issue Oct 13, 2016
This fixes issues with people seeing `regeneratorRuntime` is not defined when ember-concurrency / ember-maybe-import-regenerator are deeply nested dependent addons.

[This new ember app](https://github.com/v3ss0n/ember-paper-menu-error-concurrency) demonstrates the bug and is fixed with this change to ember-paper.

Prior art: ember-cli/ember-cli#3718 (comment)
PeterMead pushed a commit to AzuraGroup/ember-localforage-adapter that referenced this issue Oct 26, 2016
PeterMead pushed a commit to AzuraGroup/ember-cli-uuid that referenced this issue Oct 26, 2016
PeterMead added a commit to AzuraGroup/ember-localforage-adapter that referenced this issue Nov 25, 2016
jbailey4 added a commit to anandts88/ember-validator that referenced this issue Feb 28, 2017
The `app` argument in the `included` hook varies based on whether the addon is being used by another addon/engine (nested) or being consumed by an application. This PR attempts to solve all the scenarios in lieu of better, public api.

See ember-cli/ember-cli#3718
noslouch pushed a commit to nypublicradio/ember-hifi that referenced this issue Mar 13, 2017
@kybishop
Copy link

kybishop commented May 8, 2017

@stefanpenner @rwjblue I have to ask... why is this closed? Nearly two years out and nearly every major addon has wackiness like this 1 2 3.

Might it be possible for us to have a master issue for this which summarizes both the issue itself and the preferred workaround(s)? This thread has grown quite long, with a lot of addons referencing it when implementing a workaround, but little in the way of explanation on what the core issue is.

I'm happy to make this writeup/issue myself, and would love a hand (maybe via Slack?) understanding the pieces and current fixups.

@ef4
Copy link
Contributor

ef4 commented May 8, 2017

@kybishop has a good point.

I don't have the full context on what is the right implementation, but the end goal would be:

1. One correct way to do it that works in some sufficiently new ember-cli version.
2. A polyfill addon that allows you to do 1 in old ember-cli versions.

@rwjblue
Copy link
Member

rwjblue commented May 8, 2017

I have to ask... why is this closed?

Because the current design was intended so this isn't a bug. We use this issue tracker to deal with bugs, not feature requests.

Nearly two years out and nearly every major addon has wackiness like this 1 2 3.

FWIW, this.import has been around for a while (2.7 I think?), and has a polyfill that apps can include.

Might it be possible for us to have a master issue for this which summarizes both the issue itself and the preferred workaround(s)?
...
I'm happy to make this writeup/issue myself, and would love a hand (maybe via Slack?) understanding the pieces and current fixups.

In general, a long dead issue is not a great place to have a discussion. I'd suggest an issue in the ember-cli/rfcs repo with a basic write-up of the issue and how it impacts folks. Happy to help chat through the various approaches with you in slack...

@kybishop
Copy link

kybishop commented May 9, 2017

@rwjblue Fair!

I'll ping you in slack soon to chat through the various options. Hope to learn enough to document the pros and cons of the various solutions and add to the ember-cli docs.

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

No branches or pull requests