diff --git a/packages/core/src/core_private_export.ts b/packages/core/src/core_private_export.ts index d9178c5c13..82e56380ad 100644 --- a/packages/core/src/core_private_export.ts +++ b/packages/core/src/core_private_export.ts @@ -8,6 +8,7 @@ export {ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS} from './application_ref'; export {APP_ID_RANDOM_PROVIDER as ɵAPP_ID_RANDOM_PROVIDER} from './application_tokens'; +export {defaultIterableDiffers as ɵdefaultIterableDiffers} from './change_detection/change_detection'; export {devModeEqual as ɵdevModeEqual} from './change_detection/change_detection_util'; export {isListLikeIterable as ɵisListLikeIterable} from './change_detection/change_detection_util'; export {ChangeDetectorStatus as ɵChangeDetectorStatus, isDefaultChangeDetectionStrategy as ɵisDefaultChangeDetectionStrategy} from './change_detection/constants'; diff --git a/packages/core/src/core_render3_private_export.ts b/packages/core/src/core_render3_private_export.ts index 57ddac7a13..a50c5e30a3 100644 --- a/packages/core/src/core_render3_private_export.ts +++ b/packages/core/src/core_render3_private_export.ts @@ -24,6 +24,7 @@ export { PublicFeature as ɵPublicFeature, NgOnChangesFeature as ɵNgOnChangesFeature, CssSelectorList as ɵCssSelectorList, + markDirty as ɵmarkDirty, NC as ɵNC, C as ɵC, E as ɵE, diff --git a/packages/core/src/di/injector.ts b/packages/core/src/di/injector.ts index 5d3bf0c1a6..db286b326e 100644 --- a/packages/core/src/di/injector.ts +++ b/packages/core/src/di/injector.ts @@ -446,7 +446,9 @@ export function setCurrentInjector(injector: Injector | null): Injector|null { export function inject( token: Type| InjectionToken, notFoundValue?: undefined, flags?: InjectFlags): T; export function inject( - token: Type| InjectionToken, notFoundValue: T | null, flags?: InjectFlags): T|null; + token: Type| InjectionToken, notFoundValue: T, flags?: InjectFlags): T; +export function inject( + token: Type| InjectionToken, notFoundValue: null, flags?: InjectFlags): T|null; export function inject( token: Type| InjectionToken, notFoundValue?: T | null, flags = InjectFlags.Default): T| null { diff --git a/packages/core/src/render3/component.ts b/packages/core/src/render3/component.ts index f4c654c0fa..13c579b458 100644 --- a/packages/core/src/render3/component.ts +++ b/packages/core/src/render3/component.ts @@ -129,7 +129,7 @@ export function renderComponent( const rootContext: RootContext = { // Incomplete initialization due to circular reference. component: null !, - scheduler: opts.scheduler || requestAnimationFrame, + scheduler: opts.scheduler || requestAnimationFrame.bind(window), clean: CLEAN_PROMISE, }; const rootView = createLView( 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 d52f46bee1..ff48fd607c 100644 --- a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json @@ -251,6 +251,12 @@ { "name": "extendStatics" }, + { + "name": "extractDirectiveDef" + }, + { + "name": "extractPipeDef" + }, { "name": "firstTemplatePass" }, diff --git a/packages/core/test/bundling/todo/BUILD.bazel b/packages/core/test/bundling/todo/BUILD.bazel new file mode 100644 index 0000000000..b4aafd601a --- /dev/null +++ b/packages/core/test/bundling/todo/BUILD.bazel @@ -0,0 +1,91 @@ +package(default_visibility = ["//visibility:public"]) + +load("//tools:defaults.bzl", "ts_library", "ivy_ng_module") +load("//tools/symbol-extractor:index.bzl", "js_expected_symbol_test") +load("//packages/bazel/src:ng_rollup_bundle.bzl", "ng_rollup_bundle") +load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test") +load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver") + +ivy_ng_module( + name = "todo", + srcs = ["index.ts"], + deps = [ + "//packages/common", + "//packages/core", + ], +) + +ng_rollup_bundle( + name = "bundle", + # TODO(alexeagle): This is inconsistent. + # We try to teach users to always have their workspace at the start of a + # path, to disambiguate from other workspaces. + # Here, the rule implementation is looking in an execroot where the layout + # has an "external" directory for external dependencies. + # This should probably start with "angular/" and let the rule deal with it. + entry_point = "packages/core/test/bundling/todo/index.js", + deps = [ + ":todo", + "//packages/core", + ], +) + +ts_library( + name = "test_lib", + testonly = 1, + srcs = glob(["*_spec.ts"]), + deps = [ + "//packages:types", + "//packages/core/testing", + ], +) + +jasmine_node_test( + name = "test", + data = [ + ":bundle", + ":bundle.js", + ":bundle.min.js.brotli", + ":bundle.min_debug.js", + ], + deps = [":test_lib"], +) + +js_expected_symbol_test( + name = "symbol_test", + src = ":bundle.min_debug.js", + golden = ":bundle.golden_symbols.json", +) + +genrule( + name = "tslib", + srcs = [ + "//:node_modules/tslib/tslib.js", + ], + outs = [ + "tslib.js", + ], + cmd = "cp $< $@", +) + +ts_devserver( + name = "devserver", + entry_module = "angular/packages/core/test/bundling/todo/index", + serving_path = "/bundle.min.js", + static_files = [ + "index.html", + ":tslib", + ], + deps = [":todo"], +) + +# Even though this is `ts_devserver` rule, we are using it as simple static server +# This is mostly broken for `ibazel`, use `:devserver` instead. +ts_devserver( + name = "prodserver", + static_files = [ + ":bundle.min_debug.js", + ":bundle.min.js", + "index.html", + ], +) diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json new file mode 100644 index 0000000000..98b88a420f --- /dev/null +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -0,0 +1,887 @@ +[ + { + "name": "APP_ROOT" + }, + { + "name": "AnonymousSubject" + }, + { + "name": "AppState" + }, + { + "name": "ArgumentOutOfRangeError" + }, + { + "name": "CIRCULAR$1" + }, + { + "name": "CLEAN_PROMISE" + }, + { + "name": "CommonModule" + }, + { + "name": "ConnectableSubscriber" + }, + { + "name": "Context" + }, + { + "name": "CountedSubject" + }, + { + "name": "DefaultIterableDiffer" + }, + { + "name": "DefaultIterableDifferFactory" + }, + { + "name": "DelayMessage" + }, + { + "name": "EMPTY$1" + }, + { + "name": "EMPTY$2" + }, + { + "name": "EMPTY_ARRAY$1" + }, + { + "name": "EMPTY_RENDERER_TYPE_ID" + }, + { + "name": "ElementRef$1" + }, + { + "name": "EmbeddedViewRef$1" + }, + { + "name": "EmptyError" + }, + { + "name": "EventEmitter" + }, + { + "name": "GET_PROPERTY_NAME$1" + }, + { + "name": "GroupDurationSubscriber" + }, + { + "name": "GroupedObservable" + }, + { + "name": "INJECTOR" + }, + { + "name": "Inject" + }, + { + "name": "InjectionToken" + }, + { + "name": "InnerRefCountSubscription" + }, + { + "name": "InnerSubscriber" + }, + { + "name": "IterableChangeRecord_" + }, + { + "name": "NG_HOST_SYMBOL" + }, + { + "name": "NG_PROJECT_AS_ATTR_NAME" + }, + { + "name": "NONE" + }, + { + "name": "NOT_YET" + }, + { + "name": "NO_CHANGE" + }, + { + "name": "NULL_INJECTOR$1" + }, + { + "name": "NgForOf" + }, + { + "name": "NgForOfContext" + }, + { + "name": "NgOnChangesFeature" + }, + { + "name": "Notification" + }, + { + "name": "NullInjector" + }, + { + "name": "ObjectUnsubscribedError" + }, + { + "name": "Observable" + }, + { + "name": "ObserveOnMessage" + }, + { + "name": "ObserveOnSubscriber" + }, + { + "name": "Optional" + }, + { + "name": "OuterSubscriber" + }, + { + "name": "PARAMETERS" + }, + { + "name": "PRIVATE_PREFIX" + }, + { + "name": "QueueAction" + }, + { + "name": "R3Injector" + }, + { + "name": "ROOT_DIRECTIVE_INDICES" + }, + { + "name": "RecordViewTuple" + }, + { + "name": "RefCountOperator$1" + }, + { + "name": "RefCountSubscriber$1" + }, + { + "name": "ReplayEvent" + }, + { + "name": "SafeSubscriber" + }, + { + "name": "Self" + }, + { + "name": "SequenceEqualCompareToSubscriber" + }, + { + "name": "SimpleChange" + }, + { + "name": "SkipSelf" + }, + { + "name": "StaticArrayIterator" + }, + { + "name": "StaticIterator" + }, + { + "name": "Subject" + }, + { + "name": "SubjectSubscriber" + }, + { + "name": "SubjectSubscription" + }, + { + "name": "Subscriber" + }, + { + "name": "Subscription" + }, + { + "name": "SubscriptionDelaySubscriber" + }, + { + "name": "THROW_IF_NOT_FOUND" + }, + { + "name": "TemplateRef$1" + }, + { + "name": "TimeInterval" + }, + { + "name": "ToDoAppComponent" + }, + { + "name": "ToDoAppModule" + }, + { + "name": "TodoComponent" + }, + { + "name": "UNDEFINED_RENDERER_TYPE_ID" + }, + { + "name": "USE_VALUE$1" + }, + { + "name": "UnsubscriptionError" + }, + { + "name": "ViewContainerRef$1" + }, + { + "name": "ZipBufferIterator" + }, + { + "name": "_CLEAN_PROMISE" + }, + { + "name": "_DuplicateItemRecordList" + }, + { + "name": "_DuplicateMap" + }, + { + "name": "_ROOT_DIRECTIVE_INDICES" + }, + { + "name": "_THROW_IF_NOT_FOUND" + }, + { + "name": "__extends" + }, + { + "name": "__global" + }, + { + "name": "__read" + }, + { + "name": "__self" + }, + { + "name": "__spread" + }, + { + "name": "__window" + }, + { + "name": "_c0" + }, + { + "name": "_c1" + }, + { + "name": "_currentInjector" + }, + { + "name": "_devMode" + }, + { + "name": "_enable_super_gross_mode_that_will_cause_bad_things" + }, + { + "name": "_getComponentHostLElementNode" + }, + { + "name": "_global" + }, + { + "name": "_renderCompCount" + }, + { + "name": "_symbolIterator" + }, + { + "name": "addComponentLogic" + }, + { + "name": "addDestroyable" + }, + { + "name": "addRemoveViewFromContainer" + }, + { + "name": "addToViewTree" + }, + { + "name": "appendChild" + }, + { + "name": "baseDirectiveCreate" + }, + { + "name": "bind" + }, + { + "name": "bindingUpdated" + }, + { + "name": "buildTNodeFlags" + }, + { + "name": "cacheMatchingDirectivesForNode" + }, + { + "name": "cacheMatchingLocalNames" + }, + { + "name": "callHooks" + }, + { + "name": "canInsertNativeNode" + }, + { + "name": "checkNoChanges" + }, + { + "name": "checkNoChangesMode" + }, + { + "name": "componentRefresh" + }, + { + "name": "config" + }, + { + "name": "container" + }, + { + "name": "couldBeInjectableType" + }, + { + "name": "createInjector" + }, + { + "name": "createLNode" + }, + { + "name": "createLView" + }, + { + "name": "createOutput" + }, + { + "name": "createTNode" + }, + { + "name": "createTView" + }, + { + "name": "currentView" + }, + { + "name": "deepForEach" + }, + { + "name": "defaultIterableDiffers" + }, + { + "name": "defineComponent" + }, + { + "name": "defineDirective" + }, + { + "name": "defineInjectable" + }, + { + "name": "defineInjector" + }, + { + "name": "detectChanges" + }, + { + "name": "detectChangesInternal" + }, + { + "name": "directiveCreate" + }, + { + "name": "dispatch" + }, + { + "name": "dispatchBufferClose" + }, + { + "name": "dispatchBufferCreation" + }, + { + "name": "dispatchBufferTimeSpanOnly" + }, + { + "name": "dispatchNext$2" + }, + { + "name": "dispatchNext$3" + }, + { + "name": "dispatchNotification" + }, + { + "name": "dispatchWindowClose" + }, + { + "name": "dispatchWindowCreation" + }, + { + "name": "dispatchWindowTimeSpanOnly" + }, + { + "name": "domRendererFactory3" + }, + { + "name": "elementClassNamed" + }, + { + "name": "elementEnd" + }, + { + "name": "elementProperty" + }, + { + "name": "elementStart" + }, + { + "name": "empty" + }, + { + "name": "empty$1" + }, + { + "name": "emptyScheduled" + }, + { + "name": "enterView" + }, + { + "name": "errorObject" + }, + { + "name": "executeHooks" + }, + { + "name": "executeInitAndContentHooks" + }, + { + "name": "executeInitHooks" + }, + { + "name": "extendStatics" + }, + { + "name": "extractDirectiveDef" + }, + { + "name": "extractPipeDef" + }, + { + "name": "findAttrIndexInNode" + }, + { + "name": "findFirstRNode" + }, + { + "name": "findNextRNodeSibling" + }, + { + "name": "firstTemplatePass" + }, + { + "name": "flattenUnsubscriptionErrors" + }, + { + "name": "forwardRef" + }, + { + "name": "fromArray" + }, + { + "name": "generateInitialInputs" + }, + { + "name": "generatePropertyAliases" + }, + { + "name": "getClosureSafeProperty$1" + }, + { + "name": "getDirectiveInstance" + }, + { + "name": "getNextLNodeWithProjection" + }, + { + "name": "getNextOrParentSiblingNode" + }, + { + "name": "getNullInjector" + }, + { + "name": "getOrCreateContainerRef" + }, + { + "name": "getOrCreateElementRef" + }, + { + "name": "getOrCreateNodeInjector" + }, + { + "name": "getOrCreateNodeInjectorForNode" + }, + { + "name": "getOrCreateTView" + }, + { + "name": "getOrCreateTemplateRef" + }, + { + "name": "getPreviousIndex" + }, + { + "name": "getPreviousOrParentNode" + }, + { + "name": "getPromiseCtor" + }, + { + "name": "getRenderer" + }, + { + "name": "getRootView" + }, + { + "name": "getSymbolIterator" + }, + { + "name": "getSymbolIterator$1" + }, + { + "name": "getTypeNameForDebugging" + }, + { + "name": "getTypeNameForDebugging$1" + }, + { + "name": "hack_declareDirectives" + }, + { + "name": "hasDeps" + }, + { + "name": "hasOnDestroy" + }, + { + "name": "hostElement" + }, + { + "name": "hostReportError" + }, + { + "name": "initBindings" + }, + { + "name": "initChangeDetectorIfExisting" + }, + { + "name": "inject" + }, + { + "name": "injectArgs" + }, + { + "name": "injectTemplateRef" + }, + { + "name": "injectViewContainerRef" + }, + { + "name": "injectableDefRecord" + }, + { + "name": "insertChild" + }, + { + "name": "insertView" + }, + { + "name": "interpolation1" + }, + { + "name": "invertObject" + }, + { + "name": "isArray" + }, + { + "name": "isArrayLike" + }, + { + "name": "isCssClassMatching" + }, + { + "name": "isDevMode" + }, + { + "name": "isDifferent" + }, + { + "name": "isExistingProvider" + }, + { + "name": "isFactoryProvider" + }, + { + "name": "isFunction" + }, + { + "name": "isJsObject" + }, + { + "name": "isListLikeIterable" + }, + { + "name": "isNodeMatchingSelector" + }, + { + "name": "isNodeMatchingSelectorList" + }, + { + "name": "isObject" + }, + { + "name": "isPositive" + }, + { + "name": "isProceduralRenderer" + }, + { + "name": "isPromise" + }, + { + "name": "isScheduler" + }, + { + "name": "isTrustedSubscriber" + }, + { + "name": "isTypeProvider" + }, + { + "name": "isValueProvider" + }, + { + "name": "iterateListLike" + }, + { + "name": "iterator" + }, + { + "name": "leaveView" + }, + { + "name": "listener" + }, + { + "name": "locateHostElement" + }, + { + "name": "looseIdentical" + }, + { + "name": "makeMetadataCtor" + }, + { + "name": "makeParamDecorator" + }, + { + "name": "makeRecord" + }, + { + "name": "markDirty" + }, + { + "name": "markDirtyIfOnPush" + }, + { + "name": "markViewDirty" + }, + { + "name": "noop" + }, + { + "name": "notImplemented" + }, + { + "name": "observable" + }, + { + "name": "of" + }, + { + "name": "pipeFromArray" + }, + { + "name": "providerToRecord" + }, + { + "name": "queue" + }, + { + "name": "queueComponentIndexForCheck" + }, + { + "name": "queueContentHooks" + }, + { + "name": "queueDestroyHooks" + }, + { + "name": "queueHostBindingForCheck" + }, + { + "name": "queueInitHooks" + }, + { + "name": "queueLifecycleHooks" + }, + { + "name": "queueViewHooks" + }, + { + "name": "refCount" + }, + { + "name": "refreshChildComponents" + }, + { + "name": "refreshDirectives" + }, + { + "name": "refreshDynamicChildren" + }, + { + "name": "renderComponent" + }, + { + "name": "renderComponentOrTemplate" + }, + { + "name": "renderEmbeddedTemplate" + }, + { + "name": "resetApplicationState" + }, + { + "name": "resolveForwardRef" + }, + { + "name": "resolveRendererType2" + }, + { + "name": "rxSubscriber" + }, + { + "name": "saveNameToExportMap" + }, + { + "name": "saveResolvedLocalsInData" + }, + { + "name": "scalar" + }, + { + "name": "scheduleTick" + }, + { + "name": "setCurrentInjector" + }, + { + "name": "setHostBindings" + }, + { + "name": "setInputsForProperty" + }, + { + "name": "setInputsFromAttrs" + }, + { + "name": "setUpAttributes" + }, + { + "name": "setViewNext" + }, + { + "name": "stringify" + }, + { + "name": "stringify$1" + }, + { + "name": "subscribeTo" + }, + { + "name": "subscribeToArray" + }, + { + "name": "subscribeToIterable" + }, + { + "name": "subscribeToObservable" + }, + { + "name": "subscribeToPromise" + }, + { + "name": "subscribeToResult" + }, + { + "name": "text" + }, + { + "name": "textBinding" + }, + { + "name": "throwError" + }, + { + "name": "throwErrorIfNoChangesMode" + }, + { + "name": "throwMultipleComponentError" + }, + { + "name": "tick" + }, + { + "name": "toSubscriber" + }, + { + "name": "trackByIdentity" + }, + { + "name": "tryCatch" + }, + { + "name": "tryCatcher" + }, + { + "name": "viewAttached" + }, + { + "name": "wrapListenerWithDirtyAndDefault" + }, + { + "name": "wrapListenerWithDirtyLogic" + }, + { + "name": "ɵ0" + } +] \ No newline at end of file diff --git a/packages/core/test/bundling/todo/index.html b/packages/core/test/bundling/todo/index.html new file mode 100644 index 0000000000..0143a83674 --- /dev/null +++ b/packages/core/test/bundling/todo/index.html @@ -0,0 +1,55 @@ + + + + + + Angular Todo Example + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/core/test/bundling/todo/index.ts b/packages/core/test/bundling/todo/index.ts new file mode 100644 index 0000000000..ab325079f9 --- /dev/null +++ b/packages/core/test/bundling/todo/index.ts @@ -0,0 +1,111 @@ +/** + * @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 {CommonModule, NgForOf} from '@angular/common'; +import {Component, EventEmitter, InjectFlags, Injectable, Input, IterableDiffers, NgModule, Output, createInjector, defineInjector, inject, ɵComponentDef as ComponentDef, ɵComponentType as ComponentType, ɵDirectiveDef as DirectiveDef, ɵDirectiveType as DirectiveType, ɵNgOnChangesFeature as NgOnChangesFeature, ɵdefaultIterableDiffers as defaultIterableDiffers, ɵdefineDirective as defineDirective, ɵinjectTemplateRef as injectTemplateRef, ɵinjectViewContainerRef as injectViewContainerRef, ɵmarkDirty as markDirty, ɵrenderComponent as renderComponent} from '@angular/core'; + +export interface ToDo { + text: string; + done: boolean; +} +@Injectable({providedIn: 'root'}) +export class AppState { + todos: ToDo[] = [ + {text: 'Demonstrate Components', done: false}, + {text: 'Demonstrate Structural Directives', done: true}, + {text: 'Demonstrate NgModules', done: false}, + {text: 'Demonstrate zoneless change detection', done: false}, + {text: 'Demonstrate internationalization', done: false}, + ]; + + static DEFAULT_TODO = {text: '', done: false}; +} + +@Component({ + selector: 'todo', + // TODO(misko): `[class.done]` and `[value]` should be `todo.done` not `todo && todo.todo.done` + // The reason for the guard is that template executes creation and binding together + // but NgForOf expects creation and binding separate. + template: ` +
+ &ngsp; + {{todo && todo.text}}&ngsp; + +
+ ` +}) +export class TodoComponent { + @Input() + todo: ToDo = AppState.DEFAULT_TODO; + + @Output() + archive = new EventEmitter(); + + onCheckboxClick() { this.todo.done = !this.todo.done; } + + onArchiveClick() { this.archive.emit(this.todo); } +} + +@Component({ + selector: 'todo-app', + template: ` +

ToDo Application

+
+ +
+ count: {{appState.todos.length}}. + ` +}) +export class ToDoAppComponent { + public appState: AppState; + + constructor(/**appState: AppState*/) { + // TODO(misko): Injection is broken because the compiler generates incorrect code. + this.appState = new AppState(); + } + + onArchive(item: ToDo) { + const todos = this.appState.todos; + todos.splice(todos.indexOf(item)); + markDirty(this); + } +} + +// TODO(misko): This hack is here because common is not compiled with Ivy flag turned on. +(CommonModule as any).ngInjectorDef = defineInjector({factory: () => new CommonModule}); + +// TODO(misko): This hack is here because common is not compiled with Ivy flag turned on. +(NgForOf as any).ngDirectiveDef = defineDirective({ + type: NgForOf, + selectors: [['', 'ngFor', '', 'ngForOf', '']], + factory: () => new NgForOf( + injectViewContainerRef(), injectTemplateRef(), + // TODO(misko): inject does not work since it needs to be directiveInject + // inject(IterableDiffers, defaultIterableDiffers) + defaultIterableDiffers), + features: [NgOnChangesFeature({ + ngForOf: 'ngForOf', + ngForTrackBy: 'ngForTrackBy', + ngForTemplate: 'ngForTemplate', + })], + inputs: { + ngForOf: 'ngForOf', + ngForTrackBy: 'ngForTrackBy', + ngForTemplate: 'ngForTemplate', + } +}); + + +@NgModule({declarations: [ToDoAppComponent, TodoComponent], imports: [CommonModule]}) +export class ToDoAppModule { +} + +renderComponent(ToDoAppComponent, { + // TODO(misko): This should run without injector. + injector: createInjector(ToDoAppModule) +}); \ No newline at end of file diff --git a/packages/core/test/bundling/todo/treeshaking_spec.ts b/packages/core/test/bundling/todo/treeshaking_spec.ts new file mode 100644 index 0000000000..417118e08c --- /dev/null +++ b/packages/core/test/bundling/todo/treeshaking_spec.ts @@ -0,0 +1,42 @@ +/** + * @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 {withBody} from '@angular/core/testing'; +import * as fs from 'fs'; +import * as path from 'path'; + +const UTF8 = { + encoding: 'utf-8' +}; +const PACKAGE = 'angular/packages/core/test/bundling/todo'; + +describe('functional test for todo', () => { + it('should render todo when not minified', withBody('', () => { + require(path.join(PACKAGE, 'bundle.js')); + expect(document.body.textContent).toContain('ToDo Application'); + expect(document.body.textContent).toContain('count: 5.'); + // TODO(misko): disabled until `ViewContainerRef` is fixed + // expect(document.body.textContent).toContain('Demonstrate Components'); + })); + + it('should render todo when debug minified', withBody('', () => { + require(path.join(PACKAGE, 'bundle.min_debug.js')); + expect(document.body.textContent).toContain('ToDo Application'); + expect(document.body.textContent).toContain('count: 5.'); + // TODO(misko): disabled until `ViewContainerRef` is fixed + // expect(document.body.textContent).toContain('Demonstrate Components'); + })); + + it('should render todo when fully minified', withBody('', () => { + require(path.join(PACKAGE, 'bundle.min.js')); + expect(document.body.textContent).toContain('ToDo Application'); + expect(document.body.textContent).toContain('count: 5.'); + // TODO(misko): disabled until `ViewContainerRef` is fixed + // expect(document.body.textContent).toContain('Demonstrate Components'); + })); +}); diff --git a/packages/core/testing/src/render3.ts b/packages/core/testing/src/render3.ts index 14f172bd0e..e7cdcd3a64 100644 --- a/packages/core/testing/src/render3.ts +++ b/packages/core/testing/src/render3.ts @@ -85,6 +85,7 @@ export function ensureDocument(): void { // we are in node.js. const window = domino.createWindow('', 'http://localhost'); savedDocument = (global as any).document; + (global as any).window = window; (global as any).document = window.document; // Trick to avoid Event patching from // https://github.com/angular/angular/blob/7cf5e95ac9f0f2648beebf0d5bd9056b79946970/packages/platform-browser/src/dom/events/dom_events.ts#L112-L132 @@ -109,6 +110,7 @@ export function ensureDocument(): void { export function cleanupDocument(): void { if (savedDocument) { (global as any).document = savedDocument; + (global as any).window = undefined; savedDocument = undefined; } if (savedNode) { diff --git a/tools/public_api_guard/core/core.d.ts b/tools/public_api_guard/core/core.d.ts index eff1662adf..f803756993 100644 --- a/tools/public_api_guard/core/core.d.ts +++ b/tools/public_api_guard/core/core.d.ts @@ -370,7 +370,8 @@ export declare const HostListener: HostListenerDecorator; /** @experimental */ export declare function inject(token: Type | InjectionToken, notFoundValue?: undefined, flags?: InjectFlags): T; -export declare function inject(token: Type | InjectionToken, notFoundValue: T | null, flags?: InjectFlags): T | null; +export declare function inject(token: Type | InjectionToken, notFoundValue: T, flags?: InjectFlags): T; +export declare function inject(token: Type | InjectionToken, notFoundValue: null, flags?: InjectFlags): T | null; /** @stable */ export declare const Inject: InjectDecorator;