Skip to content

Commit

Permalink
fix(lifecycles): defer connectedCallback processing until all compone…
Browse files Browse the repository at this point in the history
…nts are registered (#1930)
  • Loading branch information
robinsummerhill authored and manucorporat committed Oct 9, 2019
1 parent f5817a0 commit 0f302eb
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/runtime/bootstrap-lazy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export const bootstrapLazy = (lazyBundles: d.LazyBundlesRuntimeData, options: d.
const y = /*@__PURE__*/head.querySelector('meta[charset]');
const visibilityStyle = /*@__PURE__*/doc.createElement('style');
let appLoadFallback: any;
const deferredConnectedCallbacks: {connectedCallback: () => void}[] = [];
let isBootstrapping = true;

Object.assign(plt, options);
plt.$resourcesUrl$ = new URL(options.resourcesUrl || './', doc.baseURI).href;
if (options.syncQueue) {
Expand Down Expand Up @@ -100,11 +103,17 @@ export const bootstrapLazy = (lazyBundles: d.LazyBundlesRuntimeData, options: d.
}

connectedCallback() {
if (appLoadFallback) {
clearTimeout(appLoadFallback);
appLoadFallback = null;
if (isBootstrapping) {
// connectedCallback will be processed once all components have been registered
deferredConnectedCallbacks.push(this);
} else {
if (appLoadFallback) {
clearTimeout(appLoadFallback);
appLoadFallback = null;
}

plt.jmp(() => connectedCallback(this, cmpMeta));
}
plt.jmp(() => connectedCallback(this, cmpMeta));
}

disconnectedCallback() {
Expand Down Expand Up @@ -135,6 +144,10 @@ export const bootstrapLazy = (lazyBundles: d.LazyBundlesRuntimeData, options: d.
}
}));

// Process deferred connectedCallbacks now all components have been registered
isBootstrapping = false;
deferredConnectedCallbacks.forEach(host => host.connectedCallback());

// visibilityStyle.innerHTML = cmpTags.map(t => `${t}:not(.hydrated)`) + '{display:none}';
visibilityStyle.innerHTML = cmpTags + '{visibility:hidden}.hydrated{visibility:inherit}';
visibilityStyle.setAttribute('data-styles', '');
Expand Down
33 changes: 33 additions & 0 deletions test/karma/test-app/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ export namespace Components {
'strAttr'?: string;
}
interface BadSharedJsx {}
interface CmpA {}
interface CmpB {}
interface CmpC {}
interface ConditionalBasic {}
interface ConditionalRerender {}
interface ConditionalRerenderRoot {}
Expand Down Expand Up @@ -236,6 +239,24 @@ declare global {
new (): HTMLBadSharedJsxElement;
};

interface HTMLCmpAElement extends Components.CmpA, HTMLStencilElement {}
var HTMLCmpAElement: {
prototype: HTMLCmpAElement;
new (): HTMLCmpAElement;
};

interface HTMLCmpBElement extends Components.CmpB, HTMLStencilElement {}
var HTMLCmpBElement: {
prototype: HTMLCmpBElement;
new (): HTMLCmpBElement;
};

interface HTMLCmpCElement extends Components.CmpC, HTMLStencilElement {}
var HTMLCmpCElement: {
prototype: HTMLCmpCElement;
new (): HTMLCmpCElement;
};

interface HTMLConditionalBasicElement extends Components.ConditionalBasic, HTMLStencilElement {}
var HTMLConditionalBasicElement: {
prototype: HTMLConditionalBasicElement;
Expand Down Expand Up @@ -742,6 +763,9 @@ declare global {
'attribute-host': HTMLAttributeHostElement;
'attribute-html-root': HTMLAttributeHtmlRootElement;
'bad-shared-jsx': HTMLBadSharedJsxElement;
'cmp-a': HTMLCmpAElement;
'cmp-b': HTMLCmpBElement;
'cmp-c': HTMLCmpCElement;
'conditional-basic': HTMLConditionalBasicElement;
'conditional-rerender': HTMLConditionalRerenderElement;
'conditional-rerender-root': HTMLConditionalRerenderRootElement;
Expand Down Expand Up @@ -859,6 +883,9 @@ declare namespace LocalJSX {
'strAttr'?: string;
}
interface BadSharedJsx {}
interface CmpA {}
interface CmpB {}
interface CmpC {}
interface ConditionalBasic {}
interface ConditionalRerender {}
interface ConditionalRerenderRoot {}
Expand Down Expand Up @@ -1012,6 +1039,9 @@ declare namespace LocalJSX {
'attribute-host': AttributeHost;
'attribute-html-root': AttributeHtmlRoot;
'bad-shared-jsx': BadSharedJsx;
'cmp-a': CmpA;
'cmp-b': CmpB;
'cmp-c': CmpC;
'conditional-basic': ConditionalBasic;
'conditional-rerender': ConditionalRerender;
'conditional-rerender-root': ConditionalRerenderRoot;
Expand Down Expand Up @@ -1112,6 +1142,9 @@ declare module "@stencil/core" {
'attribute-host': LocalJSX.AttributeHost & JSXBase.HTMLAttributes<HTMLAttributeHostElement>;
'attribute-html-root': LocalJSX.AttributeHtmlRoot & JSXBase.HTMLAttributes<HTMLAttributeHtmlRootElement>;
'bad-shared-jsx': LocalJSX.BadSharedJsx & JSXBase.HTMLAttributes<HTMLBadSharedJsxElement>;
'cmp-a': LocalJSX.CmpA & JSXBase.HTMLAttributes<HTMLCmpAElement>;
'cmp-b': LocalJSX.CmpB & JSXBase.HTMLAttributes<HTMLCmpBElement>;
'cmp-c': LocalJSX.CmpC & JSXBase.HTMLAttributes<HTMLCmpCElement>;
'conditional-basic': LocalJSX.ConditionalBasic & JSXBase.HTMLAttributes<HTMLConditionalBasicElement>;
'conditional-rerender': LocalJSX.ConditionalRerender & JSXBase.HTMLAttributes<HTMLConditionalRerenderElement>;
'conditional-rerender-root': LocalJSX.ConditionalRerenderRoot & JSXBase.HTMLAttributes<HTMLConditionalRerenderRootElement>;
Expand Down
20 changes: 20 additions & 0 deletions test/karma/test-app/lifecycle-nested/cmp-a.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Component, h } from "@stencil/core";
import output from "./output";

@Component({
tag: "cmp-a",
shadow: true
})
export class Cmpa {
async componentWillLoad() {
output("componentWillLoad-a");
}

async componentDidLoad() {
output("componentDidLoad-a");
}

render() {
return <slot />;
}
}
20 changes: 20 additions & 0 deletions test/karma/test-app/lifecycle-nested/cmp-b.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {Component, h } from "@stencil/core";
import output from "./output";

@Component({
tag: "cmp-b",
shadow: true
})
export class Cmpb {
async componentWillLoad() {
output("componentWillLoad-b");
}

async componentDidLoad() {
output("componentDidLoad-b");
}

render() {
return <slot />;
}
}
20 changes: 20 additions & 0 deletions test/karma/test-app/lifecycle-nested/cmp-c.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Host, Component, h } from "@stencil/core";
import output from "./output";

@Component({
tag: "cmp-c",
shadow: true
})
export class Cmpc {
async componentWillLoad() {
output("componentWillLoad-c");
}

componentDidLoad() {
output("componentDidLoad-c");
}

render() {
return( <Host><div>hello</div></Host>);
}
}
14 changes: 14 additions & 0 deletions test/karma/test-app/lifecycle-nested/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<meta charset="utf8" />
<script src="/build/testapp.esm.js" type="module"></script>
<script src="/build/testapp.js" nomodule></script>

<!-- Component are nested in reverse alphabetical order -->

<cmp-c>
<cmp-b>
<cmp-a></cmp-a>
</cmp-b>
</cmp-c>

<ol id="lifecycle-loads" class="lifecycle-loads"></ol>
24 changes: 24 additions & 0 deletions test/karma/test-app/lifecycle-nested/karma.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { setupDomTests } from '../util';


describe('lifecycle-nested', function() {
const { setupDom, tearDownDom } = setupDomTests(document);
let app: HTMLElement;

beforeEach(async () => {
app = await setupDom('/lifecycle-nested/index.html');
});
afterEach(tearDownDom);

it('fire load methods in order for nested elements', async () => {
let loads = app.querySelectorAll('.lifecycle-loads li');
expect(loads.length).toBe(6);
expect(loads[0].textContent).toBe('componentWillLoad-c');
expect(loads[1].textContent).toBe('componentWillLoad-b');
expect(loads[2].textContent).toBe('componentWillLoad-a');
expect(loads[3].textContent).toBe('componentDidLoad-a');
expect(loads[4].textContent).toBe('componentDidLoad-b');
expect(loads[5].textContent).toBe('componentDidLoad-c');
});

});
5 changes: 5 additions & 0 deletions test/karma/test-app/lifecycle-nested/output.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default function(msg: string, id = "lifecycle-loads") {
const listEntry = document.createElement("li");
listEntry.innerText = msg;
document.getElementById(id)!.appendChild(listEntry);
}

0 comments on commit 0f302eb

Please sign in to comment.