Skip to content

Commit 3859bcc

Browse files
benleshmhevery
authored andcommitted
refactor(ivy): remove ɵɵelementAttribute instruction (angular#30640)
PR Close angular#30640
1 parent 30efb6b commit 3859bcc

File tree

12 files changed

+151
-115
lines changed

12 files changed

+151
-115
lines changed

packages/compiler/src/render3/r3_identifiers.ts

-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ export class Identifiers {
3737
static componentHostSyntheticListener:
3838
o.ExternalReference = {name: 'ɵɵcomponentHostSyntheticListener', moduleName: CORE};
3939

40-
static elementAttribute: o.ExternalReference = {name: 'ɵɵelementAttribute', moduleName: CORE};
41-
4240
static attribute: o.ExternalReference = {name: 'ɵɵattribute', moduleName: CORE};
4341

4442
static attributeInterpolate1:

packages/core/src/core_render3_private_export.ts

-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ export {
126126
ɵɵenableBindings,
127127
ɵɵdisableBindings,
128128
ɵɵallocHostVars,
129-
ɵɵelementAttribute,
130129
ɵɵelementContainerStart,
131130
ɵɵelementContainerEnd,
132131
ɵɵstyling,

packages/core/src/render3/i18n.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@
77
*/
88

99
import '../util/ng_i18n_closure_mode';
10+
1011
import {getPluralCase} from '../i18n/localization';
1112
import {SRCSET_ATTRS, URI_ATTRS, VALID_ATTRS, VALID_ELEMENTS, getTemplateContent} from '../sanitization/html_sanitizer';
1213
import {InertBodyHelper} from '../sanitization/inert_body';
1314
import {_sanitizeUrl, sanitizeSrcset} from '../sanitization/url_sanitizer';
1415
import {addAllToArray} from '../util/array_utils';
1516
import {assertDataInRange, assertDefined, assertEqual, assertGreaterThan} from '../util/assert';
17+
1618
import {attachPatchData} from './context_discovery';
17-
import {elementAttributeInternal, setDelayProjection, ɵɵload, ɵɵtextBinding} from './instructions/all';
19+
import {setDelayProjection, ɵɵload, ɵɵtextBinding} from './instructions/all';
1820
import {attachI18nOpCodesDebug} from './instructions/lview_debug';
19-
import {allocExpando, elementPropertyInternal, getOrCreateTNode, setInputsForProperty} from './instructions/shared';
21+
import {allocExpando, elementAttributeInternal, elementPropertyInternal, getOrCreateTNode, setInputsForProperty} from './instructions/shared';
2022
import {LContainer, NATIVE} from './interfaces/container';
2123
import {COMMENT_MARKER, ELEMENT_MARKER, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuType, TI18n, TIcu} from './interfaces/i18n';
2224
import {TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode} from './interfaces/node';
@@ -755,10 +757,9 @@ function readCreateOpCodes(
755757
const elementNodeIndex = opCode >>> I18nMutateOpCode.SHIFT_REF;
756758
const attrName = createOpCodes[++i] as string;
757759
const attrValue = createOpCodes[++i] as string;
758-
const renderer = viewData[RENDERER];
759760
// This code is used for ICU expressions only, since we don't support
760761
// directives/components in ICUs, we don't need to worry about inputs here
761-
elementAttributeInternal(elementNodeIndex, attrName, attrValue, viewData, renderer);
762+
elementAttributeInternal(elementNodeIndex, attrName, attrValue, viewData);
762763
break;
763764
default:
764765
throw new Error(`Unable to determine the type of mutate operation for "${opCode}"`);
@@ -988,8 +989,7 @@ function i18nAttributesFirstPass(tView: TView, index: number, values: string[])
988989
generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes);
989990
} else {
990991
const lView = getLView();
991-
const renderer = lView[RENDERER];
992-
elementAttributeInternal(previousElementIndex, attrName, value, lView, renderer);
992+
elementAttributeInternal(previousElementIndex, attrName, value, lView);
993993
// Check if that attribute is a directive input
994994
const tNode = getTNode(previousElementIndex, lView);
995995
const dataValue = tNode.inputs && tNode.inputs[attrName];

packages/core/src/render3/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ export {
4747
ɵɵdirectiveInject,
4848

4949
ɵɵelement,
50-
ɵɵelementAttribute,
5150
ɵɵelementContainerEnd,
5251

5352
ɵɵelementContainerStart,

packages/core/src/render3/instructions/attribute.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import {SanitizerFn} from '../interfaces/sanitization';
9-
import {getSelectedIndex} from '../state';
9+
import {getLView, getSelectedIndex} from '../state';
10+
import {NO_CHANGE} from '../tokens';
1011

11-
import {ɵɵelementAttribute} from './element';
1212
import {ɵɵbind} from './property';
13+
import {elementAttributeInternal} from './shared';
14+
15+
1316

1417
/**
1518
* Updates the value of or removes a bound attribute on an Element.
@@ -27,6 +30,10 @@ import {ɵɵbind} from './property';
2730
export function ɵɵattribute(
2831
name: string, value: any, sanitizer?: SanitizerFn | null, namespace?: string) {
2932
const index = getSelectedIndex();
33+
const lView = getLView();
3034
// TODO(FW-1340): Refactor to remove the use of other instructions here.
31-
return ɵɵelementAttribute(index, name, ɵɵbind(value), sanitizer, namespace);
35+
const bound = ɵɵbind(value);
36+
if (bound !== NO_CHANGE) {
37+
return elementAttributeInternal(index, name, bound, lView, sanitizer, namespace);
38+
}
3239
}

packages/core/src/render3/instructions/attribute_interpolation.ts

+41-14
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import {SanitizerFn} from '../interfaces/sanitization';
9-
import {getSelectedIndex} from '../state';
10-
import {ɵɵelementAttribute} from './element';
9+
import {getLView, getSelectedIndex} from '../state';
10+
import {NO_CHANGE} from '../tokens';
11+
1112
import {ɵɵinterpolation1, ɵɵinterpolation2, ɵɵinterpolation3, ɵɵinterpolation4, ɵɵinterpolation5, ɵɵinterpolation6, ɵɵinterpolation7, ɵɵinterpolation8, ɵɵinterpolationV} from './interpolation';
12-
import {TsickleIssue1009} from './shared';
13+
import {TsickleIssue1009, elementAttributeInternal} from './shared';
1314

1415

1516

@@ -41,12 +42,13 @@ export function ɵɵattributeInterpolate1(
4142
attrName: string, prefix: string, v0: any, suffix: string, sanitizer?: SanitizerFn,
4243
namespace?: string): TsickleIssue1009 {
4344
const index = getSelectedIndex();
45+
const lView = getLView();
4446

4547
// TODO(FW-1340): Refactor to remove the use of other instructions here.
4648
const interpolatedValue = ɵɵinterpolation1(prefix, v0, suffix);
47-
48-
ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace);
49-
49+
if (interpolatedValue !== NO_CHANGE) {
50+
elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace);
51+
}
5052
return ɵɵattributeInterpolate1;
5153
}
5254

@@ -80,10 +82,13 @@ export function ɵɵattributeInterpolate2(
8082
attrName: string, prefix: string, v0: any, i0: string, v1: any, suffix: string,
8183
sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 {
8284
const index = getSelectedIndex();
85+
const lView = getLView();
8386

8487
// TODO(FW-1340): Refactor to remove the use of other instructions here.
8588
const interpolatedValue = ɵɵinterpolation2(prefix, v0, i0, v1, suffix);
86-
ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace);
89+
if (interpolatedValue !== NO_CHANGE) {
90+
elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace);
91+
}
8792
return ɵɵattributeInterpolate2;
8893
}
8994

@@ -120,10 +125,13 @@ export function ɵɵattributeInterpolate3(
120125
attrName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any,
121126
suffix: string, sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 {
122127
const index = getSelectedIndex();
128+
const lView = getLView();
123129

124130
// TODO(FW-1340): Refactor to remove the use of other instructions here.
125131
const interpolatedValue = ɵɵinterpolation3(prefix, v0, i0, v1, i1, v2, suffix);
126-
ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace);
132+
if (interpolatedValue !== NO_CHANGE) {
133+
elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace);
134+
}
127135
return ɵɵattributeInterpolate3;
128136
}
129137

@@ -162,10 +170,13 @@ export function ɵɵattributeInterpolate4(
162170
attrName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
163171
v3: any, suffix: string, sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 {
164172
const index = getSelectedIndex();
173+
const lView = getLView();
165174

166175
// TODO(FW-1340): Refactor to remove the use of other instructions here.
167176
const interpolatedValue = ɵɵinterpolation4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
168-
ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace);
177+
if (interpolatedValue !== NO_CHANGE) {
178+
elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace);
179+
}
169180
return ɵɵattributeInterpolate4;
170181
}
171182

@@ -207,10 +218,13 @@ export function ɵɵattributeInterpolate5(
207218
v3: any, i3: string, v4: any, suffix: string, sanitizer?: SanitizerFn,
208219
namespace?: string): TsickleIssue1009 {
209220
const index = getSelectedIndex();
221+
const lView = getLView();
210222

211223
// TODO(FW-1340): Refactor to remove the use of other instructions here.
212224
const interpolatedValue = ɵɵinterpolation5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
213-
ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace);
225+
if (interpolatedValue !== NO_CHANGE) {
226+
elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace);
227+
}
214228
return ɵɵattributeInterpolate5;
215229
}
216230

@@ -254,10 +268,13 @@ export function ɵɵattributeInterpolate6(
254268
v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string, sanitizer?: SanitizerFn,
255269
namespace?: string): TsickleIssue1009 {
256270
const index = getSelectedIndex();
271+
const lView = getLView();
257272
// TODO(FW-1340): Refactor to remove the use of other instructions here.
258273
const interpolatedValue =
259274
ɵɵinterpolation6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
260-
ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace);
275+
if (interpolatedValue !== NO_CHANGE) {
276+
elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace);
277+
}
261278
return ɵɵattributeInterpolate6;
262279
}
263280

@@ -303,10 +320,13 @@ export function ɵɵattributeInterpolate7(
303320
v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string,
304321
sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 {
305322
const index = getSelectedIndex();
323+
const lView = getLView();
306324
// TODO(FW-1340): Refactor to remove the use of other instructions here.
307325
const interpolatedValue =
308326
ɵɵinterpolation7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
309-
ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace);
327+
if (interpolatedValue !== NO_CHANGE) {
328+
elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace);
329+
}
310330
return ɵɵattributeInterpolate7;
311331
}
312332

@@ -354,10 +374,13 @@ export function ɵɵattributeInterpolate8(
354374
v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any,
355375
suffix: string, sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 {
356376
const index = getSelectedIndex();
377+
const lView = getLView();
357378
// TODO(FW-1340): Refactor to remove the use of other instructions here.
358379
const interpolatedValue =
359380
ɵɵinterpolation8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
360-
ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace);
381+
if (interpolatedValue !== NO_CHANGE) {
382+
elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace);
383+
}
361384
return ɵɵattributeInterpolate8;
362385
}
363386

@@ -391,7 +414,11 @@ export function ɵɵattributeInterpolateV(
391414
attrName: string, values: any[], sanitizer?: SanitizerFn,
392415
namespace?: string): TsickleIssue1009 {
393416
const index = getSelectedIndex();
417+
const lView = getLView();
394418
// TODO(FW-1340): Refactor to remove the use of other instructions here.
395-
ɵɵelementAttribute(index, attrName, ɵɵinterpolationV(values), sanitizer, namespace);
419+
const interpolated = ɵɵinterpolationV(values);
420+
if (interpolated !== NO_CHANGE) {
421+
elementAttributeInternal(index, attrName, interpolated, lView, sanitizer, namespace);
422+
}
396423
return ɵɵattributeInterpolateV;
397424
}

packages/core/src/render3/instructions/element.ts

+5-55
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,14 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import {validateAgainstEventAttributes} from '../../sanitization/sanitization';
98
import {assertDataInRange, assertDefined, assertEqual} from '../../util/assert';
109
import {assertHasParent} from '../assert';
1110
import {attachPatchData} from '../context_discovery';
1211
import {registerPostOrderHooks} from '../hooks';
1312
import {TAttributes, TNodeFlags, TNodeType} from '../interfaces/node';
14-
import {RElement, Renderer3, isProceduralRenderer} from '../interfaces/renderer';
15-
import {SanitizerFn} from '../interfaces/sanitization';
13+
import {RElement} from '../interfaces/renderer';
1614
import {StylingContext} from '../interfaces/styling';
17-
import {BINDING_INDEX, HEADER_OFFSET, LView, QUERIES, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
15+
import {BINDING_INDEX, HEADER_OFFSET, QUERIES, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
1816
import {assertNodeType} from '../node_assert';
1917
import {appendChild} from '../node_manipulation';
2018
import {applyOnCreateInstructions} from '../node_util';
@@ -23,14 +21,14 @@ import {getInitialClassNameValue, getInitialStyleStringValue, initializeStaticCo
2321
import {getStylingContextFromLView, hasClassInput, hasStyleInput} from '../styling/util';
2422
import {registerInitialStylingIntoContext} from '../styling_next/instructions';
2523
import {runtimeIsNewStylingInUse} from '../styling_next/state';
26-
import {NO_CHANGE} from '../tokens';
2724
import {attrsStylingIndexOf, setUpAttributes} from '../util/attrs_utils';
28-
import {renderStringify} from '../util/misc_utils';
29-
import {getNativeByIndex, getNativeByTNode, getTNode} from '../util/view_utils';
25+
import {getNativeByTNode, getTNode} from '../util/view_utils';
26+
3027
import {createDirectivesAndLocals, elementCreate, executeContentQueries, getOrCreateTNode, initializeTNodeInputs, setInputsForProperty, setNodeStylingTemplate} from './shared';
3128
import {getActiveDirectiveStylingIndex} from './styling';
3229

3330

31+
3432
/**
3533
* Create DOM element. The instruction must later be followed by `elementEnd()` call.
3634
*
@@ -197,54 +195,6 @@ export function ɵɵelement(
197195
ɵɵelementEnd();
198196
}
199197

200-
201-
/**
202-
* Updates the value or removes an attribute on an Element.
203-
*
204-
* @param index The index of the element in the data array
205-
* @param name name The name of the attribute.
206-
* @param value value The attribute is removed when value is `null` or `undefined`.
207-
* Otherwise the attribute value is set to the stringified value.
208-
* @param sanitizer An optional function used to sanitize the value.
209-
* @param namespace Optional namespace to use when setting the attribute.
210-
*
211-
* @codeGenApi
212-
*/
213-
export function ɵɵelementAttribute(
214-
index: number, name: string, value: any, sanitizer?: SanitizerFn | null,
215-
namespace?: string): void {
216-
if (value !== NO_CHANGE) {
217-
const lView = getLView();
218-
const renderer = lView[RENDERER];
219-
elementAttributeInternal(index, name, value, lView, renderer, sanitizer, namespace);
220-
}
221-
}
222-
223-
export function elementAttributeInternal(
224-
index: number, name: string, value: any, lView: LView, renderer: Renderer3,
225-
sanitizer?: SanitizerFn | null, namespace?: string) {
226-
ngDevMode && validateAgainstEventAttributes(name);
227-
const element = getNativeByIndex(index, lView) as RElement;
228-
if (value == null) {
229-
ngDevMode && ngDevMode.rendererRemoveAttribute++;
230-
isProceduralRenderer(renderer) ? renderer.removeAttribute(element, name, namespace) :
231-
element.removeAttribute(name);
232-
} else {
233-
ngDevMode && ngDevMode.rendererSetAttribute++;
234-
const tNode = getTNode(index, lView);
235-
const strValue =
236-
sanitizer == null ? renderStringify(value) : sanitizer(value, tNode.tagName || '', name);
237-
238-
239-
if (isProceduralRenderer(renderer)) {
240-
renderer.setAttribute(element, name, strValue, namespace);
241-
} else {
242-
namespace ? element.setAttributeNS(namespace, name, strValue) :
243-
element.setAttribute(name, strValue);
244-
}
245-
}
246-
}
247-
248198
/**
249199
* Assign static attribute values to a host element.
250200
*

packages/core/src/render3/instructions/shared.ts

+29-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {Injector} from '../../di';
99
import {ErrorHandler} from '../../error_handler';
1010
import {Type} from '../../interface/type';
1111
import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata} from '../../metadata/schema';
12-
import {validateAgainstEventProperties} from '../../sanitization/sanitization';
12+
import {validateAgainstEventAttributes, validateAgainstEventProperties} from '../../sanitization/sanitization';
1313
import {Sanitizer} from '../../sanitization/security';
1414
import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertLessThan, assertNotEqual, assertNotSame} from '../../util/assert';
1515
import {createNamedArrayType} from '../../util/named_array_type';
@@ -35,7 +35,7 @@ import {initializeStaticContext as initializeStaticStylingContext} from '../styl
3535
import {ANIMATION_PROP_PREFIX, isAnimationProp} from '../styling/util';
3636
import {NO_CHANGE} from '../tokens';
3737
import {attrsStylingIndexOf} from '../util/attrs_utils';
38-
import {INTERPOLATION_DELIMITER, stringifyForError} from '../util/misc_utils';
38+
import {INTERPOLATION_DELIMITER, renderStringify, stringifyForError} from '../util/misc_utils';
3939
import {getLViewParent, getRootContext} from '../util/view_traversal_utils';
4040
import {getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getTNode, isComponent, isComponentDef, isContentQueryHost, isLContainer, isRootView, readPatchedLView, resetPreOrderHookFlags, unwrapRNode, viewAttachedToChangeDetector} from '../util/view_utils';
4141

@@ -1303,6 +1303,33 @@ function addComponentLogic<T>(
13031303
}
13041304
}
13051305

1306+
export function elementAttributeInternal(
1307+
index: number, name: string, value: any, lView: LView, sanitizer?: SanitizerFn | null,
1308+
namespace?: string) {
1309+
ngDevMode && assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.');
1310+
ngDevMode && validateAgainstEventAttributes(name);
1311+
const element = getNativeByIndex(index, lView) as RElement;
1312+
const renderer = lView[RENDERER];
1313+
if (value == null) {
1314+
ngDevMode && ngDevMode.rendererRemoveAttribute++;
1315+
isProceduralRenderer(renderer) ? renderer.removeAttribute(element, name, namespace) :
1316+
element.removeAttribute(name);
1317+
} else {
1318+
ngDevMode && ngDevMode.rendererSetAttribute++;
1319+
const tNode = getTNode(index, lView);
1320+
const strValue =
1321+
sanitizer == null ? renderStringify(value) : sanitizer(value, tNode.tagName || '', name);
1322+
1323+
1324+
if (isProceduralRenderer(renderer)) {
1325+
renderer.setAttribute(element, name, strValue, namespace);
1326+
} else {
1327+
namespace ? element.setAttributeNS(namespace, name, strValue) :
1328+
element.setAttribute(name, strValue);
1329+
}
1330+
}
1331+
}
1332+
13061333
/**
13071334
* Sets initial input properties on directive instances from attribute data
13081335
*

packages/core/src/render3/jit/environment.ts

-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ export const angularCoreEnv: {[name: string]: Function} =
4646
'ɵɵNgOnChangesFeature': r3.ɵɵNgOnChangesFeature,
4747
'ɵɵProvidersFeature': r3.ɵɵProvidersFeature,
4848
'ɵɵInheritDefinitionFeature': r3.ɵɵInheritDefinitionFeature,
49-
'ɵɵelementAttribute': r3.ɵɵelementAttribute,
5049
'ɵɵbind': r3.ɵɵbind,
5150
'ɵɵcontainer': r3.ɵɵcontainer,
5251
'ɵɵnextContext': r3.ɵɵnextContext,

0 commit comments

Comments
 (0)