Skip to content

Commit 29f1898

Browse files
author
Robert Jackson
committed
[BUGFIX release] Avoid re-freezing already frozen objects.
When a helper is invoked we pass in the arguments, those arguments are frozen (via Object.freeze) so that helpers can't mutate them (and cause issues in the rendering engine itself). When a helper doesn't have hash arguments, we use a shared `EMPTY_HASH` empty object to avoid allocating a bunch of empty objects for no reason (we do roughly the same thing when no positional params are passed). Since these objects are shared they are being frozen over and over again (throughout the lifetime of the running application). Turns out that there is what we think is almost certainly a bug in Chrome, where re-freezing the same object many times starts taking significantly more time upon each freeze attempt. This change introduces a guard to ensure we do not re-freeze repeatedly. Thanks to @krisselden for identifying the root cause.
1 parent 5291c74 commit 29f1898

File tree

1 file changed

+19
-12
lines changed

1 file changed

+19
-12
lines changed

packages/ember-glimmer/lib/utils/references.js

+19-12
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ export const UPDATE = symbol('UPDATE');
3838

3939
export { NULL_REFERENCE, UNDEFINED_REFERENCE } from '@glimmer/runtime';
4040

41+
let maybeFreeze = () => {};
42+
if (DEBUG) {
43+
maybeFreeze = (obj) => {
44+
// re-freezing an already frozen object introduces a significant
45+
// performance penalty on Chrome (tested through 59).
46+
//
47+
// See: https://bugs.chromium.org/p/v8/issues/detail?id=6450
48+
if (!Object.isFrozen(obj) && HAS_NATIVE_WEAKMAP) {
49+
Object.freeze(obj);
50+
}
51+
}
52+
}
53+
4154
// @abstract
4255
// @implements PathReference
4356
class EmberPathReference {
@@ -296,10 +309,8 @@ export class SimpleHelperReference extends CachedReference {
296309
let namedValue = named.value();
297310

298311
if (DEBUG) {
299-
if (HAS_NATIVE_WEAKMAP) {
300-
Object.freeze(positionalValue);
301-
Object.freeze(namedValue);
302-
}
312+
maybeFreeze(positionalValue);
313+
maybeFreeze(namedValue);
303314
}
304315

305316
let result = helper(positionalValue, namedValue);
@@ -333,10 +344,8 @@ export class SimpleHelperReference extends CachedReference {
333344
let namedValue = named.value();
334345

335346
if (DEBUG) {
336-
if (HAS_NATIVE_WEAKMAP) {
337-
Object.freeze(positionalValue);
338-
Object.freeze(namedValue);
339-
}
347+
maybeFreeze(positionalValue);
348+
maybeFreeze(namedValue);
340349
}
341350

342351
return helper(positionalValue, namedValue);
@@ -365,10 +374,8 @@ export class ClassBasedHelperReference extends CachedReference {
365374
let namedValue = named.value();
366375

367376
if (DEBUG) {
368-
if (HAS_NATIVE_WEAKMAP) {
369-
Object.freeze(positionalValue);
370-
Object.freeze(namedValue);
371-
}
377+
maybeFreeze(positionalValue);
378+
maybeFreeze(namedValue);
372379
}
373380

374381
return instance.compute(positionalValue, namedValue);

0 commit comments

Comments
 (0)