Skip to content

Commit

Permalink
fix(core): guard usages of performance.mark (angular#52505)
Browse files Browse the repository at this point in the history
While `performance.mark` is available on all supported browsers and node.js version this API is not available in JSDOM which is used by Jest and Cloudflare worker.

This commit, updates the usage to a safer variant.

PR Close angular#52505
  • Loading branch information
alan-agius4 authored and Abseil-byte committed Nov 5, 2023
1 parent a54634b commit 3c939ce
Show file tree
Hide file tree
Showing 11 changed files with 48 additions and 11 deletions.
4 changes: 2 additions & 2 deletions packages/common/http/src/transfer_cache.ts
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {APP_BOOTSTRAP_LISTENER, ApplicationRef, inject, InjectionToken, makeStateKey, Provider, StateKey, TransferState, ɵformatRuntimeError as formatRuntimeError, ɵtruncateMiddle as truncateMiddle, ɵwhenStable as whenStable} from '@angular/core';
import {APP_BOOTSTRAP_LISTENER, ApplicationRef, inject, InjectionToken, makeStateKey, Provider, StateKey, TransferState, ɵformatRuntimeError as formatRuntimeError, ɵperformanceMark as performanceMark, ɵtruncateMiddle as truncateMiddle, ɵwhenStable as whenStable} from '@angular/core';
import {Observable, of} from 'rxjs';
import {tap} from 'rxjs/operators';

Expand Down Expand Up @@ -227,7 +227,7 @@ export function withHttpTransferCache(cacheOptions: HttpTransferCacheOptions): P
{
provide: CACHE_OPTIONS,
useFactory: (): CacheOptions => {
performance.mark('mark_use_counter', {detail: {feature: 'NgHttpTransferCache'}});
performanceMark('mark_use_counter', {detail: {feature: 'NgHttpTransferCache'}});
return {isCacheActive: true, ...cacheOptions};
}
},
Expand Down
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {booleanAttribute, Directive, ElementRef, inject, Injector, Input, NgZone, numberAttribute, OnChanges, OnDestroy, OnInit, PLATFORM_ID, Renderer2, SimpleChanges, ɵformatRuntimeError as formatRuntimeError, ɵIMAGE_CONFIG as IMAGE_CONFIG, ɵIMAGE_CONFIG_DEFAULTS as IMAGE_CONFIG_DEFAULTS, ɵImageConfig as ImageConfig, ɵRuntimeError as RuntimeError, ɵSafeValue as SafeValue, ɵunwrapSafeValue as unwrapSafeValue} from '@angular/core';
import {booleanAttribute, Directive, ElementRef, inject, Injector, Input, NgZone, numberAttribute, OnChanges, OnDestroy, OnInit, PLATFORM_ID, Renderer2, SimpleChanges, ɵformatRuntimeError as formatRuntimeError, ɵIMAGE_CONFIG as IMAGE_CONFIG, ɵIMAGE_CONFIG_DEFAULTS as IMAGE_CONFIG_DEFAULTS, ɵImageConfig as ImageConfig, ɵperformanceMark as performanceMark, ɵRuntimeError as RuntimeError, ɵSafeValue as SafeValue, ɵunwrapSafeValue as unwrapSafeValue} from '@angular/core';

import {RuntimeErrorCode} from '../../errors';
import {isPlatformServer} from '../../platform_id';
Expand Down Expand Up @@ -302,7 +302,7 @@ export class NgOptimizedImage implements OnInit, OnChanges, OnDestroy {

/** @nodoc */
ngOnInit() {
performance.mark('mark_use_counter', {'detail': {'feature': 'NgOptimizedImage'}});
performanceMark('mark_use_counter', {'detail': {'feature': 'NgOptimizedImage'}});

if (ngDevMode) {
const ngZone = this.injector.get(NgZone);
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/core_private_export.ts
Expand Up @@ -41,5 +41,6 @@ export {booleanAttribute, numberAttribute} from './util/coercion';
export {devModeEqual as ɵdevModeEqual} from './util/comparison';
export {global as ɵglobal} from './util/global';
export {isPromise as ɵisPromise, isSubscribable as ɵisSubscribable} from './util/lang';
export {performanceMark as ɵperformanceMark} from './util/performance';
export {stringify as ɵstringify, truncateMiddle as ɵtruncateMiddle} from './util/stringify';
export {NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR} from './view/provider_flags';
3 changes: 2 additions & 1 deletion packages/core/src/defer/instructions.ts
Expand Up @@ -29,6 +29,7 @@ import {isPlatformBrowser} from '../render3/util/misc_utils';
import {getConstant, getTNode, removeLViewOnDestroy, storeLViewOnDestroy} from '../render3/util/view_utils';
import {addLViewToLContainer, createAndRenderEmbeddedLView, removeLViewFromLContainer, shouldAddViewToDom} from '../render3/view_manipulation';
import {assertDefined, throwError} from '../util/assert';
import {performanceMark} from '../util/performance';

import {invokeAllTriggerCleanupFns, invokeTriggerCleanupFns, storeTriggerCleanupFn} from './cleanup';
import {onHover, onInteraction, onViewport, registerDomTrigger} from './dom_triggers';
Expand Down Expand Up @@ -129,7 +130,7 @@ export function ɵɵdefer(
ɵɵtemplate(index, null, 0, 0);

if (tView.firstCreatePass) {
performance.mark('mark_use_counter', {detail: {feature: 'NgDefer'}});
performanceMark('mark_use_counter', {detail: {feature: 'NgDefer'}});

const tDetails: TDeferBlockDetails = {
primaryTmplIndex,
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/hydration/api.ts
Expand Up @@ -20,6 +20,7 @@ import {enableLocateOrCreateTextNodeImpl} from '../render3/instructions/text';
import {getDocument} from '../render3/interfaces/document';
import {isPlatformBrowser} from '../render3/util/misc_utils';
import {TransferState} from '../transfer_state';
import {performanceMark} from '../util/performance';
import {NgZone} from '../zone';

import {cleanupDehydratedViews} from './cleanup';
Expand Down Expand Up @@ -136,7 +137,7 @@ export function withDomHydration(): EnvironmentProviders {
}
}
if (isEnabled) {
performance.mark('mark_use_counter', {detail: {feature: 'NgHydration'}});
performanceMark('mark_use_counter', {detail: {feature: 'NgHydration'}});
}
return isEnabled;
},
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/render3/after_render_hooks.ts
Expand Up @@ -13,6 +13,7 @@ import {ErrorHandler} from '../error_handler';
import {RuntimeError, RuntimeErrorCode} from '../errors';
import {DestroyRef} from '../linker/destroy_ref';
import {assertGreaterThan} from '../util/assert';
import {performanceMark} from '../util/performance';
import {NgZone} from '../zone';

import {isPlatformBrowser} from './util/misc_utils';
Expand Down Expand Up @@ -224,7 +225,7 @@ export function afterRender(callback: VoidFunction, options?: AfterRenderOptions
return NOOP_AFTER_RENDER_REF;
}

performance.mark('mark_use_counter', {detail: {feature: 'NgAfterRender'}});
performanceMark('mark_use_counter', {detail: {feature: 'NgAfterRender'}});

const afterRenderEventManager = injector.get(AfterRenderEventManager);
// Lazily initialize the handler implementation, if necessary. This is so that it can be
Expand Down Expand Up @@ -300,7 +301,7 @@ export function afterNextRender(
return NOOP_AFTER_RENDER_REF;
}

performance.mark('mark_use_counter', {detail: {feature: 'NgAfterNextRender'}});
performanceMark('mark_use_counter', {detail: {feature: 'NgAfterNextRender'}});

const afterRenderEventManager = injector.get(AfterRenderEventManager);
// Lazily initialize the handler implementation, if necessary. This is so that it can be
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/render3/features/standalone_feature.ts
Expand Up @@ -10,6 +10,7 @@ import {ɵɵdefineInjectable as defineInjectable} from '../../di/interface/defs'
import {internalImportProvidersFrom} from '../../di/provider_collection';
import {EnvironmentInjector} from '../../di/r3_injector';
import {OnDestroy} from '../../interface/lifecycle_hooks';
import {performanceMark} from '../../util/performance';
import {ComponentDef} from '../interfaces/definition';
import {createEnvironmentInjector} from '../ng_module_ref';

Expand Down Expand Up @@ -75,7 +76,7 @@ const PERF_MARK_STANDALONE = {
* @codeGenApi
*/
export function ɵɵStandaloneFeature(definition: ComponentDef<unknown>) {
performance.mark('mark_use_counter', PERF_MARK_STANDALONE);
performanceMark('mark_use_counter', PERF_MARK_STANDALONE);
definition.getStandaloneInjector = (parentInjector: EnvironmentInjector) => {
return parentInjector.get(StandaloneService).getOrCreateStandaloneInjector(definition);
};
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/render3/instructions/control_flow.ts
Expand Up @@ -12,6 +12,7 @@ import {TrackByFunction} from '../../change_detection';
import {DehydratedContainerView} from '../../hydration/interfaces';
import {findMatchingDehydratedView} from '../../hydration/views';
import {assertDefined} from '../../util/assert';
import {performanceMark} from '../../util/performance';
import {assertLContainer, assertLView, assertTNode} from '../assert';
import {bindingUpdated} from '../bindings';
import {CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/container';
Expand Down Expand Up @@ -42,7 +43,7 @@ const PERF_MARK_CONTROL_FLOW = {
* @codeGenApi
*/
export function ɵɵconditional<T>(containerIndex: number, matchingTemplateIndex: number, value?: T) {
performance.mark('mark_use_counter', PERF_MARK_CONTROL_FLOW);
performanceMark('mark_use_counter', PERF_MARK_CONTROL_FLOW);

const hostLView = getLView();
const bindingIndex = nextBindingIndex();
Expand Down Expand Up @@ -148,7 +149,7 @@ export function ɵɵrepeaterCreate(
tagName: string|null, attrsIndex: number|null, trackByFn: TrackByFunction<unknown>,
trackByUsesComponentInstance?: boolean, emptyTemplateFn?: ComponentTemplate<unknown>,
emptyDecls?: number, emptyVars?: number): void {
performance.mark('mark_use_counter', PERF_MARK_CONTROL_FLOW);
performanceMark('mark_use_counter', PERF_MARK_CONTROL_FLOW);
const hasEmptyBlock = emptyTemplateFn !== undefined;
const hostLView = getLView();
const boundTrackBy = trackByUsesComponentInstance ?
Expand Down
22 changes: 22 additions & 0 deletions packages/core/src/util/performance.ts
@@ -0,0 +1,22 @@
/**
* @license
* Copyright Google LLC 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
*/

// tslint:disable:no-performance
/**
* A guarded `performance.mark`.
*
* This method exists because while all supported browser and node.js version supported by Angular
* support performance.mark API. This is not the case for other environments such as JSDOM and
* Cloudflare workers.
*/
export function performanceMark(
markName: string,
markOptions?: PerformanceMarkOptions|undefined,
): PerformanceMark|undefined {
return performance?.mark?.(markName, markOptions);
}
6 changes: 6 additions & 0 deletions packages/core/test/bundling/defer/bundle.golden_symbols.json
Expand Up @@ -1685,6 +1685,9 @@
{
"name": "init_partial"
},
{
"name": "init_performance"
},
{
"name": "init_pipe"
},
Expand Down Expand Up @@ -2204,6 +2207,9 @@
{
"name": "onLeave"
},
{
"name": "performanceMark"
},
{
"name": "populateDehydratedViewsInLContainer"
},
Expand Down
Expand Up @@ -1178,6 +1178,9 @@
{
"name": "onLeave"
},
{
"name": "performanceMark"
},
{
"name": "populateDehydratedViewsInLContainerImpl"
},
Expand Down

0 comments on commit 3c939ce

Please sign in to comment.