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

DI error when injecting DOM.Element into SlotCustomAttribute #17

Closed
RomkeVdMeulen opened this Issue Dec 23, 2016 · 51 comments

Comments

Projects
None yet
10 participants
@RomkeVdMeulen

RomkeVdMeulen commented Dec 23, 2016

I'm submitting a bug report

  • Library Version:
    1.1.0

  • Operating System:
    Linux (Ubuntu)

  • Node Version:
    6.5.0

  • JSPM
    0.16.29

  • Browser:
    all

  • Language:
    TypeScript 2.0.3

  • Aurelia bundler:
    0.4.0

When adding <div slot="x"> anywhere, I get this error:

aurelia.js:16441 Uncaught Error: Error invoking SlotCustomAttribute. Check the inner error for details.
------------------------------------------------
Inner Error:
Message: key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?
Inner Error Stack:
Error: key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?
    at validateKey (http://localhost:8080/myproject/frontend/bundles/aurelia.js:6664:13)
    at Container.get (http://localhost:8080/myproject/frontend/bundles/aurelia.js:6810:7)
    at Container.elementContainerGet [as get] (http://localhost:8080/myproject/frontend/bundles/aurelia.js:8642:17)
    at Object.invoke (http://localhost:8080/myproject/frontend/bundles/aurelia.js:6700:33)
    at InvocationHandler.invoke (http://localhost:8080/myproject/frontend/bundles/aurelia.js:6678:168)
    at Container.invoke (http://localhost:8080/myproject/frontend/bundles/aurelia.js:6873:25)
    at ProviderResolver.get (http://localhost:8080/myproject/frontend/bundles/aurelia.js:8601:74)
    at Container.get (http://localhost:8080/myproject/frontend/bundles/aurelia.js:6828:23)
    at Container.elementContainerGet [as get] (http://localhost:8080/myproject/frontend/bundles/aurelia.js:8642:17)
    at HtmlBehaviorResource.create (http://localhost:8080/myproject/frontend/bundles/aurelia.js:10198:58)
End Inner Error Stack

If I go into the source and replace DOM.Element with Element in the SlotCustomAttribute injection, named slots function as expected.

I suspected that this error was somehow related to aurelia/binding#376, however the problem persists after upgrading to metadata 1.0.3.

The project has a custom bootstrap using bootstrapper 2.0.1 that looks something like this:

bootstrap((aurelia: Aurelia) => {
	aurelia.use
		.defaultBindingLanguage()
		.defaultResources()
		.globalResources(myResourcePaths)
		.plugin("aurelia-animator-css", (animator: any) => {
			animator.useAnimationDoneClasses = true;
			animator.verifyKeyframesExist = false;
		})
		.plugin("aurelia-property-injection")
		.plugin("aurelia-dialog", (dialog: any) => {
			dialog.useDefaults().useCSS(null);
			dialog.settings.ignoreTransitions = true;
		});

	aurelia.container.registerInstance(MyAppConfig, config);

	aurelia.start().then(() => {
		let myInitService: AppInitService = aurelia.container.get(AppInitService);
		myInitService.start();

		aurelia.enhance({}, document.body);
		templatingEngine = aurelia.container.get(TemplatingEngine);
	});
});
@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Dec 23, 2016

Member

Are you using webpack? Do you have all your dependencies up to date? @niieani This sounds like the old load order problem for webpack.

Member

EisenbergEffect commented Dec 23, 2016

Are you using webpack? Do you have all your dependencies up to date? @niieani This sounds like the old load order problem for webpack.

@RomkeVdMeulen

This comment has been minimized.

Show comment
Hide comment
@RomkeVdMeulen

RomkeVdMeulen Dec 23, 2016

No, using JSPM. And everything is completely up to date.

RomkeVdMeulen commented Dec 23, 2016

No, using JSPM. And everything is completely up to date.

@RomkeVdMeulen

This comment has been minimized.

Show comment
Hide comment
@RomkeVdMeulen

RomkeVdMeulen Jan 16, 2017

Any suggestions for a workaround perhaps? It's preventing me from using named slots in my custom components.

RomkeVdMeulen commented Jan 16, 2017

Any suggestions for a workaround perhaps? It's preventing me from using named slots in my custom components.

@niieani

This comment has been minimized.

Show comment
Hide comment
@niieani

niieani Jan 17, 2017

Member

Can you post a GitHub repo which reproduces the issue?

Member

niieani commented Jan 17, 2017

Can you post a GitHub repo which reproduces the issue?

@jods4

This comment has been minimized.

Show comment
Hide comment
@jods4

jods4 Feb 15, 2017

Contributor

Someone reported this when trying the new webpack plugin.
Please let me know what the resolution is. If it involves tweaking the JSPM build, I'll update Webpack accordingly.

Contributor

jods4 commented Feb 15, 2017

Someone reported this when trying the new webpack plugin.
Please let me know what the resolution is. If it involves tweaking the JSPM build, I'll update Webpack accordingly.

@RomkeVdMeulen

This comment has been minimized.

Show comment
Hide comment
@RomkeVdMeulen

RomkeVdMeulen Feb 15, 2017

@niieani Sorry, I missed your reply. I'll see if I can reliably reproduce the issue.

RomkeVdMeulen commented Feb 15, 2017

@niieani Sorry, I missed your reply. I'll see if I can reliably reproduce the issue.

@mike-suggitt

This comment has been minimized.

Show comment
Hide comment
@mike-suggitt

mike-suggitt Feb 16, 2017

Same issue here 👍

mike-suggitt commented Feb 16, 2017

Same issue here 👍

@nmocruz

This comment has been minimized.

Show comment
Hide comment
@nmocruz

nmocruz Feb 17, 2017

@niieani
same issue here. In my case using webpack.
I have a repo to reproduce this. https://github.com/nmocruz/tudu/

It's on #/tasks page, It trying to load page-header or breadcrumb components.

nmocruz commented Feb 17, 2017

@niieani
same issue here. In my case using webpack.
I have a repo to reproduce this. https://github.com/nmocruz/tudu/

It's on #/tasks page, It trying to load page-header or breadcrumb components.

@EisenbergEffect EisenbergEffect self-assigned this Feb 18, 2017

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Feb 19, 2017

Member

I created a basic custom element that uses named slots. It is a CLI project, and has no errors. Works exactly as it should. Can someone put a simplest possible code sample in here? I only need a class and the view that defines the slots so I can try it out in my own project.

Member

EisenbergEffect commented Feb 19, 2017

I created a basic custom element that uses named slots. It is a CLI project, and has no errors. Works exactly as it should. Can someone put a simplest possible code sample in here? I only need a class and the view that defines the slots so I can try it out in my own project.

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Feb 19, 2017

Member

For reference, here's what I've created to test, which works exactly as expected without errors.

slot-test.js
export class SlotTest {
  
}
slot-test.html
<template>
  <div>Text before the named slot.</div>
  <slot name="named">
    Fallback for the named slot.
  </slot>
  <div>Text after the named slot.</div>
  <slot>Fallback for the default slot.</slot>
</template>
app.html
<template>
  <require from="./slot-test"></require>

  <h1>${message}</h1>
  
  <slot-test>
    Text that gets projected into the default slot.
    <div slot="named">Text that gets projected into the named slot.</div>
  </slot-test>
  
  <slot-test></slot-test>
</template>
Member

EisenbergEffect commented Feb 19, 2017

For reference, here's what I've created to test, which works exactly as expected without errors.

slot-test.js
export class SlotTest {
  
}
slot-test.html
<template>
  <div>Text before the named slot.</div>
  <slot name="named">
    Fallback for the named slot.
  </slot>
  <div>Text after the named slot.</div>
  <slot>Fallback for the default slot.</slot>
</template>
app.html
<template>
  <require from="./slot-test"></require>

  <h1>${message}</h1>
  
  <slot-test>
    Text that gets projected into the default slot.
    <div slot="named">Text that gets projected into the named slot.</div>
  </slot-test>
  
  <slot-test></slot-test>
</template>
@nmocruz

This comment has been minimized.

Show comment
Hide comment
@nmocruz

nmocruz Feb 19, 2017

@EisenbergEffect the https://github.com/nmocruz/tudu/ was not running!? it's not simple, because I'm using the aspnet/javascriptServices,,

nmocruz commented Feb 19, 2017

@EisenbergEffect the https://github.com/nmocruz/tudu/ was not running!? it's not simple, because I'm using the aspnet/javascriptServices,,

@jods4

This comment has been minimized.

Show comment
Hide comment
@jods4

jods4 Feb 19, 2017

Contributor

In chat @MeirionHughes and @Vheissu both had a repro. Hopefully they can share.

Contributor

jods4 commented Feb 19, 2017

In chat @MeirionHughes and @Vheissu both had a repro. Hopefully they can share.

@RichiCoder1

This comment has been minimized.

Show comment
Hide comment
@RichiCoder1

RichiCoder1 Feb 28, 2017

Just ran into this too. Webpack + NPM\Yarn here. I threw together a really trivial webpack example and couldn't reproduce. Not sure what's going on.

RichiCoder1 commented Feb 28, 2017

Just ran into this too. Webpack + NPM\Yarn here. I threw together a really trivial webpack example and couldn't reproduce. Not sure what's going on.

@MeirionHughes

This comment has been minimized.

Show comment
Hide comment
@MeirionHughes

MeirionHughes Feb 28, 2017

@jods4 nothing special, literally your new webpack stuff with a simple named slot under custom-element

MeirionHughes commented Feb 28, 2017

@jods4 nothing special, literally your new webpack stuff with a simple named slot under custom-element

@RichiCoder1

This comment has been minimized.

Show comment
Hide comment
@RichiCoder1

RichiCoder1 Feb 28, 2017

@MeirionHughes Could you try upgrading your dependencies? I spun up a new webpack project, and upgraded my current one, and neither had this issue.

RichiCoder1 commented Feb 28, 2017

@MeirionHughes Could you try upgrading your dependencies? I spun up a new webpack project, and upgraded my current one, and neither had this issue.

@RichiCoder1

This comment has been minimized.

Show comment
Hide comment
@RichiCoder1

RichiCoder1 Mar 2, 2017

And now I'm at a loss. Same project, minor changes, different computer, and the issue has reappeared.

Edit: But I can reliably switch between two commits that are good & bad! @EisenbergEffect if you'd like, I can email you (or the appropriate team member) a project zip that reproduces.

Edit Edit: I can't quite narrow it down, but it looks like it had something to do with either aurelia-pal or aurelia-templating getting updated from 1.2.0 to 1.3.0?

RichiCoder1 commented Mar 2, 2017

And now I'm at a loss. Same project, minor changes, different computer, and the issue has reappeared.

Edit: But I can reliably switch between two commits that are good & bad! @EisenbergEffect if you'd like, I can email you (or the appropriate team member) a project zip that reproduces.

Edit Edit: I can't quite narrow it down, but it looks like it had something to do with either aurelia-pal or aurelia-templating getting updated from 1.2.0 to 1.3.0?

@RichiCoder1

This comment has been minimized.

Show comment
Hide comment
@RichiCoder1

RichiCoder1 Mar 10, 2017

More repro detail: When I add aurelia-validation to my vendor chunk in webpack, this issue appears without fail. Removing it reverts it. I'm mystified as to why. Maybe it's pulling something into the vendor chunk it shouldn't for whatever reason?

const path = require("path");
const webpack = require("webpack");
const ManifestPlugin = require("webpack-manifest-plugin");
const { AureliaPlugin } = require("aurelia-webpack-plugin");
// TODO: this is only temporary until a patched aurelia release is published.
const coreDeps = require("aurelia-core-dependencies");

module.exports = {
  entry: { 
    "vendor": [
      "moment", 
      "datatables.net"
    ],
    "main": "aurelia-bootstrapper" 
  },
  
  devtool: 'source-map',

  output: {
    path: path.resolve(__dirname, "../wwwroot/dist"),
    publicPath: "/dist/",
    filename: "[name].bundle.js",    
    chunkFilename: "[name].chunk.js"
  },

  resolve: {
    extensions: [".ts", ".js"],
    modules: ["src", "node_modules"].map(x => path.resolve(x)),
    symlinks: false
  },

  module: {
      rules: [
      { test: /\.css$/i, use: [ "css-loader?importLoaders=1", "postcss-loader"] },
      { test: /\.scss/i, use: [ "css-loader?importLoaders=1", "postcss-loader", "sass-loader"] },
      { test: /\.ts$/i, use: "ts-loader" },
      { test: /\.html$/i, use: "html-loader" },
      { test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/, use: 'file-loader'}
    ]
  },  

  plugins: [
    new AureliaPlugin({
      features: { svg: false, polyfills: "esnext" }
    }),
    coreDeps,
    new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor', minChinks: Infinity
    }),
    new ManifestPlugin()
  ]
};

vs

const path = require("path");
const webpack = require("webpack");
const ManifestPlugin = require("webpack-manifest-plugin");
const { AureliaPlugin } = require("aurelia-webpack-plugin");
// TODO: this is only temporary until a patched aurelia release is published.
const coreDeps = require("aurelia-core-dependencies");

module.exports = {
  entry: { 
    "vendor": [
      "moment", 
      "datatables.net",
      "aurelia-validation"
    ],
    "main": "aurelia-bootstrapper" 
  },
  
  devtool: 'source-map',

  output: {
    path: path.resolve(__dirname, "../wwwroot/dist"),
    publicPath: "/dist/",
    filename: "[name].bundle.js",    
    chunkFilename: "[name].chunk.js"
  },

  resolve: {
    extensions: [".ts", ".js"],
    modules: ["src", "node_modules"].map(x => path.resolve(x)),
    symlinks: false
  },

  module: {
      rules: [
      { test: /\.css$/i, use: [ "css-loader?importLoaders=1", "postcss-loader"] },
      { test: /\.scss/i, use: [ "css-loader?importLoaders=1", "postcss-loader", "sass-loader"] },
      { test: /\.ts$/i, use: "ts-loader" },
      { test: /\.html$/i, use: "html-loader" },
      { test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/, use: 'file-loader'}
    ]
  },  

  plugins: [
    new AureliaPlugin({
      features: { svg: false, polyfills: "esnext" }
    }),
    coreDeps,
    new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor', minChinks: Infinity
    }),
    new ManifestPlugin()
  ]
};

RichiCoder1 commented Mar 10, 2017

More repro detail: When I add aurelia-validation to my vendor chunk in webpack, this issue appears without fail. Removing it reverts it. I'm mystified as to why. Maybe it's pulling something into the vendor chunk it shouldn't for whatever reason?

const path = require("path");
const webpack = require("webpack");
const ManifestPlugin = require("webpack-manifest-plugin");
const { AureliaPlugin } = require("aurelia-webpack-plugin");
// TODO: this is only temporary until a patched aurelia release is published.
const coreDeps = require("aurelia-core-dependencies");

module.exports = {
  entry: { 
    "vendor": [
      "moment", 
      "datatables.net"
    ],
    "main": "aurelia-bootstrapper" 
  },
  
  devtool: 'source-map',

  output: {
    path: path.resolve(__dirname, "../wwwroot/dist"),
    publicPath: "/dist/",
    filename: "[name].bundle.js",    
    chunkFilename: "[name].chunk.js"
  },

  resolve: {
    extensions: [".ts", ".js"],
    modules: ["src", "node_modules"].map(x => path.resolve(x)),
    symlinks: false
  },

  module: {
      rules: [
      { test: /\.css$/i, use: [ "css-loader?importLoaders=1", "postcss-loader"] },
      { test: /\.scss/i, use: [ "css-loader?importLoaders=1", "postcss-loader", "sass-loader"] },
      { test: /\.ts$/i, use: "ts-loader" },
      { test: /\.html$/i, use: "html-loader" },
      { test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/, use: 'file-loader'}
    ]
  },  

  plugins: [
    new AureliaPlugin({
      features: { svg: false, polyfills: "esnext" }
    }),
    coreDeps,
    new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor', minChinks: Infinity
    }),
    new ManifestPlugin()
  ]
};

vs

const path = require("path");
const webpack = require("webpack");
const ManifestPlugin = require("webpack-manifest-plugin");
const { AureliaPlugin } = require("aurelia-webpack-plugin");
// TODO: this is only temporary until a patched aurelia release is published.
const coreDeps = require("aurelia-core-dependencies");

module.exports = {
  entry: { 
    "vendor": [
      "moment", 
      "datatables.net",
      "aurelia-validation"
    ],
    "main": "aurelia-bootstrapper" 
  },
  
  devtool: 'source-map',

  output: {
    path: path.resolve(__dirname, "../wwwroot/dist"),
    publicPath: "/dist/",
    filename: "[name].bundle.js",    
    chunkFilename: "[name].chunk.js"
  },

  resolve: {
    extensions: [".ts", ".js"],
    modules: ["src", "node_modules"].map(x => path.resolve(x)),
    symlinks: false
  },

  module: {
      rules: [
      { test: /\.css$/i, use: [ "css-loader?importLoaders=1", "postcss-loader"] },
      { test: /\.scss/i, use: [ "css-loader?importLoaders=1", "postcss-loader", "sass-loader"] },
      { test: /\.ts$/i, use: "ts-loader" },
      { test: /\.html$/i, use: "html-loader" },
      { test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/, use: 'file-loader'}
    ]
  },  

  plugins: [
    new AureliaPlugin({
      features: { svg: false, polyfills: "esnext" }
    }),
    coreDeps,
    new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor', minChinks: Infinity
    }),
    new ManifestPlugin()
  ]
};
@jods4

This comment has been minimized.

Show comment
Hide comment
@jods4

jods4 Mar 10, 2017

Contributor

@RichiCoder1 makes me wonder if the issue is non-determinist and depends on the evaluation order of Aurelia libraries.

Contributor

jods4 commented Mar 10, 2017

@RichiCoder1 makes me wonder if the issue is non-determinist and depends on the evaluation order of Aurelia libraries.

@RichiCoder1

This comment has been minimized.

Show comment
Hide comment
@RichiCoder1

RichiCoder1 Mar 10, 2017

@jods4 That's what I'm thinking too. Something's getting shuffled in the wrong direction by webpack (and possible JSPM?).

RichiCoder1 commented Mar 10, 2017

@jods4 That's what I'm thinking too. Something's getting shuffled in the wrong direction by webpack (and possible JSPM?).

@WillsonHaw

This comment has been minimized.

Show comment
Hide comment
@WillsonHaw

WillsonHaw Mar 11, 2017

So debugging through this, in my situation, it's because of the switch from aurelia-bootstrapper-webpack to aurelia-bootstrapper. Looking at aurelia-bootstrapper-webpack, the first thing it does is run initialize() from aurelia-pal-browser. Sure enough, if I add import {initialize} from 'aurelia-pal-browser'; and run initialize as the first thing in aurelia-bootstrapper, everything works again. Of course, this is most likely not the correct fix since the bootstrapper is actually running asynchoronously.

WillsonHaw commented Mar 11, 2017

So debugging through this, in my situation, it's because of the switch from aurelia-bootstrapper-webpack to aurelia-bootstrapper. Looking at aurelia-bootstrapper-webpack, the first thing it does is run initialize() from aurelia-pal-browser. Sure enough, if I add import {initialize} from 'aurelia-pal-browser'; and run initialize as the first thing in aurelia-bootstrapper, everything works again. Of course, this is most likely not the correct fix since the bootstrapper is actually running asynchoronously.

@jods4

This comment has been minimized.

Show comment
Hide comment
@jods4

jods4 Mar 11, 2017

Contributor

That's an interesting observation, but I think it's only because doing so might change the order in which modules are loaded.

I'm saying this because the initial bug report was using JSPM so no aurelia-bootstrapper-webpack, and because there is really nothing related to DI in Aurelia-pal-browser...

Contributor

jods4 commented Mar 11, 2017

That's an interesting observation, but I think it's only because doing so might change the order in which modules are loaded.

I'm saying this because the initial bug report was using JSPM so no aurelia-bootstrapper-webpack, and because there is really nothing related to DI in Aurelia-pal-browser...

@RichiCoder1

This comment has been minimized.

Show comment
Hide comment
@RichiCoder1

RichiCoder1 Mar 11, 2017

@jods4 Buuuut, the specific issues is that DI isn't seeing Element, correct? Maybe it's a weird issue with DI not properly picking up DOM.Element, specifically for SlotCustomAtribute's inject because of a weird loader order issue?

RichiCoder1 commented Mar 11, 2017

@jods4 Buuuut, the specific issues is that DI isn't seeing Element, correct? Maybe it's a weird issue with DI not properly picking up DOM.Element, specifically for SlotCustomAtribute's inject because of a weird loader order issue?

@WillsonHaw

This comment has been minimized.

Show comment
Hide comment
@WillsonHaw

WillsonHaw Mar 12, 2017

It's the fact that aurelia-pal-browser initializes DOM.Element as the very first thing that it does. Because the initialization of DOM.Element in aurelia-pal is asynchronous, it's not ready when the DI is occuring in aurelia-templating. You can do the same thing by just creating an empty file with

import 'aurelia-pal-browser';
import {DOM} from 'aurelia-pal';
console.log(DOM.Element);

and

import {DOM} from 'aurelia-pal';
console.log(DOM.Element);

You'll notice in the first one DOM.Element exists, and the second one DOM.Element does not.

WillsonHaw commented Mar 12, 2017

It's the fact that aurelia-pal-browser initializes DOM.Element as the very first thing that it does. Because the initialization of DOM.Element in aurelia-pal is asynchronous, it's not ready when the DI is occuring in aurelia-templating. You can do the same thing by just creating an empty file with

import 'aurelia-pal-browser';
import {DOM} from 'aurelia-pal';
console.log(DOM.Element);

and

import {DOM} from 'aurelia-pal';
console.log(DOM.Element);

You'll notice in the first one DOM.Element exists, and the second one DOM.Element does not.

@jods4

This comment has been minimized.

Show comment
Hide comment
@jods4

jods4 Mar 12, 2017

Contributor

Yeah maybe we're getting closer.

But aurelia-bootstrapper initiliazes the PAL
https://github.com/aurelia/bootstrapper/blob/master/src/index.js#L108
before loading aurelia-framework (which loads the DI and the rest of the gang).

Contributor

jods4 commented Mar 12, 2017

Yeah maybe we're getting closer.

But aurelia-bootstrapper initiliazes the PAL
https://github.com/aurelia/bootstrapper/blob/master/src/index.js#L108
before loading aurelia-framework (which loads the DI and the rest of the gang).

@RichiCoder1

This comment has been minimized.

Show comment
Hide comment
@RichiCoder1

RichiCoder1 Mar 12, 2017

@jods4 In my case, it looks like when I add aurelia-validation to my vendor entry point using CommonsChunkPlugin, aurelia-templating, aurelia-pal, and aurelia-dependency-injection are all lifted w/ it, but not aurelia-pal-browser or aurelia-polyfills. Or at least the latter two don't "run first". This means I A) get the curious error caught TypeError: Reflect.getOwnMetadata is not a function because aurelia-polyfills isn't running before aurelia-metadata, and B) I'm 90% sure that aurelia-pal-browser isn't getting run before aurelia-templating's aurelia-pal, resulting the @inject(DOM.Element) on SlotCustomAttribute resolving to @inject(null). Does that make sense?

RichiCoder1 commented Mar 12, 2017

@jods4 In my case, it looks like when I add aurelia-validation to my vendor entry point using CommonsChunkPlugin, aurelia-templating, aurelia-pal, and aurelia-dependency-injection are all lifted w/ it, but not aurelia-pal-browser or aurelia-polyfills. Or at least the latter two don't "run first". This means I A) get the curious error caught TypeError: Reflect.getOwnMetadata is not a function because aurelia-polyfills isn't running before aurelia-metadata, and B) I'm 90% sure that aurelia-pal-browser isn't getting run before aurelia-templating's aurelia-pal, resulting the @inject(DOM.Element) on SlotCustomAttribute resolving to @inject(null). Does that make sense?

