From 9dc52d9d04b8e91c1f251391cbc3cae1f44cb19c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Tue, 23 Oct 2018 15:33:01 -0700 Subject: [PATCH] feat(ivy): expose a series of debug console tools (#26705) PR Close #26705 --- .../core/src/core_render3_private_export.ts | 4 +- packages/core/src/render3/component.ts | 3 +- packages/core/src/render3/index.ts | 1 - .../core/src/render3/publish_global_util.ts | 64 +++++++++++++++++++ .../test/render3/dev_mode_publish_spec.ts | 43 +++++++++++++ 5 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 packages/core/src/render3/publish_global_util.ts create mode 100644 packages/core/test/render3/dev_mode_publish_spec.ts diff --git a/packages/core/src/core_render3_private_export.ts b/packages/core/src/core_render3_private_export.ts index 6cdc1c1c78..cfdba19488 100644 --- a/packages/core/src/core_render3_private_export.ts +++ b/packages/core/src/core_render3_private_export.ts @@ -223,5 +223,7 @@ export { SWITCH_RENDERER2_FACTORY__POST_R3__ as ɵSWITCH_RENDERER2_FACTORY__POST_R3__, } from './render/api'; - +export { + publishGlobalUtil as ɵpublishGlobalUtil +} from './render3/publish_global_util'; // clang-format on diff --git a/packages/core/src/render3/component.ts b/packages/core/src/render3/component.ts index 314247526b..f34eae623f 100644 --- a/packages/core/src/render3/component.ts +++ b/packages/core/src/render3/component.ts @@ -22,10 +22,10 @@ import {TElementNode, TNodeFlags, TNodeType} from './interfaces/node'; import {PlayerHandler} from './interfaces/player'; import {RElement, RNode, 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 {getRootView, readElementValue, readPatchedLViewData, stringify} from './util'; - // Root component will always have an element index of 0 and an injector size of 1 const ROOT_EXPANDO_INSTRUCTIONS = [0, 1]; @@ -106,6 +106,7 @@ export function renderComponent( Type/* Type as workaround for: Microsoft/TypeScript/issues/4881 */ , opts: CreateComponentOptions = {}): T { + ngDevMode && publishDefaultGlobalUtils(); ngDevMode && assertComponentType(componentType); const rendererFactory = opts.rendererFactory || domRendererFactory3; const sanitizer = opts.sanitizer || null; diff --git a/packages/core/src/render3/index.ts b/packages/core/src/render3/index.ts index a34f2fec4a..08f80f3e4e 100644 --- a/packages/core/src/render3/index.ts +++ b/packages/core/src/render3/index.ts @@ -5,7 +5,6 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ - import {LifecycleHooksFeature, getHostElement, getRenderedText, renderComponent, whenRendered} from './component'; import {defineBase, defineComponent, defineDirective, defineNgModule, definePipe} from './definition'; import {InheritDefinitionFeature} from './features/inherit_definition_feature'; diff --git a/packages/core/src/render3/publish_global_util.ts b/packages/core/src/render3/publish_global_util.ts new file mode 100644 index 0000000000..5db9ad072b --- /dev/null +++ b/packages/core/src/render3/publish_global_util.ts @@ -0,0 +1,64 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {global} from '../util'; +import {getComponent, getDirectives, getHostComponent, getInjector, getRootComponents} from './discovery_utils'; + +/** + * This file introduces series of globally accessible debug tools + * to allow for the Angular debugging story to function. + * + * To see this in action run the following command: + * + * bazel run --define=compile=local + * //packages/core/test/bundling/todo:devserver + * + * Then load `localhost:5432` and start using the console tools. + */ + +/** + * This value reflects the property on the window where the dev + * tools are patched (window.ngDev). + * */ +export const GLOBAL_PUBLISH_EXPANDO_KEY = 'ngDev'; + +/* + * Publishes a collection of default debug tools onto `window._ng_`. + * + * These functions are available globally when Angular is in development + * mode and are automatically stripped away from prod mode is on. + */ +let _published = false; +export function publishDefaultGlobalUtils() { + if (!_published) { + _published = true; + publishGlobalUtil('getComponent', getComponent); + publishGlobalUtil('getHostComponent', getHostComponent); + publishGlobalUtil('getInjector', getInjector); + publishGlobalUtil('getRootComponents', getRootComponents); + publishGlobalUtil('getDirectives', getDirectives); + } +} + +export declare type GlobalDevModeContainer = { + [GLOBAL_PUBLISH_EXPANDO_KEY]: {[fnName: string]: Function}; +}; + +/** + * Publishes the given function to `window.ngDevMode` so that it can be + * used from the browser console when an application is not in production. + */ +export function publishGlobalUtil(name: string, fn: Function): void { + const w = global as any as GlobalDevModeContainer; + if (w) { + let container = w[GLOBAL_PUBLISH_EXPANDO_KEY]; + if (!container) { + container = w[GLOBAL_PUBLISH_EXPANDO_KEY] = {}; + } + container[name] = fn; + } +} diff --git a/packages/core/test/render3/dev_mode_publish_spec.ts b/packages/core/test/render3/dev_mode_publish_spec.ts new file mode 100644 index 0000000000..38e450e581 --- /dev/null +++ b/packages/core/test/render3/dev_mode_publish_spec.ts @@ -0,0 +1,43 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {getComponent, getDirectives, getHostComponent, getInjector, getRootComponents} from '../../src/render3/discovery_utils'; +import {GLOBAL_PUBLISH_EXPANDO_KEY, GlobalDevModeContainer, publishDefaultGlobalUtils, publishGlobalUtil} from '../../src/render3/publish_global_util'; +import {global} from '../../src/util'; + +describe('dev mode utils', () => { + describe('devModePublish', () => { + it('should publish a function to the window', () => { + const w = global as any as GlobalDevModeContainer; + expect(w[GLOBAL_PUBLISH_EXPANDO_KEY]['foo']).toBeFalsy(); + const fooFn = () => {}; + publishGlobalUtil('foo', fooFn); + expect(w[GLOBAL_PUBLISH_EXPANDO_KEY]['foo']).toBe(fooFn); + }); + }); + + describe('publishDefaultGlobalUtils', () => { + beforeEach(() => publishDefaultGlobalUtils()); + + it('should publish getComponent', () => { assertPublished('getComponent', getComponent); }); + + it('should publish getRootComponents', + () => { assertPublished('getRootComponents', getRootComponents); }); + + it('should publish getDirectives', () => { assertPublished('getDirectives', getDirectives); }); + + it('should publish getHostComponent', + () => { assertPublished('getHostComponent', getHostComponent); }); + + it('should publish getInjector', () => { assertPublished('getInjector', getInjector); }); + }); +}); + +function assertPublished(name: string, value: {}) { + const w = global as any as GlobalDevModeContainer; + expect(w[GLOBAL_PUBLISH_EXPANDO_KEY][name]).toBe(value); +}