chore(): update core providers

This commit is contained in:
Adam Bradley
2017-06-14 22:45:01 -05:00
parent d406c45226
commit 041b45f8aa
3 changed files with 162 additions and 53 deletions

View File

@ -60,58 +60,108 @@ export function setupCore(config: Config, plt: Platform, domCtrl: DomController,
function getQueueController(win: any, zone: NgZone) { function getQueueController(win: any, zone: NgZone) {
const hostScheduleDefer: Function = win['requestIdleCallback']; function now() {
const callbacks: Function[] = []; return win.performance.now();
let pending = false; }
function doWork(deadlineObj: any) { const highPromise = Promise.resolve();
// let's see if we've got time to take care of things
while (deadlineObj.timeRemaining() > 1 && callbacks.length > 0) { const highCallbacks: Function[] = [];
// do some work while within the allowed time const mediumCallbacks: Function[] = [];
// shift the array and fire off the callbacks from the beginning const lowCallbacks: Function[] = [];
// once we run out of time or callbacks we'll stop
callbacks.shift()(); let resolvePending = false;
let ricPending = false;
function doHighPriority() {
// holy geez we need to get this stuff done and fast
// all high priority callbacks should be fired off immediately
while (highCallbacks.length > 0) {
highCallbacks.shift()();
}
resolvePending = false;
}
function doWork() {
const start = now();
// always run all of the high priority work if there is any
doHighPriority();
while (mediumCallbacks.length > 0 && (now() - start < 40)) {
mediumCallbacks.shift()();
}
if (mediumCallbacks.length === 0) {
// we successfully drained the medium queue or the medium queue is empty
// so now let's drain the low queue with our remaining time
while (lowCallbacks.length > 0 && (now() - start < 40)) {
lowCallbacks.shift()();
}
} }
// check to see if we still have work to do // check to see if we still have work to do
if (pending = (callbacks.length > 0)) { if (ricPending = (mediumCallbacks.length > 0 || lowCallbacks.length > 0)) {
// everyone just settle down now // everyone just settle down now
// we already don't have time to do anything in this callback // we already don't have time to do anything in this callback
// let's throw the next one in a requestAnimationFrame // let's throw the next one in a requestAnimationFrame
// so we can just simmer down for a bit // so we can just simmer down for a bit
zone.runOutsideAngular(() => { zone.runOutsideAngular(() => {
requestAnimationFrame(flush); win.requestAnimationFrame(flush);
}); });
} }
} }
function flush() { function flush() {
// always force a bunch of callbacks to run, but still have // always run all of the high priority work if there is any
doHighPriority();
// always force a bunch of medium callbacks to run, but still have
// a throttle on how many can run in a certain time // a throttle on how many can run in a certain time
const start = performance.now(); const start = now();
while (callbacks.length > 0 && (performance.now() - start < 4)) { while (mediumCallbacks.length > 0 && (now() - start < 4)) {
callbacks.shift()(); mediumCallbacks.shift()();
} }
if (pending = (callbacks.length > 0)) { if (ricPending = (mediumCallbacks.length > 0 || lowCallbacks.length > 0)) {
// still more to do yet, but we've run out of time // still more to do yet, but we've run out of time
// let's let thing cool off and try again after a raf // let's let this thing cool off and try again in the next ric
zone.runOutsideAngular(() => { zone.runOutsideAngular(() => {
hostScheduleDefer(doWork); win.requestAnimationFrame(doWork);
}); });
} }
} }
function add(cb: Function) { function add(cb: Function, priority?: number) {
// add the work to the end of the callbacks if (priority === 3) {
callbacks.push(cb); // uses Promise.resolve() for next tick
highCallbacks.push(cb);
if (!pending) { if (!resolvePending) {
// not already pending work to do, so let's tee it up // not already pending work to do, so let's tee it up
pending = true; resolvePending = true;
zone.runOutsideAngular(() => { highPromise.then(doHighPriority);
hostScheduleDefer(doWork); }
});
} else {
if (priority === 1) {
lowCallbacks.push(cb);
} else {
// defaults to medium priority
// uses requestIdleCallback
mediumCallbacks.push(cb);
}
if (!ricPending) {
// not already pending work to do, so let's tee it up
ricPending = true;
zone.runOutsideAngular(() => {
win.requestAnimationFrame(doWork);
});
}
} }
} }

View File

@ -102,6 +102,14 @@ export class DomController {
} }
} }
now() {
return this.plt.win().performance.now();
}
raf(cb: any) {
return this.plt.raf(cb);
}
private _queue() { private _queue() {
const self = this; const self = this;
if (!self.q) { if (!self.q) {

View File

@ -260,6 +260,7 @@ export interface DomControllerApi {
read: DomControllerCallback; read: DomControllerCallback;
write: DomControllerCallback; write: DomControllerCallback;
raf: DomControllerCallback; raf: DomControllerCallback;
now(): number;
} }
export interface RafCallback { export interface RafCallback {
@ -285,15 +286,20 @@ export interface LoadComponentData {
[modeCode: string]: string; [modeCode: string]: string;
}; };
/**
* slot meta
*/
[2]: number;
/** /**
* props * props
*/ */
[2]: any[]; [3]: any[];
/** /**
* bundle priority * bundle priority
*/ */
[3]: LoadPriority; [4]: LoadPriority;
} }
@ -413,7 +419,7 @@ export interface ComponentWatchersData {
export interface ModulesImporterFn { export interface ModulesImporterFn {
(importer: any, h: Function, Ionic: Ionic): void; (importer: any, h: Function, t: Function, Ionic: Ionic): void;
} }
@ -527,8 +533,7 @@ export interface ComponentMeta {
modesMeta?: {[modeCode: string]: ModeMeta}; modesMeta?: {[modeCode: string]: ModeMeta};
isShadowMeta?: boolean; isShadowMeta?: boolean;
hostMeta?: HostMeta; hostMeta?: HostMeta;
hasSlotsMeta?: boolean; slotMeta?: number;
namedSlotsMeta?: string[];
componentModuleMeta?: any; componentModuleMeta?: any;
priorityMeta?: LoadPriority; priorityMeta?: LoadPriority;
} }
@ -618,7 +623,7 @@ export interface HostElement extends HTMLElement {
$instance?: Component; $instance?: Component;
// private methods // private methods
_render: (isInitialRender: boolean) => void; _render: (isUpdateRender?: boolean) => void;
_initLoad: () => void; _initLoad: () => void;
_queueUpdate: () => void; _queueUpdate: () => void;
@ -638,25 +643,23 @@ export interface HostElement extends HTMLElement {
export interface RendererApi { export interface RendererApi {
(oldVnode: VNode | Element, vnode: VNode, hostContentNodes?: HostContentNodes, hydrating?: boolean): VNode; (oldVNode: VNode | Element, newVNode: VNode, isUpdate?: boolean, hostContentNodes?: HostContentNodes): VNode;
} }
export interface DomApi { export interface DomApi {
$head: HTMLHeadElement; $head: HTMLHeadElement;
$body: HTMLElement; $body: HTMLElement;
$isElement(node: any): boolean; $nodeType(node: any): number;
$isText(node: any): boolean;
$isComment(node: any): boolean;
$createEvent(): CustomEvent; $createEvent(): CustomEvent;
$createElement<K extends keyof HTMLElementTagNameMap>(tagName: K): HTMLElementTagNameMap[K]; $createElement<K extends keyof HTMLElementTagNameMap>(tagName: K): HTMLElementTagNameMap[K];
$createElement(tagName: string): HTMLElement; $createElement(tagName: string): HTMLElement;
$createElementNS(namespace: string, tagName: string): any; $createElementNS(namespace: string, tagName: string): any;
$createTextNode(text: string): Text; $createTextNode(text: string): Text;
$createComment(text: string): Comment;
$insertBefore(parentNode: Node, newNode: Node, referenceNode: Node): void; $insertBefore(parentNode: Node, newNode: Node, referenceNode: Node): void;
$removeChild(node: Node, child: Node): void; $removeChild(node: Node, child: Node): void;
$appendChild(node: Node, child: Node): void; $appendChild(node: Node, child: Node): void;
$childNodes(node: Node): NodeList;
$parentNode(node: Node): Node; $parentNode(node: Node): Node;
$nextSibling(node: Node): Node; $nextSibling(node: Node): Node;
$tagName(elm: any): string; $tagName(elm: any): string;
@ -683,32 +686,80 @@ export interface Hyperscript {
} }
export interface VNode {
sel?: string | undefined;
vdata?: VNodeData | undefined;
vchildren?: Array<VNode | string> | undefined;
elm?: Node | undefined | HostElement;
vtext?: string | undefined;
vkey?: Key;
}
export interface HostContentNodes { export interface HostContentNodes {
defaultSlot?: Node[]; defaultSlot?: Node[];
namedSlots?: {[slotName: string]: Node[]}; namedSlots?: {[slotName: string]: Node[]};
} }
export type CssClassObject = { [className: string]: boolean }; export type CssClassObject = { [className: string]: boolean };
export interface VNode {
// using v prefixes largely so closure has no issue property renaming
vtag: string;
vtext: string;
vchildren: VNode[];
vprops: any;
vattrs: any;
vclass: CssClassObject;
vstyle: any;
vlisteners: any;
vkey: Key;
elm: Element|Node;
vnamespace: any;
assignedListener: any;
skipDataOnUpdate: boolean;
skipChildrenOnUpdate: boolean;
}
export interface VNodeData { export interface VNodeData {
props?: any; props?: any;
attrs?: any; attrs?: any;
class?: CssClassObject; class?: CssClassObject;
style?: any; style?: any;
dataset?: any;
on?: any; on?: any;
vkey?: Key; key?: Key;
vns?: string; // for SVGs ns?: any; // for SVGs
}
/**
* used by production compiler
*/
export interface VNodeProdData {
/**
* props
*/
p?: any;
/**
* attrs
*/
a?: any;
/**
* css classes
*/
c?: CssClassObject;
/**
* styles
*/
s?: any;
/**
* on (event listeners)
*/
o?: any;
/**
* key
*/
k?: Key;
/**
* namespace
*/
n?: any;
/**
* check once
*/
x?: number;
} }
@ -719,7 +770,7 @@ export interface PlatformApi {
loadBundle: (bundleId: string, priority: LoadPriority, cb: Function) => void; loadBundle: (bundleId: string, priority: LoadPriority, cb: Function) => void;
render?: RendererApi; render?: RendererApi;
config: ConfigApi; config: ConfigApi;
collectHostContent: (elm: HostElement, validNamedSlots: string[]) => void; collectHostContent: (elm: HostElement, slotMeta: number) => void;
queue: QueueApi; queue: QueueApi;
css?: {[cmpModeId: string]: string}; css?: {[cmpModeId: string]: string};
isServer?: boolean; isServer?: boolean;