@RomkeVdMeulen

This comment has been minimized.

Show comment
Hide comment
@RomkeVdMeulen

RomkeVdMeulen Mar 16, 2017

Thanks for the comments so far. Based on this, I was able to create a workaround for my JSPM / Aurelia Bundler build by bundling aurelia-pal and aurelia-pal-browser separately from everything else, then adjusting the bootstrap sequence:

System.import('config.js')
		.then(function () {
			return System.import('aurelia-pal-browser');
		})
		.then(function (im) {
			im.initialize();
			return System.import('myBootstrap');
		});

It's not pretty, but by doing this at least I've gotten the SlotCustomAttribute working, as well as aurelia-validation's ValidationErrorsCustomAttribute which was giving me similar trouble. I may be able to slim down this workaround even further but I'll have to get back on that tomorrow.

UPDATE: the separate bundling doesn't seem to be necessary. Just make sure initialize is called before any other Aurelia module is loaded.

RomkeVdMeulen commented Mar 16, 2017

Thanks for the comments so far. Based on this, I was able to create a workaround for my JSPM / Aurelia Bundler build by bundling aurelia-pal and aurelia-pal-browser separately from everything else, then adjusting the bootstrap sequence:

System.import('config.js')
		.then(function () {
			return System.import('aurelia-pal-browser');
		})
		.then(function (im) {
			im.initialize();
			return System.import('myBootstrap');
		});

