Webcomponents: JSON and CSS modules dynamic import

Created on 10 Sep 2019  路  5Comments  路  Source: WICG/webcomponents

When preparing the initial implementation of JSON modules in Blink, we noticed a potentially interesting issue with dynamic import.

The original JSON module WPT test for dynamic import expected this behavior:

const result = await import(`./resource.json`);
assert_equals(result, value); // where 'value' is the same as the JSON object in resource.json

However, given the existing behavior of Synthetic Modules with dynamic import(), result actually ends up being the namespace object for the imported module, and the importer needs to check the default property to get the actual value:

const result = await import(`./resource.json`);
assert_equals(result.default, value); // where 'value' is the JSON object in resource.json

One can argue that this was just a bug in the initial test, and we did in fact end up changing the test as part of submitting the Blink code change.

It doesn't quite seem ideal ideal to make the importer dig into the namespace object's default property, but it is consistent with the existing semantics for default exports. I'm not sure whether it's a serious enough problem to consider changing the semantics of how these work. A solution would either require reimplementing JSON modules without Synthetic Modules, or extending Synthetic Modules in some way, perhaps with an addition of a custom FinishModuleImport-like callback where the implementer of the Synthetic Module can customize what gets returned from an import() of the module.

All of the above applies to CSS modules in the same way, as these too are built as a Synthetic Module with a single default export of the stylesheet.

Thoughts?
cc: @littledan @ms2ger @travisleithead @bocupp @samsebree @domenic @justinfagnani

Most helpful comment

Thanks all -- I'll consider the issue closed as there seems to be a pretty clear agreement on the direction here.

All 5 comments

This is totally reasonable and expected from my perspective. I don't think there's any other possible semantics for combining the JS module system and its default export concept.

I agree with the above, this is expected given the semantics of modules. You also can't do import { deep } from './resource.json';. This is actually a little nicer with dynamic import because at least you can destruct there: const { deep } = (await import('./resource.json')).default;

Agreed with @domenic and @matthewp as well as this:

All of the above applies to CSS modules in the same way, as these too are built as a Synthetic Module with a single default export of the stylesheet.

For CSS modules a single default export is potentially only a starting point. I have a follow-on proposal to allow for exports from a CSS module: https://github.com/w3c/csswg-drafts/issues/3714 For that we would need dynamic import to work as it does with JS modules.

Thanks all -- I'll consider the issue closed as there seems to be a pretty clear agreement on the direction here.

The initial expectation of the test case was indeed just a mistake on my side. Thanks for following up!

Was this page helpful?
0 / 5 - 0 ratings