From 19396d14cc5c21852af852bdbe40ad54b9cdbef3 Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Mon, 14 Dec 2015 16:19:22 -0800 Subject: [PATCH 01/55] docs(contributing.md): improve submit issue instructions Closes #5889 --- CONTRIBUTING.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e22ad4831f33..b8da1f04776b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,14 +48,18 @@ features, by not reporting duplicate issues. Providing the following informatio chances of your issue being dealt with quickly: * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps -* **Motivation for or Use Case** - explain why this is a bug for you +* **Angular Version** - what version of Angular is affected (e.g. 2.0.0-alpha.53) +* **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you * **Browsers and Operating System** - is this a problem with all browsers? * **Reproduce the Error** - provide a live example (using [Plunker][plunker], - [JSFiddle][jsfiddle] or [Runnable][runnable]) or a unambiguous set of steps. + [JSFiddle][jsfiddle] or [Runnable][runnable]) or a unambiguous set of steps * **Related Issues** - has a similar issue been reported before? * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be causing the problem (line of code or commit) +You can file new issues by providing the above information [here](https://github.com/angular/angular/issues/new). + + ### Submitting a Pull Request (PR) Before you submit your Pull Request (PR) consider the following guidelines: From b88a6d983fa8112aca5715182693e56683731878 Mon Sep 17 00:00:00 2001 From: Julie Ralph Date: Tue, 8 Dec 2015 19:03:21 -0800 Subject: [PATCH 02/55] refactor(testing): move common testing logic into test_injector Before, all test framework wrappers (internal for dart and js/ts, angular2_test for dart and testing for js/ts) had similar logic to keep track of current global test injector and test provider list. This change wraps that logic into one class managed by the test injector. Closes #5819 --- modules/angular2/src/testing/test_injector.ts | 49 ++++++++++++++++--- modules/angular2/src/testing/testing.ts | 32 ++++-------- .../src/testing/testing_internal.dart | 31 ++++++------ .../angular2/src/testing/testing_internal.ts | 36 ++++++-------- ...client_server_message_bus.server.spec.dart | 1 - ...client_server_message_bus.server.spec.dart | 1 - .../web_socket_message_bus_spec.dart | 1 - .../web_workers/shared/message_bus_spec.ts | 1 - .../shared/service_message_broker_spec.ts | 1 - .../worker/event_dispatcher_spec.ts | 1 - .../worker/renderer_integration_spec.ts | 6 ++- .../test/web_workers/worker/xhr_impl_spec.ts | 1 - .../lib/angular2_testing.dart | 46 +++++++---------- 13 files changed, 106 insertions(+), 101 deletions(-) diff --git a/modules/angular2/src/testing/test_injector.ts b/modules/angular2/src/testing/test_injector.ts index 377c2c9bd673..ff7880adbfb9 100644 --- a/modules/angular2/src/testing/test_injector.ts +++ b/modules/angular2/src/testing/test_injector.ts @@ -23,7 +23,7 @@ import { defaultKeyValueDiffers, ChangeDetectorGenConfig } from 'angular2/src/core/change_detection/change_detection'; -import {ExceptionHandler} from 'angular2/src/facade/exceptions'; +import {BaseException, ExceptionHandler} from 'angular2/src/facade/exceptions'; import {PipeResolver} from 'angular2/src/core/linker/pipe_resolver'; import {XHR} from 'angular2/src/compiler/xhr'; @@ -131,14 +131,49 @@ function _runtimeCompilerBindings() { ]; } -export function createTestInjector(providers: Array): Injector { - var rootInjector = Injector.resolveAndCreate(_getRootProviders()); - return rootInjector.resolveAndCreateChild(ListWrapper.concat(_getAppBindings(), providers)); +export class TestInjector { + private _instantiated: boolean = false; + + private _injector: Injector = null; + + private _providers: Array = []; + + reset() { + this._injector = null; + this._providers = []; + this._instantiated = false; + } + + addProviders(providers: Array) { + if (this._instantiated) { + throw new BaseException('Cannot add providers after test injector is instantiated'); + } + this._providers = ListWrapper.concat(this._providers, providers); + } + + createInjector() { + var rootInjector = Injector.resolveAndCreate(_getRootProviders()); + this._injector = rootInjector.resolveAndCreateChild(ListWrapper.concat( + ListWrapper.concat(_getAppBindings(), _runtimeCompilerBindings()), this._providers)); + this._instantiated = true; + return this._injector; + } + + execute(fn: FunctionWithParamTokens): any { + if (!this._instantiated) { + this.createInjector(); + } + return fn.execute(this._injector); + } } -export function createTestInjectorWithRuntimeCompiler( - providers: Array): Injector { - return createTestInjector(ListWrapper.concat(_runtimeCompilerBindings(), providers)); +var _testInjector: TestInjector = null; + +export function getTestInjector() { + if (_testInjector == null) { + _testInjector = new TestInjector(); + } + return _testInjector; } /** diff --git a/modules/angular2/src/testing/testing.ts b/modules/angular2/src/testing/testing.ts index 6112c1624499..a72c45062533 100644 --- a/modules/angular2/src/testing/testing.ts +++ b/modules/angular2/src/testing/testing.ts @@ -7,10 +7,11 @@ import {ListWrapper} from 'angular2/src/facade/collection'; import {bind} from 'angular2/core'; import { - createTestInjectorWithRuntimeCompiler, FunctionWithParamTokens, inject, - injectAsync + injectAsync, + TestInjector, + getTestInjector } from './test_injector'; export {inject, injectAsync} from './test_injector'; @@ -80,14 +81,10 @@ var jsmIt = _global.it; var jsmIIt = _global.fit; var jsmXIt = _global.xit; -var testProviders; -var injector; +var testInjector: TestInjector = getTestInjector(); // Reset the test providers before each test. -jsmBeforeEach(() => { - testProviders = []; - injector = null; -}); +jsmBeforeEach(() => { testInjector.reset(); }); /** * Allows overriding default providers of the test injector, @@ -103,8 +100,9 @@ export function beforeEachProviders(fn): void { jsmBeforeEach(() => { var providers = fn(); if (!providers) return; - testProviders = [...testProviders, ...providers]; - if (injector !== null) { + try { + testInjector.addProviders(providers); + } catch (e) { throw new Error('beforeEachProviders was called after the injector had ' + 'been used in a beforeEach or it block. This invalidates the ' + 'test injector'); @@ -176,11 +174,7 @@ function _it(jsmFn: Function, name: string, testFn: FunctionWithParamTokens | An if (testFn instanceof FunctionWithParamTokens) { jsmFn(name, (done) => { - if (!injector) { - injector = createTestInjectorWithRuntimeCompiler(testProviders); - } - - var returnedTestValue = runInTestZone(() => testFn.execute(injector), done, done.fail); + var returnedTestValue = runInTestZone(() => testInjector.execute(testFn), done, done.fail); if (_isPromiseLike(returnedTestValue)) { (>returnedTestValue).then(null, (err) => { done.fail(err); }); } @@ -209,13 +203,7 @@ export function beforeEach(fn: FunctionWithParamTokens | AnyTestFn): void { // The test case uses inject(). ie `beforeEach(inject([ClassA], (a) => { ... // }));` - jsmBeforeEach((done) => { - if (!injector) { - injector = createTestInjectorWithRuntimeCompiler(testProviders); - } - - runInTestZone(() => fn.execute(injector), done, done.fail); - }); + jsmBeforeEach((done) => { runInTestZone(() => testInjector.execute(fn), done, done.fail); }); } else { // The test case doesn't use inject(). ie `beforeEach((done) => { ... }));` if ((fn).length === 0) { diff --git a/modules/angular2/src/testing/testing_internal.dart b/modules/angular2/src/testing/testing_internal.dart index 0bc0f6d5a29f..821300b74242 100644 --- a/modules/angular2/src/testing/testing_internal.dart +++ b/modules/angular2/src/testing/testing_internal.dart @@ -21,20 +21,23 @@ import 'package:angular2/src/core/reflection/reflection.dart'; import 'package:angular2/src/core/reflection/reflection_capabilities.dart'; import 'package:angular2/src/core/di/provider.dart' show bind; -import 'package:angular2/src/core/di/injector.dart' show Injector; import 'package:angular2/src/facade/collection.dart' show StringMapWrapper; import 'test_injector.dart'; export 'test_injector.dart' show inject; -List _testBindings = []; -Injector _injector; +TestInjector _testInjector = getTestInjector(); bool _isCurrentTestAsync; +Future _currentTestFuture; bool _inIt = false; class AsyncTestCompleter { final _completer = new Completer(); + AsyncTestCompleter() { + _currentTestFuture = this.future; + } + void done() { _completer.complete(); } @@ -50,10 +53,11 @@ void testSetup() { // - Priority 1: create the test injector to be used in beforeEach() and it() gns.beforeEach(() { - _testBindings.clear(); + _testInjector.reset(); + _currentTestFuture = null; }, priority: 3); - var completerBinding = bind(AsyncTestCompleter).toFactory(() { + var completerProvider = bind(AsyncTestCompleter).toFactory(() { // Mark the test as async when an AsyncTestCompleter is injected in an it(), if (!_inIt) throw 'AsyncTestCompleter can only be injected in an "it()"'; _isCurrentTestAsync = true; @@ -62,15 +66,14 @@ void testSetup() { gns.beforeEach(() { _isCurrentTestAsync = false; - _testBindings.add(completerBinding); - _injector = createTestInjectorWithRuntimeCompiler(_testBindings); + _testInjector.addProviders([completerProvider]); }, priority: 1); } /** - * Allows overriding default bindings defined in test_injector.js. + * Allows overriding default providers defined in test_injector.js. * - * The given function must return a list of DI bindings. + * The given function must return a list of DI providers. * * Example: * @@ -81,8 +84,8 @@ void testSetup() { */ void beforeEachProviders(Function fn) { gns.beforeEach(() { - var bindings = fn(); - if (bindings != null) _testBindings.addAll(bindings); + var providers = fn(); + if (providers != null) _testInjector.addProviders(providers); }, priority: 2); } @@ -95,7 +98,7 @@ void beforeEach(fn) { if (fn is! FunctionWithParamTokens) fn = new FunctionWithParamTokens([], fn, false); gns.beforeEach(() { - fn.execute(_injector); + _testInjector.execute(fn); }); } @@ -104,9 +107,9 @@ void _it(gnsFn, name, fn) { new FunctionWithParamTokens([], fn, false); gnsFn(name, () { _inIt = true; - fn.execute(_injector); + _testInjector.execute(fn); _inIt = false; - if (_isCurrentTestAsync) return _injector.get(AsyncTestCompleter).future; + if (_isCurrentTestAsync) return _currentTestFuture; }); } diff --git a/modules/angular2/src/testing/testing_internal.ts b/modules/angular2/src/testing/testing_internal.ts index 54c01333c1f9..2dfebc146fa5 100644 --- a/modules/angular2/src/testing/testing_internal.ts +++ b/modules/angular2/src/testing/testing_internal.ts @@ -5,11 +5,7 @@ import {NgZoneZone} from 'angular2/src/core/zone/ng_zone'; import {provide} from 'angular2/core'; -import { - createTestInjectorWithRuntimeCompiler, - FunctionWithParamTokens, - inject -} from './test_injector'; +import {TestInjector, getTestInjector, FunctionWithParamTokens, inject} from './test_injector'; import {browserDetection} from './utils'; export {inject} from './test_injector'; @@ -45,7 +41,7 @@ var inIt = false; jasmine.DEFAULT_TIMEOUT_INTERVAL = 500; var globalTimeOut = browserDetection.isSlow ? 3000 : jasmine.DEFAULT_TIMEOUT_INTERVAL; -var testProviders; +var testInjector = getTestInjector(); /** * Mechanism to run `beforeEach()` functions of Angular tests. @@ -59,16 +55,17 @@ class BeforeEachRunner { beforeEach(fn: FunctionWithParamTokens | SyncTestFn): void { this._fns.push(fn); } - run(injector): void { - if (this._parent) this._parent.run(injector); + run(): void { + if (this._parent) this._parent.run(); this._fns.forEach((fn) => { - return isFunction(fn) ? (fn)() : (fn).execute(injector); + return isFunction(fn) ? (fn)() : + (testInjector.execute(fn)); }); } } // Reset the test providers before each test -jsmBeforeEach(() => { testProviders = []; }); +jsmBeforeEach(() => { testInjector.reset(); }); function _describe(jsmFn, ...args) { var parentRunner = runnerStack.length === 0 ? null : runnerStack[runnerStack.length - 1]; @@ -117,7 +114,7 @@ export function beforeEachProviders(fn): void { jsmBeforeEach(() => { var providers = fn(); if (!providers) return; - testProviders = [...testProviders, ...providers]; + testInjector.addProviders(providers); }); } @@ -147,18 +144,17 @@ function _it(jsmFn: Function, name: string, testFn: FunctionWithParamTokens | An } }); - var injector = createTestInjectorWithRuntimeCompiler([...testProviders, completerProvider]); - runner.run(injector); + testInjector.addProviders([completerProvider]); + runner.run(); inIt = true; - testFn.execute(injector); + testInjector.execute(testFn); inIt = false; }, timeOut); } else { jsmFn(name, () => { - var injector = createTestInjectorWithRuntimeCompiler(testProviders); - runner.run(injector); - testFn.execute(injector); + runner.run(); + testInjector.execute(testFn); }, timeOut); } @@ -167,14 +163,12 @@ function _it(jsmFn: Function, name: string, testFn: FunctionWithParamTokens | An if ((testFn).length === 0) { jsmFn(name, () => { - var injector = createTestInjectorWithRuntimeCompiler(testProviders); - runner.run(injector); + runner.run(); (testFn)(); }, timeOut); } else { jsmFn(name, (done) => { - var injector = createTestInjectorWithRuntimeCompiler(testProviders); - runner.run(injector); + runner.run(); (testFn)(done); }, timeOut); } diff --git a/modules/angular2/test/web_workers/debug_tools/multi_client_server_message_bus.server.spec.dart b/modules/angular2/test/web_workers/debug_tools/multi_client_server_message_bus.server.spec.dart index 43494c9e6a52..857b948b0b3d 100644 --- a/modules/angular2/test/web_workers/debug_tools/multi_client_server_message_bus.server.spec.dart +++ b/modules/angular2/test/web_workers/debug_tools/multi_client_server_message_bus.server.spec.dart @@ -11,7 +11,6 @@ import "package:angular2/testing_internal.dart" iit, expect, beforeEach, - createTestInjector, beforeEachProviders, SpyObject, proxy; diff --git a/modules/angular2/test/web_workers/debug_tools/single_client_server_message_bus.server.spec.dart b/modules/angular2/test/web_workers/debug_tools/single_client_server_message_bus.server.spec.dart index 0cf86f781b0c..50ca5f15ae0b 100644 --- a/modules/angular2/test/web_workers/debug_tools/single_client_server_message_bus.server.spec.dart +++ b/modules/angular2/test/web_workers/debug_tools/single_client_server_message_bus.server.spec.dart @@ -10,7 +10,6 @@ import "package:angular2/testing_internal.dart" it, expect, beforeEach, - createTestInjector, beforeEachProviders, SpyObject, proxy; diff --git a/modules/angular2/test/web_workers/debug_tools/web_socket_message_bus_spec.dart b/modules/angular2/test/web_workers/debug_tools/web_socket_message_bus_spec.dart index 6823eb008ad0..9b87a3e28155 100644 --- a/modules/angular2/test/web_workers/debug_tools/web_socket_message_bus_spec.dart +++ b/modules/angular2/test/web_workers/debug_tools/web_socket_message_bus_spec.dart @@ -8,7 +8,6 @@ import "package:angular2/testing_internal.dart" it, expect, beforeEach, - createTestInjector, beforeEachProviders, SpyObject, proxy; diff --git a/modules/angular2/test/web_workers/shared/message_bus_spec.ts b/modules/angular2/test/web_workers/shared/message_bus_spec.ts index e4fcc2ade053..1e3073c94ed5 100644 --- a/modules/angular2/test/web_workers/shared/message_bus_spec.ts +++ b/modules/angular2/test/web_workers/shared/message_bus_spec.ts @@ -5,7 +5,6 @@ import { it, expect, beforeEach, - createTestInjectorWithRuntimeCompiler, beforeEachProviders, SpyObject, proxy diff --git a/modules/angular2/test/web_workers/shared/service_message_broker_spec.ts b/modules/angular2/test/web_workers/shared/service_message_broker_spec.ts index 9b0b148221e0..d30be8bc593a 100644 --- a/modules/angular2/test/web_workers/shared/service_message_broker_spec.ts +++ b/modules/angular2/test/web_workers/shared/service_message_broker_spec.ts @@ -5,7 +5,6 @@ import { it, expect, beforeEach, - createTestInjectorWithRuntimeCompiler, beforeEachProviders, SpyObject, proxy diff --git a/modules/angular2/test/web_workers/worker/event_dispatcher_spec.ts b/modules/angular2/test/web_workers/worker/event_dispatcher_spec.ts index 5efa1ea81108..a97d1b00967d 100644 --- a/modules/angular2/test/web_workers/worker/event_dispatcher_spec.ts +++ b/modules/angular2/test/web_workers/worker/event_dispatcher_spec.ts @@ -5,7 +5,6 @@ import { it, expect, beforeEach, - createTestInjectorWithRuntimeCompiler, beforeEachProviders, SpyObject, proxy diff --git a/modules/angular2/test/web_workers/worker/renderer_integration_spec.ts b/modules/angular2/test/web_workers/worker/renderer_integration_spec.ts index dbeca905823a..8f56648945ed 100644 --- a/modules/angular2/test/web_workers/worker/renderer_integration_spec.ts +++ b/modules/angular2/test/web_workers/worker/renderer_integration_spec.ts @@ -7,8 +7,8 @@ import { iit, expect, beforeEach, - createTestInjectorWithRuntimeCompiler, beforeEachProviders, + TestInjector, TestComponentBuilder } from "angular2/testing_internal"; import {DOM} from 'angular2/src/platform/dom/dom_adapter'; @@ -102,12 +102,14 @@ export function main() { beforeEachProviders(() => { var uiRenderProtoViewStore = new RenderProtoViewRefStore(false); uiRenderViewStore = new RenderViewWithFragmentsStore(false); - uiInjector = createTestInjectorWithRuntimeCompiler([ + var testInjector = new TestInjector(); + testInjector.addProviders([ provide(RenderProtoViewRefStore, {useValue: uiRenderProtoViewStore}), provide(RenderViewWithFragmentsStore, {useValue: uiRenderViewStore}), provide(DomRenderer, {useClass: DomRenderer_}), provide(Renderer, {useExisting: DomRenderer}) ]); + uiInjector = testInjector.createInjector(); var uiSerializer = uiInjector.get(Serializer); var domRenderer = uiInjector.get(DomRenderer); var workerRenderProtoViewStore = new RenderProtoViewRefStore(true); diff --git a/modules/angular2/test/web_workers/worker/xhr_impl_spec.ts b/modules/angular2/test/web_workers/worker/xhr_impl_spec.ts index 83fe0f9828e7..dfb68279afcf 100644 --- a/modules/angular2/test/web_workers/worker/xhr_impl_spec.ts +++ b/modules/angular2/test/web_workers/worker/xhr_impl_spec.ts @@ -5,7 +5,6 @@ import { it, expect, beforeEach, - createTestInjectorWithRuntimeCompiler, beforeEachProviders } from 'angular2/testing_internal'; import {SpyMessageBroker} from './spies'; diff --git a/modules_dart/angular2_testing/lib/angular2_testing.dart b/modules_dart/angular2_testing/lib/angular2_testing.dart index 60d1302dd358..da737b3863b3 100644 --- a/modules_dart/angular2_testing/lib/angular2_testing.dart +++ b/modules_dart/angular2_testing/lib/angular2_testing.dart @@ -1,11 +1,8 @@ library angular2_testing.angular2_testing; import 'package:test/test.dart'; -import 'package:test/src/backend/invoker.dart'; -import 'package:test/src/backend/live_test.dart'; import 'package:angular2/angular2.dart'; -import 'package:angular2/src/core/di/injector.dart' show Injector; import 'package:angular2/src/core/di/metadata.dart' show InjectMetadata; import 'package:angular2/src/core/di/exceptions.dart' show NoAnnotationError; import 'package:angular2/platform/browser_static.dart' show BrowserDomAdapter; @@ -31,6 +28,13 @@ void initAngularTests() { reflector.reflectionCapabilities = new ReflectionCapabilities(); } +void _addTestInjectorTearDown() { + // Multiple resets are harmless. + tearDown(() { + _testInjector.reset(); + }); +} + /// Allows overriding default bindings defined in test_injector.dart. /// /// The given function must return a list of DI providers. @@ -45,13 +49,17 @@ void initAngularTests() { /// ``` void setUpProviders(Iterable providerFactory()) { setUp(() { - if (_currentInjector != null) { + try { + _testInjector.addProviders(providerFactory()); + } catch(e) { throw 'setUpProviders was called after the injector had ' 'been used in a setUp or test block. This invalidates the ' 'test injector'; } - _currentTestProviders.addAll(providerFactory()); + }); + + _addTestInjectorTearDown(); } dynamic _runInjectableFunction(Function fn) { @@ -72,11 +80,8 @@ dynamic _runInjectableFunction(Function fn) { tokens.add(token); } - if (_currentInjector == null) { - _currentInjector = createTestInjectorWithRuntimeCompiler(_currentTestProviders); - } var injectFn = new FunctionWithParamTokens(tokens, fn, false); - return injectFn.execute(_currentInjector); + return _testInjector.execute(injectFn); } /// Use the test injector to get bindings and run a function. @@ -92,6 +97,8 @@ void ngSetUp(Function fn) { setUp(() async { await _runInjectableFunction(fn); }); + + _addTestInjectorTearDown(); } /// Add a test which can use the test injector. @@ -108,25 +115,8 @@ void ngTest(String description, Function fn, test(description, () async { await _runInjectableFunction(fn); }, testOn: testOn, timeout: timeout, skip: skip, onPlatform: onPlatform); -} - -final _providersExpando = - new Expando>('Providers for the current test'); -final _injectorExpando = - new Expando('Angular Injector for the current test'); - -List get _currentTestProviders { - if (_providersExpando[_currentTest] == null) { - return _providersExpando[_currentTest] = []; - } - return _providersExpando[_currentTest]; -} -Injector get _currentInjector => _injectorExpando[_currentTest]; -void set _currentInjector(Injector newInjector) { - _injectorExpando[_currentTest] = newInjector; + _addTestInjectorTearDown(); } -// TODO: warning, the Invoker.current.liveTest is not a settled API and is -// subject to change in future versions of package:test. -LiveTest get _currentTest => Invoker.current.liveTest; +final TestInjector _testInjector = getTestInjector(); From a79fe057f9426b181fa1c112255e08db5f1c0a67 Mon Sep 17 00:00:00 2001 From: Tamas Csaba Date: Sun, 13 Dec 2015 12:45:19 +0100 Subject: [PATCH 03/55] fix(changelog): fix rxjs operator import paths Closes #5864 --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccb7547bba12..f5fd6240d676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -259,9 +259,9 @@ import * as core from 'angular2/core'; * Operators and Observables from RxJS (e.g. .map(), .toArray(), .toPromise(), etc ) now need to be explicitly imported (once per operator in your app) ``` - import {Observable} from 'angular2/angular2' - import 'rxjs/operators/map'; - import 'rxjs/observable/interval' + import {Observable} from 'rxjs/Observable'; + import 'rxjs/add/operators/map'; + import 'rxjs/add/observable/interval'; Observable.interval(1000).subscribe(...); From 1c779d8b9e1771f1d238b778564a59f32784b436 Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Mon, 14 Dec 2015 15:28:57 +0100 Subject: [PATCH 04/55] docs(bundles): document existing bundles and their usage Closes #5777 Closes #5878 --- gulpfile.js | 7 ++- modules/angular2/docs/bundles/overview.md | 77 +++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 modules/angular2/docs/bundles/overview.md diff --git a/gulpfile.js b/gulpfile.js index 69a5cc057cc0..ee1466927aee 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1113,6 +1113,10 @@ gulp.task('!bundle.testing', ['build.js.dev'], function() { {sourceMaps: true}); }); +gulp.task('!bundles.js.docs', function() { + gulp.src('modules/angular2/docs/bundles/*').pipe(gulp.dest('dist/js/bundle')); +}); + gulp.task('!bundles.js.umd', ['build.js.dev'], function() { var q = require('q'); var webpack = q.denodeify(require('webpack')); @@ -1252,7 +1256,8 @@ gulp.task('bundles.js', '!bundle.web_worker.js.dev.deps', 'bundles.js.umd.min', '!bundle.testing', - '!bundle.ng.polyfills' + '!bundle.ng.polyfills', + '!bundles.js.docs' ], function(done) { runSequence('!bundle.copy', '!bundles.js.checksize', done); }); diff --git a/modules/angular2/docs/bundles/overview.md b/modules/angular2/docs/bundles/overview.md new file mode 100644 index 000000000000..cded69e52cbb --- /dev/null +++ b/modules/angular2/docs/bundles/overview.md @@ -0,0 +1,77 @@ +# TL;DR; + +* If you write ES5 use _one_ of the `UMD` bundles. +* If you experiment with Angular2 using online prototyping tools like [plnkr](http://plnkr.co/) or similar use `System.register` bundles with SystemJS loader. +* If you use build tools like Browserify or WebPack - bundle Angular2 as part of your build. +* For all the above cases you must use `angular2-polyfills.js` in a `script` tag to easily include polyfills and external dependencies. + +# Modules, barrels and bundles + +Angular2 source code is authored using the ES2015 standardized module format where one module corresponds to exactly one file. Multiple modules (files) can be logically grouped into so-called "barrels". + A bundle is a file the contains all the code for one or more barrels. + +Most bundles come in several flavors: +* regular and minified (got `.min` in their name); +* regular and "development" (have `.dev` in their name) - "development" bundles contain in-line source maps and don't have minified flavor (minification removes in-lined source maps). + +# Bundles, their content and usage scenarios + +Angular 2 distributes several types of bundles targeted at specific usages: + * users writing ES5 code without any transpilation steps + * users experimenting with Angular 2 and TypeScript/ES2015 using online tools like plunker, jsbin or similar + +Since each identified scenario has slightly different requirements and constraints there are specific bundles for each use-case. + +## ES5 and ngUpgrade users + +ES5 users and AngularJS 1.x users interested in the `ngUpgrade` path can take advantage of the bundles in the [UMD format](https://github.com/umdjs/umd). + Those are coarse-grained bundles that combine many barrels in one final file. + +filename | list of barrels | dev/prod | minified? +------------|-------------------|----------|-------------|--------------|------------- +`angular2.umd.js` | `RxJS`, `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade`| prod | no +`angular2.umd.min.js` | `RxJS`, `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade` | prod | yes +`angular2.umd.dev.js` | `RxJS`, `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade` | dev | no +`angular2-testing.umd.dev.js` | `RxJS`, `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/http`, `angular2/router`, `angular2/instrumentation`, `angular2/upgrade`, `angular2/testing`, `angular2/http/testing`, `angular2/router/testing` | dev | no + +**Warning**: bundles in the `UMD` format are _not_ "additive". A single application should use only one bundle from the above list. + +## SystemJS loader users + +[SystemJS loader](https://github.com/systemjs/systemjs) with on-the-fly (in a browser) transpilations support is very useful for quick experiments using tools like plunker, jsbin or similar. +For this scenario Angular 2 is distributed with bundles in the [System.register format](https://github.com/ModuleLoader/es6-module-loader/wiki/System.register-Explained): + +filename | list of barrels | dev/prod | minified? +------------|-------------------|----------|-------------|--------------|------------- +`angular2.js` | `RxJS`, `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/instrumentation`| prod | no +`angular2.min.js` | `RxJS`, `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/instrumentation`| prod | yes +`angular2.dev.js` | `RxJS`, `angular2/core`, `angular2/common`, `angular2/compiler`, `angular2/platform/browser`, `angular2/platform/common_dom`, `angular2/instrumentation`| dev | no +`http.js` | `angular2/http` | prod | no +`http.min.js` | `angular2/http` | prod | yes +`http.dev.js` | `angular2/http` | dev | no +`router.js` | `angular2/router` | prod | no +`router.min.js` | `angular2/router` | prod | yes +`router.dev.js` | `angular2/router` | dev | no +`upgrade.js` | `angular2/upgrade` | prod | no +`upgrade.min.js` | `angular2/upgrade` | prod | yes +`upgrade.dev.js` | `angular2/upgrade` | dev | no +`testing.dev.js` | `angular2/testing`, `angular2/http/testing`, `angular2/router/testing` | dev | no + +**Note**: bundles in the `System.register` format are "additive" - it is quite common to include several bundles in one application. +For example people using Angular 2 with `http` and `router` would include: `angular2.js`, `http.js` and `router.js`. + +## Browserify / JSPM / Rollup / WebPack users + +Angular 2 doesn't provide any bundles for use with packaging tools Browserify or WebPack. Those tools are sophisticated enough to build optimal bundles for production use from individual Angular 2 files distributed in the npm package. +An example of an Angular 2 project built with WebPack can be found in the [angular2-seed](https://github.com/angular/angular2-seed) repository. + +# Polyfills and external dependencies + +Polyfills are required for Angular 2 to function properly (the exact list depends on the browser used) and external dependencies ([zone.js](https://github.com/angular/zone.js)). +To ease setup of Angular 2 applications there is one file - `angular2-polyfills.js` - that combines: +* a pollyfill mandatory for all browsers: [reflect-metadata](https://www.npmjs.com/package/reflect-metadata) +* [zone.js](https://github.com/angular/zone.js) + +**Note**: `angular2-polyfills.js` contains code that should be loaded into the browser as the very first code of the web application even before the module loader. The preferred solution is to load the mentioned file in a `script` tag as early as possible. + +Users of pre-ES6 browsers might need to add an ES6 shim (e.g. [es6-shim](https://github.com/paulmillr/es6-shim)) \ No newline at end of file From 5a04ffec3ef51f11cb919b4246bf18b8f5e274ef Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Sun, 13 Dec 2015 17:35:33 -0800 Subject: [PATCH 05/55] refactor(Directive): drop moduleId moduleId is only used by components to resolve urls. Directives have no templates and do not need moduleId. Closes #5873 --- .../angular2/src/compiler/runtime_metadata.ts | 7 +-- .../src/core/linker/directive_resolver.ts | 1 - modules/angular2/src/core/metadata.dart | 2 - modules/angular2/src/core/metadata.ts | 2 - .../angular2/src/core/metadata/directives.ts | 46 +++++++++---------- .../src/mock/directive_resolver_mock.ts | 1 - .../test/compiler/runtime_metadata_spec.ts | 21 ++++----- .../test/compiler/template_compiler_spec.ts | 2 +- modules/angular2/test/public_api_spec.ts | 2 - 9 files changed, 37 insertions(+), 47 deletions(-) diff --git a/modules/angular2/src/compiler/runtime_metadata.ts b/modules/angular2/src/compiler/runtime_metadata.ts index 2f7951a55388..1fceb0e859d0 100644 --- a/modules/angular2/src/compiler/runtime_metadata.ts +++ b/modules/angular2/src/compiler/runtime_metadata.ts @@ -32,12 +32,13 @@ export class RuntimeMetadataResolver { var meta = this._cache.get(directiveType); if (isBlank(meta)) { var dirMeta = this._directiveResolver.resolve(directiveType); - var moduleUrl = calcModuleUrl(directiveType, dirMeta); + var moduleUrl = null; var templateMeta = null; var changeDetectionStrategy = null; if (dirMeta instanceof md.ComponentMetadata) { var cmpMeta = dirMeta; + moduleUrl = calcModuleUrl(directiveType, cmpMeta); var viewMeta = this._viewResolver.resolve(directiveType); templateMeta = new cpl.CompileTemplateMetadata({ encapsulation: viewMeta.encapsulation, @@ -107,8 +108,8 @@ function isValidDirective(value: Type): boolean { return isPresent(value) && (value instanceof Type); } -function calcModuleUrl(type: Type, dirMeta: md.DirectiveMetadata): string { - var moduleId = dirMeta.moduleId; +function calcModuleUrl(type: Type, cmpMetadata: md.ComponentMetadata): string { + var moduleId = cmpMetadata.moduleId; if (isPresent(moduleId)) { var scheme = getUrlScheme(moduleId); return isPresent(scheme) && scheme.length > 0 ? moduleId : diff --git a/modules/angular2/src/core/linker/directive_resolver.ts b/modules/angular2/src/core/linker/directive_resolver.ts index 380cbc9f2204..1d19c4e9fe69 100644 --- a/modules/angular2/src/core/linker/directive_resolver.ts +++ b/modules/angular2/src/core/linker/directive_resolver.ts @@ -132,7 +132,6 @@ export class DirectiveResolver { outputs: mergedOutputs, host: mergedHost, exportAs: dm.exportAs, - moduleId: dm.moduleId, queries: mergedQueries, providers: dm.providers }); diff --git a/modules/angular2/src/core/metadata.dart b/modules/angular2/src/core/metadata.dart index e47ed69c342a..ec9f12cfacf2 100644 --- a/modules/angular2/src/core/metadata.dart +++ b/modules/angular2/src/core/metadata.dart @@ -27,7 +27,6 @@ class Directive extends DirectiveMetadata { List bindings, List providers, String exportAs, - String moduleId, Map queries}) : super( selector: selector, @@ -39,7 +38,6 @@ class Directive extends DirectiveMetadata { bindings: bindings, providers: providers, exportAs: exportAs, - moduleId: moduleId, queries: queries); } diff --git a/modules/angular2/src/core/metadata.ts b/modules/angular2/src/core/metadata.ts index a6f758837ca3..df3292be0f00 100644 --- a/modules/angular2/src/core/metadata.ts +++ b/modules/angular2/src/core/metadata.ts @@ -146,7 +146,6 @@ export interface DirectiveFactory { bindings?: any[], providers?: any[], exportAs?: string, - moduleId?: string, queries?: {[key: string]: any} }): DirectiveDecorator; new (obj: { @@ -159,7 +158,6 @@ export interface DirectiveFactory { bindings?: any[], providers?: any[], exportAs?: string, - moduleId?: string, queries?: {[key: string]: any} }): DirectiveMetadata; } diff --git a/modules/angular2/src/core/metadata/directives.ts b/modules/angular2/src/core/metadata/directives.ts index 4c0c3ec611ca..b936e95509e0 100644 --- a/modules/angular2/src/core/metadata/directives.ts +++ b/modules/angular2/src/core/metadata/directives.ts @@ -696,26 +696,6 @@ export class DirectiveMetadata extends InjectableMetadata { */ exportAs: string; - /** - * The module id of the module that contains the directive. - * Needed to be able to resolve relative urls for templates and styles. - * In Dart, this can be determined automatically and does not need to be set. - * In CommonJS, this can always be set to `module.id`. - * - * ## Simple Example - * - * ``` - * @Directive({ - * selector: 'someDir', - * moduleId: module.id - * }) - * class SomeDir { - * } - * - * ``` - */ - moduleId: string; - // TODO: add an example after ContentChildren and ViewChildren are in master /** * Configures the queries that will be injected into the directive. @@ -752,7 +732,7 @@ export class DirectiveMetadata extends InjectableMetadata { queries: {[key: string]: any}; constructor({selector, inputs, outputs, properties, events, host, bindings, providers, exportAs, - moduleId, queries}: { + queries}: { selector?: string, inputs?: string[], outputs?: string[], @@ -762,7 +742,6 @@ export class DirectiveMetadata extends InjectableMetadata { providers?: any[], /** @deprecated */ bindings?: any[], exportAs?: string, - moduleId?: string, queries?: {[key: string]: any} } = {}) { super(); @@ -773,7 +752,6 @@ export class DirectiveMetadata extends InjectableMetadata { this._events = events; this.host = host; this.exportAs = exportAs; - this.moduleId = moduleId; this.queries = queries; this._providers = providers; this._bindings = bindings; @@ -865,6 +843,26 @@ export class ComponentMetadata extends DirectiveMetadata { private _viewProviders: any[]; private _viewBindings: any[]; + /** + * The module id of the module that contains the component. + * Needed to be able to resolve relative urls for templates and styles. + * In Dart, this can be determined automatically and does not need to be set. + * In CommonJS, this can always be set to `module.id`. + * + * ## Simple Example + * + * ``` + * @Directive({ + * selector: 'someDir', + * moduleId: module.id + * }) + * class SomeDir { + * } + * + * ``` + */ + moduleId: string; + templateUrl: string; template: string; @@ -913,7 +911,6 @@ export class ComponentMetadata extends DirectiveMetadata { events: events, host: host, exportAs: exportAs, - moduleId: moduleId, bindings: bindings, providers: providers, queries: queries @@ -929,6 +926,7 @@ export class ComponentMetadata extends DirectiveMetadata { this.directives = directives; this.pipes = pipes; this.encapsulation = encapsulation; + this.moduleId = moduleId; } } diff --git a/modules/angular2/src/mock/directive_resolver_mock.ts b/modules/angular2/src/mock/directive_resolver_mock.ts index 9b1e0993feb8..b6a6451265c9 100644 --- a/modules/angular2/src/mock/directive_resolver_mock.ts +++ b/modules/angular2/src/mock/directive_resolver_mock.ts @@ -47,7 +47,6 @@ export class MockDirectiveResolver extends DirectiveResolver { host: dm.host, providers: providers, exportAs: dm.exportAs, - moduleId: dm.moduleId, queries: dm.queries }); } diff --git a/modules/angular2/test/compiler/runtime_metadata_spec.ts b/modules/angular2/test/compiler/runtime_metadata_spec.ts index 46fd18e4097c..50ca069ca241 100644 --- a/modules/angular2/test/compiler/runtime_metadata_spec.ts +++ b/modules/angular2/test/compiler/runtime_metadata_spec.ts @@ -70,10 +70,10 @@ export function main() { it('should use the moduleUrl from the reflector if none is given', inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => { - var value: string = resolver.getMetadata(DirectiveWithoutModuleId).type.moduleUrl; + var value: string = resolver.getMetadata(ComponentWithoutModuleId).type.moduleUrl; var expectedEndValue = IS_DART ? 'base/dist/dart/angular2/test/compiler/runtime_metadata_spec.dart' : './'; - expect((value).endsWith(expectedEndValue)).toBe(true); + expect(value.endsWith(expectedEndValue)).toBe(true); })); }); @@ -82,7 +82,7 @@ export function main() { it('should return the directive metadatas', inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => { expect(resolver.getViewDirectivesMetadata(ComponentWithEverything)) - .toEqual([resolver.getMetadata(DirectiveWithoutModuleId)]); + .toEqual([resolver.getMetadata(SomeDirective)]); })); describe("platform directives", () => { @@ -91,10 +91,7 @@ export function main() { it('should include platform directives when available', inject([RuntimeMetadataResolver], (resolver: RuntimeMetadataResolver) => { expect(resolver.getViewDirectivesMetadata(ComponentWithEverything)) - .toEqual([ - resolver.getMetadata(ADirective), - resolver.getMetadata(DirectiveWithoutModuleId) - ]); + .toEqual([resolver.getMetadata(ADirective), resolver.getMetadata(SomeDirective)]); })); }); }); @@ -102,14 +99,16 @@ export function main() { }); } - - @Directive({selector: 'a-directive'}) class ADirective { } @Directive({selector: 'someSelector'}) -class DirectiveWithoutModuleId { +class SomeDirective { +} + +@Component({selector: 'someComponent', template: ''}) +class ComponentWithoutModuleId { } @Component({ @@ -131,7 +130,7 @@ class DirectiveWithoutModuleId { encapsulation: ViewEncapsulation.Emulated, styles: ['someStyle'], styleUrls: ['someStyleUrl'], - directives: [DirectiveWithoutModuleId] + directives: [SomeDirective] }) class ComponentWithEverything implements OnChanges, OnInit, DoCheck, OnDestroy, AfterContentInit, AfterContentChecked, AfterViewInit, diff --git a/modules/angular2/test/compiler/template_compiler_spec.ts b/modules/angular2/test/compiler/template_compiler_spec.ts index b09c0bc9ff96..cb5c0234ebf4 100644 --- a/modules/angular2/test/compiler/template_compiler_spec.ts +++ b/modules/angular2/test/compiler/template_compiler_spec.ts @@ -321,7 +321,7 @@ class CompWithEmbeddedTemplate { } -@Directive({selector: 'plain', moduleId: THIS_MODULE_ID}) +@Directive({selector: 'plain'}) @View({template: ''}) class NonComponent { } diff --git a/modules/angular2/test/public_api_spec.ts b/modules/angular2/test/public_api_spec.ts index 5d7c2d915b69..71fe8210bab3 100644 --- a/modules/angular2/test/public_api_spec.ts +++ b/modules/angular2/test/public_api_spec.ts @@ -923,7 +923,6 @@ var NG_CORE = [ 'Directive.events', 'Directive.exportAs', 'Directive.host', - 'Directive.moduleId', 'Directive.inputs', 'Directive.properties', 'Directive.queries', @@ -935,7 +934,6 @@ var NG_CORE = [ 'DirectiveMetadata.events', 'DirectiveMetadata.exportAs', 'DirectiveMetadata.host', - 'DirectiveMetadata.moduleId', 'DirectiveMetadata.inputs', 'DirectiveMetadata.properties', 'DirectiveMetadata.queries', From 80a5e47e61241c2287b162d609f117ea6ae00515 Mon Sep 17 00:00:00 2001 From: Alex Rickabaugh Date: Thu, 3 Dec 2015 15:49:09 -0800 Subject: [PATCH 06/55] docs(*): Document a lot more symbols that are missing comments in our generated docs. --- .../common/forms/ts/validators/validators.ts | 30 +++++++ .../compiler/ts/url_resolver/url_resolver.ts | 19 +++++ .../debug/ts/debug_element/debug_element.ts | 16 ++++ .../examples/platform/dom/debug/ts/by/by.ts | 17 ++++ .../debug_element_view_listener/providers.ts | 10 +++ .../examples/testing/ts/fake_async.ts | 29 +++++++ .../angular2/examples/testing/ts/matchers.ts | 40 ++++++++++ modules/angular2/http.ts | 4 + modules/angular2/router.ts | 2 + .../common/directives/observable_list_diff.ts | 5 ++ .../directives/control_value_accessor.ts | 5 ++ .../forms/directives/ng_control_status.ts | 4 + .../src/common/forms/directives/validators.ts | 24 ++++++ .../angular2/src/common/forms/form_builder.ts | 2 + .../angular2/src/common/forms/validators.ts | 4 +- modules/angular2/src/common/pipes.ts | 7 ++ .../angular2/src/common/pipes/common_pipes.ts | 7 ++ modules/angular2/src/compiler/compiler.ts | 4 + .../src/compiler/directive_metadata.ts | 12 +++ .../angular2/src/compiler/source_module.ts | 6 ++ modules/angular2/src/compiler/template_ast.ts | 75 +++++++++++++++++- .../src/compiler/template_compiler.ts | 5 ++ .../angular2/src/compiler/template_parser.ts | 7 ++ modules/angular2/src/compiler/url_resolver.ts | 15 +++- modules/angular2/src/compiler/xhr.ts | 4 + modules/angular2/src/compiler/xhr_mock.ts | 24 ++++++ .../change_detection/change_detection_util.ts | 7 +- .../change_detection/change_detector_ref.ts | 2 +- .../src/core/change_detection/constants.ts | 13 ++++ .../differs/iterable_differs.ts | 4 + .../differs/keyvalue_differs.ts | 3 + .../angular2/src/core/debug/debug_element.ts | 59 +++++++++++++- modules/angular2/src/core/di/provider.ts | 11 ++- .../src/core/linker/component_url_mapper.ts | 8 +- modules/angular2/src/core/linker/view_ref.ts | 2 +- .../angular2/src/core/linker/view_resolver.ts | 3 + modules/angular2/src/core/metadata.ts | 12 +++ modules/angular2/src/core/profile/wtf_impl.ts | 3 + .../src/core/reflection/reflection.ts | 4 + .../angular2/src/core/reflection/reflector.ts | 7 ++ modules/angular2/src/core/render/api.ts | 33 +++++++- .../src/core/testability/testability.ts | 10 +++ modules/angular2/src/core/zone/ng_zone.ts | 6 ++ modules/angular2/src/facade/collection.ts | 4 + modules/angular2/src/facade/exceptions.ts | 3 + modules/angular2/src/facade/lang.ts | 4 + .../angular2/src/http/backends/browser_xhr.ts | 6 +- .../src/http/backends/jsonp_backend.ts | 22 ++++++ modules/angular2/src/http/http.ts | 2 +- .../src/mock/directive_resolver_mock.ts | 4 + modules/angular2/src/mock/location_mock.ts | 3 + .../angular2/src/mock/mock_application_ref.ts | 3 + .../src/mock/mock_location_strategy.ts | 4 + modules/angular2/src/mock/ng_zone_mock.ts | 3 + .../src/platform/browser/browser_adapter.ts | 3 + .../angular2/src/platform/browser_common.ts | 10 +++ modules/angular2/src/platform/dom/debug/by.ts | 27 ++++++- .../dom/debug/debug_element_view_listener.ts | 12 +++ .../src/router/route_config_decorator.ts | 7 ++ .../angular2/src/router/route_definition.ts | 6 ++ modules/angular2/src/testing/fake_async.ts | 19 ++++- modules/angular2/src/testing/matchers.ts | 78 ++++++++++++++++++- modules/angular2/src/testing/test_injector.ts | 14 +++- modules/angular2/src/testing/testing.ts | 14 +++- .../angular2/src/testing/testing_internal.ts | 3 + 65 files changed, 793 insertions(+), 22 deletions(-) create mode 100644 modules/angular2/examples/common/forms/ts/validators/validators.ts create mode 100644 modules/angular2/examples/compiler/ts/url_resolver/url_resolver.ts create mode 100644 modules/angular2/examples/core/debug/ts/debug_element/debug_element.ts create mode 100644 modules/angular2/examples/platform/dom/debug/ts/by/by.ts create mode 100644 modules/angular2/examples/platform/dom/debug/ts/debug_element_view_listener/providers.ts create mode 100644 modules/angular2/examples/testing/ts/fake_async.ts create mode 100644 modules/angular2/examples/testing/ts/matchers.ts diff --git a/modules/angular2/examples/common/forms/ts/validators/validators.ts b/modules/angular2/examples/common/forms/ts/validators/validators.ts new file mode 100644 index 000000000000..6744c8b5ed92 --- /dev/null +++ b/modules/angular2/examples/common/forms/ts/validators/validators.ts @@ -0,0 +1,30 @@ +import {Component} from 'angular2/core'; +import {MinLengthValidator, MaxLengthValidator} from 'angular2/common'; + +// #docregion min +@Component({ + selector: 'min-cmp', + directives: [MinLengthValidator], + template: ` +
+