It's not pretty, but by doing this at least I've gotten the SlotCustomAttribute working, as well as aurelia-validation's ValidationErrorsCustomAttribute which was giving me similar trouble. I may be able to slim down this workaround even further but I'll have to get back on that tomorrow.

UPDATE: the separate bundling doesn't seem to be necessary. Just make sure initialize is called before any other Aurelia module is loaded.

@jods4

This comment has been minimized.

Show comment
Hide comment
@jods4

jods4 Mar 16, 2017

Contributor

@RomkeVdMeulen The normal initialization sequence would/should do this, so I'm curious what you have in myBootstrap.

Contributor

jods4 commented Mar 16, 2017

@RomkeVdMeulen The normal initialization sequence would/should do this, so I'm curious what you have in myBootstrap.

@WillsonHaw

This comment has been minimized.

Show comment
Hide comment
@WillsonHaw

WillsonHaw Mar 16, 2017

It should do this, but it's not. I had to do the same thing as @RomkeVdMeulen and manually initialize aurelia-pal-browser synchronously so that DOM.Element is ready when it's injected into SlotCustomAttribute.

WillsonHaw commented Mar 16, 2017

It should do this, but it's not. I had to do the same thing as @RomkeVdMeulen and manually initialize aurelia-pal-browser synchronously so that DOM.Element is ready when it's injected into SlotCustomAttribute.

