diff --git a/packages/core/src/render3/component.ts b/packages/core/src/render3/component.ts index 50ac44e53eb41..02b08e98e363e 100644 --- a/packages/core/src/render3/component.ts +++ b/packages/core/src/render3/component.ts @@ -21,11 +21,11 @@ import {CLEAN_PROMISE, createLViewData, createNodeAtIndex, createTView, getOrCre import {ComponentDef, ComponentType} from './interfaces/definition'; import {TElementNode, TNodeFlags, TNodeType} from './interfaces/node'; import {PlayerHandler} from './interfaces/player'; -import {RElement, RNode, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer'; +import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer'; import {CONTEXT, HEADER_OFFSET, HOST, HOST_NODE, INJECTOR, LViewData, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view'; import {publishDefaultGlobalUtils} from './publish_global_util'; import {enterView, leaveView, resetComponentState} from './state'; -import {getRootView, readElementValue, readPatchedLViewData, stringify} from './util'; +import {defaultScheduler, getRootView, readElementValue, readPatchedLViewData, stringify} from './util'; /** Options that control how the component should be bootstrapped. */ @@ -117,8 +117,7 @@ export function renderComponent( const hostRNode = locateHostElement(rendererFactory, opts.host || componentTag); const rootFlags = componentDef.onPush ? LViewFlags.Dirty | LViewFlags.IsRoot : LViewFlags.CheckAlways | LViewFlags.IsRoot; - const rootContext = createRootContext( - opts.scheduler || requestAnimationFrame.bind(window), opts.playerHandler || null); + const rootContext = createRootContext(opts.scheduler, opts.playerHandler); const renderer = rendererFactory.createRenderer(hostRNode, componentDef); const rootView: LViewData = createLViewData( @@ -132,7 +131,7 @@ export function renderComponent( const componentView = createRootComponentView(hostRNode, componentDef, rootView, renderer, sanitizer); component = createRootComponent( - hostRNode, componentView, componentDef, rootView, rootContext, opts.hostFeatures || null); + componentView, componentDef, rootView, rootContext, opts.hostFeatures || null); refreshDescendantViews(rootView, null); } finally { @@ -184,8 +183,8 @@ export function createRootComponentView( * renderComponent() and ViewContainerRef.createComponent(). */ export function createRootComponent( - hostRNode: RNode | null, componentView: LViewData, componentDef: ComponentDef, - rootView: LViewData, rootContext: RootContext, hostFeatures: HostFeature[] | null): any { + componentView: LViewData, componentDef: ComponentDef, rootView: LViewData, + rootContext: RootContext, hostFeatures: HostFeature[] | null): any { const tView = rootView[TVIEW]; // Create directive instance with factory() and store at next index in viewData const component = instantiateRootComponent(tView, rootView, componentDef); @@ -201,10 +200,10 @@ export function createRootComponent( export function createRootContext( - scheduler: (workFn: () => void) => void, playerHandler?: PlayerHandler|null): RootContext { + scheduler?: (workFn: () => void) => void, playerHandler?: PlayerHandler|null): RootContext { return { components: [], - scheduler: scheduler, + scheduler: scheduler || defaultScheduler, clean: CLEAN_PROMISE, playerHandler: playerHandler || null, flags: RootContextFlags.Empty diff --git a/packages/core/src/render3/component_ref.ts b/packages/core/src/render3/component_ref.ts index 65cae6fc9c6ef..240a84cb0e913 100644 --- a/packages/core/src/render3/component_ref.ts +++ b/packages/core/src/render3/component_ref.ts @@ -26,7 +26,7 @@ import {TElementNode, TNode, TNodeType, TViewNode} from './interfaces/node'; import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer'; import {FLAGS, HEADER_OFFSET, INJECTOR, LViewData, LViewFlags, RootContext, TVIEW} from './interfaces/view'; import {enterView, leaveView} from './state'; -import {getTNode} from './util'; +import {defaultScheduler, getTNode} from './util'; import {createElementRef} from './view_engine_compatibility'; import {RootViewRef, ViewRef} from './view_ref'; @@ -62,10 +62,7 @@ export const ROOT_CONTEXT = new InjectionToken( */ export const SCHEDULER = new InjectionToken<((fn: () => void) => void)>('SCHEDULER_TOKEN', { providedIn: 'root', - factory: () => { - const useRaf = typeof requestAnimationFrame !== 'undefined' && typeof window !== 'undefined'; - return useRaf ? requestAnimationFrame.bind(window) : setTimeout; - }, + factory: () => defaultScheduler, }); /** @@ -118,9 +115,8 @@ export class ComponentFactory extends viewEngine_ComponentFactory { const rootFlags = this.componentDef.onPush ? LViewFlags.Dirty | LViewFlags.IsRoot : LViewFlags.CheckAlways | LViewFlags.IsRoot; - const rootContext: RootContext = ngModule && !isInternalRootView ? - ngModule.injector.get(ROOT_CONTEXT) : - createRootContext(requestAnimationFrame.bind(window)); + const rootContext: RootContext = + ngModule && !isInternalRootView ? ngModule.injector.get(ROOT_CONTEXT) : createRootContext(); const renderer = rendererFactory.createRenderer(hostRNode, this.componentDef); // Create the root view. Uses empty TView and ContentTemplate. @@ -174,8 +170,7 @@ export class ComponentFactory extends viewEngine_ComponentFactory { // executed here? // Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref component = createRootComponent( - hostRNode, componentView, this.componentDef, rootView, rootContext, - [LifecycleHooksFeature]); + componentView, this.componentDef, rootView, rootContext, [LifecycleHooksFeature]); refreshDescendantViews(rootView, RenderFlags.Create); } finally { diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index e5f9b03178ad6..593e751884dbc 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -358,7 +358,7 @@ export function renderEmbeddedTemplate( let oldView: LViewData; if (viewToRender[FLAGS] & LViewFlags.IsRoot) { // This is a root view inside the view tree - tickRootContext(viewToRender[CONTEXT] as RootContext); + tickRootContext(getRootContext(viewToRender)); } else { try { setIsParent(true); diff --git a/packages/core/src/render3/util.ts b/packages/core/src/render3/util.ts index 041d18fc05ddb..9c0a9599ab758 100644 --- a/packages/core/src/render3/util.ts +++ b/packages/core/src/render3/util.ts @@ -7,6 +7,7 @@ */ import {devModeEqual} from '../change_detection/change_detection_util'; +import {global} from '../util'; import {assertDefined, assertLessThan} from './assert'; import {ACTIVE_INDEX, LContainer} from './interfaces/container'; @@ -154,7 +155,10 @@ export function getRootView(target: LViewData | {}): LViewData { } export function getRootContext(viewOrComponent: LViewData | {}): RootContext { - return getRootView(viewOrComponent)[CONTEXT] as RootContext; + const rootView = getRootView(viewOrComponent); + ngDevMode && + assertDefined(rootView[CONTEXT], 'RootView has no context. Perhaps it is disconnected?'); + return rootView[CONTEXT] as RootContext; } /** @@ -241,3 +245,8 @@ export function getParentInjectorTNode( } return parentTNode; } + +export const defaultScheduler = + (typeof requestAnimationFrame !== 'undefined' && requestAnimationFrame || // browser only + setTimeout // everything else + ).bind(global); \ No newline at end of file diff --git a/packages/core/test/bundling/animation_world/bundle.golden_symbols.json b/packages/core/test/bundling/animation_world/bundle.golden_symbols.json index d1820679870f6..5e218cbe8abbd 100644 --- a/packages/core/test/bundling/animation_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/animation_world/bundle.golden_symbols.json @@ -434,6 +434,9 @@ { "name": "decreaseElementDepthCount" }, + { + "name": "defaultScheduler" + }, { "name": "defineComponent" }, diff --git a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json index 68b7707cb40bc..f003bb3597f0a 100644 --- a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json @@ -119,6 +119,15 @@ { "name": "ViewEncapsulation" }, + { + "name": "__self" + }, + { + "name": "__window" + }, + { + "name": "_global" + }, { "name": "_renderCompCount" }, @@ -182,6 +191,9 @@ { "name": "createViewQuery" }, + { + "name": "defaultScheduler" + }, { "name": "defineComponent" }, @@ -305,6 +317,12 @@ { "name": "getRendererFactory" }, + { + "name": "getRootContext" + }, + { + "name": "getRootView" + }, { "name": "getTView" }, diff --git a/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json b/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json index dc428cb1308dd..03928badcd754 100644 --- a/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world_r2/bundle.golden_symbols.json @@ -680,6 +680,9 @@ { "name": "defaultErrorLogger" }, + { + "name": "defaultScheduler" + }, { "name": "defineComponent" }, @@ -929,6 +932,12 @@ { "name": "getRendererFactory" }, + { + "name": "getRootContext" + }, + { + "name": "getRootView" + }, { "name": "getSymbolIterator$1" }, diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json index e0fc08ffe4dd4..d74e653e4d536 100644 --- a/packages/core/test/bundling/todo/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -491,6 +491,9 @@ { "name": "decreaseElementDepthCount" }, + { + "name": "defaultScheduler" + }, { "name": "defineComponent" }, diff --git a/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json b/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json index 1aad0043204f4..cecfc71b4e3f8 100644 --- a/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json @@ -1415,6 +1415,9 @@ { "name": "defaultKeyValueDiffers" }, + { + "name": "defaultScheduler" + }, { "name": "defineComponent" },