Skip to content

Commit f422bfd

Browse files
mohd-akramjaylinski
authored andcommitted
Improve rendering performance
Avoid unnecessary copies via Utils.extend in hot paths.
1 parent 25c696b commit f422bfd

File tree

4 files changed

+31
-47
lines changed

4 files changed

+31
-47
lines changed

lib/handlebars/helpers.js

+2-1
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

-11
This file was deleted.

lib/handlebars/internal/proto-access.js

+15-17
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

+14-18
Original file line numberDiff line numberDiff line change
@@ -71,25 +71,18 @@ export function template(templateSpec, env) {
7171
}
7272
partial = env.VM.resolvePartial.call(this, partial, context, options);
7373

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

8679
if (result == null && env.compile) {
8780
options.partials[options.name] = env.compile(
8881
partial,
8982
templateSpec.compilerOptions,
9083
env
9184
);
92-
result = options.partials[options.name](context, extendedOptions);
85+
result = options.partials[options.name](context, options);
9386
}
9487
if (result != null) {
9588
if (options.indent) {
@@ -255,8 +248,9 @@ export function template(templateSpec, env) {
255248

256249
function _setup(options) {
257250
if (!options.partial) {
258-
let mergedHelpers = Utils.extend({}, env.helpers, options.helpers);
259-
wrapHelpersToPassLookupProperty(mergedHelpers, container);
251+
let mergedHelpers = {};
252+
addHelpers(mergedHelpers, env.helpers, container);
253+
addHelpers(mergedHelpers, options.helpers, container);
260254
container.helpers = mergedHelpers;
261255

262256
if (templateSpec.usePartial) {
@@ -417,16 +411,18 @@ function executeDecorators(fn, prog, container, depths, data, blockParams) {
417411
return prog;
418412
}
419413

420-
function wrapHelpersToPassLookupProperty(mergedHelpers, container) {
421-
Object.keys(mergedHelpers).forEach((helperName) => {
422-
let helper = mergedHelpers[helperName];
414+
function addHelpers(mergedHelpers, helpers, container) {
415+
if (!helpers) return;
416+
Object.keys(helpers).forEach((helperName) => {
417+
let helper = helpers[helperName];
423418
mergedHelpers[helperName] = passLookupPropertyOption(helper, container);
424419
});
425420
}
426421

427422
function passLookupPropertyOption(helper, container) {
428423
const lookupProperty = container.lookupProperty;
429424
return wrapHelper(helper, (options) => {
430-
return Utils.extend({ lookupProperty }, options);
425+
options.lookupProperty = lookupProperty;
426+
return options;
431427
});
432428
}

0 commit comments

Comments
 (0)