@RomkeVdMeulen

This comment has been minimized.

Show comment
Hide comment
@RomkeVdMeulen

RomkeVdMeulen Mar 16, 2017

@jods4 All kinds of fun while we're slowly migrating our frontend from JSF to Aurelia. But it starts with:

import {Aurelia, LogManager, TemplatingEngine} from "aurelia-framework";
  1. Importing from aurelia-framework leads to loading of aurelia-templating.
  2. Loading aurelia-templating leads to (_dec6 = (0, _aureliaDependencyInjection.inject)(_aureliaPal.DOM.Element) being evaluated before bootstrap() has had a chance to run and _aureliaPal.DOM.Element is still uninitialized.
  3. Injecting undefined leads to the dark side...

So I would expect that basically any custom bootstrap that loads Aurelia modules with a dependency on aurelia-templating before calling bootstrap() would run into this problem eventually.

RomkeVdMeulen commented Mar 16, 2017

@jods4 All kinds of fun while we're slowly migrating our frontend from JSF to Aurelia. But it starts with:

import {Aurelia, LogManager, TemplatingEngine} from "aurelia-framework";
  1. Importing from aurelia-framework leads to loading of aurelia-templating.
  2. Loading aurelia-templating leads to (_dec6 = (0, _aureliaDependencyInjection.inject)(_aureliaPal.DOM.Element) being evaluated before bootstrap() has had a chance to run and _aureliaPal.DOM.Element is still uninitialized.
  3. Injecting undefined leads to the dark side...

So I would expect that basically any custom bootstrap that loads Aurelia modules with a dependency on aurelia-templating before calling bootstrap() would run into this problem eventually.

@jods4

This comment has been minimized.

Show comment
Hide comment
@jods4

jods4 Mar 16, 2017

Contributor

@RomkeVdMeulen I think that's the gist of it really.
Your custom bootstrap sequence loads aurelia-framework (or more accurately -- transitively -- aurelia-templating) before aurelia-pal-browser is initialized.

Now the question is: what do we want to make of this?

I think the boot sequence is a bit complicated. We could make import "aurelia-pal-browser" without requiring a call to initialize() but that would not definitely solve the problem, as the order of evaluation of import modules is not defined by the spec, AFAIK. So at the moment you have to load aurelia-framework dynamically when you are sure that the PAL was initialized.

The "natural" way to work around this would be an explicit dependency/import on the PAL from aurelia-templating, but the issue here is that aurelia-templating does not statically know which PAL we want to import (browser, node, worker...).

Contributor

jods4 commented Mar 16, 2017

@RomkeVdMeulen I think that's the gist of it really.
Your custom bootstrap sequence loads aurelia-framework (or more accurately -- transitively -- aurelia-templating) before aurelia-pal-browser is initialized.

Now the question is: what do we want to make of this?

I think the boot sequence is a bit complicated. We could make import "aurelia-pal-browser" without requiring a call to initialize() but that would not definitely solve the problem, as the order of evaluation of import modules is not defined by the spec, AFAIK. So at the moment you have to load aurelia-framework dynamically when you are sure that the PAL was initialized.

The "natural" way to work around this would be an explicit dependency/import on the PAL from aurelia-templating, but the issue here is that aurelia-templating does not statically know which PAL we want to import (browser, node, worker...).

@RomkeVdMeulen

This comment has been minimized.

Show comment
Hide comment
@RomkeVdMeulen

RomkeVdMeulen Mar 16, 2017

It's a difficult problem to be sure. One other alternative is to simply document the dependency and have people who want to setup custom booting manually initialize the PAL before loading any modules. Not exactly a very satisfying answer either, but I can't figure out a good solution for this problem.

RomkeVdMeulen commented Mar 16, 2017

It's a difficult problem to be sure. One other alternative is to simply document the dependency and have people who want to setup custom booting manually initialize the PAL before loading any modules. Not exactly a very satisfying answer either, but I can't figure out a good solution for this problem.

@WillsonHaw

This comment has been minimized.

Show comment
Hide comment
@WillsonHaw

WillsonHaw Mar 16, 2017

So in my case, my imports start with

import {bootstrap as bootstrapAurelia} from 'aurelia-bootstrapper';
import {Aurelia, PLATFORM} from 'aurelia-framework';

Because we need to use the Aurelia typings, we need to bring in framework before the bootstrapper is done initializing. Because of this, we get the same error and use the same workaround by manually importing aurelia-pal-browser

WillsonHaw commented Mar 16, 2017

So in my case, my imports start with

import {bootstrap as bootstrapAurelia} from 'aurelia-bootstrapper';
import {Aurelia, PLATFORM} from 'aurelia-framework';

Because we need to use the Aurelia typings, we need to bring in framework before the bootstrapper is done initializing. Because of this, we get the same error and use the same workaround by manually importing aurelia-pal-browser

@jods4

This comment has been minimized.

Show comment
Hide comment
@jods4

jods4 Mar 16, 2017

Contributor

Because we need to use the Aurelia typings

If you only use types (e.g. Aurelia), then the import will be removed by Typescript so aurelia-framework will not be loaded.

If you use PLATFORM as code then the module is imported and your are subject to the bug.

I believe you might be able to work around your problem by importing PLATFORM from aurelia-pal instead.

Contributor

jods4 commented Mar 16, 2017

Because we need to use the Aurelia typings

If you only use types (e.g. Aurelia), then the import will be removed by Typescript so aurelia-framework will not be loaded.

If you use PLATFORM as code then the module is imported and your are subject to the bug.

I believe you might be able to work around your problem by importing PLATFORM from aurelia-pal instead.

@m-andrew-albright

This comment has been minimized.

Show comment
Hide comment
@m-andrew-albright

m-andrew-albright Mar 17, 2017

For what it's worth, my team is using webpack 2, and I just hit this issue yesterday when trying to make use of named slots for the first time. We don't have crazy custom initialization or anything.

main.js imports:

import { LogManager } from 'aurelia-framework';
import { ConsoleAppender } from 'aurelia-logging-console';
import { HandleAuth } from 'handle-auth';
import 'whatwg-fetch';
import 'active-tab';
import 'bootstrap';
import 'babel-polyfill';
import 'sass-imports';

our dependencies (the relevant (I think) ones):

    "aurelia-animator-css": "1.0.1",
    "aurelia-binding": "1.2.0",
    "aurelia-bootstrapper-webpack": "1.1.0",
    "aurelia-dependency-injection": "1.3.0",
    "aurelia-dialog": "1.0.0-beta.3.0.1",
    "aurelia-event-aggregator": "1.0.1",
    "aurelia-fetch-client": "1.1.1",
    "aurelia-framework": "1.1.0",
    "aurelia-froala-editor": "2.5.0",
    "aurelia-history-browser": "1.0.0",
    "aurelia-i18n": "1.3.0",
    "aurelia-loader-webpack": "2.1.0",
    "aurelia-logging-console": "1.0.0",
    "aurelia-notification": "1.0.0",
    "aurelia-pal-browser": "1.1.0",
    "aurelia-polyfills": "1.2.0",
    "aurelia-route-recognizer": "1.1.0",
    "aurelia-router": "1.1.1",
    "aurelia-templating": "1.2.0",
    "aurelia-templating-binding": "1.2.0",
    "aurelia-templating-resources": "1.2.0",
    "aurelia-templating-router": "1.0.1",

and some possibly relevant devDependencies:

    "aurelia-protractor-plugin": "1.0.1",
    "aurelia-tools": "1.0.0",
    "aurelia-webpack-plugin": "1.2.0",
    "webpack": "2.2.1",

m-andrew-albright commented Mar 17, 2017

For what it's worth, my team is using webpack 2, and I just hit this issue yesterday when trying to make use of named slots for the first time. We don't have crazy custom initialization or anything.

main.js imports:

import { LogManager } from 'aurelia-framework';
import { ConsoleAppender } from 'aurelia-logging-console';
import { HandleAuth } from 'handle-auth';
import 'whatwg-fetch';
import 'active-tab';
import 'bootstrap';
import 'babel-polyfill';
import 'sass-imports';

our dependencies (the relevant (I think) ones):

    "aurelia-animator-css": "1.0.1",
    "aurelia-binding": "1.2.0",
    "aurelia-bootstrapper-webpack": "1.1.0",
    "aurelia-dependency-injection": "1.3.0",
    "aurelia-dialog": "1.0.0-beta.3.0.1",
    "aurelia-event-aggregator": "1.0.1",
    "aurelia-fetch-client": "1.1.1",
    "aurelia-framework": "1.1.0",
    "aurelia-froala-editor": "2.5.0",
    "aurelia-history-browser": "1.0.0",
    "aurelia-i18n": "1.3.0",
    "aurelia-loader-webpack": "2.1.0",
    "aurelia-logging-console": "1.0.0",
    "aurelia-notification": "1.0.0",
    "aurelia-pal-browser": "1.1.0",
    "aurelia-polyfills": "1.2.0",
    "aurelia-route-recognizer": "1.1.0",
    "aurelia-router": "1.1.1",
    "aurelia-templating": "1.2.0",
    "aurelia-templating-binding": "1.2.0",
    "aurelia-templating-resources": "1.2.0",
    "aurelia-templating-router": "1.0.1",

and some possibly relevant devDependencies:

    "aurelia-protractor-plugin": "1.0.1",
    "aurelia-tools": "1.0.0",
    "aurelia-webpack-plugin": "1.2.0",
    "webpack": "2.2.1",
@RomkeVdMeulen

This comment has been minimized.

Show comment
Hide comment
@RomkeVdMeulen

RomkeVdMeulen Mar 17, 2017

@m-andrew-albright Just import { LogManager } from 'aurelia-framework'; is enough to trigger this problem. You might be able to work around this by only loading the logging code and setting it up after bootstrap() has run. Or you can call initialize() from aurelia-pal-browser before loading your main.js.

RomkeVdMeulen commented Mar 17, 2017

@m-andrew-albright Just import { LogManager } from 'aurelia-framework'; is enough to trigger this problem. You might be able to work around this by only loading the logging code and setting it up after bootstrap() has run. Or you can call initialize() from aurelia-pal-browser before loading your main.js.

@jods4

This comment has been minimized.

Show comment
Hide comment
@jods4

jods4 Mar 17, 2017

Contributor

@m-andrew-albright
LogManager from aurelia-framework is basically export * as LogManager from 'aurelia-logging'.
By taking a dependency on aurelia-logging directly you might work around the issue.

Contributor

jods4 commented Mar 17, 2017

@m-andrew-albright
LogManager from aurelia-framework is basically export * as LogManager from 'aurelia-logging'.
By taking a dependency on aurelia-logging directly you might work around the issue.

@jods4

This comment has been minimized.

Show comment
Hide comment
@jods4

jods4 Apr 1, 2017

Contributor

A quick note after seeing several upgrading users hitting this.

This issue is made more prominent because of CommonsChunkPlugin and the pattern that was suggested by @easy-webpack.

Many users have taken the (bad) habit of listing all their aurelia modules as entry point in a vendor chunk and then including that in the page.
Because they are all entry points, they are executed before aurelia-pal is properly initialized and there's at least one module that can't be loaded before the PAL is initialized and triggers this bug.

I think we need to mitigate this issue but I'm not sure how:

  • It seems bad that module have visible side-effects and can't be loaded in any order (I don't know which module exactly is at fault here)?
  • Should we force PAL initialization earlier, e.g. from the webpack build itself? Probably won't work because vendor bundles are included first.
  • If importing aurelia-pal-browser was enough to properly initialize it, then it would probably be a lot easier. Listing it first in the vendor entries would then work?
  • Com: we could fix the easy-webpack config and educate on how to create a vendor bundle that doesn't execute its contents (e.g. by putting the commons in a brand new chunk and importing that).
Contributor

jods4 commented Apr 1, 2017

A quick note after seeing several upgrading users hitting this.

This issue is made more prominent because of CommonsChunkPlugin and the pattern that was suggested by @easy-webpack.

Many users have taken the (bad) habit of listing all their aurelia modules as entry point in a vendor chunk and then including that in the page.
Because they are all entry points, they are executed before aurelia-pal is properly initialized and there's at least one module that can't be loaded before the PAL is initialized and triggers this bug.

I think we need to mitigate this issue but I'm not sure how:

  • It seems bad that module have visible side-effects and can't be loaded in any order (I don't know which module exactly is at fault here)?
  • Should we force PAL initialization earlier, e.g. from the webpack build itself? Probably won't work because vendor bundles are included first.
  • If importing aurelia-pal-browser was enough to properly initialize it, then it would probably be a lot easier. Listing it first in the vendor entries would then work?
  • Com: we could fix the easy-webpack config and educate on how to create a vendor bundle that doesn't execute its contents (e.g. by putting the commons in a brand new chunk and importing that).
