diff --git a/packages/core/src/render3/definition.ts b/packages/core/src/render3/definition.ts index bdf33b1176..3616b5e81e 100644 --- a/packages/core/src/render3/definition.ts +++ b/packages/core/src/render3/definition.ts @@ -10,7 +10,8 @@ import {RendererType2} from '../render/api'; import {Type} from '../type'; import {resolveRendererType2} from '../view/util'; -import {componentRefresh, diPublic} from './instructions'; +import {diPublic} from './di'; +import {componentRefresh} from './instructions'; import {ComponentDef, ComponentDefArgs, DirectiveDef, DirectiveDefArgs} from './interfaces/definition'; diff --git a/packages/core/src/render3/di.ts b/packages/core/src/render3/di.ts index db626027df..65c669e160 100644 --- a/packages/core/src/render3/di.ts +++ b/packages/core/src/render3/di.ts @@ -17,10 +17,12 @@ import {ViewContainerRef as viewEngine_ViewContainerRef} from '../linker/view_co import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, ViewRef as viewEngine_ViewRef} from '../linker/view_ref'; import {Type} from '../type'; +import {assertPreviousIsParent, getPreviousOrParentNode} from './instructions'; import {ComponentTemplate, DirectiveDef, TypedDirectiveDef} from './interfaces/definition'; import {LInjector} from './interfaces/injector'; -import {LContainerNode, LElementNode, LNodeFlags} from './interfaces/node'; -import {assertNodeType} from './node_assert'; +import {LContainerNode, LElementNode, LNode, LNodeFlags} from './interfaces/node'; +import {QueryReadType} from './interfaces/query'; +import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert'; import {notImplemented, stringify} from './util'; @@ -87,6 +89,11 @@ export function bloomAdd(injector: LInjector, type: Type): void { } } +export function getOrCreateNodeInjector(): LInjector { + ngDevMode && assertPreviousIsParent(); + return getOrCreateNodeInjectorForNode(getPreviousOrParentNode() as LElementNode | LContainerNode); +} + /** * Creates (or gets an existing) injector for a given element or container. * @@ -151,6 +158,71 @@ export function diPublicInInjector(di: LInjector, def: TypedDirectiveDef): bloomAdd(di, def.type); } +/** + * Makes a directive public to the DI system by adding it to an injector's bloom filter. + * + * @param def The definition of the directive to be made public + */ +export function diPublic(def: TypedDirectiveDef): void { + diPublicInInjector(getOrCreateNodeInjector(), def); +} + +/** + * Searches for an instance of the given directive type up the injector tree and returns + * that instance if found. + * + * If not found, it will propagate up to the next parent injector until the token + * is found or the top is reached. + * + * Usage example (in factory function): + * + * class SomeDirective { + * constructor(directive: DirectiveA) {} + * + * static ngDirectiveDef = defineDirective({ + * type: SomeDirective, + * factory: () => new SomeDirective(inject(DirectiveA)) + * }); + * } + * + * @param token The directive type to search for + * @param flags Injection flags (e.g. CheckParent) + * @returns The instance found + */ +export function inject(token: Type, flags?: InjectFlags): T { + return getOrCreateInjectable(getOrCreateNodeInjector(), token, flags); +} + +/** + * Creates an ElementRef and stores it on the injector. + * Or, if the ElementRef already exists, retrieves the existing ElementRef. + * + * @returns The ElementRef instance to use + */ +export function injectElementRef(): viewEngine_ElementRef { + return getOrCreateElementRef(getOrCreateNodeInjector()); +} + +/** + * Creates a TemplateRef and stores it on the injector. Or, if the TemplateRef already + * exists, retrieves the existing TemplateRef. + * + * @returns The TemplateRef instance to use + */ +export function injectTemplateRef(): viewEngine_TemplateRef { + return getOrCreateTemplateRef(getOrCreateNodeInjector()); +} + +/** + * Creates a ViewContainerRef and stores it on the injector. Or, if the ViewContainerRef + * already exists, retrieves the existing ViewContainerRef. + * + * @returns The ViewContainerRef instance to use + */ +export function injectViewContainerRef(): viewEngine_ViewContainerRef { + return getOrCreateContainerRef(getOrCreateNodeInjector()); +} + /** * Searches for an instance of the given directive type up the injector tree and returns * that instance if found. @@ -300,6 +372,10 @@ export function bloomFindPossibleInjector(startInjector: LInjector, bloomBit: nu return null; } +export class ReadFromInjectorFn { + constructor(readonly read: (injector: LInjector, node: LNode, directiveIndex?: number) => T) {} +} + /** * Creates an ElementRef for a given node injector and stores it on the injector. * Or, if the ElementRef already exists, retrieves the existing ElementRef. @@ -311,6 +387,31 @@ export function getOrCreateElementRef(di: LInjector): viewEngine_ElementRef { return di.elementRef || (di.elementRef = new ElementRef(di.node.native)); } +export const QUERY_READ_TEMPLATE_REF = >>( + new ReadFromInjectorFn>( + (injector: LInjector) => getOrCreateTemplateRef(injector)) as any); + +export const QUERY_READ_CONTAINER_REF = >( + new ReadFromInjectorFn( + (injector: LInjector) => getOrCreateContainerRef(injector)) as any); + +export const QUERY_READ_ELEMENT_REF = + >(new ReadFromInjectorFn( + (injector: LInjector) => getOrCreateElementRef(injector)) as any); + +export const QUERY_READ_FROM_NODE = + (new ReadFromInjectorFn((injector: LInjector, node: LNode, directiveIdx: number) => { + ngDevMode && assertNodeOfPossibleTypes(node, LNodeFlags.Container, LNodeFlags.Element); + if (directiveIdx > -1) { + return node.view.data[directiveIdx]; + } else if ((node.flags & LNodeFlags.TYPE_MASK) === LNodeFlags.Element) { + return getOrCreateElementRef(injector); + } else if ((node.flags & LNodeFlags.TYPE_MASK) === LNodeFlags.Container) { + return getOrCreateTemplateRef(injector); + } + throw new Error('fail'); + }) as any as QueryReadType); + /** A ref to a node's native element. */ class ElementRef implements viewEngine_ElementRef { readonly nativeElement: any; diff --git a/packages/core/src/render3/index.ts b/packages/core/src/render3/index.ts index 542358231e..1fde6ee071 100644 --- a/packages/core/src/render3/index.ts +++ b/packages/core/src/render3/index.ts @@ -8,8 +8,11 @@ import {createComponentRef, detectChanges, getHostElement, markDirty, renderComponent} from './component'; import {NgOnChangesFeature, PublicFeature, defineComponent, defineDirective} from './definition'; +import {InjectFlags} from './di'; import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType} from './interfaces/definition'; +export {InjectFlags, QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, inject, injectElementRef, injectTemplateRef, injectViewContainerRef} from './di'; + // Naming scheme: // - Capital letters are for creating things: T(Text), E(Element), D(Directive), V(View), // C(Container), L(Listener) @@ -20,7 +23,6 @@ import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveD // - lower case for closing: c(containerEnd), e(elementEnd), v(viewEnd) // clang-format off export { - inject, injectElementRef, injectTemplateRef, injectViewContainerRef, LifecycleHook, @@ -57,17 +59,21 @@ export { projection as P, projectionDef as pD, - query as Q, - queryRefresh as qR, - text as T, textBinding as t, viewStart as V, viewEnd as v, } from './instructions'; + +export { + QueryList, + + query as Q, + queryRefresh as qR, +} from './query'; // clang-format on -export {QueryList} from './query'; + export { ComponentDef, ComponentTemplate, @@ -81,4 +87,3 @@ export { defineDirective, }; export {createComponentRef, detectChanges, getHostElement, markDirty, renderComponent}; -export {InjectFlags} from './di'; diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index a3b54f4266..c2f0dadaf4 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -25,12 +25,9 @@ import {assertNodeType} from './node_assert'; import {appendChild, insertChild, insertView, processProjectedNode, removeView} from './node_manipulation'; import {isNodeMatchingSelector} from './node_selector_matcher'; import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveType, TypedDirectiveDef, TypedComponentDef} from './interfaces/definition'; -import {InjectFlags, diPublicInInjector, getOrCreateNodeInjectorForNode, getOrCreateElementRef, getOrCreateTemplateRef, getOrCreateContainerRef, getOrCreateInjectable} from './di'; -import {QueryList, LQuery_} from './query'; import {RComment, RElement, RText, Renderer3, RendererFactory3, ProceduralRenderer3, ObjectOrientedRenderer3, RendererStyleFlags3} from './interfaces/renderer'; import {isDifferent, stringify} from './util'; -export {queryRefresh} from './query'; /** * Enum used by the lifecycle (l) instruction to determine which lifecycle hook is requesting @@ -331,76 +328,6 @@ export function renderComponentOrTemplate( } } -export function getOrCreateNodeInjector(): LInjector { - ngDevMode && assertPreviousIsParent(); - return getOrCreateNodeInjectorForNode(previousOrParentNode as LElementNode | LContainerNode); -} - -/** - * Makes a directive public to the DI system by adding it to an injector's bloom filter. - * - * @param def The definition of the directive to be made public - */ -export function diPublic(def: TypedDirectiveDef): void { - diPublicInInjector(getOrCreateNodeInjector(), def); -} - -/** - * Searches for an instance of the given directive type up the injector tree and returns - * that instance if found. - * - * If not found, it will propagate up to the next parent injector until the token - * is found or the top is reached. - * - * Usage example (in factory function): - * - * class SomeDirective { - * constructor(directive: DirectiveA) {} - * - * static ngDirectiveDef = defineDirective({ - * type: SomeDirective, - * factory: () => new SomeDirective(inject(DirectiveA)) - * }); - * } - * - * @param token The directive type to search for - * @param flags Injection flags (e.g. CheckParent) - * @returns The instance found - */ -export function inject(token: Type, flags?: InjectFlags): T { - return getOrCreateInjectable(getOrCreateNodeInjector(), token, flags); -} - -/** - * Creates an ElementRef and stores it on the injector. - * Or, if the ElementRef already exists, retrieves the existing ElementRef. - * - * @returns The ElementRef instance to use - */ -export function injectElementRef(): ElementRef { - return getOrCreateElementRef(getOrCreateNodeInjector()); -} - -/** - * Creates a TemplateRef and stores it on the injector. Or, if the TemplateRef already - * exists, retrieves the existing TemplateRef. - * - * @returns The TemplateRef instance to use - */ -export function injectTemplateRef(): TemplateRef { - return getOrCreateTemplateRef(getOrCreateNodeInjector()); -} - -/** - * Creates a ViewContainerRef and stores it on the injector. Or, if the ViewContainerRef - * already exists, retrieves the existing ViewContainerRef. - * - * @returns The ViewContainerRef instance to use - */ -export function injectViewContainerRef(): ViewContainerRef { - return getOrCreateContainerRef(getOrCreateNodeInjector()); -} - ////////////////////////// //// Element ////////////////////////// @@ -1892,19 +1819,15 @@ function valueInData(data: any[], index: number, value?: T): T { return value !; } -export function query( - predicate: Type| string[], descend?: boolean, - read?: QueryReadType | Type): QueryList { - ngDevMode && assertPreviousIsParent(); - const queryList = new QueryList(); - const query = currentQuery || (currentQuery = new LQuery_()); - query.track(queryList, predicate, descend, read); - return queryList; +export function getCurrentQuery(QueryType: {new (): LQuery}): LQuery { + return currentQuery || (currentQuery = new QueryType()); } +export function getPreviousOrParentNode(): LNode { + return previousOrParentNode; +} - -function assertPreviousIsParent() { +export function assertPreviousIsParent() { assertEqual(isParent, true, 'isParent'); } diff --git a/packages/core/src/render3/interfaces/query.ts b/packages/core/src/render3/interfaces/query.ts index 2ed3fe1d94..4cc308ea67 100644 --- a/packages/core/src/render3/interfaces/query.ts +++ b/packages/core/src/render3/interfaces/query.ts @@ -9,6 +9,7 @@ import {QueryList} from '../../linker'; import {Type} from '../../type'; +import {LInjector} from './injector'; import {LContainerNode, LNode, LViewNode} from './node'; @@ -48,15 +49,10 @@ export interface LQuery { */ track( queryList: QueryList, predicate: Type|string[], descend?: boolean, - read?: QueryReadType|Type): void; + read?: QueryReadType|Type): void; } -/** An enum representing possible values of the "read" option for queries. */ -export const enum QueryReadType { - ElementRef = 0, - ViewContainerRef = 1, - TemplateRef = 2, -} +export class QueryReadType { private defeatStructuralTyping: any; } // Note: This hack is necessary so we don't erroneously get a circular dependency // failure based on types. diff --git a/packages/core/src/render3/query.ts b/packages/core/src/render3/query.ts index 4a3196a9bb..be57f29d85 100644 --- a/packages/core/src/render3/query.ts +++ b/packages/core/src/render3/query.ts @@ -16,7 +16,8 @@ import {TemplateRef as viewEngine_TemplateRef} from '../linker/template_ref'; import {Type} from '../type'; import {assertNotNull} from './assert'; -import {getOrCreateContainerRef, getOrCreateElementRef, getOrCreateNodeInjectorForNode, getOrCreateTemplateRef} from './di'; +import {ReadFromInjectorFn, getOrCreateNodeInjectorForNode} from './di'; +import {assertPreviousIsParent, getCurrentQuery} from './instructions'; import {DirectiveDef, TypedDirectiveDef, unusedValueExportToPlacateAjd as unused1} from './interfaces/definition'; import {LInjector, unusedValueExportToPlacateAjd as unused2} from './interfaces/injector'; import {LContainerNode, LElementNode, LNode, LNodeFlags, LViewNode, TNode, unusedValueExportToPlacateAjd as unused3} from './interfaces/node'; @@ -26,6 +27,20 @@ import {assertNodeOfPossibleTypes} from './node_assert'; const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4; +export function query( + predicate: Type| string[], descend?: boolean, + read?: QueryReadType| Type): QueryList { + ngDevMode && assertPreviousIsParent(); + const queryList = new QueryList(); + const query = getCurrentQuery(LQuery_); + query.track(queryList, predicate, descend, read); + return queryList; +} + +export function queryRefresh(query: QueryList): boolean { + return (query as any)._refresh(); +} + /** * A predicate which determines if a given element/directive should be included in the query */ @@ -53,7 +68,7 @@ export interface QueryPredicate { /** * Indicates which token should be read from DI for this query. */ - read: QueryReadType|null; + read: QueryReadType|Type|null; /** * Values which have been located. @@ -71,7 +86,7 @@ export class LQuery_ implements LQuery { track( queryList: viewEngine_QueryList, predicate: Type|string[], descend?: boolean, - read?: QueryReadType): void { + read?: QueryReadType|Type): void { // TODO(misko): This is not right. In case of inherited state, a calling track will incorrectly // mutate parent. if (descend) { @@ -152,26 +167,13 @@ function geIdxOfMatchingDirective(node: LNode, type: Type): number|null { return null; } -function readDefaultInjectable(nodeInjector: LInjector, node: LNode): viewEngine_ElementRef| - viewEngine_TemplateRef|undefined { - ngDevMode && assertNodeOfPossibleTypes(node, LNodeFlags.Container, LNodeFlags.Element); - if ((node.flags & LNodeFlags.TYPE_MASK) === LNodeFlags.Element) { - return getOrCreateElementRef(nodeInjector); - } else if ((node.flags & LNodeFlags.TYPE_MASK) === LNodeFlags.Container) { - return getOrCreateTemplateRef(nodeInjector); - } -} - function readFromNodeInjector( - nodeInjector: LInjector, node: LNode, read: QueryReadType | Type): any { - if (read === QueryReadType.ElementRef) { - return getOrCreateElementRef(nodeInjector); - } else if (read === QueryReadType.ViewContainerRef) { - return getOrCreateContainerRef(nodeInjector); - } else if (read === QueryReadType.TemplateRef) { - return getOrCreateTemplateRef(nodeInjector); + nodeInjector: LInjector, node: LNode, read: QueryReadType| Type| null, + directiveIdx: number = -1): any { + if (read instanceof ReadFromInjectorFn) { + return read.read(nodeInjector, node, directiveIdx); } else { - const matchingIdx = geIdxOfMatchingDirective(node, read); + const matchingIdx = geIdxOfMatchingDirective(node, read as Type); if (matchingIdx !== null) { return node.view.data[matchingIdx]; } @@ -203,17 +205,12 @@ function add(predicate: QueryPredicate| null, node: LNode) { // is anything on a node matching a selector? if (directiveIdx !== null) { if (predicate.read !== null) { - const requestedRead = readFromNodeInjector(nodeInjector, node, predicate.read); - if (requestedRead !== null) { - predicate.values.push(requestedRead); + const result = readFromNodeInjector(nodeInjector, node, predicate.read !, directiveIdx); + if (result !== null) { + predicate.values.push(result); } } else { - // is local name pointing to a directive? - if (directiveIdx > -1) { - predicate.values.push(node.view.data[directiveIdx]); - } else { - predicate.values.push(readDefaultInjectable(nodeInjector, node)); - } + predicate.values.push(node.view.data[directiveIdx]); } } } @@ -224,7 +221,7 @@ function add(predicate: QueryPredicate| null, node: LNode) { function createPredicate( previous: QueryPredicate| null, queryList: QueryList, predicate: Type| string[], - read: QueryReadType | null): QueryPredicate { + read: QueryReadType| Type| null): QueryPredicate { const isArray = Array.isArray(predicate); const values = []; if ((queryList as any as QueryList_)._valuesTree === null) { @@ -309,7 +306,3 @@ class QueryList_/* implements viewEngine_QueryList */ { // it can't be implemented only extended. export type QueryList = viewEngine_QueryList; export const QueryList: typeof viewEngine_QueryList = QueryList_ as any; - -export function queryRefresh(query: QueryList): boolean { - return (query as any as QueryList_)._refresh(); -} diff --git a/packages/core/test/render3/di_spec.ts b/packages/core/test/render3/di_spec.ts index 6b8429f2f9..62ffbaa44b 100644 --- a/packages/core/test/render3/di_spec.ts +++ b/packages/core/test/render3/di_spec.ts @@ -8,9 +8,9 @@ import {ElementRef, TemplateRef, ViewContainerRef} from '@angular/core'; -import {bloomAdd, bloomFindPossibleInjector} from '../../src/render3/di'; +import {bloomAdd, bloomFindPossibleInjector, getOrCreateNodeInjector} from '../../src/render3/di'; import {C, E, PublicFeature, T, V, b, b2, cR, cr, defineDirective, e, inject, injectElementRef, injectTemplateRef, injectViewContainerRef, m, t, v} from '../../src/render3/index'; -import {createLNode, createLView, enterView, getOrCreateNodeInjector, leaveView} from '../../src/render3/instructions'; +import {createLNode, createLView, enterView, leaveView} from '../../src/render3/instructions'; import {LInjector} from '../../src/render3/interfaces/injector'; import {LNodeFlags} from '../../src/render3/interfaces/node'; diff --git a/packages/core/test/render3/query_spec.ts b/packages/core/test/render3/query_spec.ts index da5f841f40..3e05dfbde0 100644 --- a/packages/core/test/render3/query_spec.ts +++ b/packages/core/test/render3/query_spec.ts @@ -5,12 +5,14 @@ * 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 {QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF} from '../../src/render3/di'; import {C, E, Q, QueryList, e, m, qR} from '../../src/render3/index'; import {QueryReadType} from '../../src/render3/interfaces/query'; import {createComponent, createDirective, renderComponent} from './render_util'; + /** * Helper function to check if a given candidate object resembles ElementRef * @param candidate @@ -91,7 +93,7 @@ describe('query', () => { const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) { let tmp: any; if (cm) { - m(0, Q(Child, false, QueryReadType.ElementRef)); + m(0, Q(Child, false, QUERY_READ_ELEMENT_REF)); elToQuery = E(1, 'div', null, [Child]); e(); } @@ -173,7 +175,7 @@ describe('query', () => { const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) { let tmp: any; if (cm) { - m(0, Q(['foo'])); + m(0, Q(['foo'], false, QUERY_READ_ELEMENT_REF)); elToQuery = E(1, 'div', null, null, ['foo', '']); e(); E(2, 'div'); @@ -203,7 +205,7 @@ describe('query', () => { const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) { let tmp: any; if (cm) { - m(0, Q(['foo', 'bar'])); + m(0, Q(['foo', 'bar'], undefined, QUERY_READ_ELEMENT_REF)); el1ToQuery = E(1, 'div', null, null, ['foo', '']); e(); E(2, 'div'); @@ -234,7 +236,7 @@ describe('query', () => { const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) { let tmp: any; if (cm) { - m(0, Q(['foo'], false, QueryReadType.ElementRef)); + m(0, Q(['foo'], false, QUERY_READ_ELEMENT_REF)); elToQuery = E(1, 'div', null, null, ['foo', '']); e(); E(2, 'div'); @@ -260,7 +262,7 @@ describe('query', () => { const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) { let tmp: any; if (cm) { - m(0, Q(['foo'], false, QueryReadType.ViewContainerRef)); + m(0, Q(['foo'], false, QUERY_READ_CONTAINER_REF)); E(1, 'div', null, null, ['foo', '']); e(); } @@ -283,7 +285,7 @@ describe('query', () => { const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) { let tmp: any; if (cm) { - m(0, Q(['foo'], false, QueryReadType.ViewContainerRef)); + m(0, Q(['foo'], false, QUERY_READ_CONTAINER_REF)); C(1, undefined, undefined, undefined, undefined, ['foo', '']); } qR(tmp = m>(0)) && (ctx.query = tmp as QueryList); @@ -306,7 +308,7 @@ describe('query', () => { const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) { let tmp: any; if (cm) { - m(0, Q(['foo'], false, QueryReadType.ElementRef)); + m(0, Q(['foo'], false, QUERY_READ_ELEMENT_REF)); C(1, undefined, undefined, undefined, undefined, ['foo', '']); } qR(tmp = m>(0)) && (ctx.query = tmp as QueryList); @@ -330,7 +332,7 @@ describe('query', () => { const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) { let tmp: any; if (cm) { - m(0, Q(['foo'])); + m(0, Q(['foo'], undefined, QUERY_READ_TEMPLATE_REF)); C(1, undefined, undefined, undefined, undefined, ['foo', '']); } qR(tmp = m>(0)) && (ctx.query = tmp as QueryList); @@ -353,7 +355,7 @@ describe('query', () => { const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) { let tmp: any; if (cm) { - m(0, Q(['foo'], false, QueryReadType.TemplateRef)); + m(0, Q(['foo'], false, QUERY_READ_TEMPLATE_REF)); C(1, undefined, undefined, undefined, undefined, ['foo', '']); } qR(tmp = m>(0)) && (ctx.query = tmp as QueryList); @@ -465,7 +467,7 @@ describe('query', () => { const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) { let tmp: any; if (cm) { - m(0, Q(['foo'], undefined, QueryReadType.ElementRef)); + m(0, Q(['foo'], undefined, QUERY_READ_ELEMENT_REF)); div = E(1, 'div', null, [Child], ['foo', 'child']); e(); } @@ -491,7 +493,7 @@ describe('query', () => { const Cmpt = createComponent('cmpt', function(ctx: any, cm: boolean) { let tmp: any; if (cm) { - m(0, Q(['foo', 'bar'])); + m(0, Q(['foo', 'bar'], undefined, QUERY_READ_FROM_NODE)); div = E(1, 'div', null, [Child], ['foo', '', 'bar', 'child']); { childInstance = m(2); } e();