Year:

+
+` +}) +class MinLengthTestComponent { +} +// #enddocregion + +// #docregion max +@Component({ + selector: 'max-cmp', + directives: [MaxLengthValidator], + template: ` +
+

Year:

+
+` +}) +class MaxLengthTestComponent { +} +// #enddocregion diff --git a/modules/angular2/examples/compiler/ts/url_resolver/url_resolver.ts b/modules/angular2/examples/compiler/ts/url_resolver/url_resolver.ts new file mode 100644 index 000000000000..3910a38a1a82 --- /dev/null +++ b/modules/angular2/examples/compiler/ts/url_resolver/url_resolver.ts @@ -0,0 +1,19 @@ +import {provide} from 'angular2/core'; +import {bootstrap} from 'angular2/bootstrap'; +import {UrlResolver} from 'angular2/compiler'; + +var MyApp; + +// #docregion url_resolver +class MyUrlResolver extends UrlResolver { + resolve(baseUrl: string, url: string): string { + // Serve CSS files from a special CDN. + if (url.substr(-4) === '.css') { + return super.resolve('http://cdn.myapp.com/css/', url); + } + return super.resolve(baseUrl, url); + } +} + +bootstrap(MyApp, [provide(UrlResolver, {useClass: MyUrlResolver})]); +// #enddocregion diff --git a/modules/angular2/examples/core/debug/ts/debug_element/debug_element.ts b/modules/angular2/examples/core/debug/ts/debug_element/debug_element.ts new file mode 100644 index 000000000000..ebda75d05c34 --- /dev/null +++ b/modules/angular2/examples/core/debug/ts/debug_element/debug_element.ts @@ -0,0 +1,16 @@ +import {DebugElement, Scope} from 'angular2/core'; + +var debugElement: DebugElement; +var predicate; + +// #docregion scope_all +debugElement.query(predicate, Scope.all); +// #enddocregion + +// #docregion scope_light +debugElement.query(predicate, Scope.light); +// #enddocregion + +// #docregion scope_view +debugElement.query(predicate, Scope.view); +// #enddocregion diff --git a/modules/angular2/examples/platform/dom/debug/ts/by/by.ts b/modules/angular2/examples/platform/dom/debug/ts/by/by.ts new file mode 100644 index 000000000000..58c888328cc4 --- /dev/null +++ b/modules/angular2/examples/platform/dom/debug/ts/by/by.ts @@ -0,0 +1,17 @@ +import {By} from 'angular2/platform/browser'; +import {DebugElement, Scope} from 'angular2/core'; + +var debugElement: DebugElement; +class MyDirective {} + +// #docregion by_all +debugElement.query(By.all(), Scope.all); +// #enddocregion + +// #docregion by_css +debugElement.query(By.css('[attribute]'), Scope.all); +// #enddocregion + +// #docregion by_directive +debugElement.query(By.directive(MyDirective), Scope.all); +// #enddocregion diff --git a/modules/angular2/examples/platform/dom/debug/ts/debug_element_view_listener/providers.ts b/modules/angular2/examples/platform/dom/debug/ts/debug_element_view_listener/providers.ts new file mode 100644 index 000000000000..b9dec70aaeac --- /dev/null +++ b/modules/angular2/examples/platform/dom/debug/ts/debug_element_view_listener/providers.ts @@ -0,0 +1,10 @@ +import {Component} from 'angular2/core'; +import {bootstrap, ELEMENT_PROBE_PROVIDERS} from 'angular2/platform/browser'; + +@Component({selector: 'my-component'}) +class MyAppComponent { +} + +// #docregion providers +bootstrap(MyAppComponent, [ELEMENT_PROBE_PROVIDERS]); +// #enddocregion \ No newline at end of file diff --git a/modules/angular2/examples/testing/ts/fake_async.ts b/modules/angular2/examples/testing/ts/fake_async.ts new file mode 100644 index 000000000000..55bb766b91af --- /dev/null +++ b/modules/angular2/examples/testing/ts/fake_async.ts @@ -0,0 +1,29 @@ +import {describe, it, fakeAsync, expect, tick, clearPendingTimers} from 'angular2/testing'; + +// #docregion basic +describe('this test', () => { + it('looks async but is synchronous', fakeAsync((): void => { + var flag = false; + setTimeout(() => { flag = true; }, 100); + expect(flag).toBe(false); + tick(50); + expect(flag).toBe(false); + tick(50); + expect(flag).toBe(true); + })); +}); +// #enddocregion + +// #docregion pending +describe('this test', () => { + it('aborts a timer', fakeAsync((): void => { + // This timer is scheduled but doesn't need to complete for the + // test to pass (maybe it's a timeout for some operation). + // Leaving it will cause the test to fail... + setTimeout(() => {}, 100); + + // Unless we clean it up first. + clearPendingTimers(); + })); +}); +// #enddocregion \ No newline at end of file diff --git a/modules/angular2/examples/testing/ts/matchers.ts b/modules/angular2/examples/testing/ts/matchers.ts new file mode 100644 index 000000000000..f0bf7d2818dc --- /dev/null +++ b/modules/angular2/examples/testing/ts/matchers.ts @@ -0,0 +1,40 @@ +import {expect} from 'angular2/testing'; + +var value: any; +var element: any; +var exception: any; + +abstract class OtherClass {} +class SomeClass {} + +// #docregion toBePromise +expect(value).toBePromise(); +// #enddocregion + +// #docregion toBeAnInstanceOf +expect(value).toBeAnInstanceOf(SomeClass); +// #enddocregion + +// #docregion toHaveText +expect(element).toHaveText('Hello world!'); +// #enddocregion + +// #docregion toHaveCssClass +expect(element).toHaveCssClass('current'); +// #enddocregion + +// #docregion toHaveCssStyle +expect(element).toHaveCssStyle({width: '100px', height: 'auto'}); +// #enddocregion + +// #docregion toContainError +expect(exception).toContainError('Failed to load'); +// #enddocregion + +// #docregion toThrowErrorWith +expect(() => { throw 'Failed to load'; }).toThrowErrorWith('Failed to load'); +// #enddocregion + +// #docregion toImplement +expect(SomeClass).toImplement(OtherClass); +// #enddocregion diff --git a/modules/angular2/http.ts b/modules/angular2/http.ts index 69c918d4ee63..5341e23191a0 100644 --- a/modules/angular2/http.ts +++ b/modules/angular2/http.ts @@ -166,6 +166,8 @@ export const HTTP_PROVIDERS: any[] = [ ]; /** + * See {@link HTTP_PROVIDERS} instead. + * * @deprecated */ export const HTTP_BINDINGS = HTTP_PROVIDERS; @@ -291,6 +293,8 @@ export const JSONP_PROVIDERS: any[] = [ ]; /** + * See {@link JSONP_PROVIDERS} instead. + * * @deprecated */ export const JSON_BINDINGS = JSONP_PROVIDERS; diff --git a/modules/angular2/router.ts b/modules/angular2/router.ts index 8d5409952dd4..4cea18950a6a 100644 --- a/modules/angular2/router.ts +++ b/modules/angular2/router.ts @@ -98,6 +98,8 @@ export const ROUTER_PROVIDERS: any[] = CONST_EXPR([ ]); /** + * Use {@link ROUTER_PROVIDERS} instead. + * * @deprecated */ export const ROUTER_BINDINGS = ROUTER_PROVIDERS; diff --git a/modules/angular2/src/common/directives/observable_list_diff.ts b/modules/angular2/src/common/directives/observable_list_diff.ts index 08d07c500770..ee99cf404765 100644 --- a/modules/angular2/src/common/directives/observable_list_diff.ts +++ b/modules/angular2/src/common/directives/observable_list_diff.ts @@ -2,4 +2,9 @@ // I need to be here to make TypeScript think this is a module. import {} from 'angular2/src/facade/lang'; + +/** + * This module exists in Dart, but not in Typescript. This exported symbol + * is only here to help Typescript think this is a module. + */ export var workaround_empty_observable_list_diff: any; diff --git a/modules/angular2/src/common/forms/directives/control_value_accessor.ts b/modules/angular2/src/common/forms/directives/control_value_accessor.ts index 33a907ba62a8..90820f7d7071 100644 --- a/modules/angular2/src/common/forms/directives/control_value_accessor.ts +++ b/modules/angular2/src/common/forms/directives/control_value_accessor.ts @@ -26,4 +26,9 @@ export interface ControlValueAccessor { registerOnTouched(fn: any): void; } +/** + * Used to provide a {@link ControlValueAccessor} for form controls. + * + * See {@link DefaultValueAccessor} for how to implement one. + */ export const NG_VALUE_ACCESSOR: OpaqueToken = CONST_EXPR(new OpaqueToken("NgValueAccessor")); \ No newline at end of file diff --git a/modules/angular2/src/common/forms/directives/ng_control_status.ts b/modules/angular2/src/common/forms/directives/ng_control_status.ts index 39f07e6ea475..38b7ccdabb4c 100644 --- a/modules/angular2/src/common/forms/directives/ng_control_status.ts +++ b/modules/angular2/src/common/forms/directives/ng_control_status.ts @@ -2,6 +2,10 @@ import {Directive, Self} from 'angular2/core'; import {NgControl} from './ng_control'; import {isBlank, isPresent} from 'angular2/src/facade/lang'; +/** + * Directive automatically applied to Angular forms that sets CSS classes + * based on control status (valid/invalid/dirty/etc). + */ @Directive({ selector: '[ngControl],[ngModel],[ngFormControl]', host: { diff --git a/modules/angular2/src/common/forms/directives/validators.ts b/modules/angular2/src/common/forms/directives/validators.ts index 53ca2ae56aaf..dcb3189bccdc 100644 --- a/modules/angular2/src/common/forms/directives/validators.ts +++ b/modules/angular2/src/common/forms/directives/validators.ts @@ -45,8 +45,20 @@ const REQUIRED_VALIDATOR = export class RequiredValidator { } +/** + * Provivder which adds {@link MinLengthValidator} to {@link NG_VALIDATORS}. + * + * ## Example: + * + * {@example common/forms/ts/validators/validators.ts region='min'} + */ const MIN_LENGTH_VALIDATOR = CONST_EXPR( new Provider(NG_VALIDATORS, {useExisting: forwardRef(() => MinLengthValidator), multi: true})); + +/** + * A directive which installs the {@link MinLengthValidator} for any `ngControl`, + * `ngFormControl`, or control with `ngModel` that also has a `minlength` attribute. + */ @Directive({ selector: '[minlength][ngControl],[minlength][ngFormControl],[minlength][ngModel]', providers: [MIN_LENGTH_VALIDATOR] @@ -61,8 +73,20 @@ export class MinLengthValidator implements Validator { validate(c: Control): {[key: string]: any} { return this._validator(c); } } +/** + * Provider which adds {@link MaxLengthValidator} to {@link NG_VALIDATORS}. + * + * ## Example: + * + * {@example common/forms/ts/validators/validators.ts region='max'} + */ const MAX_LENGTH_VALIDATOR = CONST_EXPR( new Provider(NG_VALIDATORS, {useExisting: forwardRef(() => MaxLengthValidator), multi: true})); + +/** + * A directive which installs the {@link MaxLengthValidator} for any `ngControl, `ngFormControl`, + * or control with `ngModel` that also has a `maxlength` attribute. + */ @Directive({ selector: '[maxlength][ngControl],[maxlength][ngFormControl],[maxlength][ngModel]', providers: [MAX_LENGTH_VALIDATOR] diff --git a/modules/angular2/src/common/forms/form_builder.ts b/modules/angular2/src/common/forms/form_builder.ts index 11f415b33501..b6ef3fdc7c9a 100644 --- a/modules/angular2/src/common/forms/form_builder.ts +++ b/modules/angular2/src/common/forms/form_builder.ts @@ -119,6 +119,8 @@ export class FormBuilder { export const FORM_PROVIDERS: Type[] = CONST_EXPR([FormBuilder]); /** + * See {@link FORM_PROVIDERS} instead. + * * @deprecated */ export const FORM_BINDINGS = FORM_PROVIDERS; diff --git a/modules/angular2/src/common/forms/validators.ts b/modules/angular2/src/common/forms/validators.ts index ee8bc60dad3c..f9cdc1c64762 100644 --- a/modules/angular2/src/common/forms/validators.ts +++ b/modules/angular2/src/common/forms/validators.ts @@ -14,7 +14,6 @@ import * as modelModule from './model'; * ### Example * * {@example core/forms/ts/ng_validators/ng_validators.ts region='ng_validators'} - * ``` */ export const NG_VALIDATORS: OpaqueToken = CONST_EXPR(new OpaqueToken("NgValidators")); @@ -32,8 +31,7 @@ export const NG_ASYNC_VALIDATORS: OpaqueToken = CONST_EXPR(new OpaqueToken("NgAs * Provides a set of validators used by form controls. * * A validator is a function that processes a {@link Control} or collection of - * controls and returns a {@link StringMap} of errors. A null map means that - * validation has passed. + * controls and returns a map of errors. A null map means that validation has passed. * * ### Example * diff --git a/modules/angular2/src/common/pipes.ts b/modules/angular2/src/common/pipes.ts index 93950e9a9d08..7c7a25c1ef26 100644 --- a/modules/angular2/src/common/pipes.ts +++ b/modules/angular2/src/common/pipes.ts @@ -20,6 +20,13 @@ export {LowerCasePipe} from './pipes/lowercase_pipe'; export {NumberPipe, DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe'; export {UpperCasePipe} from './pipes/uppercase_pipe'; +/** + * A collection of Angular core pipes that are likely to be used in each and every + * application. + * + * This collection can be used to quickly enumerate all the built-in pipes in the `pipes` + * property of the `@Component` or `@View` decorators. + */ export const COMMON_PIPES = CONST_EXPR([ AsyncPipe, UpperCasePipe, diff --git a/modules/angular2/src/common/pipes/common_pipes.ts b/modules/angular2/src/common/pipes/common_pipes.ts index 7773c9332f00..ac6dc36c099a 100644 --- a/modules/angular2/src/common/pipes/common_pipes.ts +++ b/modules/angular2/src/common/pipes/common_pipes.ts @@ -12,6 +12,13 @@ import {DatePipe} from './date_pipe'; import {DecimalPipe, PercentPipe, CurrencyPipe} from './number_pipe'; import {CONST_EXPR} from 'angular2/src/facade/lang'; +/** + * A collection of Angular core pipes that are likely to be used in each and every + * application. + * + * This collection can be used to quickly enumerate all the built-in pipes in the `pipes` + * property of the `@Component` or `@View` decorators. + */ export const COMMON_PIPES = CONST_EXPR([ AsyncPipe, UpperCasePipe, diff --git a/modules/angular2/src/compiler/compiler.ts b/modules/angular2/src/compiler/compiler.ts index 76a112f8798e..c35bc9104c7d 100644 --- a/modules/angular2/src/compiler/compiler.ts +++ b/modules/angular2/src/compiler/compiler.ts @@ -31,6 +31,10 @@ function _createChangeDetectorGenConfig() { return new ChangeDetectorGenConfig(assertionsEnabled(), false, true); } +/** + * A set of providers that provide `RuntimeCompiler` and its dependencies to use for + * template compilation. + */ export const COMPILER_PROVIDERS: Array = CONST_EXPR([ Lexer, Parser, diff --git a/modules/angular2/src/compiler/directive_metadata.ts b/modules/angular2/src/compiler/directive_metadata.ts index 5033a183cbeb..f82f6b031a37 100644 --- a/modules/angular2/src/compiler/directive_metadata.ts +++ b/modules/angular2/src/compiler/directive_metadata.ts @@ -21,6 +21,9 @@ import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/linker/i // group 2: "event" from "(event)" var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g; +/** + * Metadata regarding compilation of a type. + */ export class CompileTypeMetadata { runtime: Type; name: string; @@ -49,6 +52,9 @@ export class CompileTypeMetadata { } } +/** + * Metadata regarding compilation of a template. + */ export class CompileTemplateMetadata { encapsulation: ViewEncapsulation; template: string; @@ -98,6 +104,9 @@ export class CompileTemplateMetadata { } } +/** + * Metadata regarding compilation of a directive. + */ export class CompileDirectiveMetadata { static create({type, isComponent, dynamicLoadable, selector, exportAs, changeDetection, inputs, outputs, host, lifecycleHooks, template}: { @@ -250,6 +259,9 @@ export class CompileDirectiveMetadata { } } +/** + * Construct {@link CompileDirectiveMetadata} from {@link ComponentTypeMetadata} and a selector. + */ export function createHostComponentMeta(componentType: CompileTypeMetadata, componentSelector: string): CompileDirectiveMetadata { var template = CssSelector.parse(componentSelector)[0].getMatchingElementTemplate(); diff --git a/modules/angular2/src/compiler/source_module.ts b/modules/angular2/src/compiler/source_module.ts index 4a5c8be44dff..49dc23a9bf6e 100644 --- a/modules/angular2/src/compiler/source_module.ts +++ b/modules/angular2/src/compiler/source_module.ts @@ -6,6 +6,9 @@ export function moduleRef(moduleUrl): string { return `#MODULE[${moduleUrl}]`; } +/** + * Represents generated source code with module references. Internal to the Angular compiler. + */ export class SourceModule { constructor(public moduleUrl: string, public sourceWithModuleRefs: string) {} @@ -39,6 +42,9 @@ export class SourceExpressions { constructor(public declarations: string[], public expressions: string[]) {} } +/** + * Represents generated source code with imports. Internal to the Angular compiler. + */ export class SourceWithImports { constructor(public source: string, public imports: string[][]) {} } diff --git a/modules/angular2/src/compiler/template_ast.ts b/modules/angular2/src/compiler/template_ast.ts index 8c31180f969b..1b79d32be5a2 100644 --- a/modules/angular2/src/compiler/template_ast.ts +++ b/modules/angular2/src/compiler/template_ast.ts @@ -3,17 +3,33 @@ import {isPresent} from 'angular2/src/facade/lang'; import {CompileDirectiveMetadata} from './directive_metadata'; import {ParseSourceSpan} from './parse_util'; +/** + * An Abstract Syntax Tree node representing part of a parsed Angular template. + */ export interface TemplateAst { + /** + * The source span from which this node was parsed. + */ sourceSpan: ParseSourceSpan; + + /** + * Visit this node and possibly transform it. + */ visit(visitor: TemplateAstVisitor, context: any): any; } +/** + * A segment of text within the template. + */ export class TextAst implements TemplateAst { constructor(public value: string, public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {} visit(visitor: TemplateAstVisitor, context: any): any { return visitor.visitText(this, context); } } +/** + * A bound expression within the text of a template. + */ export class BoundTextAst implements TemplateAst { constructor(public value: AST, public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {} @@ -22,11 +38,17 @@ export class BoundTextAst implements TemplateAst { } } +/** + * A plain attribute on an element. + */ export class AttrAst implements TemplateAst { constructor(public name: string, public value: string, public sourceSpan: ParseSourceSpan) {} visit(visitor: TemplateAstVisitor, context: any): any { return visitor.visitAttr(this, context); } } +/** + * A binding for an element property (e.g. `[property]="expression"`). + */ export class BoundElementPropertyAst implements TemplateAst { constructor(public name: string, public type: PropertyBindingType, public value: AST, public unit: string, public sourceSpan: ParseSourceSpan) {} @@ -35,6 +57,9 @@ export class BoundElementPropertyAst implements TemplateAst { } } +/** + * A binding for an element event (e.g. `(event)="handler()"`). + */ export class BoundEventAst implements TemplateAst { constructor(public name: string, public target: string, public handler: AST, public sourceSpan: ParseSourceSpan) {} @@ -50,6 +75,9 @@ export class BoundEventAst implements TemplateAst { } } +/** + * A variable declaration on an element (e.g. `#var="expression"`). + */ export class VariableAst implements TemplateAst { constructor(public name: string, public value: string, public sourceSpan: ParseSourceSpan) {} visit(visitor: TemplateAstVisitor, context: any): any { @@ -57,6 +85,9 @@ export class VariableAst implements TemplateAst { } } +/** + * An element declaration in a template. + */ export class ElementAst implements TemplateAst { constructor(public name: string, public attrs: AttrAst[], public inputs: BoundElementPropertyAst[], public outputs: BoundEventAst[], @@ -67,11 +98,17 @@ export class ElementAst implements TemplateAst { return visitor.visitElement(this, context); } + /** + * Whether the element has any active bindings (inputs, outputs, vars, or directives). + */ isBound(): boolean { return (this.inputs.length > 0 || this.outputs.length > 0 || this.exportAsVars.length > 0 || this.directives.length > 0); } + /** + * Get the component associated with this element, if any. + */ getComponent(): CompileDirectiveMetadata { return this.directives.length > 0 && this.directives[0].directive.isComponent ? this.directives[0].directive : @@ -79,6 +116,9 @@ export class ElementAst implements TemplateAst { } } +/** + * A `