@RomkeVdMeulen

This comment has been minimized.

Show comment
Hide comment
@RomkeVdMeulen

RomkeVdMeulen Feb 23, 2018

Still running into this nearly a year later. Any closer to a solution?

RomkeVdMeulen commented Feb 23, 2018

Still running into this nearly a year later. Any closer to a solution?

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Feb 23, 2018

Member

It must somehow be related to the loading of the PAL. @jods4 Do you have any idea how we can help @RomkeVdMeulen out here? From a code perspective, the SlotCustomAttribute is very basic and isn't doing anything special. Full source:

@inject(DOM.Element)
export class SlotCustomAttribute {
  constructor(element) {
    this.element = element;
    this.element.auSlotAttribute = this;
  }

  valueChanged(newValue, oldValue) {

  }
}

Any ideas?

Member

EisenbergEffect commented Feb 23, 2018

It must somehow be related to the loading of the PAL. @jods4 Do you have any idea how we can help @RomkeVdMeulen out here? From a code perspective, the SlotCustomAttribute is very basic and isn't doing anything special. Full source:

@inject(DOM.Element)
export class SlotCustomAttribute {
  constructor(element) {
    this.element = element;
    this.element.auSlotAttribute = this;
  }

  valueChanged(newValue, oldValue) {

  }
}

