Skip to content

Commit b9b1686

Browse files
committed
30e6760 fix(core): Fix a bug where snapshotted functions are being run twice if they return a nullish/falsey value. (#59073)
1 parent a7722c5 commit b9b1686

File tree

5 files changed

+121
-20
lines changed

5 files changed

+121
-20
lines changed

BUILD_INFO

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
Fri Dec 6 00:10:04 UTC 2024
2-
f15ccb94b9737741e66f00af32f282a29b06f7a0
1+
Fri Dec 6 00:24:15 UTC 2024
2+
30e676098d72e9e11a6628b9716668df08f18c62

fesm2022/compiler.mjs

Lines changed: 109 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @license Angular v19.1.0-next.2+sha-f15ccb9
2+
* @license Angular v19.1.0-next.2+sha-30e6760
33
* (c) 2010-2024 Google LLC. https://angular.io/
44
* License: MIT
55
*/
@@ -3014,6 +3014,10 @@ class Identifiers {
30143014
static declareLet = { name: 'ɵɵdeclareLet', moduleName: CORE };
30153015
static storeLet = { name: 'ɵɵstoreLet', moduleName: CORE };
30163016
static readContextLet = { name: 'ɵɵreadContextLet', moduleName: CORE };
3017+
static attachSourceLocations = {
3018+
name: 'ɵɵattachSourceLocations',
3019+
moduleName: CORE,
3020+
};
30173021
static NgOnChangesFeature = { name: 'ɵɵNgOnChangesFeature', moduleName: CORE };
30183022
static InheritDefinitionFeature = {
30193023
name: 'ɵɵInheritDefinitionFeature',
@@ -8937,6 +8941,10 @@ var OpKind;
89378941
* A creation op that corresponds to i18n attributes on an element.
89388942
*/
89398943
OpKind[OpKind["I18nAttributes"] = 49] = "I18nAttributes";
8944+
/**
8945+
* Creation op that attaches the location at which an element was defined in a template to it.
8946+
*/
8947+
OpKind[OpKind["SourceLocation"] = 50] = "SourceLocation";
89408948
})(OpKind || (OpKind = {}));
89418949
/**
89428950
* Distinguishes different kinds of IR expressions.
@@ -10478,6 +10486,7 @@ function transformExpressionsInOp(op, transform, flags) {
1047810486
case OpKind.I18nAttributes:
1047910487
case OpKind.IcuPlaceholder:
1048010488
case OpKind.DeclareLet:
10489+
case OpKind.SourceLocation:
1048110490
// These operations contain no expressions.
1048210491
break;
1048310492
default:
@@ -11269,6 +11278,15 @@ function createI18nAttributesOp(xref, handle, target) {
1126911278
...TRAIT_CONSUMES_SLOT,
1127011279
};
1127111280
}
11281+
/** Create a `SourceLocationOp`. */
11282+
function createSourceLocationOp(templatePath, locations) {
11283+
return {
11284+
kind: OpKind.SourceLocation,
11285+
templatePath,
11286+
locations,
11287+
...NEW_OP,
11288+
};
11289+
}
1127211290

1127311291
function createHostPropertyOp(name, expression, isAnimationTrigger, i18nContext, securityContext, sourceSpan) {
1127411292
return {
@@ -11331,12 +11349,16 @@ class ComponentCompilationJob extends CompilationJob {
1133111349
i18nUseExternalIds;
1133211350
deferMeta;
1133311351
allDeferrableDepsFn;
11334-
constructor(componentName, pool, compatibility, relativeContextFilePath, i18nUseExternalIds, deferMeta, allDeferrableDepsFn) {
11352+
relativeTemplatePath;
11353+
enableDebugLocations;
11354+
constructor(componentName, pool, compatibility, relativeContextFilePath, i18nUseExternalIds, deferMeta, allDeferrableDepsFn, relativeTemplatePath, enableDebugLocations) {
1133511355
super(componentName, pool, compatibility);
1133611356
this.relativeContextFilePath = relativeContextFilePath;
1133711357
this.i18nUseExternalIds = i18nUseExternalIds;
1133811358
this.deferMeta = deferMeta;
1133911359
this.allDeferrableDepsFn = allDeferrableDepsFn;
11360+
this.relativeTemplatePath = relativeTemplatePath;
11361+
this.enableDebugLocations = enableDebugLocations;
1134011362
this.root = new ViewCompilationUnit(this, this.allocateXrefId(), null);
1134111363
this.views.set(this.root.xref, this.root);
1134211364
}
@@ -22840,6 +22862,9 @@ function syntheticHostProperty(name, expression, sourceSpan) {
2284022862
function pureFunction(varOffset, fn, args) {
2284122863
return callVariadicInstructionExpr(PURE_FUNCTION_CONFIG, [literal(varOffset), fn], args, [], null);
2284222864
}
22865+
function attachSourceLocation(templatePath, locations) {
22866+
return call(Identifiers.attachSourceLocations, [literal(templatePath), locations], null);
22867+
}
2284322868
/**
2284422869
* Collates the string an expression arguments for an interpolation instruction.
2284522870
*/
@@ -23279,6 +23304,20 @@ function reifyCreateOperations(unit, ops) {
2327923304
}
2328023305
OpList.replace(op, repeaterCreate(op.handle.slot, repeaterView.fnName, op.decls, op.vars, op.tag, op.attributes, op.trackByFn, op.usesComponentInstance, emptyViewFnName, emptyDecls, emptyVars, op.emptyTag, op.emptyAttributes, op.wholeSourceSpan));
2328123306
break;
23307+
case OpKind.SourceLocation:
23308+
const locationsLiteral = literalArr(op.locations.map(({ targetSlot, offset, line, column }) => {
23309+
if (targetSlot.slot === null) {
23310+
throw new Error('No slot was assigned for source location');
23311+
}
23312+
return literalArr([
23313+
literal(targetSlot.slot),
23314+
literal(offset),
23315+
literal(line),
23316+
literal(column),
23317+
]);
23318+
}));
23319+
OpList.replace(op, attachSourceLocation(op.templatePath, locationsLiteral));
23320+
break;
2328223321
case OpKind.Statement:
2328323322
// Pass statement operations directly through.
2328423323
break;
@@ -25238,6 +25277,33 @@ function generateLocalLetReferences(job) {
2523825277
}
2523925278
}
2524025279

25280+
/**
25281+
* Locates all of the elements defined in a creation block and outputs an op
25282+
* that will expose their definition location in the DOM.
25283+
*/
25284+
function attachSourceLocations(job) {
25285+
if (!job.enableDebugLocations || job.relativeTemplatePath === null) {
25286+
return;
25287+
}
25288+
for (const unit of job.units) {
25289+
const locations = [];
25290+
for (const op of unit.create) {
25291+
if (op.kind === OpKind.ElementStart || op.kind === OpKind.Element) {
25292+
const start = op.startSourceSpan.start;
25293+
locations.push({
25294+
targetSlot: op.handle,
25295+
offset: start.offset,
25296+
line: start.line,
25297+
column: start.col,
25298+
});
25299+
}
25300+
}
25301+
if (locations.length > 0) {
25302+
unit.create.push(createSourceLocationOp(job.relativeTemplatePath, locations));
25303+
}
25304+
}
25305+
}
25306+
2524125307
/**
2524225308
*
2524325309
* @license
@@ -25307,6 +25373,7 @@ const phases = [
2530725373
{ kind: CompilationJobKind.Tmpl, fn: mergeNextContextExpressions },
2530825374
{ kind: CompilationJobKind.Tmpl, fn: generateNgContainerOps },
2530925375
{ kind: CompilationJobKind.Tmpl, fn: collapseEmptyInstructions },
25376+
{ kind: CompilationJobKind.Tmpl, fn: attachSourceLocations },
2531025377
{ kind: CompilationJobKind.Tmpl, fn: disableBindings$1 },
2531125378
{ kind: CompilationJobKind.Both, fn: extractPureFunctions },
2531225379
{ kind: CompilationJobKind.Both, fn: reify },
@@ -25425,8 +25492,8 @@ function isSingleI18nIcu(meta) {
2542525492
* representation.
2542625493
* TODO: Refactor more of the ingestion code into phases.
2542725494
*/
25428-
function ingestComponent(componentName, template, constantPool, relativeContextFilePath, i18nUseExternalIds, deferMeta, allDeferrableDepsFn) {
25429-
const job = new ComponentCompilationJob(componentName, constantPool, compatibilityMode, relativeContextFilePath, i18nUseExternalIds, deferMeta, allDeferrableDepsFn);
25495+
function ingestComponent(componentName, template, constantPool, relativeContextFilePath, i18nUseExternalIds, deferMeta, allDeferrableDepsFn, relativeTemplatePath, enableDebugLocations) {
25496+
const job = new ComponentCompilationJob(componentName, constantPool, compatibilityMode, relativeContextFilePath, i18nUseExternalIds, deferMeta, allDeferrableDepsFn, relativeTemplatePath, enableDebugLocations);
2543025497
ingestNodes(job.root, template);
2543125498
return job;
2543225499
}
@@ -26450,6 +26517,32 @@ function ingestControlFlowInsertionPoint(unit, xref, node) {
2645026517
return null;
2645126518
}
2645226519

26520+
/*!
26521+
* @license
26522+
* Copyright Google LLC All Rights Reserved.
26523+
*
26524+
* Use of this source code is governed by an MIT-style license that can be
26525+
* found in the LICENSE file at https://angular.dev/license
26526+
*/
26527+
/**
26528+
* Whether to produce instructions that will attach the source location to each DOM node.
26529+
*
26530+
* !!!Important!!! at the time of writing this flag isn't exposed externally, but internal debug
26531+
* tools enable it via a local change. Any modifications to this flag need to update the
26532+
* internal tooling as well.
26533+
*/
26534+
let ENABLE_TEMPLATE_SOURCE_LOCATIONS = false;
26535+
/**
26536+
* Utility function to enable source locations. Intended to be used **only** inside unit tests.
26537+
*/
26538+
function setEnableTemplateSourceLocations(value) {
26539+
ENABLE_TEMPLATE_SOURCE_LOCATIONS = value;
26540+
}
26541+
/** Gets whether template source locations are enabled. */
26542+
function getTemplateSourceLocationsEnabled() {
26543+
return ENABLE_TEMPLATE_SOURCE_LOCATIONS;
26544+
}
26545+
2645326546
// if (rf & flags) { .. }
2645426547
function renderFlagCheckIfStmt(flags, statements) {
2645526548
return ifStmt(variable(RENDER_FLAGS).bitwiseAnd(literal(flags), null, false), statements);
@@ -28893,7 +28986,7 @@ function compileComponentFromMetadata(meta, constantPool, bindingParser) {
2889328986
allDeferrableDepsFn = variable(fnName);
2889428987
}
2889528988
// First the template is ingested into IR:
28896-
const tpl = ingestComponent(meta.name, meta.template.nodes, constantPool, meta.relativeContextFilePath, meta.i18nUseExternalIds, meta.defer, allDeferrableDepsFn);
28989+
const tpl = ingestComponent(meta.name, meta.template.nodes, constantPool, meta.relativeContextFilePath, meta.i18nUseExternalIds, meta.defer, allDeferrableDepsFn, meta.relativeTemplatePath, getTemplateSourceLocationsEnabled());
2889728990
// Then the IR is transformed to prepare it for cod egeneration.
2889828991
transform(tpl, CompilationJobKind.Tmpl);
2889928992
// Finally we emit the template function:
@@ -30353,6 +30446,7 @@ class CompilerFacadeImpl {
3035330446
viewProviders: facade.viewProviders != null ? new WrappedNodeExpr(facade.viewProviders) : null,
3035430447
relativeContextFilePath: '',
3035530448
i18nUseExternalIds: true,
30449+
relativeTemplatePath: null,
3035630450
};
3035730451
const jitExpressionSourceMap = `ng:///${facade.name}.js`;
3035830452
return this.compileComponentFromMeta(angularCoreEnv, jitExpressionSourceMap, meta);
@@ -30608,6 +30702,7 @@ function convertDeclareComponentFacadeToMetadata(decl, typeSourceSpan, sourceMap
3060830702
declarationListEmitMode: 2 /* DeclarationListEmitMode.ClosureResolved */,
3060930703
relativeContextFilePath: '',
3061030704
i18nUseExternalIds: true,
30705+
relativeTemplatePath: null,
3061130706
};
3061230707
}
3061330708
function convertDeclarationFacadeToMetadata(declaration) {
@@ -30883,7 +30978,7 @@ function publishFacade(global) {
3088330978
* @description
3088430979
* Entry point for all public APIs of the compiler package.
3088530980
*/
30886-
const VERSION = new Version('19.1.0-next.2+sha-f15ccb9');
30981+
const VERSION = new Version('19.1.0-next.2+sha-30e6760');
3088730982

3088830983
class CompilerConfig {
3088930984
defaultEncapsulation;
@@ -32735,7 +32830,7 @@ const MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION = '18.0.0';
3273532830
function compileDeclareClassMetadata(metadata) {
3273632831
const definitionMap = new DefinitionMap();
3273732832
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
32738-
definitionMap.set('version', literal('19.1.0-next.2+sha-f15ccb9'));
32833+
definitionMap.set('version', literal('19.1.0-next.2+sha-30e6760'));
3273932834
definitionMap.set('ngImport', importExpr(Identifiers.core));
3274032835
definitionMap.set('type', metadata.type);
3274132836
definitionMap.set('decorators', metadata.decorators);
@@ -32753,7 +32848,7 @@ function compileComponentDeclareClassMetadata(metadata, dependencies) {
3275332848
callbackReturnDefinitionMap.set('ctorParameters', metadata.ctorParameters ?? literal(null));
3275432849
callbackReturnDefinitionMap.set('propDecorators', metadata.propDecorators ?? literal(null));
3275532850
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_DEFER_SUPPORT_VERSION));
32756-
definitionMap.set('version', literal('19.1.0-next.2+sha-f15ccb9'));
32851+
definitionMap.set('version', literal('19.1.0-next.2+sha-30e6760'));
3275732852
definitionMap.set('ngImport', importExpr(Identifiers.core));
3275832853
definitionMap.set('type', metadata.type);
3275932854
definitionMap.set('resolveDeferredDeps', compileComponentMetadataAsyncResolver(dependencies));
@@ -32848,7 +32943,7 @@ function createDirectiveDefinitionMap(meta) {
3284832943
const definitionMap = new DefinitionMap();
3284932944
const minVersion = getMinimumVersionForPartialOutput(meta);
3285032945
definitionMap.set('minVersion', literal(minVersion));
32851-
definitionMap.set('version', literal('19.1.0-next.2+sha-f15ccb9'));
32946+
definitionMap.set('version', literal('19.1.0-next.2+sha-30e6760'));
3285232947
// e.g. `type: MyDirective`
3285332948
definitionMap.set('type', meta.type.value);
3285432949
if (meta.isStandalone !== undefined) {
@@ -33267,7 +33362,7 @@ const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
3326733362
function compileDeclareFactoryFunction(meta) {
3326833363
const definitionMap = new DefinitionMap();
3326933364
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
33270-
definitionMap.set('version', literal('19.1.0-next.2+sha-f15ccb9'));
33365+
definitionMap.set('version', literal('19.1.0-next.2+sha-30e6760'));
3327133366
definitionMap.set('ngImport', importExpr(Identifiers.core));
3327233367
definitionMap.set('type', meta.type.value);
3327333368
definitionMap.set('deps', compileDependencies(meta.deps));
@@ -33302,7 +33397,7 @@ function compileDeclareInjectableFromMetadata(meta) {
3330233397
function createInjectableDefinitionMap(meta) {
3330333398
const definitionMap = new DefinitionMap();
3330433399
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
33305-
definitionMap.set('version', literal('19.1.0-next.2+sha-f15ccb9'));
33400+
definitionMap.set('version', literal('19.1.0-next.2+sha-30e6760'));
3330633401
definitionMap.set('ngImport', importExpr(Identifiers.core));
3330733402
definitionMap.set('type', meta.type.value);
3330833403
// Only generate providedIn property if it has a non-null value
@@ -33353,7 +33448,7 @@ function compileDeclareInjectorFromMetadata(meta) {
3335333448
function createInjectorDefinitionMap(meta) {
3335433449
const definitionMap = new DefinitionMap();
3335533450
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
33356-
definitionMap.set('version', literal('19.1.0-next.2+sha-f15ccb9'));
33451+
definitionMap.set('version', literal('19.1.0-next.2+sha-30e6760'));
3335733452
definitionMap.set('ngImport', importExpr(Identifiers.core));
3335833453
definitionMap.set('type', meta.type.value);
3335933454
definitionMap.set('providers', meta.providers);
@@ -33386,7 +33481,7 @@ function createNgModuleDefinitionMap(meta) {
3338633481
throw new Error('Invalid path! Local compilation mode should not get into the partial compilation path');
3338733482
}
3338833483
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
33389-
definitionMap.set('version', literal('19.1.0-next.2+sha-f15ccb9'));
33484+
definitionMap.set('version', literal('19.1.0-next.2+sha-30e6760'));
3339033485
definitionMap.set('ngImport', importExpr(Identifiers.core));
3339133486
definitionMap.set('type', meta.type.value);
3339233487
// We only generate the keys in the metadata if the arrays contain values.
@@ -33437,7 +33532,7 @@ function compileDeclarePipeFromMetadata(meta) {
3343733532
function createPipeDefinitionMap(meta) {
3343833533
const definitionMap = new DefinitionMap();
3343933534
definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
33440-
definitionMap.set('version', literal('19.1.0-next.2+sha-f15ccb9'));
33535+
definitionMap.set('version', literal('19.1.0-next.2+sha-30e6760'));
3344133536
definitionMap.set('ngImport', importExpr(Identifiers.core));
3344233537
// e.g. `type: MyPipe`
3344333538
definitionMap.set('type', meta.type.value);

fesm2022/compiler.mjs.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.d.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @license Angular v19.1.0-next.2+sha-f15ccb9
2+
* @license Angular v19.1.0-next.2+sha-30e6760
33
* (c) 2010-2024 Google LLC. https://angular.io/
44
* License: MIT
55
*/
@@ -2974,6 +2974,11 @@ export declare interface R3ComponentMetadata<DeclarationT extends R3TemplateDepe
29742974
* expression as appears in the decorator.
29752975
*/
29762976
changeDetection: ChangeDetectionStrategy | outputAst.Expression | null;
2977+
/**
2978+
* Relative path to the component's template from the root of the project.
2979+
* Used to generate debugging information.
2980+
*/
2981+
relativeTemplatePath: string | null;
29772982
/**
29782983
* The imports expression as appears on the component decorate for standalone component. This
29792984
* field is currently needed only for local compilation, and so in other compilation modes it may
@@ -4012,6 +4017,7 @@ export declare class R3Identifiers {
40124017
static declareLet: outputAst.ExternalReference;
40134018
static storeLet: outputAst.ExternalReference;
40144019
static readContextLet: outputAst.ExternalReference;
4020+
static attachSourceLocations: outputAst.ExternalReference;
40154021
static NgOnChangesFeature: outputAst.ExternalReference;
40164022
static InheritDefinitionFeature: outputAst.ExternalReference;
40174023
static CopyDefinitionFeature: outputAst.ExternalReference;

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@angular/compiler",
3-
"version": "19.1.0-next.2+sha-f15ccb9",
3+
"version": "19.1.0-next.2+sha-30e6760",
44
"description": "Angular - the compiler library",
55
"author": "angular",
66
"license": "MIT",
@@ -11,7 +11,7 @@
1111
"tslib": "^2.3.0"
1212
},
1313
"peerDependencies": {
14-
"@angular/core": "19.1.0-next.2+sha-f15ccb9"
14+
"@angular/core": "19.1.0-next.2+sha-30e6760"
1515
},
1616
"peerDependenciesMeta": {
1717
"@angular/core": {

0 commit comments

Comments
 (0)