fix(compiler): work well with forwardRef
with useValue
/ useFactory
The new expression lowering lowers everything after `useValue` / `useFactory` into a separate exported variable. If the value was a `forwardRef`, this was passed to the runtime and resulted in errors. This change unwraps `forwardRef`s during runtime again. Note: we can’t unwrap the `forwardRef` into an exported variable during compile time, as this would defeat the purpose of the `forwardRef` in referring to something that can’t be referred to at this position.
This commit is contained in:

committed by
Victor Berchet

parent
e31a76ce24
commit
1dacae2c3c
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import * as common from '@angular/common';
|
import * as common from '@angular/common';
|
||||||
import {CUSTOM_ELEMENTS_SCHEMA, Component, Directive, EventEmitter, Inject, InjectionToken, NgModule, Output} from '@angular/core';
|
import {CUSTOM_ELEMENTS_SCHEMA, Component, Directive, EventEmitter, Inject, InjectionToken, NgModule, Output, forwardRef} from '@angular/core';
|
||||||
import {Observable} from 'rxjs/Observable';
|
import {Observable} from 'rxjs/Observable';
|
||||||
|
|
||||||
import {wrapInArray} from './funcs';
|
import {wrapInArray} from './funcs';
|
||||||
@ -18,7 +18,7 @@ export const SOME_INJECTON_TOKEN = new InjectionToken('injectionToken');
|
|||||||
selector: 'comp-providers',
|
selector: 'comp-providers',
|
||||||
template: '',
|
template: '',
|
||||||
providers: [
|
providers: [
|
||||||
{provide: 'strToken', useValue: 'strValue'},
|
{provide: 'strToken', useValue: forwardRef(() => 'strValue')},
|
||||||
{provide: SOME_INJECTON_TOKEN, useValue: 10},
|
{provide: SOME_INJECTON_TOKEN, useValue: 10},
|
||||||
{provide: 'reference', useValue: common.NgIf},
|
{provide: 'reference', useValue: common.NgIf},
|
||||||
{provide: 'complexToken', useValue: {a: 1, b: ['test', SOME_INJECTON_TOKEN]}},
|
{provide: 'complexToken', useValue: {a: 1, b: ['test', SOME_INJECTON_TOKEN]}},
|
||||||
|
@ -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 {ApplicationRef, NgModule} from '@angular/core';
|
import {ApplicationRef, NgModule, forwardRef} from '@angular/core';
|
||||||
import {FormsModule} from '@angular/forms';
|
import {FormsModule} from '@angular/forms';
|
||||||
import {MATERIAL_SANITY_CHECKS, MdButtonModule} from '@angular/material';
|
import {MATERIAL_SANITY_CHECKS, MdButtonModule} from '@angular/material';
|
||||||
import {ServerModule} from '@angular/platform-server';
|
import {ServerModule} from '@angular/platform-server';
|
||||||
@ -68,7 +68,7 @@ export {SomeModule as JitSummariesSomeModule} from './jit_summaries';
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
SomeService,
|
SomeService,
|
||||||
{provide: CUSTOM, useValue: {name: 'some name'}},
|
{provide: CUSTOM, useValue: forwardRef(() => ({name: 'some name'}))},
|
||||||
// disable sanity check for material because it throws an error when used server-side
|
// disable sanity check for material because it throws an error when used server-side
|
||||||
// see https://github.com/angular/material2/issues/6292
|
// see https://github.com/angular/material2/issues/6292
|
||||||
{provide: MATERIAL_SANITY_CHECKS, useValue: false},
|
{provide: MATERIAL_SANITY_CHECKS, useValue: false},
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
import './init';
|
||||||
|
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
import {CUSTOM} from '../src/custom_token';
|
||||||
|
import {CompWithProviders} from '../src/features';
|
||||||
|
import {MainModule} from '../src/module';
|
||||||
|
|
||||||
|
import {createComponent, createModule} from './util';
|
||||||
|
|
||||||
|
describe('template codegen output', () => {
|
||||||
|
it('should support forwardRef with useValue in components', () => {
|
||||||
|
const compFixture = createComponent(CompWithProviders);
|
||||||
|
expect(compFixture.componentInstance.ctxProp).toBe('strValue');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support forwardRef with useValue in modules', () => {
|
||||||
|
const modRef = createModule();
|
||||||
|
expect(modRef.injector.get(CUSTOM).name).toBe('some name');
|
||||||
|
});
|
||||||
|
});
|
@ -6,6 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {resolveForwardRef} from '../di/forward_ref';
|
||||||
import {Injector, THROW_IF_NOT_FOUND} from '../di/injector';
|
import {Injector, THROW_IF_NOT_FOUND} from '../di/injector';
|
||||||
import {NgModuleRef} from '../linker/ng_module_factory';
|
import {NgModuleRef} from '../linker/ng_module_factory';
|
||||||
|
|
||||||
@ -20,6 +21,10 @@ const NgModuleRefTokenKey = tokenKey(NgModuleRef);
|
|||||||
export function moduleProvideDef(
|
export function moduleProvideDef(
|
||||||
flags: NodeFlags, token: any, value: any,
|
flags: NodeFlags, token: any, value: any,
|
||||||
deps: ([DepFlags, any] | any)[]): NgModuleProviderDef {
|
deps: ([DepFlags, any] | any)[]): NgModuleProviderDef {
|
||||||
|
// Need to resolve forwardRefs as e.g. for `useValue` we
|
||||||
|
// lowered the expression and then stopped evaluating it,
|
||||||
|
// i.e. also didn't unwrap it.
|
||||||
|
value = resolveForwardRef(value);
|
||||||
const depDefs = splitDepsDsl(deps);
|
const depDefs = splitDepsDsl(deps);
|
||||||
return {
|
return {
|
||||||
// will bet set by the module definition
|
// will bet set by the module definition
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {ChangeDetectorRef, SimpleChange, SimpleChanges, WrappedValue} from '../change_detection/change_detection';
|
import {ChangeDetectorRef, SimpleChange, SimpleChanges, WrappedValue} from '../change_detection/change_detection';
|
||||||
import {Injector} from '../di';
|
import {Injector, resolveForwardRef} from '../di';
|
||||||
import {ElementRef} from '../linker/element_ref';
|
import {ElementRef} from '../linker/element_ref';
|
||||||
import {TemplateRef} from '../linker/template_ref';
|
import {TemplateRef} from '../linker/template_ref';
|
||||||
import {ViewContainerRef} from '../linker/view_container_ref';
|
import {ViewContainerRef} from '../linker/view_container_ref';
|
||||||
@ -77,6 +77,10 @@ export function _def(
|
|||||||
if (!bindings) {
|
if (!bindings) {
|
||||||
bindings = [];
|
bindings = [];
|
||||||
}
|
}
|
||||||
|
// Need to resolve forwardRefs as e.g. for `useValue` we
|
||||||
|
// lowered the expression and then stopped evaluating it,
|
||||||
|
// i.e. also didn't unwrap it.
|
||||||
|
value = resolveForwardRef(value);
|
||||||
|
|
||||||
const depDefs = splitDepsDsl(deps);
|
const depDefs = splitDepsDsl(deps);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user