Any ideas?

@jods4

This comment has been minimized.

Show comment
Hide comment
@jods4

jods4 Feb 23, 2018

Contributor

@EisenbergEffect I don't think much has changed since I last looked at this issue last year.

The problem is not in SlotCustomAttribute but in the PAL initialization sequence.

I have long forgotten the details, but I think this comment sums up the root cause; and this one describes why a common webpack pattern trips you into this bad situation and suggests a few possible work-arounds.

I am not sure what a good proper fix would be, sadly. Initialization of Aurelia is a bit convoluted. Some modules have side-effects and some have initialization functions that must be called and some complete async...

Contributor

jods4 commented Feb 23, 2018

@EisenbergEffect I don't think much has changed since I last looked at this issue last year.

The problem is not in SlotCustomAttribute but in the PAL initialization sequence.

I have long forgotten the details, but I think this comment sums up the root cause; and this one describes why a common webpack pattern trips you into this bad situation and suggests a few possible work-arounds.

I am not sure what a good proper fix would be, sadly. Initialization of Aurelia is a bit convoluted. Some modules have side-effects and some have initialization functions that must be called and some complete async...

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Feb 24, 2018

Member

On a positive note, the stuff we're doing for the experimental vNext will solve all of these problems. in the mean time, we might just need to do a bit of official documentation to provide guidance. Anyone up for putting that together?

