Skip to content

Commit e914d60

Browse files
mohd-akramjaylinski
authored andcommitted
Improve rendering performance
Avoid unnecessary copies via Utils.extend in hot paths.
1 parent 7de4b41 commit e914d60

File tree

4 files changed

+31
-47
lines changed

4 files changed

+31
-47
lines changed

lib/handlebars/helpers.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ export function moveHelperToHooks(instance, helperName, keepHelper) {
2020
if (instance.helpers[helperName]) {
2121
instance.hooks[helperName] = instance.helpers[helperName];
2222
if (!keepHelper) {
23-
delete instance.helpers[helperName];
23+
// Using delete is slow
24+
instance.helpers[helperName] = undefined;
2425
}
2526
}
2627
}

lib/handlebars/internal/create-new-lookup-object.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

lib/handlebars/internal/proto-access.js

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,30 @@
1-
import { createNewLookupObject } from './create-new-lookup-object';
1+
import { extend } from '../utils';
22
import logger from '../logger';
33

44
const loggedProperties = Object.create(null);
55

66
export function createProtoAccessControl(runtimeOptions) {
7-
let defaultMethodWhiteList = Object.create(null);
8-
defaultMethodWhiteList['constructor'] = false;
9-
defaultMethodWhiteList['__defineGetter__'] = false;
10-
defaultMethodWhiteList['__defineSetter__'] = false;
11-
defaultMethodWhiteList['__lookupGetter__'] = false;
12-
13-
let defaultPropertyWhiteList = Object.create(null);
7+
// Create an object with "null"-prototype to avoid truthy results on
8+
// prototype properties.
9+
const propertyWhiteList = Object.create(null);
1410
// eslint-disable-next-line no-proto
15-
defaultPropertyWhiteList['__proto__'] = false;
11+
propertyWhiteList['__proto__'] = false;
12+
extend(propertyWhiteList, runtimeOptions.allowedProtoProperties);
13+
14+
const methodWhiteList = Object.create(null);
15+
methodWhiteList['constructor'] = false;
16+
methodWhiteList['__defineGetter__'] = false;
17+
methodWhiteList['__defineSetter__'] = false;
18+
methodWhiteList['__lookupGetter__'] = false;
19+
extend(methodWhiteList, runtimeOptions.allowedProtoMethods);
1620

1721
return {
1822
properties: {
19-
whitelist: createNewLookupObject(
20-
defaultPropertyWhiteList,
21-
runtimeOptions.allowedProtoProperties
22-
),
23+
whitelist: propertyWhiteList,
2324
defaultValue: runtimeOptions.allowProtoPropertiesByDefault
2425
},
2526
methods: {
26-
whitelist: createNewLookupObject(
27-
defaultMethodWhiteList,
28-
runtimeOptions.allowedProtoMethods
29-
),
27+
whitelist: methodWhiteList,
3028
defaultValue: runtimeOptions.allowProtoMethodsByDefault
3129
}
3230
};

lib/handlebars/runtime.js

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,25 +74,18 @@ export function template(templateSpec, env) {
7474
}
7575
partial = env.VM.resolvePartial.call(this, partial, context, options);
7676

77-
let extendedOptions = Utils.extend({}, options, {
78-
hooks: this.hooks,
79-
protoAccessControl: this.protoAccessControl
80-
});
81-
82-
let result = env.VM.invokePartial.call(
83-
this,
84-
partial,
85-
context,
86-
extendedOptions
87-
);
77+
options.hooks = this.hooks;
78+
options.protoAccessControl = this.protoAccessControl;
79+
80+
let result = env.VM.invokePartial.call(this, partial, context, options);
8881

8982
if (result == null && env.compile) {
9083
options.partials[options.name] = env.compile(
9184
partial,
9285
templateSpec.compilerOptions,
9386
env
9487
);
95-
result = options.partials[options.name](context, extendedOptions);
88+
result = options.partials[options.name](context, options);
9689
}
9790
if (result != null) {
9891
if (options.indent) {
@@ -247,8 +240,9 @@ export function template(templateSpec, env) {
247240

248241
ret._setup = function(options) {
249242
if (!options.partial) {
250-
let mergedHelpers = Utils.extend({}, env.helpers, options.helpers);
251-
wrapHelpersToPassLookupProperty(mergedHelpers, container);
243+
let mergedHelpers = {};
244+
addHelpers(mergedHelpers, env.helpers, container);
245+
addHelpers(mergedHelpers, options.helpers, container);
252246
container.helpers = mergedHelpers;
253247

254248
if (templateSpec.usePartial) {
@@ -428,16 +422,18 @@ function executeDecorators(fn, prog, container, depths, data, blockParams) {
428422
return prog;
429423
}
430424

431-
function wrapHelpersToPassLookupProperty(mergedHelpers, container) {
432-
Object.keys(mergedHelpers).forEach(helperName => {
433-
let helper = mergedHelpers[helperName];
425+
function addHelpers(mergedHelpers, helpers, container) {
426+
if (!helpers) return;
427+
Object.keys(helpers).forEach(helperName => {
428+
let helper = helpers[helperName];
434429
mergedHelpers[helperName] = passLookupPropertyOption(helper, container);
435430
});
436431
}
437432

438433
function passLookupPropertyOption(helper, container) {
439434
const lookupProperty = container.lookupProperty;
440435
return wrapHelper(helper, options => {
441-
return Utils.extend({ lookupProperty }, options);
436+
options.lookupProperty = lookupProperty;
437+
return options;
442438
});
443439
}

0 commit comments

Comments
 (0)