View Async Module

Async Module Initialization with Inline Modules

The Problem

Modules may need to load non-JS resources that would clearly categorized as dependencies - the module is not truly ready until those resources are (example: templates for UI components). Loading APIs, like fetch() are asynchronous, and there is currently no way to make a module wait for asynchronous calls.

The Problem with Top-Level await

Top-level await, which would block execution within a module on a await expression, has been proposed as a way to solve this problem. It has a critical problem as highlighted here by Rich Harris.


Scoped Custom Element Definitions


Scoped Custom Element definitions is an oft-requested feature of Web Components. The global registry is a possible source of name collisions that may arise from coincidence, or from an app trying to define multiple versions of the same element, or from more advanced scenarios like registering mocks during tests, or a component explicitly replacing an element definition for its scope.

Since the key DOM creation APIs are global, scoping definitions is tricky because we'd need a machanis to determind which scope to use. But if we offer scoped versions of these APIs the problem is tractable. This requires that DOM creation code is upgraded to use the new scoped APIs, something that hopefully could be done in template libraries and frameworks.

This proposal adds the ability to construct CustomElementRegistrys and chain them in order to inherit custom element definitions. It uses ShadowRoot as a scope for definitions. ShadowRoot can be associated with a

View findIndexAsync.js
async function findIndexAsync(promises, predicate) {
let i = 0;
for await (const p of asyncIterate(promises)) {
if (predicate(p)) {
return i;
View custom-element-conformance.js
const NativeHTMLElement = window.HTMLElement;
const documentWrite = document.write;
const documentOpen =;
window.HTMLElement = class extends NativeHTMLElement {
constructor(...args) {
console.assert(args.length === 0);
View index.html
<!doctype html>
<script src="shadow-root.js"></script>
<div slot="main">
I'm some projected content.
View designer.html
<link rel="import" href="../polymer/polymer.html">
<polymer-element name="my-element">
:host {
position: absolute;
width: 100%;
height: 100%;
View gist-server.json
"font-roboto": "",
"iron-flex-layout": "",
"paper-material": "",
"paper-styles": "",
"polymer": "",
"webcomponentsjs": ""
View gist-server.json
"polymer": "",
"webcomponentsjs": ""
View gist:6aec137ed97cfa3db002
is: 'x-foo',
ready() {
// provides a FooService to descendents
this.provideInstance('foo-service', new FooService());
attached() {
// requests a BarService from an ancestor, re-requests if moved