Member

EisenbergEffect commented Feb 24, 2018

On a positive note, the stuff we're doing for the experimental vNext will solve all of these problems. in the mean time, we might just need to do a bit of official documentation to provide guidance. Anyone up for putting that together?

@RomkeVdMeulen

This comment has been minimized.

Show comment
Hide comment
@RomkeVdMeulen

RomkeVdMeulen Feb 24, 2018

I can do that. It took a while to find the workaround, I'd be happy to share it. I'll work on it monday.

RomkeVdMeulen commented Feb 24, 2018

I can do that. It took a while to find the workaround, I'd be happy to share it. I'll work on it monday.

@RomkeVdMeulen

This comment has been minimized.

Show comment
Hide comment
@RomkeVdMeulen

RomkeVdMeulen Feb 26, 2018

Hmm, I should probable add something to http://aurelia.io/docs/fundamentals/app-configuration-and-startup about this. However, the docs currently start with a simple custom bootstrap by adding a configuration module and setting that to the aurelia-app attribute. It will be hard to explain to people why the first example in that article will work fine, but the second one may run into this problem (especially when looking at the TypeScript examples, where the first one does an import that doesn't trigger the problem because it is used as a type, not a value). And to apply this workaround, you have to do stuff before System.import('aurelia-bootstrapper') is called, which is more complex than simple changing aurelia-app in your master template.

