fix(platform-browser-dynamic): Rename CACHED_TEMPLATE_PROVIDER to RESOURCE_CACHE_PROVIDER (#10866)

* fix(platform-browser-dynamic): Rename CACHED_TEMPLATE_PROVIDER to RESOURCE_CACHE_PROVIDER

Closes #9741

BREAKING CHANGE:

`CACHED_TEMPLATE_PROVIDER` is now renamed to `RESOURCE_CACHE_PROVIDER`

Before:

```js
import {CACHED_TEMPLATE_PROVIDER} from '@angular/platform-browser-dynamic';
```

After:

```js
import {RESOURCE_CACHE_PROVIDER} from '@angular/platform-browser-dynamic';
```

* Rename XHR -> ResourceLoader
This commit is contained in:
Hans 2016-08-17 09:24:44 -07:00 committed by vikerman
parent 951ecb4d90
commit 40e160c22c
29 changed files with 213 additions and 190 deletions

View File

@ -123,8 +123,8 @@ export class CodeGenerator {
static create( static create(
options: AngularCompilerOptions, cliOptions: NgcCliOptions, program: ts.Program, options: AngularCompilerOptions, cliOptions: NgcCliOptions, program: ts.Program,
compilerHost: ts.CompilerHost, reflectorHostContext?: ReflectorHostContext, compilerHost: ts.CompilerHost, reflectorHostContext?: ReflectorHostContext,
xhr?: compiler.XHR): CodeGenerator { resourceLoader?: compiler.ResourceLoader): CodeGenerator {
xhr = xhr || { resourceLoader = resourceLoader || {
get: (s: string) => { get: (s: string) => {
if (!compilerHost.fileExists(s)) { if (!compilerHost.fileExists(s)) {
// TODO: We should really have a test for error cases like this! // TODO: We should really have a test for error cases like this!
@ -152,7 +152,7 @@ export class CodeGenerator {
logBindingUpdate: false, logBindingUpdate: false,
useJit: false useJit: false
}); });
const normalizer = new DirectiveNormalizer(xhr, urlResolver, htmlParser, config); const normalizer = new DirectiveNormalizer(resourceLoader, urlResolver, htmlParser, config);
const expressionParser = new Parser(new Lexer()); const expressionParser = new Parser(new Lexer());
const elementSchemaRegistry = new DomElementSchemaRegistry(); const elementSchemaRegistry = new DomElementSchemaRegistry();
const console = new Console(); const console = new Console();

View File

@ -147,7 +147,7 @@ export class Extractor {
options: tsc.AngularCompilerOptions, translationsFormat: string, program: ts.Program, options: tsc.AngularCompilerOptions, translationsFormat: string, program: ts.Program,
compilerHost: ts.CompilerHost, htmlParser: compiler.i18n.HtmlParser, compilerHost: ts.CompilerHost, htmlParser: compiler.i18n.HtmlParser,
reflectorHostContext?: ReflectorHostContext): Extractor { reflectorHostContext?: ReflectorHostContext): Extractor {
const xhr: compiler.XHR = { const resourceLoader: compiler.ResourceLoader = {
get: (s: string) => { get: (s: string) => {
if (!compilerHost.fileExists(s)) { if (!compilerHost.fileExists(s)) {
// TODO: We should really have a test for error cases like this! // TODO: We should really have a test for error cases like this!
@ -169,7 +169,7 @@ export class Extractor {
useJit: false useJit: false
}); });
const normalizer = new DirectiveNormalizer(xhr, urlResolver, htmlParser, config); const normalizer = new DirectiveNormalizer(resourceLoader, urlResolver, htmlParser, config);
const expressionParser = new Parser(new Lexer()); const expressionParser = new Parser(new Lexer());
const elementSchemaRegistry = new DomElementSchemaRegistry(); const elementSchemaRegistry = new DomElementSchemaRegistry();
const console = new Console(); const console = new Console();

View File

@ -13,7 +13,7 @@
*/ */
import * as i18n from './src/i18n/index'; import * as i18n from './src/i18n/index';
export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, NgModuleResolver, OfflineCompiler, PipeResolver, RenderTypes, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, XHR, analyzeAppProvidersForDeprecatedConfiguration, createOfflineCompileUrlResolver, platformCoreDynamic} from './src/compiler'; export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, NgModuleResolver, OfflineCompiler, PipeResolver, RenderTypes, ResourceLoader, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, analyzeAppProvidersForDeprecatedConfiguration, createOfflineCompileUrlResolver, platformCoreDynamic} from './src/compiler';
export {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './src/ml_parser/interpolation_config'; export {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './src/ml_parser/interpolation_config';
export {ElementSchemaRegistry} from './src/schema/element_schema_registry'; export {ElementSchemaRegistry} from './src/schema/element_schema_registry';
export {i18n}; export {i18n};

View File

@ -15,7 +15,7 @@ export * from './compile_metadata';
export * from './offline_compiler'; export * from './offline_compiler';
export {RuntimeCompiler} from './runtime_compiler'; export {RuntimeCompiler} from './runtime_compiler';
export * from './url_resolver'; export * from './url_resolver';
export * from './xhr'; export * from './resource_loader';
export {DirectiveResolver} from './directive_resolver'; export {DirectiveResolver} from './directive_resolver';
export {PipeResolver} from './pipe_resolver'; export {PipeResolver} from './pipe_resolver';
@ -41,12 +41,13 @@ import {DirectiveResolver} from './directive_resolver';
import {PipeResolver} from './pipe_resolver'; import {PipeResolver} from './pipe_resolver';
import {NgModuleResolver} from './ng_module_resolver'; import {NgModuleResolver} from './ng_module_resolver';
import {Console, Reflector, reflector, ReflectorReader, ReflectionCapabilities} from '../core_private'; import {Console, Reflector, reflector, ReflectorReader, ReflectionCapabilities} from '../core_private';
import {XHR} from './xhr'; import {ResourceLoader} from './resource_loader';
import * as i18n from './i18n/index'; import * as i18n from './i18n/index';
const _NO_XHR: XHR = { const _NO_RESOURCE_LOADER: ResourceLoader = {
get(url: string): Promise<string>{ get(url: string): Promise<string>{
throw new Error(`No XHR implementation has been provided. Can't read the url "${url}"`);} throw new Error(
`No ResourceLoader implementation has been provided. Can't read the url "${url}"`);}
}; };
/** /**
@ -56,7 +57,7 @@ const _NO_XHR: XHR = {
export const COMPILER_PROVIDERS: Array<any|Type<any>|{[k: string]: any}|any[]> = [ export const COMPILER_PROVIDERS: Array<any|Type<any>|{[k: string]: any}|any[]> = [
{provide: Reflector, useValue: reflector}, {provide: Reflector, useValue: reflector},
{provide: ReflectorReader, useExisting: Reflector}, {provide: ReflectorReader, useExisting: Reflector},
{provide: XHR, useValue: _NO_XHR}, {provide: ResourceLoader, useValue: _NO_RESOURCE_LOADER},
Console, Console,
Lexer, Lexer,
Parser, Parser,
@ -101,7 +102,7 @@ export function analyzeAppProvidersForDeprecatedConfiguration(appProviders: any[
const deprecationMessages: string[] = []; const deprecationMessages: string[] = [];
// Note: This is a hack to still support the old way // Note: This is a hack to still support the old way
// of configuring platform directives / pipes and the compiler xhr. // of configuring platform directives / pipes and the compiler resource loader.
// This will soon be deprecated! // This will soon be deprecated!
const tempInj = ReflectiveInjector.resolveAndCreate(appProviders); const tempInj = ReflectiveInjector.resolveAndCreate(appProviders);
const compilerConfig: CompilerConfig = tempInj.get(CompilerConfig, null); const compilerConfig: CompilerConfig = tempInj.get(CompilerConfig, null);
@ -112,11 +113,11 @@ export function analyzeAppProvidersForDeprecatedConfiguration(appProviders: any[
deprecationMessages.push( deprecationMessages.push(
`Passing CompilerConfig as a regular provider is deprecated. Use "compilerOptions" use a custom "CompilerFactory" platform provider instead.`); `Passing CompilerConfig as a regular provider is deprecated. Use "compilerOptions" use a custom "CompilerFactory" platform provider instead.`);
} }
const xhr = tempInj.get(XHR, null); const resourceLoader = tempInj.get(ResourceLoader, null);
if (xhr) { if (resourceLoader) {
compilerProviders.push([{provide: XHR, useValue: xhr}]); compilerProviders.push([{provide: ResourceLoader, useValue: resourceLoader}]);
deprecationMessages.push( deprecationMessages.push(
`Passing XHR as regular provider is deprecated. Pass the provider via "compilerOptions" instead.`); `Passing ResourceLoader as regular provider is deprecated. Pass the provider via "compilerOptions" instead.`);
} }
const compilerOptions: CompilerOptions = { const compilerOptions: CompilerOptions = {
useJit: useJit, useJit: useJit,

View File

@ -15,36 +15,36 @@ import {isBlank, isPresent} from './facade/lang';
import * as html from './ml_parser/ast'; import * as html from './ml_parser/ast';
import {HtmlParser} from './ml_parser/html_parser'; import {HtmlParser} from './ml_parser/html_parser';
import {InterpolationConfig} from './ml_parser/interpolation_config'; import {InterpolationConfig} from './ml_parser/interpolation_config';
import {ResourceLoader} from './resource_loader';
import {extractStyleUrls, isStyleUrlResolvable} from './style_url_resolver'; import {extractStyleUrls, isStyleUrlResolvable} from './style_url_resolver';
import {PreparsedElementType, preparseElement} from './template_parser/template_preparser'; import {PreparsedElementType, preparseElement} from './template_parser/template_preparser';
import {UrlResolver} from './url_resolver'; import {UrlResolver} from './url_resolver';
import {SyncAsyncResult} from './util'; import {SyncAsyncResult} from './util';
import {XHR} from './xhr';
@Injectable() @Injectable()
export class DirectiveNormalizer { export class DirectiveNormalizer {
private _xhrCache = new Map<string, Promise<string>>(); private _resourceLoaderCache = new Map<string, Promise<string>>();
constructor( constructor(
private _xhr: XHR, private _urlResolver: UrlResolver, private _htmlParser: HtmlParser, private _resourceLoader: ResourceLoader, private _urlResolver: UrlResolver,
private _config: CompilerConfig) {} private _htmlParser: HtmlParser, private _config: CompilerConfig) {}
clearCache() { this._xhrCache.clear(); } clearCache() { this._resourceLoaderCache.clear(); }
clearCacheFor(normalizedDirective: CompileDirectiveMetadata) { clearCacheFor(normalizedDirective: CompileDirectiveMetadata) {
if (!normalizedDirective.isComponent) { if (!normalizedDirective.isComponent) {
return; return;
} }
this._xhrCache.delete(normalizedDirective.template.templateUrl); this._resourceLoaderCache.delete(normalizedDirective.template.templateUrl);
normalizedDirective.template.externalStylesheets.forEach( normalizedDirective.template.externalStylesheets.forEach(
(stylesheet) => { this._xhrCache.delete(stylesheet.moduleUrl); }); (stylesheet) => { this._resourceLoaderCache.delete(stylesheet.moduleUrl); });
} }
private _fetch(url: string): Promise<string> { private _fetch(url: string): Promise<string> {
var result = this._xhrCache.get(url); var result = this._resourceLoaderCache.get(url);
if (!result) { if (!result) {
result = this._xhr.get(url); result = this._resourceLoader.get(url);
this._xhrCache.set(url, result); this._resourceLoaderCache.set(url, result);
} }
return result; return result;
} }

View File

@ -6,11 +6,10 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
// TODO: vsavkin rename it into TemplateLoader
/** /**
* An interface for retrieving documents by URL that the compiler uses * An interface for retrieving documents by URL that the compiler uses
* to load templates. * to load templates.
*/ */
export class XHR { export class ResourceLoader {
get(url: string): Promise<string> { return null; } get(url: string): Promise<string> { return null; }
} }

View File

@ -9,13 +9,13 @@
import {CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata'; import {CompileDirectiveMetadata, CompileStylesheetMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata';
import {CompilerConfig} from '@angular/compiler/src/config'; import {CompilerConfig} from '@angular/compiler/src/config';
import {DirectiveNormalizer} from '@angular/compiler/src/directive_normalizer'; import {DirectiveNormalizer} from '@angular/compiler/src/directive_normalizer';
import {XHR} from '@angular/compiler/src/xhr'; import {ResourceLoader} from '@angular/compiler/src/resource_loader';
import {MockXHR} from '@angular/compiler/testing/xhr_mock'; import {MockResourceLoader} from '@angular/compiler/testing/resource_loader_mock';
import {ViewEncapsulation} from '@angular/core/src/metadata/view'; import {ViewEncapsulation} from '@angular/core/src/metadata/view';
import {TestBed} from '@angular/core/testing'; import {TestBed} from '@angular/core/testing';
import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {SpyXHR} from './spies'; import {SpyResourceLoader} from './spies';
import {TEST_COMPILER_PROVIDERS} from './test_bindings'; import {TEST_COMPILER_PROVIDERS} from './test_bindings';
export function main() { export function main() {
@ -115,9 +115,10 @@ export function main() {
it('should load a template from a url that is resolved against moduleUrl', it('should load a template from a url that is resolved against moduleUrl',
inject( inject(
[AsyncTestCompleter, DirectiveNormalizer, XHR], [AsyncTestCompleter, DirectiveNormalizer, ResourceLoader],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: MockXHR) => { (async: AsyncTestCompleter, normalizer: DirectiveNormalizer,
xhr.expect('package:some/module/sometplurl.html', 'a'); resourceLoader: MockResourceLoader) => {
resourceLoader.expect('package:some/module/sometplurl.html', 'a');
normalizer normalizer
.normalizeTemplateAsync(dirType, new CompileTemplateMetadata({ .normalizeTemplateAsync(dirType, new CompileTemplateMetadata({
encapsulation: null, encapsulation: null,
@ -131,14 +132,15 @@ export function main() {
expect(template.templateUrl).toEqual('package:some/module/sometplurl.html'); expect(template.templateUrl).toEqual('package:some/module/sometplurl.html');
async.done(); async.done();
}); });
xhr.flush(); resourceLoader.flush();
})); }));
it('should resolve styles on the annotation against the moduleUrl', it('should resolve styles on the annotation against the moduleUrl',
inject( inject(
[AsyncTestCompleter, DirectiveNormalizer, XHR], [AsyncTestCompleter, DirectiveNormalizer, ResourceLoader],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: MockXHR) => { (async: AsyncTestCompleter, normalizer: DirectiveNormalizer,
xhr.expect('package:some/module/tpl/sometplurl.html', ''); resourceLoader: MockResourceLoader) => {
resourceLoader.expect('package:some/module/tpl/sometplurl.html', '');
normalizer normalizer
.normalizeTemplateAsync(dirType, new CompileTemplateMetadata({ .normalizeTemplateAsync(dirType, new CompileTemplateMetadata({
encapsulation: null, encapsulation: null,
@ -151,14 +153,15 @@ export function main() {
expect(template.styleUrls).toEqual(['package:some/module/test.css']); expect(template.styleUrls).toEqual(['package:some/module/test.css']);
async.done(); async.done();
}); });
xhr.flush(); resourceLoader.flush();
})); }));
it('should resolve styles in the template against the templateUrl', it('should resolve styles in the template against the templateUrl',
inject( inject(
[AsyncTestCompleter, DirectiveNormalizer, XHR], [AsyncTestCompleter, DirectiveNormalizer, ResourceLoader],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: MockXHR) => { (async: AsyncTestCompleter, normalizer: DirectiveNormalizer,
xhr.expect( resourceLoader: MockResourceLoader) => {
resourceLoader.expect(
'package:some/module/tpl/sometplurl.html', '<style>@import test.css</style>'); 'package:some/module/tpl/sometplurl.html', '<style>@import test.css</style>');
normalizer normalizer
.normalizeTemplateAsync(dirType, new CompileTemplateMetadata({ .normalizeTemplateAsync(dirType, new CompileTemplateMetadata({
@ -172,21 +175,24 @@ export function main() {
expect(template.styleUrls).toEqual(['package:some/module/tpl/test.css']); expect(template.styleUrls).toEqual(['package:some/module/tpl/test.css']);
async.done(); async.done();
}); });
xhr.flush(); resourceLoader.flush();
})); }));
}); });
describe('normalizeExternalStylesheets', () => { describe('normalizeExternalStylesheets', () => {
beforeEach( beforeEach(() => {
() => { TestBed.configureCompiler({providers: [{provide: XHR, useClass: SpyXHR}]}); }); TestBed.configureCompiler(
{providers: [{provide: ResourceLoader, useClass: SpyResourceLoader}]});
});
it('should load an external stylesheet', it('should load an external stylesheet',
inject( inject(
[AsyncTestCompleter, DirectiveNormalizer, XHR], [AsyncTestCompleter, DirectiveNormalizer, ResourceLoader],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: SpyXHR) => { (async: AsyncTestCompleter, normalizer: DirectiveNormalizer,
programXhrSpy(xhr, {'package:some/module/test.css': 'a'}); resourceLoader: SpyResourceLoader) => {
programResourceLoaderSpy(resourceLoader, {'package:some/module/test.css': 'a'});
normalizer normalizer
.normalizeExternalStylesheets(new CompileTemplateMetadata({ .normalizeExternalStylesheets(new CompileTemplateMetadata({
template: '', template: '',
@ -206,9 +212,10 @@ export function main() {
it('should load stylesheets referenced by external stylesheets', it('should load stylesheets referenced by external stylesheets',
inject( inject(
[AsyncTestCompleter, DirectiveNormalizer, XHR], [AsyncTestCompleter, DirectiveNormalizer, ResourceLoader],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: SpyXHR) => { (async: AsyncTestCompleter, normalizer: DirectiveNormalizer,
programXhrSpy(xhr, { resourceLoader: SpyResourceLoader) => {
programResourceLoaderSpy(resourceLoader, {
'package:some/module/test.css': 'a@import "test2.css"', 'package:some/module/test.css': 'a@import "test2.css"',
'package:some/module/test2.css': 'b' 'package:some/module/test2.css': 'b'
}); });
@ -238,9 +245,10 @@ export function main() {
describe('caching', () => { describe('caching', () => {
it('should work for templateUrl', it('should work for templateUrl',
inject( inject(
[AsyncTestCompleter, DirectiveNormalizer, XHR], [AsyncTestCompleter, DirectiveNormalizer, ResourceLoader],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: MockXHR) => { (async: AsyncTestCompleter, normalizer: DirectiveNormalizer,
xhr.expect('package:some/module/cmp.html', 'a'); resourceLoader: MockResourceLoader) => {
resourceLoader.expect('package:some/module/cmp.html', 'a');
var templateMeta = new CompileTemplateMetadata({ var templateMeta = new CompileTemplateMetadata({
templateUrl: 'cmp.html', templateUrl: 'cmp.html',
}); });
@ -254,7 +262,7 @@ export function main() {
expect(templates[1].template).toEqual('a'); expect(templates[1].template).toEqual('a');
async.done(); async.done();
}); });
xhr.flush(); resourceLoader.flush();
})); }));
}); });
@ -426,7 +434,7 @@ export function main() {
}); });
} }
function programXhrSpy(spy: SpyXHR, results: {[key: string]: string}) { function programResourceLoaderSpy(spy: SpyResourceLoader, results: {[key: string]: string}) {
spy.spy('get').andCallFake((url: string): Promise<any> => { spy.spy('get').andCallFake((url: string): Promise<any> => {
var result = results[url]; var result = results[url];
if (result) { if (result) {

View File

@ -6,21 +6,21 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {DirectiveResolver, XHR, i18n} from '@angular/compiler'; import {DirectiveResolver, ResourceLoader, i18n} from '@angular/compiler';
import {MockDirectiveResolver} from '@angular/compiler/testing'; import {MockDirectiveResolver} from '@angular/compiler/testing';
import {Compiler, Component, DebugElement, Injector, TRANSLATIONS, TRANSLATIONS_FORMAT} from '@angular/core'; import {Compiler, Component, DebugElement, Injector, TRANSLATIONS, TRANSLATIONS_FORMAT} from '@angular/core';
import {TestBed, fakeAsync} from '@angular/core/testing'; import {TestBed, fakeAsync} from '@angular/core/testing';
import {beforeEach, TestComponentBuilder, ddescribe, describe, iit, inject, it, xdescribe, xit,} from '@angular/core/testing/testing_internal'; import {beforeEach, TestComponentBuilder, ddescribe, describe, iit, inject, it, xdescribe, xit,} from '@angular/core/testing/testing_internal';
import {expect} from '@angular/platform-browser/testing/matchers'; import {expect} from '@angular/platform-browser/testing/matchers';
import {By} from '@angular/platform-browser/src/dom/debug/by'; import {By} from '@angular/platform-browser/src/dom/debug/by';
import {SpyXHR} from '../spies'; import {SpyResourceLoader} from '../spies';
import {NgLocalization} from '@angular/common'; import {NgLocalization} from '@angular/common';
import {stringifyElement} from '@angular/platform-browser/testing/browser_util'; import {stringifyElement} from '@angular/platform-browser/testing/browser_util';
export function main() { export function main() {
describe('i18n integration spec', () => { describe('i18n integration spec', () => {
let compiler: Compiler; let compiler: Compiler;
let xhr: SpyXHR; let xhr: SpyResourceLoader;
let tcb: TestComponentBuilder; let tcb: TestComponentBuilder;
let dirResolver: MockDirectiveResolver; let dirResolver: MockDirectiveResolver;
let injector: Injector; let injector: Injector;
@ -28,7 +28,7 @@ export function main() {
beforeEach(() => { beforeEach(() => {
TestBed.configureCompiler({ TestBed.configureCompiler({
providers: [ providers: [
{provide: XHR, useClass: SpyXHR}, {provide: ResourceLoader, useClass: SpyResourceLoader},
{provide: NgLocalization, useClass: FrLocalization}, {provide: NgLocalization, useClass: FrLocalization},
{provide: TRANSLATIONS, useValue: XTB}, {provide: TRANSLATIONS, useValue: XTB},
{provide: TRANSLATIONS_FORMAT, useValue: 'xtb'}, {provide: TRANSLATIONS_FORMAT, useValue: 'xtb'},
@ -37,8 +37,8 @@ export function main() {
}); });
beforeEach(fakeAsync(inject( beforeEach(fakeAsync(inject(
[Compiler, TestComponentBuilder, XHR, DirectiveResolver, Injector], [Compiler, TestComponentBuilder, ResourceLoader, DirectiveResolver, Injector],
(_compiler: Compiler, _tcb: TestComponentBuilder, _xhr: SpyXHR, (_compiler: Compiler, _tcb: TestComponentBuilder, _xhr: SpyResourceLoader,
_dirResolver: MockDirectiveResolver, _injector: Injector) => { _dirResolver: MockDirectiveResolver, _injector: Injector) => {
compiler = _compiler; compiler = _compiler;
tcb = _tcb; tcb = _tcb;

View File

@ -6,15 +6,15 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {MockXHR} from '@angular/compiler/testing/xhr_mock'; import {MockResourceLoader} from '@angular/compiler/testing/resource_loader_mock';
import {AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it} from '@angular/core/testing/testing_internal';
import {isPresent} from '../src/facade/lang'; import {isPresent} from '../src/facade/lang';
export function main() { export function main() {
describe('MockXHR', () => { describe('MockResourceLoader', () => {
var xhr: MockXHR; var resourceLoader: MockResourceLoader;
beforeEach(() => { xhr = new MockXHR(); }); beforeEach(() => { resourceLoader = new MockResourceLoader(); });
function expectResponse( function expectResponse(
request: Promise<string>, url: string, response: string, done: () => void = null) { request: Promise<string>, url: string, response: string, done: () => void = null) {
@ -45,70 +45,71 @@ export function main() {
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
var url = '/foo'; var url = '/foo';
var response = 'bar'; var response = 'bar';
xhr.when(url, response); resourceLoader.when(url, response);
expectResponse(xhr.get(url), url, response, () => async.done()); expectResponse(resourceLoader.get(url), url, response, () => async.done());
xhr.flush(); resourceLoader.flush();
})); }));
it('should return an error from the definitions', it('should return an error from the definitions',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
var url = '/foo'; var url = '/foo';
var response: any /** TODO #9100 */ = null; var response: any /** TODO #9100 */ = null;
xhr.when(url, response); resourceLoader.when(url, response);
expectResponse(xhr.get(url), url, response, () => async.done()); expectResponse(resourceLoader.get(url), url, response, () => async.done());
xhr.flush(); resourceLoader.flush();
})); }));
it('should return a response from the expectations', it('should return a response from the expectations',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
var url = '/foo'; var url = '/foo';
var response = 'bar'; var response = 'bar';
xhr.expect(url, response); resourceLoader.expect(url, response);
expectResponse(xhr.get(url), url, response, () => async.done()); expectResponse(resourceLoader.get(url), url, response, () => async.done());
xhr.flush(); resourceLoader.flush();
})); }));
it('should return an error from the expectations', it('should return an error from the expectations',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
var url = '/foo'; var url = '/foo';
var response: any /** TODO #9100 */ = null; var response: any /** TODO #9100 */ = null;
xhr.expect(url, response); resourceLoader.expect(url, response);
expectResponse(xhr.get(url), url, response, () => async.done()); expectResponse(resourceLoader.get(url), url, response, () => async.done());
xhr.flush(); resourceLoader.flush();
})); }));
it('should not reuse expectations', () => { it('should not reuse expectations', () => {
var url = '/foo'; var url = '/foo';
var response = 'bar'; var response = 'bar';
xhr.expect(url, response); resourceLoader.expect(url, response);
xhr.get(url); resourceLoader.get(url);
xhr.get(url); resourceLoader.get(url);
expect(() => { xhr.flush(); }).toThrowError('Unexpected request /foo'); expect(() => { resourceLoader.flush(); }).toThrowError('Unexpected request /foo');
}); });
it('should return expectations before definitions', it('should return expectations before definitions',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
var url = '/foo'; var url = '/foo';
xhr.when(url, 'when'); resourceLoader.when(url, 'when');
xhr.expect(url, 'expect'); resourceLoader.expect(url, 'expect');
expectResponse(xhr.get(url), url, 'expect'); expectResponse(resourceLoader.get(url), url, 'expect');
expectResponse(xhr.get(url), url, 'when', () => async.done()); expectResponse(resourceLoader.get(url), url, 'when', () => async.done());
xhr.flush(); resourceLoader.flush();
})); }));
it('should throw when there is no definitions or expectations', () => { it('should throw when there is no definitions or expectations', () => {
xhr.get('/foo'); resourceLoader.get('/foo');
expect(() => { xhr.flush(); }).toThrowError('Unexpected request /foo'); expect(() => { resourceLoader.flush(); }).toThrowError('Unexpected request /foo');
}); });
it('should throw when flush is called without any pending requests', it('should throw when flush is called without any pending requests', () => {
() => { expect(() => { xhr.flush(); }).toThrowError('No pending requests to flush'); }); expect(() => { resourceLoader.flush(); }).toThrowError('No pending requests to flush');
});
it('should throw on unsatisfied expectations', () => { it('should throw on unsatisfied expectations', () => {
xhr.expect('/foo', 'bar'); resourceLoader.expect('/foo', 'bar');
xhr.when('/bar', 'foo'); resourceLoader.when('/bar', 'foo');
xhr.get('/bar'); resourceLoader.get('/bar');
expect(() => { xhr.flush(); }).toThrowError('Unsatisfied requests: /foo'); expect(() => { resourceLoader.flush(); }).toThrowError('Unsatisfied requests: /foo');
}); });
}); });
} }

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {DirectiveResolver, XHR} from '@angular/compiler'; import {DirectiveResolver, ResourceLoader} from '@angular/compiler';
import {MockDirectiveResolver} from '@angular/compiler/testing'; import {MockDirectiveResolver} from '@angular/compiler/testing';
import {Compiler, Component, ComponentFactory, Injectable, Injector, Input, NgModule, NgModuleFactory, Type} from '@angular/core'; import {Compiler, Component, ComponentFactory, Injectable, Injector, Input, NgModule, NgModuleFactory, Type} from '@angular/core';
import {ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing'; import {ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing';
@ -16,7 +16,7 @@ import {expect} from '@angular/platform-browser/testing/matchers';
import {ViewMetadata} from '../core_private'; import {ViewMetadata} from '../core_private';
import {stringify} from '../src/facade/lang'; import {stringify} from '../src/facade/lang';
import {SpyXHR} from './spies'; import {SpyResourceLoader} from './spies';
@Component({selector: 'child-cmp', template: 'childComp'}) @Component({selector: 'child-cmp', template: 'childComp'})
class ChildComp { class ChildComp {
@ -33,21 +33,23 @@ class SomeCompWithUrlTemplate {
export function main() { export function main() {
describe('RuntimeCompiler', () => { describe('RuntimeCompiler', () => {
let compiler: Compiler; let compiler: Compiler;
let xhr: SpyXHR; let resourceLoader: SpyResourceLoader;
let tcb: TestComponentBuilder; let tcb: TestComponentBuilder;
let dirResolver: MockDirectiveResolver; let dirResolver: MockDirectiveResolver;
let injector: Injector; let injector: Injector;
beforeEach( beforeEach(() => {
() => { TestBed.configureCompiler({providers: [{provide: XHR, useClass: SpyXHR}]}); }); TestBed.configureCompiler(
{providers: [{provide: ResourceLoader, useClass: SpyResourceLoader}]});
});
beforeEach(fakeAsync(inject( beforeEach(fakeAsync(inject(
[Compiler, TestComponentBuilder, XHR, DirectiveResolver, Injector], [Compiler, TestComponentBuilder, ResourceLoader, DirectiveResolver, Injector],
(_compiler: Compiler, _tcb: TestComponentBuilder, _xhr: SpyXHR, (_compiler: Compiler, _tcb: TestComponentBuilder, _resourceLoader: SpyResourceLoader,
_dirResolver: MockDirectiveResolver, _injector: Injector) => { _dirResolver: MockDirectiveResolver, _injector: Injector) => {
compiler = _compiler; compiler = _compiler;
tcb = _tcb; tcb = _tcb;
xhr = _xhr; resourceLoader = _resourceLoader;
dirResolver = _dirResolver; dirResolver = _dirResolver;
injector = _injector; injector = _injector;
}))); })));
@ -55,13 +57,13 @@ export function main() {
describe('clearCacheFor', () => { describe('clearCacheFor', () => {
it('should support changing the content of a template referenced via templateUrl', it('should support changing the content of a template referenced via templateUrl',
fakeAsync(() => { fakeAsync(() => {
xhr.spy('get').andCallFake(() => Promise.resolve('init')); resourceLoader.spy('get').andCallFake(() => Promise.resolve('init'));
let compFixture = let compFixture =
tcb.overrideView(SomeComp, new ViewMetadata({templateUrl: '/myComp.html'})) tcb.overrideView(SomeComp, new ViewMetadata({templateUrl: '/myComp.html'}))
.createFakeAsync(SomeComp); .createFakeAsync(SomeComp);
expect(compFixture.nativeElement).toHaveText('init'); expect(compFixture.nativeElement).toHaveText('init');
xhr.spy('get').andCallFake(() => Promise.resolve('new content')); resourceLoader.spy('get').andCallFake(() => Promise.resolve('new content'));
// Note: overrideView is calling .clearCacheFor... // Note: overrideView is calling .clearCacheFor...
compFixture = tcb.overrideView(SomeComp, new ViewMetadata({templateUrl: '/myComp.html'})) compFixture = tcb.overrideView(SomeComp, new ViewMetadata({templateUrl: '/myComp.html'}))
.createFakeAsync(SomeComp); .createFakeAsync(SomeComp);
@ -91,7 +93,7 @@ export function main() {
describe('compileComponentSync', () => { describe('compileComponentSync', () => {
it('should throw when using a templateUrl that has not been compiled before', () => { it('should throw when using a templateUrl that has not been compiled before', () => {
xhr.spy('get').andCallFake(() => Promise.resolve('')); resourceLoader.spy('get').andCallFake(() => Promise.resolve(''));
expect(() => tcb.createSync(SomeCompWithUrlTemplate)) expect(() => tcb.createSync(SomeCompWithUrlTemplate))
.toThrowError( .toThrowError(
`Can't compile synchronously as ${stringify(SomeCompWithUrlTemplate)} is still being loaded!`); `Can't compile synchronously as ${stringify(SomeCompWithUrlTemplate)} is still being loaded!`);
@ -99,7 +101,7 @@ export function main() {
it('should throw when using a templateUrl in a nested component that has not been compiled before', it('should throw when using a templateUrl in a nested component that has not been compiled before',
() => { () => {
xhr.spy('get').andCallFake(() => Promise.resolve('')); resourceLoader.spy('get').andCallFake(() => Promise.resolve(''));
let localTcb = let localTcb =
tcb.overrideView(SomeComp, new ViewMetadata({template: '', directives: [ChildComp]})) tcb.overrideView(SomeComp, new ViewMetadata({template: '', directives: [ChildComp]}))
.overrideView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'})); .overrideView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'}));
@ -110,7 +112,7 @@ export function main() {
it('should allow to use templateUrl components that have been loaded before', it('should allow to use templateUrl components that have been loaded before',
fakeAsync(() => { fakeAsync(() => {
xhr.spy('get').andCallFake(() => Promise.resolve('hello')); resourceLoader.spy('get').andCallFake(() => Promise.resolve('hello'));
tcb.createFakeAsync(SomeCompWithUrlTemplate); tcb.createFakeAsync(SomeCompWithUrlTemplate);
let compFixture = tcb.createSync(SomeCompWithUrlTemplate); let compFixture = tcb.createSync(SomeCompWithUrlTemplate);
expect(compFixture.nativeElement).toHaveText('hello'); expect(compFixture.nativeElement).toHaveText('hello');
@ -126,7 +128,7 @@ export function main() {
class SomeModule { class SomeModule {
} }
xhr.spy('get').andCallFake(() => Promise.resolve('hello')); resourceLoader.spy('get').andCallFake(() => Promise.resolve('hello'));
let ngModuleFactory: NgModuleFactory<any>; let ngModuleFactory: NgModuleFactory<any>;
compiler.compileModuleAsync(SomeModule).then((f) => ngModuleFactory = f); compiler.compileModuleAsync(SomeModule).then((f) => ngModuleFactory = f);
tick(); tick();
@ -141,7 +143,7 @@ export function main() {
class SomeModule { class SomeModule {
} }
xhr.spy('get').andCallFake(() => Promise.resolve('')); resourceLoader.spy('get').andCallFake(() => Promise.resolve(''));
expect(() => compiler.compileModuleSync(SomeModule)) expect(() => compiler.compileModuleSync(SomeModule))
.toThrowError( .toThrowError(
`Can't compile synchronously as ${stringify(SomeCompWithUrlTemplate)} is still being loaded!`); `Can't compile synchronously as ${stringify(SomeCompWithUrlTemplate)} is still being loaded!`);
@ -153,7 +155,7 @@ export function main() {
class SomeModule { class SomeModule {
} }
xhr.spy('get').andCallFake(() => Promise.resolve('')); resourceLoader.spy('get').andCallFake(() => Promise.resolve(''));
dirResolver.setView(SomeComp, new ViewMetadata({template: '', directives: [ChildComp]})); dirResolver.setView(SomeComp, new ViewMetadata({template: '', directives: [ChildComp]}));
dirResolver.setView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'})); dirResolver.setView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'}));
expect(() => compiler.compileModuleSync(SomeModule)) expect(() => compiler.compileModuleSync(SomeModule))
@ -170,7 +172,7 @@ export function main() {
class SomeModule { class SomeModule {
} }
xhr.spy('get').andCallFake(() => Promise.resolve('hello')); resourceLoader.spy('get').andCallFake(() => Promise.resolve('hello'));
compiler.compileModuleAsync(SomeModule); compiler.compileModuleAsync(SomeModule);
tick(); tick();

View File

@ -6,10 +6,10 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {XHR} from '@angular/compiler/src/xhr'; import {ResourceLoader} from '@angular/compiler/src/resource_loader';
import {SpyObject, proxy} from '@angular/core/testing/testing_internal'; import {SpyObject, proxy} from '@angular/core/testing/testing_internal';
export class SpyXHR extends SpyObject { export class SpyResourceLoader extends SpyObject {
constructor() { super(XHR); } constructor() { super(ResourceLoader); }
} }

View File

@ -6,13 +6,13 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {ElementSchemaRegistry, UrlResolver, XHR} from '@angular/compiler'; import {ElementSchemaRegistry, ResourceLoader, UrlResolver} from '@angular/compiler';
import {createUrlResolverWithoutPackagePrefix} from '@angular/compiler/src/url_resolver'; import {createUrlResolverWithoutPackagePrefix} from '@angular/compiler/src/url_resolver';
import {MockSchemaRegistry} from '@angular/compiler/testing'; import {MockSchemaRegistry} from '@angular/compiler/testing';
import {MockXHR} from '@angular/compiler/testing/xhr_mock'; import {MockResourceLoader} from '@angular/compiler/testing/resource_loader_mock';
export var TEST_COMPILER_PROVIDERS: any[] = [ export var TEST_COMPILER_PROVIDERS: any[] = [
{provide: ElementSchemaRegistry, useValue: new MockSchemaRegistry({}, {})}, {provide: ElementSchemaRegistry, useValue: new MockSchemaRegistry({}, {})},
{provide: XHR, useClass: MockXHR}, {provide: ResourceLoader, useClass: MockResourceLoader},
{provide: UrlResolver, useFactory: createUrlResolverWithoutPackagePrefix} {provide: UrlResolver, useFactory: createUrlResolverWithoutPackagePrefix}
]; ];

View File

@ -8,16 +8,16 @@
import {BaseException} from '@angular/core'; import {BaseException} from '@angular/core';
import {XHR} from '../index'; import {ResourceLoader} from '../index';
import {ListWrapper, Map} from '../src/facade/collection'; import {ListWrapper, Map} from '../src/facade/collection';
import {isBlank, normalizeBlank} from '../src/facade/lang'; import {isBlank, normalizeBlank} from '../src/facade/lang';
/** /**
* A mock implementation of {@link XHR} that allows outgoing requests to be mocked * A mock implementation of {@link ResourceLoader} that allows outgoing requests to be mocked
* and responded to within a single test, without going to the network. * and responded to within a single test, without going to the network.
*/ */
export class MockXHR extends XHR { export class MockResourceLoader extends ResourceLoader {
private _expectations: _Expectation[] = []; private _expectations: _Expectation[] = [];
private _definitions = new Map<string, string>(); private _definitions = new Map<string, string>();
private _requests: _PendingRequest[] = []; private _requests: _PendingRequest[] = [];

View File

@ -53,7 +53,8 @@ export class XHRConnection implements Connection {
// load event handler // load event handler
let onLoad = () => { let onLoad = () => {
// responseText is the old-school way of retrieving response (supported by IE8 & 9) // responseText is the old-school way of retrieving response (supported by IE8 & 9)
// response/responseType properties were introduced in XHR Level2 spec (supported by // response/responseType properties were introduced in ResourceLoader Level2 spec (supported
// by
// IE10) // IE10)
let body = isPresent(_xhr.response) ? _xhr.response : _xhr.responseText; let body = isPresent(_xhr.response) ? _xhr.response : _xhr.responseText;
// Implicitly strip a potential XSSI prefix. // Implicitly strip a potential XSSI prefix.

View File

@ -27,7 +27,7 @@ import {Response} from '../src/static_response';
*/ */
export class MockConnection implements Connection { export class MockConnection implements Connection {
// TODO Name `readyState` should change to be more generic, and states could be made to be more // TODO Name `readyState` should change to be more generic, and states could be made to be more
// descriptive than XHR states. // descriptive than ResourceLoader states.
/** /**
* Describes the state of the connection, based on `XMLHttpRequest.readyState`, but with * Describes the state of the connection, based on `XMLHttpRequest.readyState`, but with
* additional states. For example, state 5 indicates an aborted connection. * additional states. For example, state 5 indicates an aborted connection.
@ -105,7 +105,7 @@ export class MockConnection implements Connection {
* *
*/ */
mockError(err?: Error) { mockError(err?: Error) {
// Matches XHR semantics // Matches ResourceLoader semantics
this.readyState = ReadyState.Done; this.readyState = ReadyState.Done;
this.response.error(err); this.response.error(err);
} }

View File

@ -6,21 +6,22 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {XHR, analyzeAppProvidersForDeprecatedConfiguration, platformCoreDynamic} from '@angular/compiler'; import {ResourceLoader, analyzeAppProvidersForDeprecatedConfiguration, platformCoreDynamic} from '@angular/compiler';
import {ApplicationRef, COMPILER_OPTIONS, CUSTOM_ELEMENTS_SCHEMA, CompilerFactory, CompilerOptions, ComponentRef, NgModule, PlatformRef, Provider, Type, createPlatformFactory} from '@angular/core'; import {ApplicationRef, COMPILER_OPTIONS, CUSTOM_ELEMENTS_SCHEMA, CompilerFactory, CompilerOptions, ComponentRef, NgModule, PlatformRef, Provider, Type, createPlatformFactory} from '@angular/core';
import {BrowserModule, WORKER_SCRIPT, WorkerAppModule, platformWorkerUi} from '@angular/platform-browser'; import {BrowserModule, WORKER_SCRIPT, WorkerAppModule, platformWorkerUi} from '@angular/platform-browser';
import {Console} from './core_private'; import {Console} from './core_private';
import {INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS} from './src/platform_providers'; import {INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS} from './src/platform_providers';
import {CachedXHR} from './src/xhr/xhr_cache'; import {CachedResourceLoader} from './src/resource_loader/resource_loader_cache';
import {XHRImpl} from './src/xhr/xhr_impl'; import {ResourceLoaderImpl} from './src/resource_loader/resource_loader_impl';
/** /**
* @experimental * @experimental
*/ */
export const CACHED_TEMPLATE_PROVIDER: Provider[] = [{provide: XHR, useClass: CachedXHR}]; export const RESOURCE_CACHE_PROVIDER: Provider[] =
[{provide: ResourceLoader, useClass: CachedResourceLoader}];
/** /**
* @experimental API related to bootstrapping are still under review. * @experimental API related to bootstrapping are still under review.
@ -46,12 +47,12 @@ export function bootstrapWorkerUi(
/** /**
* @experimental API related to bootstrapping are still under review. * @experimental API related to bootstrapping are still under review.
*/ */
export const platformWorkerAppDynamic = export const platformWorkerAppDynamic = createPlatformFactory(
createPlatformFactory(platformCoreDynamic, 'workerAppDynamic', [{ platformCoreDynamic, 'workerAppDynamic', [{
provide: COMPILER_OPTIONS, provide: COMPILER_OPTIONS,
useValue: {providers: [{provide: XHR, useClass: XHRImpl}]}, useValue: {providers: [{provide: ResourceLoader, useClass: ResourceLoaderImpl}]},
multi: true multi: true
}]); }]);
function normalizeArray(arr: any[]): any[] { function normalizeArray(arr: any[]): any[] {
return arr ? arr : []; return arr ? arr : [];

View File

@ -6,18 +6,18 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {XHR} from '@angular/compiler'; import {ResourceLoader} from '@angular/compiler';
import {COMPILER_OPTIONS} from '@angular/core'; import {COMPILER_OPTIONS} from '@angular/core';
import {INTERNAL_BROWSER_PLATFORM_PROVIDERS} from '../platform_browser_private'; import {INTERNAL_BROWSER_PLATFORM_PROVIDERS} from '../platform_browser_private';
import {XHRImpl} from './xhr/xhr_impl'; import {ResourceLoaderImpl} from './resource_loader/resource_loader_impl';
export const INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS: any[] = [ export const INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS: any[] = [
INTERNAL_BROWSER_PLATFORM_PROVIDERS, INTERNAL_BROWSER_PLATFORM_PROVIDERS,
{ {
provide: COMPILER_OPTIONS, provide: COMPILER_OPTIONS,
useValue: {providers: [{provide: XHR, useClass: XHRImpl}]}, useValue: {providers: [{provide: ResourceLoader, useClass: ResourceLoaderImpl}]},
multi: true multi: true
}, },
]; ];

View File

@ -6,25 +6,26 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {XHR} from '@angular/compiler'; import {ResourceLoader} from '@angular/compiler';
import {BaseException} from '@angular/core'; import {BaseException} from '@angular/core';
import {global} from '../facade/lang'; import {global} from '../facade/lang';
/** /**
* An implementation of XHR that uses a template cache to avoid doing an actual * An implementation of ResourceLoader that uses a template cache to avoid doing an actual
* XHR. * ResourceLoader.
* *
* The template cache needs to be built and loaded into window.$templateCache * The template cache needs to be built and loaded into window.$templateCache
* via a separate mechanism. * via a separate mechanism.
*/ */
export class CachedXHR extends XHR { export class CachedResourceLoader extends ResourceLoader {
private _cache: {[url: string]: string}; private _cache: {[url: string]: string};
constructor() { constructor() {
super(); super();
this._cache = (<any>global).$templateCache; this._cache = (<any>global).$templateCache;
if (this._cache == null) { if (this._cache == null) {
throw new BaseException('CachedXHR: Template cache was not found in $templateCache.'); throw new BaseException(
'CachedResourceLoader: Template cache was not found in $templateCache.');
} }
} }
@ -32,7 +33,8 @@ export class CachedXHR extends XHR {
if (this._cache.hasOwnProperty(url)) { if (this._cache.hasOwnProperty(url)) {
return Promise.resolve(this._cache[url]); return Promise.resolve(this._cache[url]);
} else { } else {
return <Promise<any>>Promise.reject('CachedXHR: Did not find cached template for ' + url); return <Promise<any>>Promise.reject(
'CachedResourceLoader: Did not find cached template for ' + url);
} }
} }
} }

View File

@ -5,13 +5,13 @@
* Use of this source code is governed by an MIT-style license that can be * 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 * found in the LICENSE file at https://angular.io/license
*/ */
import {XHR} from '@angular/compiler'; import {ResourceLoader} from '@angular/compiler';
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {isPresent} from '../facade/lang'; import {isPresent} from '../facade/lang';
@Injectable() @Injectable()
export class XHRImpl extends XHR { export class ResourceLoaderImpl extends ResourceLoader {
get(url: string): Promise<string> { get(url: string): Promise<string> {
var resolve: (result: any) => void; var resolve: (result: any) => void;
var reject: (error: any) => void; var reject: (error: any) => void;
@ -25,7 +25,8 @@ export class XHRImpl extends XHR {
xhr.onload = function() { xhr.onload = function() {
// responseText is the old-school way of retrieving response (supported by IE8 & 9) // responseText is the old-school way of retrieving response (supported by IE8 & 9)
// response/responseType properties were introduced in XHR Level2 spec (supported by IE10) // response/responseType properties were introduced in ResourceLoader Level2 spec (supported
// by IE10)
var response = isPresent(xhr.response) ? xhr.response : xhr.responseText; var response = isPresent(xhr.response) ? xhr.response : xhr.responseText;
// normalize IE9 bug (http://bugs.jquery.com/ticket/1450) // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)

View File

@ -6,29 +6,29 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {UrlResolver, XHR} from '@angular/compiler'; import {ResourceLoader, UrlResolver} from '@angular/compiler';
import {BaseException, Component} from '@angular/core'; import {BaseException, Component} from '@angular/core';
import {TestBed, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing'; import {TestBed, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
import {AsyncTestCompleter, TestComponentBuilder, beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xit} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter, TestComponentBuilder, beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {expect} from '@angular/platform-browser/testing/matchers'; import {expect} from '@angular/platform-browser/testing/matchers';
import {CachedXHR} from '../../src/xhr/xhr_cache'; import {CachedResourceLoader} from '../../src/resource_loader/resource_loader_cache';
import {setTemplateCache} from './xhr_cache_setter'; import {setTemplateCache} from './resource_loader_cache_setter';
export function main() { export function main() {
describe('CachedXHR', () => { describe('CachedResourceLoader', () => {
var xhr: CachedXHR; var xhr: CachedResourceLoader;
function createCachedXHR(): CachedXHR { function createCachedResourceLoader(): CachedResourceLoader {
setTemplateCache({'test.html': '<div>Hello</div>'}); setTemplateCache({'test.html': '<div>Hello</div>'});
return new CachedXHR(); return new CachedResourceLoader();
} }
beforeEach(() => { beforeEach(() => {
TestBed.configureCompiler({ TestBed.configureCompiler({
providers: [ providers: [
{provide: UrlResolver, useClass: TestUrlResolver}, {provide: UrlResolver, useClass: TestUrlResolver},
{provide: XHR, useFactory: createCachedXHR} {provide: ResourceLoader, useFactory: createCachedResourceLoader}
] ]
}); });
}); });
@ -36,14 +36,14 @@ export function main() {
it('should throw exception if $templateCache is not found', () => { it('should throw exception if $templateCache is not found', () => {
setTemplateCache(null); setTemplateCache(null);
expect(() => { expect(() => {
xhr = new CachedXHR(); xhr = new CachedResourceLoader();
}).toThrowError('CachedXHR: Template cache was not found in $templateCache.'); }).toThrowError('CachedResourceLoader: Template cache was not found in $templateCache.');
}); });
it('should resolve the Promise with the cached file content on success', it('should resolve the Promise with the cached file content on success',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
setTemplateCache({'test.html': '<div>Hello</div>'}); setTemplateCache({'test.html': '<div>Hello</div>'});
xhr = new CachedXHR(); xhr = new CachedResourceLoader();
xhr.get('test.html').then((text) => { xhr.get('test.html').then((text) => {
expect(text).toEqual('<div>Hello</div>'); expect(text).toEqual('<div>Hello</div>');
async.done(); async.done();
@ -52,7 +52,7 @@ export function main() {
it('should reject the Promise on failure', it('should reject the Promise on failure',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
xhr = new CachedXHR(); xhr = new CachedResourceLoader();
xhr.get('unknown.html') xhr.get('unknown.html')
.then((text) => { throw new BaseException('Not expected to succeed.'); }) .then((text) => { throw new BaseException('Not expected to succeed.'); })
.catch((error) => { async.done(); }); .catch((error) => { async.done(); });

View File

@ -7,11 +7,11 @@
*/ */
import {AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {XHRImpl} from '../../src/xhr/xhr_impl'; import {ResourceLoaderImpl} from '../../src/resource_loader/resource_loader_impl';
export function main() { export function main() {
describe('XHRImpl', () => { describe('ResourceLoaderImpl', () => {
var xhr: XHRImpl; var resourceLoader: ResourceLoaderImpl;
// TODO(juliemr): This file currently won't work with dart unit tests run using // TODO(juliemr): This file currently won't work with dart unit tests run using
// exclusive it or describe (iit or ddescribe). This is because when // exclusive it or describe (iit or ddescribe). This is because when
@ -22,11 +22,11 @@ export function main() {
var url200 = '/base/modules/@angular/platform-browser/test/browser/static_assets/200.html'; var url200 = '/base/modules/@angular/platform-browser/test/browser/static_assets/200.html';
var url404 = '/bad/path/404.html'; var url404 = '/bad/path/404.html';
beforeEach(() => { xhr = new XHRImpl(); }); beforeEach(() => { resourceLoader = new ResourceLoaderImpl(); });
it('should resolve the Promise with the file content on success', it('should resolve the Promise with the file content on success',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
xhr.get(url200).then((text) => { resourceLoader.get(url200).then((text) => {
expect(text.trim()).toEqual('<p>hey</p>'); expect(text.trim()).toEqual('<p>hey</p>');
async.done(); async.done();
}); });
@ -34,7 +34,7 @@ export function main() {
it('should reject the Promise on failure', it('should reject the Promise on failure',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
xhr.get(url404).catch((e) => { resourceLoader.get(url404).catch((e) => {
expect(e).toEqual(`Failed to load ${url404}`); expect(e).toEqual(`Failed to load ${url404}`);
async.done(); async.done();
return null; return null;

View File

@ -6,11 +6,11 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {XHR} from '@angular/compiler'; import {ResourceLoader} from '@angular/compiler';
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {TestBed, async, fakeAsync, inject, tick} from '@angular/core/testing'; import {TestBed, async, fakeAsync, inject, tick} from '@angular/core/testing';
import {XHRImpl} from '../src/xhr/xhr_impl'; import {ResourceLoaderImpl} from '../src/resource_loader/resource_loader_impl';
@ -46,12 +46,13 @@ export function main() {
afterEach(() => { expect(actuallyDone).toEqual(true); }); afterEach(() => { expect(actuallyDone).toEqual(true); });
it('should run async tests with XHRs', async(() => { it('should run async tests with ResourceLoaders', async(() => {
var xhr = new XHRImpl(); var resourceLoader = new ResourceLoaderImpl();
xhr.get('/base/modules/@angular/platform-browser/test/static_assets/test.html') resourceLoader
.get('/base/modules/@angular/platform-browser/test/static_assets/test.html')
.then(() => { actuallyDone = true; }); .then(() => { actuallyDone = true; });
}), }),
10000); // Long timeout here because this test makes an actual XHR. 10000); // Long timeout here because this test makes an actual ResourceLoader.
}); });
describe('using the test injector with the inject helper', () => { describe('using the test injector with the inject helper', () => {
@ -61,8 +62,10 @@ export function main() {
{providers: [{provide: FancyService, useValue: new FancyService()}]}); {providers: [{provide: FancyService, useValue: new FancyService()}]});
}); });
it('provides a real XHR instance', it('provides a real ResourceLoader instance',
inject([XHR], (xhr: XHR) => { expect(xhr instanceof XHRImpl).toBeTruthy(); })); inject([ResourceLoader], (resourceLoader: ResourceLoader) => {
expect(resourceLoader instanceof ResourceLoaderImpl).toBeTruthy();
}));
it('should allow the use of fakeAsync', it('should allow the use of fakeAsync',
fakeAsync(inject([FancyService], (service: any /** TODO #9100 */) => { fakeAsync(inject([FancyService], (service: any /** TODO #9100 */) => {
@ -96,7 +99,7 @@ export function main() {
var restoreJasmineIt = () => { jasmine.getEnv().it = originalJasmineIt; }; var restoreJasmineIt = () => { jasmine.getEnv().it = originalJasmineIt; };
it('should fail when an XHR fails', (done: any /** TODO #9100 */) => { it('should fail when an ResourceLoader fails', (done: any /** TODO #9100 */) => {
var itPromise = patchJasmineIt(); var itPromise = patchJasmineIt();
it('should fail with an error from a promise', async(() => { it('should fail with an error from a promise', async(() => {
@ -125,7 +128,8 @@ export function main() {
.toEqual('from external template\n'); .toEqual('from external template\n');
}); });
}), }),
10000); // Long timeout here because this test makes an actual XHR, and is slow on Edge. 10000); // Long timeout here because this test makes an actual ResourceLoader, and is slow
// on Edge.
}); });
}); });
} }

View File

@ -31,7 +31,7 @@ export function setRootDomAdapter(adapter: DomAdapter) {
* Provides DOM operations in an environment-agnostic way. * Provides DOM operations in an environment-agnostic way.
*/ */
export abstract class DomAdapter { export abstract class DomAdapter {
public xhrType: Type<any> = null; public resourceLoaderType: Type<any> = null;
abstract hasProperty(element: any /** TODO #9100 */, name: string): boolean; abstract hasProperty(element: any /** TODO #9100 */, name: string): boolean;
abstract setProperty(el: Element, name: string, value: any): any /** TODO #9100 */; abstract setProperty(el: Element, name: string, value: any): any /** TODO #9100 */;
abstract getProperty(el: Element, name: string): any; abstract getProperty(el: Element, name: string): any;
@ -43,7 +43,7 @@ export abstract class DomAdapter {
abstract logGroupEnd(): any /** TODO #9100 */; abstract logGroupEnd(): any /** TODO #9100 */;
/** @deprecated */ /** @deprecated */
getXHR(): Type<any> { return this.xhrType; } getResourceLoader(): Type<any> { return this.resourceLoaderType; }
/** /**
* Maps attribute names to their corresponding property names for cases * Maps attribute names to their corresponding property names for cases

View File

@ -50,7 +50,7 @@ export class WorkerDomAdapter extends DomAdapter {
getProperty(el: Element, name: string): any { throw 'not implemented'; } getProperty(el: Element, name: string): any { throw 'not implemented'; }
invoke(el: Element, methodName: string, args: any[]): any { throw 'not implemented'; } invoke(el: Element, methodName: string, args: any[]): any { throw 'not implemented'; }
getXHR(): Type<any> { throw 'not implemented'; } getResourceLoader(): Type<any> { throw 'not implemented'; }
get attrToPropMap(): {[key: string]: string} { throw 'not implemented'; } get attrToPropMap(): {[key: string]: string} { throw 'not implemented'; }
set attrToPropMap(value: {[key: string]: string}) { throw 'not implemented'; } set attrToPropMap(value: {[key: string]: string}) { throw 'not implemented'; }

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {XHR} from '@angular/compiler'; import {ResourceLoader} from '@angular/compiler';
import {APP_INITIALIZER, CUSTOM_ELEMENTS_SCHEMA, Component, Directive, ExceptionHandler, Inject, Input, NgModule, OnDestroy, PLATFORM_INITIALIZER, Pipe, createPlatformFactory} from '@angular/core'; import {APP_INITIALIZER, CUSTOM_ELEMENTS_SCHEMA, Component, Directive, ExceptionHandler, Inject, Input, NgModule, OnDestroy, PLATFORM_INITIALIZER, Pipe, createPlatformFactory} from '@angular/core';
import {ApplicationRef, destroyPlatform} from '@angular/core/src/application_ref'; import {ApplicationRef, destroyPlatform} from '@angular/core/src/application_ref';
import {Console} from '@angular/core/src/console'; import {Console} from '@angular/core/src/console';

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {CompilerConfig, XHR} from '@angular/compiler'; import {CompilerConfig, ResourceLoader} from '@angular/compiler';
import {CUSTOM_ELEMENTS_SCHEMA, Component, Directive, Injectable, Input, NgModule, Pipe} from '@angular/core'; import {CUSTOM_ELEMENTS_SCHEMA, Component, Directive, Injectable, Input, NgModule, Pipe} from '@angular/core';
import {TestBed, async, fakeAsync, inject, tick, withModule} from '@angular/core/testing'; import {TestBed, async, fakeAsync, inject, tick, withModule} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/matchers'; import {expect} from '@angular/platform-browser/testing/matchers';
@ -368,10 +368,11 @@ export function main() {
describe('providers', () => { describe('providers', () => {
beforeEach(() => { beforeEach(() => {
let xhrGet = let resourceLoaderGet = jasmine.createSpy('resourceLoaderGet')
jasmine.createSpy('xhrGet').and.returnValue(Promise.resolve('Hello world!')); .and.returnValue(Promise.resolve('Hello world!'));
TestBed.configureTestingModule({declarations: [CompWithUrlTemplate]}); TestBed.configureTestingModule({declarations: [CompWithUrlTemplate]});
TestBed.configureCompiler({providers: [{provide: XHR, useValue: {get: xhrGet}}]}); TestBed.configureCompiler(
{providers: [{provide: ResourceLoader, useValue: {get: resourceLoaderGet}}]});
}); });
it('should use set up providers', fakeAsync(() => { it('should use set up providers', fakeAsync(() => {
@ -480,10 +481,12 @@ export function main() {
}); });
describe('components', () => { describe('components', () => {
let xhrGet: jasmine.Spy; let resourceLoaderGet: jasmine.Spy;
beforeEach(() => { beforeEach(() => {
xhrGet = jasmine.createSpy('xhrGet').and.returnValue(Promise.resolve('Hello world!')); resourceLoaderGet = jasmine.createSpy('resourceLoaderGet')
TestBed.configureCompiler({providers: [{provide: XHR, useValue: {get: xhrGet}}]}); .and.returnValue(Promise.resolve('Hello world!'));
TestBed.configureCompiler(
{providers: [{provide: ResourceLoader, useValue: {get: resourceLoaderGet}}]});
}); });
it('should report an error for declared components with templateUrl which never call TestBed.compileComponents', it('should report an error for declared components with templateUrl which never call TestBed.compileComponents',

View File

@ -14,7 +14,7 @@ import {isPresent, isBlank, global, setValueOnPath, DateWrapper} from '../src/fa
import {BaseException} from '../src/facade/exceptions'; import {BaseException} from '../src/facade/exceptions';
import {SelectorMatcher, CssSelector} from '../compiler_private'; import {SelectorMatcher, CssSelector} from '../compiler_private';
import {Type} from '@angular/core'; import {Type} from '@angular/core';
import {XHR} from '@angular/compiler'; import {ResourceLoader} from '@angular/compiler';
var parser: any /** TODO #9100 */ = null; var parser: any /** TODO #9100 */ = null;
var serializer: any /** TODO #9100 */ = null; var serializer: any /** TODO #9100 */ = null;
@ -69,7 +69,7 @@ export class Parse5DomAdapter extends DomAdapter {
logGroupEnd() {} logGroupEnd() {}
getXHR(): Type<XHR> { return XHR; } getResourceLoader(): Type<ResourceLoader> { return ResourceLoader; }
get attrToPropMap() { return _attrToPropMap; } get attrToPropMap() { return _attrToPropMap; }

View File

@ -1,11 +1,11 @@
/** @experimental */ /** @experimental */
export declare function bootstrapWorkerUi(workerScriptUri: string, customProviders?: Provider[]): Promise<PlatformRef>; export declare function bootstrapWorkerUi(workerScriptUri: string, customProviders?: Provider[]): Promise<PlatformRef>;
/** @experimental */
export declare const CACHED_TEMPLATE_PROVIDER: Provider[];
/** @experimental */ /** @experimental */
export declare const platformBrowserDynamic: (extraProviders?: any[]) => PlatformRef; export declare const platformBrowserDynamic: (extraProviders?: any[]) => PlatformRef;
/** @experimental */ /** @experimental */
export declare const platformWorkerAppDynamic: (extraProviders?: any[]) => PlatformRef; export declare const platformWorkerAppDynamic: (extraProviders?: any[]) => PlatformRef;
/** @experimental */
export declare const RESOURCE_CACHE_PROVIDER: Provider[];