Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ describe('compiler compliance', () => {
selectors: [["", "hostBindingDir", ""]],
factory: function HostBindingDir_Factory(t) { return new (t || HostBindingDir)(); },
hostBindings: function HostBindingDir_HostBindings(dirIndex, elIndex) {
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵloadDirective(dirIndex).dirId));
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵload(dirIndex).dirId));
},
hostVars: 1,
features: [$r3$.ɵPublicFeature]
Expand Down Expand Up @@ -632,7 +632,7 @@ describe('compiler compliance', () => {
selectors: [["host-binding-comp"]],
factory: function HostBindingComp_Factory(t) { return new (t || HostBindingComp)(); },
hostBindings: function HostBindingComp_HostBindings(dirIndex, elIndex) {
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵpureFunction1(1, $ff$, $r3$.ɵloadDirective(dirIndex).id)));
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵpureFunction1(1, $ff$, $r3$.ɵload(dirIndex).id)));
},
hostVars: 3,
features: [$r3$.ɵPublicFeature],
Expand Down Expand Up @@ -1343,7 +1343,7 @@ describe('compiler compliance', () => {
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, SomeDirective, false));
},
contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) {
const instance = $r3$.ɵloadDirective(dirIndex);
const instance = $r3$.ɵload(dirIndex);
var $tmp$;
($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList(queryStartIndex))) && ($instance$.someDir = $tmp$.first));
($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList((queryStartIndex + 1)))) && ($instance$.someDirList = $tmp$));
Expand Down Expand Up @@ -1403,7 +1403,7 @@ describe('compiler compliance', () => {
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, ["myRef1", "myRef2", "myRef3"], false));
},
contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) {
const instance = $r3$.ɵloadDirective(dirIndex);
const instance = $r3$.ɵload(dirIndex);
var $tmp$;
($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList(queryStartIndex))) && (instance.myRef = $tmp$.first));
($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList((queryStartIndex + 1)))) && (instance.myRefs = $tmp$));
Expand Down Expand Up @@ -1452,7 +1452,7 @@ describe('compiler compliance', () => {
$r3$.ɵregisterContentQuery($r3$.ɵquery(null, ["myRef1", "myRef2", "myRef3"], false, ElementRef));
},
contentQueriesRefresh: function ContentQueryComponent_ContentQueriesRefresh(dirIndex, queryStartIndex) {
const instance = $r3$.ɵloadDirective(dirIndex);
const instance = $r3$.ɵload(dirIndex);
var $tmp$;
($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList(queryStartIndex))) && (instance.myRef = $tmp$.first));
($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList((queryStartIndex + 1)))) && (instance.myRefs = $tmp$));
Expand Down
13 changes: 5 additions & 8 deletions packages/compiler-cli/test/ngtsc/ngtsc_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,17 +463,14 @@ describe('ngtsc behavioral tests', () => {
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents)
.toContain(
`i0.ɵelementProperty(elIndex, "attr.hello", i0.ɵbind(i0.ɵloadDirective(dirIndex).foo));`);
.toContain(`i0.ɵelementProperty(elIndex, "attr.hello", i0.ɵbind(i0.ɵload(dirIndex).foo));`);
expect(jsContents)
.toContain(
`i0.ɵelementProperty(elIndex, "prop", i0.ɵbind(i0.ɵloadDirective(dirIndex).bar));`);
.toContain(`i0.ɵelementProperty(elIndex, "prop", i0.ɵbind(i0.ɵload(dirIndex).bar));`);
expect(jsContents)
.toContain(
'i0.ɵelementProperty(elIndex, "class.someclass", i0.ɵbind(i0.ɵloadDirective(dirIndex).someClass))');
expect(jsContents).toContain('i0.ɵloadDirective(dirIndex).onClick($event)');
expect(jsContents)
.toContain('i0.ɵloadDirective(dirIndex).onChange(i0.ɵloadDirective(dirIndex).arg)');
'i0.ɵelementProperty(elIndex, "class.someclass", i0.ɵbind(i0.ɵload(dirIndex).someClass))');
expect(jsContents).toContain('i0.ɵload(dirIndex).onClick($event)');
expect(jsContents).toContain('i0.ɵload(dirIndex).onChange(i0.ɵload(dirIndex).arg)');
});

it('should correctly recognize local symbols', () => {
Expand Down
1 change: 0 additions & 1 deletion packages/compiler/src/render3/r3_identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ export class Identifiers {
static pipeBindV: o.ExternalReference = {name: 'ɵpipeBindV', moduleName: CORE};

static load: o.ExternalReference = {name: 'ɵload', moduleName: CORE};
static loadDirective: o.ExternalReference = {name: 'ɵloadDirective', moduleName: CORE};
static loadQueryList: o.ExternalReference = {name: 'ɵloadQueryList', moduleName: CORE};

static pipe: o.ExternalReference = {name: 'ɵpipe', moduleName: CORE};
Expand Down
9 changes: 4 additions & 5 deletions packages/compiler/src/render3/view/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,10 +475,9 @@ function createContentQueriesRefreshFunction(meta: R3DirectiveMetadata): o.Expre
// var $tmp$: any;
const temporary = temporaryAllocator(statements, TEMPORARY_NAME);

// const $instance$ = $r3$.ɵloadDirective(dirIndex);
statements.push(
directiveInstanceVar.set(o.importExpr(R3.loadDirective).callFn([o.variable('dirIndex')]))
.toDeclStmt(o.INFERRED_TYPE, [o.StmtModifier.Final]));
// const $instance$ = $r3$.ɵload(dirIndex);
statements.push(directiveInstanceVar.set(o.importExpr(R3.load).callFn([o.variable('dirIndex')]))
.toDeclStmt(o.INFERRED_TYPE, [o.StmtModifier.Final]));

meta.queries.forEach((query: R3QueryMetadata, idx: number) => {
const loadQLArg = o.variable('queryStartIndex');
Expand Down Expand Up @@ -582,7 +581,7 @@ function createHostBindingsFunction(

// Calculate the host property bindings
const bindings = bindingParser.createBoundHostProperties(directiveSummary, hostBindingSourceSpan);
const bindingContext = o.importExpr(R3.loadDirective).callFn([o.variable('dirIndex')]);
const bindingContext = o.importExpr(R3.load).callFn([o.variable('dirIndex')]);
if (bindings) {
const valueConverter = new ValueConverter(
constantPool,
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/core_render3_private_export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ export {
embeddedViewStart as ɵembeddedViewStart,
query as ɵquery,
registerContentQuery as ɵregisterContentQuery,
loadDirective as ɵloadDirective,
projection as ɵprojection,
bind as ɵbind,
interpolation1 as ɵinterpolation1,
Expand Down
10 changes: 4 additions & 6 deletions packages/core/src/render3/VIEW_DATA.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@ NOTE:

## `EXPANDO`

*TODO*: This section is to be implemented.

`EXPANDO` contains information on data which size is not known at compile time.
Examples include:
- `Component`/`Directives` since we don't know at compile time which directives will match.
Expand Down Expand Up @@ -203,7 +201,7 @@ The `EXPANDO` section needs additional information for information stored in `TV

| Index | `TView.expandoInstructions` | Meaning
| ----: | ---------------------------: | -------
| 0 | -10 | Negative numbers signifies pointers to elements. In this case 10 (`<child>`)
| 0 | -10 | Negative numbers signify pointers to elements. In this case 10 (`<child>`)
| 1 | 2 | Injector size. Number of values to skip to get to Host Bindings.
| 2 | Child.ngComponentDef.hostBindings | The function to call. (Only when `hostVars` is not `0`)
| 3 | Child.ngComponentDef.hostVars | Number of host bindings to process. (Only when `hostVars` is not `0`)
Expand All @@ -215,9 +213,9 @@ The reason for this layout is to make the host binding update efficient using th
let currentDirectiveIndex = -1;
let currentElementIndex = -1;
// This is global state which is used internally by hostBindings to know where the offset is
let bindingRootIndex = tView.expandoStart;
for(var i = 0; i < tview.expandoInstructions.length; i++) {
let instruction = tview.expandoInstructions[i];
let bindingRootIndex = tView.expandoStartIndex;
for(var i = 0; i < tView.expandoInstructions.length; i++) {
let instruction = tView.expandoInstructions[i];
if (typeof instruction === 'number') {
// Numbers are used to update the indices.
if (instruction < 0) {
Expand Down
23 changes: 11 additions & 12 deletions packages/core/src/render3/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ import {assertComponentType, assertDefined} from './assert';
import {getLElementFromComponent, readPatchedLViewData} from './context_discovery';
import {getComponentDef} from './definition';
import {queueInitHooks, queueLifecycleHooks} from './hooks';
import {PlayerHandler} from './interfaces/player';

import {CLEAN_PROMISE, baseDirectiveCreate, createLViewData, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, hostElement, leaveView, locateHostElement, setHostBindings, queueHostBindingForCheck,} from './instructions';
import {CLEAN_PROMISE, baseDirectiveCreate, createLViewData, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, hostElement, leaveView, locateHostElement, prefillHostVars, setHostBindings} from './instructions';
import {ComponentDef, ComponentType} from './interfaces/definition';
import {LElementNode} from './interfaces/node';
import {LElementNode, TNodeFlags} from './interfaces/node';
import {PlayerHandler} from './interfaces/player';
import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
import {CONTEXT, INJECTOR, LViewData, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
import {getRootView, stringify} from './util';
Expand Down Expand Up @@ -151,15 +150,16 @@ export function renderComponent<T>(
export function createRootComponent<T>(
elementNode: LElementNode, componentDef: ComponentDef<T>, rootView: LViewData,
rootContext: RootContext, hostFeatures: HostFeature[] | null): any {
// Create directive instance with factory() and store at index 0 in directives array
const component = baseDirectiveCreate(0, componentDef.factory() as T, componentDef, elementNode);
// Create directive instance with factory() and store at next index in viewData
const component =
baseDirectiveCreate(rootView.length, componentDef.factory() as T, componentDef, elementNode);

if (componentDef.hostBindings) queueHostBindingForCheck(0, componentDef.hostVars);
rootContext.components.push(component);
(elementNode.data as LViewData)[CONTEXT] = component;

hostFeatures && hostFeatures.forEach((feature) => feature(component, componentDef));
setHostBindings(rootView[TVIEW].hostBindings);
if (rootView[TVIEW].firstTemplatePass) prefillHostVars(componentDef.hostVars);
setHostBindings();
return component;
}

Expand Down Expand Up @@ -190,11 +190,10 @@ export function createRootContext(
*/
export function LifecycleHooksFeature(component: any, def: ComponentDef<any>): void {
const rootTView = readPatchedLViewData(component) ![TVIEW];
const dirIndex = rootTView.data.length - 1;

// Root component is always created at dir index 0
queueInitHooks(0, def.onInit, def.doCheck, rootTView);
// Directive starting index 0, directive count 1 -> directive flags: 1
queueLifecycleHooks(1, rootTView);
queueInitHooks(dirIndex, def.onInit, def.doCheck, rootTView);
queueLifecycleHooks(dirIndex << TNodeFlags.DirectiveStartingIndexShift | 1, rootTView);
}

/**
Expand Down
13 changes: 6 additions & 7 deletions packages/core/src/render3/component_ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,6 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {

// Create element node at index 0 in data array
elementNode = hostElement(componentTag, hostNode, this.componentDef);

// TODO: should LifecycleHooksFeature and other host features be generated by the compiler and
// executed here?
// Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref
component = createRootComponent(
elementNode, this.componentDef, rootView, rootContext, [LifecycleHooksFeature]);

tElementNode = getTNode(0) as TElementNode;

// Transform the arrays of native nodes into a LNode structure that can be consumed by the
Expand All @@ -168,6 +161,12 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
}
}

// TODO: should LifecycleHooksFeature and other host features be generated by the compiler and
// executed here?
// Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref
component = createRootComponent(
elementNode, this.componentDef, rootView, rootContext, [LifecycleHooksFeature]);

// Execute the template in creation mode only, and then turn off the CreationMode flag
const componentView = elementNode.data as LViewData;
renderEmbeddedTemplate(componentView, componentView[TVIEW], component, RenderFlags.Create);
Expand Down
47 changes: 21 additions & 26 deletions packages/core/src/render3/context_discovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import './ng_dev_mode';
import {assertEqual} from './assert';
import {LElementNode, TNode, TNodeFlags} from './interfaces/node';
import {RElement} from './interfaces/renderer';
import {CONTEXT, DIRECTIVES, HEADER_OFFSET, LViewData, TVIEW} from './interfaces/view';
import {CONTEXT, HEADER_OFFSET, LViewData, TVIEW} from './interfaces/view';

/**
* This property will be monkey-patched on elements, components and directives
Expand Down Expand Up @@ -99,7 +99,7 @@ export function getContext(target: any): LContext|null {
if (nodeIndex == -1) {
throw new Error('The provided directive was not found in the application');
}
directives = discoverDirectives(nodeIndex, lViewData);
directives = discoverDirectives(nodeIndex, lViewData, false);
} else {
nodeIndex = findViaNativeElement(lViewData, target as RElement);
if (nodeIndex == -1) {
Expand Down Expand Up @@ -306,21 +306,17 @@ function findViaDirective(lViewData: LViewData, directiveInstance: {}): number {
// element bound to the directive being search lives somewhere
// in the view data. We loop through the nodes and check their
// list of directives for the instance.
const directivesAcrossView = lViewData[DIRECTIVES];
let tNode = lViewData[TVIEW].firstChild;
if (directivesAcrossView != null) {
while (tNode) {
const directiveIndexStart = getDirectiveStartIndex(tNode);
const directiveIndexEnd = getDirectiveEndIndex(tNode, directiveIndexStart);
for (let i = directiveIndexStart; i < directiveIndexEnd; i++) {
if (directivesAcrossView[i] === directiveInstance) {
return tNode.index;
}
while (tNode) {
const directiveIndexStart = getDirectiveStartIndex(tNode);
const directiveIndexEnd = getDirectiveEndIndex(tNode, directiveIndexStart);
for (let i = directiveIndexStart; i < directiveIndexEnd; i++) {
if (lViewData[i] === directiveInstance) {
return tNode.index;
}
tNode = traverseNextElement(tNode);
}
tNode = traverseNextElement(tNode);
}

return -1;
}

Expand All @@ -341,21 +337,20 @@ function getLNodeFromViewData(lViewData: LViewData, lElementIndex: number): LEle
}

/**
* Returns a list of directives extracted from the given view. Does not contain
* the component.
* Returns a list of directives extracted from the given view based on the
* provided list of directive index values.
*
* @param nodeIndex The node index
* @param lViewData The target view data
* @param includeComponents Whether or not to include components in returned directives
*/
export function discoverDirectives(nodeIndex: number, lViewData: LViewData): any[]|null {
const directivesAcrossView = lViewData[DIRECTIVES];
if (directivesAcrossView != null) {
const tNode = lViewData[TVIEW].data[nodeIndex] as TNode;
let directiveStartIndex = getDirectiveStartIndex(tNode);
const directiveEndIndex = getDirectiveEndIndex(tNode, directiveStartIndex);
if (tNode.flags & TNodeFlags.isComponent) directiveStartIndex++;
return directivesAcrossView.slice(directiveStartIndex, directiveEndIndex);
}
return null;
export function discoverDirectives(
nodeIndex: number, lViewData: LViewData, includeComponents: boolean): any[]|null {
const tNode = lViewData[TVIEW].data[nodeIndex] as TNode;
let directiveStartIndex = getDirectiveStartIndex(tNode);
const directiveEndIndex = getDirectiveEndIndex(tNode, directiveStartIndex);
if (!includeComponents && tNode.flags & TNodeFlags.isComponent) directiveStartIndex++;
return lViewData.slice(directiveStartIndex, directiveEndIndex);
}

/**
Expand All @@ -372,7 +367,7 @@ export function discoverLocalRefs(lViewData: LViewData, lNodeIndex: number): {[k
const directiveIndex = tNode.localNames[i + 1] as number;
result[localRefName] = directiveIndex === -1 ?
getLNodeFromViewData(lViewData, lNodeIndex) !.native :
lViewData[DIRECTIVES] ![directiveIndex];
lViewData[directiveIndex];
}
return result;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/render3/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class Render3DebugContext implements DebugContext {
// TODO(vicb): add view providers when supported
get providerTokens(): any[] {
// TODO(vicb): why/when
const directiveDefs = this.view[TVIEW].directives;
const directiveDefs = this.view[TVIEW].data;
if (this.nodeIndex === null || directiveDefs == null) {
return [];
}
Expand Down
Loading