@EisenbergEffect: you originally wrote this doc article. How would you suggest we warn people about this? Perhaps we should add a notice somewhere between the first and second code samples that links to this issue?

RomkeVdMeulen commented Feb 26, 2018

Hmm, I should probable add something to http://aurelia.io/docs/fundamentals/app-configuration-and-startup about this. However, the docs currently start with a simple custom bootstrap by adding a configuration module and setting that to the aurelia-app attribute. It will be hard to explain to people why the first example in that article will work fine, but the second one may run into this problem (especially when looking at the TypeScript examples, where the first one does an import that doesn't trigger the problem because it is used as a type, not a value). And to apply this workaround, you have to do stuff before System.import('aurelia-bootstrapper') is called, which is more complex than simple changing aurelia-app in your master template.

@EisenbergEffect: you originally wrote this doc article. How would you suggest we warn people about this? Perhaps we should add a notice somewhere between the first and second code samples that links to this issue?

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Feb 26, 2018

Member

@RomkeVdMeulen Give that a try. Ping me when you submit the PR and we can go over it together through comments, refining it until we think it's clear.

Member

EisenbergEffect commented Feb 26, 2018

@RomkeVdMeulen Give that a try. Ping me when you submit the PR and we can go over it together through comments, refining it until we think it's clear.

@RomkeVdMeulen

This comment has been minimized.

Show comment
Hide comment
@RomkeVdMeulen

RomkeVdMeulen Feb 27, 2018

Is there any way for me to build and preview my changes to the doc article?

RomkeVdMeulen commented Feb 27, 2018

Is there any way for me to build and preview my changes to the doc article?

RomkeVdMeulen added a commit to RomkeVdMeulen/framework that referenced this issue Feb 27, 2018

doc(app-config): add a warning about aurelia/pal-browser#17
Users need to manually initialize the PAL before importing Aurelia
modules in their configuration module.
@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Feb 27, 2018

Member

It's a bit of a pain. In general, if it looks ok on GitHub, it should be fine on our site. I test all the new content and am happy to make any fixes for you. Don't worry too much about it.

Member

EisenbergEffect commented Feb 27, 2018

It's a bit of a pain. In general, if it looks ok on GitHub, it should be fine on our site. I test all the new content and am happy to make any fixes for you. Don't worry too much about it.

EisenbergEffect added a commit to aurelia/framework that referenced this issue Feb 27, 2018

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Feb 27, 2018

Member

Going to close this issue for now since it's documented and since we're already got this solved in our vNext work.

Member

EisenbergEffect commented Feb 27, 2018

Going to close this issue for now since it's documented and since we're already got this solved in our vNext work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment