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

[Module Unification] Routes can only be nested two levels deep #17217

Closed
buschtoens opened this issue Nov 20, 2018 · 10 comments
Closed

[Module Unification] Routes can only be nested two levels deep #17217

buschtoens opened this issue Nov 20, 2018 · 10 comments

Comments

@buschtoens
Copy link
Contributor

buschtoens commented Nov 20, 2018

Defining routes nested more than two levels deep or even just providing a callback does not work MU applications and triggers the error below.

requirejs.js:74 Uncaught TypeError: Cannot read property 'defaultType' of undefined
    at RequireJSRegistry._checkDefaultType (requirejs.js:74)
    at RequireJSRegistry._detectModule (requirejs.js:63)
    at RequireJSRegistry.has (requirejs.js:85)
    at Resolver._serializeAndVerify (resolver.js:118)
    at Resolver.identify (resolver.js:94)
    at Resolver.resolve (resolver.js:104)
    at Class.resolve (index.js:149)
    at Class.resolve (index.js:15)
    at Class.superWrapper [as resolve] (utils.js:308)
    at _resolve (container.js:807)

Exemplary failing router:

Router.map(function() {
  // this fails
  this.route('foo', function() {
    this.route('bar', function() {
      // You don't even need to register a third-level route. Just providing the
      // callback triggers the error, likely because of the implicit `index` route.
      // this.route('qux');
    });
  });

  // this works just fine
  this.route('one', function() {
    this.route('two');
  });
});

Reproduction repo: https://github.com/buschtoens/mu-nested-routes

@buschtoens
Copy link
Contributor Author

buschtoens commented Nov 20, 2018

The problem seems to be somewhere in glimmer-resolver/resolver.ts#identify. Routes generate non-sensical specifiers with an IMO incorrect rootName property:

{
  type: "route",
  name: "index",
  namespace: undefined,
  collection: "routes",
  rootName: "foo/bar"
}

I think it should rather look like this:

{
  type: "route",
  name: "foo/bar/index",
  collection: "routes",
  rootName: "mu-nested-routes"
}

Or maybe?

{
  type: "route",
  name: "index",
  namespace: "foo/bar",
  collection: "routes",
  rootName: "mu-nested-routes"
}

@buschtoens
Copy link
Contributor Author

I assume the glimmer-wrapper in ember-resolver is the correct place to submit a failing test case to.

@NullVoxPopuli
Copy link
Sponsor Contributor

@buschtoens have you tried the fallback resolver?
the fallback resolver is currently what https://emberclear.io uses

@buschtoens
Copy link
Contributor Author

@NullVoxPopuli I am already using the fallback resolver, as can be seen here. But that is actually a very good point to make. I'll give the glimmer-wrapper a try instead. Thanks a lot!

@buschtoens
Copy link
Contributor Author

buschtoens commented Nov 20, 2018

@NullVoxPopuli No luck here. Apparently fallback and glimmer-wrapper use the same buggy code paths.

fallback first tries the glimmer-wrapper resolver, and if that one cannot find a result, will fall back to the classic resolver:

https://github.com/ember-cli/ember-resolver/blob/7647d14d242b08d40305dfdbef2e028f1a19b4de/mu-trees/addon/resolvers/fallback/index.js#L6-L15

@NullVoxPopuli
Copy link
Sponsor Contributor

excellent! (one less thing to fix)

@buschtoens
Copy link
Contributor Author

buschtoens commented Nov 20, 2018

Ha! I just found out that this only happens, if the third-level Route or Controller are auto-generated. If the app actually provides a route.js and controller.js, there's no error. I've updated the reproduction repo to show this as well.

@buschtoens
Copy link
Contributor Author

I think I've pinned down the issue. So in L90 s looks like this:

{
  type: "controller",
  name: "index",
  namespace: "foo/bar",
  collection: "routes",
  rootName: "dummy"
}

The resolver cannot find the Controller, as it is not explicitly defined and thus should be auto-generated. But before resorting to auto-generation, the resolver tries as to find a fitting addon first in L92-L100.

s then looks like this:

{
  type: "controller",
  name: "index",
  namespace: undefined,
  collection: "routes",
  rootName: "foo/bar"
}

This is then serialized as controller:/foo/bar/routes/index in _serializeAndVerify by serializeSpecifier. It is then deserialized in has as:

{
  type: "controller",
  name: "index",
  namespace: "routes",
  collection: "bar",
  rootName: "foo"
}

Notice how this differs from the prior specifier:

{
  type: "controller",
  name: "index",
-  namespace: undefined,
+  namespace: "routes",
-  collection: "routes",
+  collection: "bar",
-  rootName: "foo/bar"
+  rootName: "foo"
}

What ultimately causes the TypeError then is that that _checkDefaultType expects the specified collection to always exist:

  _checkDefaultType(specifier) {
    let {defaultType} = this._config.collections[specifier.collection];
    return defaultType && defaultType === specifier.type;
  }

A simple fix to make this safer would be:

  _checkDefaultType(specifier) {
    let { defaultType } = this._config.collections[specifier.collection] || {};
    return defaultType && defaultType === specifier.type;
  }

However this does not fix the inconsistent de-/serialization. But is this actually a problem we need to worry about? The input specifier already looks off to me.

In any case, I'll prep a PR for the above fix and test it.

@gossi
Copy link

gossi commented Dec 29, 2018

This can be marked as closed 😃 Maybe cut a release for ember-resolver that contains the fix (it's already on master)

@locks
Copy link
Contributor

locks commented May 30, 2019

Closing, thanks!

@locks locks closed this as completed May 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants