From 668d2fab5e5edea49b87a0bca7bea2b06de34c42 Mon Sep 17 00:00:00 2001 From: Mohamed Akram Date: Fri, 6 Sep 2024 18:00:11 +0400 Subject: [PATCH] Simplify helper wrapper This improves performance slightly and gives the wrapper function a more descriptive name to help with debugging/profiling. --- lib/handlebars/helpers.js | 29 +++++++++++++++++++++++++++ lib/handlebars/internal/wrapHelper.js | 13 ------------ lib/handlebars/runtime.js | 24 ++-------------------- 3 files changed, 31 insertions(+), 35 deletions(-) delete mode 100644 lib/handlebars/internal/wrapHelper.js diff --git a/lib/handlebars/helpers.js b/lib/handlebars/helpers.js index 0a6e44024..ede74bac0 100644 --- a/lib/handlebars/helpers.js +++ b/lib/handlebars/helpers.js @@ -25,3 +25,32 @@ export function moveHelperToHooks(instance, helperName, keepHelper) { } } } + +export function mergeHelpers(env, options, container) { + const mergedHelpers = {}; + addHelpers(mergedHelpers, env.helpers, container); + addHelpers(mergedHelpers, options.helpers, container); + return mergedHelpers; +} + +function addHelpers(mergedHelpers, helpers, container) { + if (!helpers) return; + Object.keys(helpers).forEach(helperName => { + const helper = helpers[helperName]; + mergedHelpers[helperName] = passLookupPropertyOption(helper, container); + }); +} + +function passLookupPropertyOption(helper, container) { + if (typeof helper !== 'function') { + // This should not happen, but apparently it does in https://github.com/wycats/handlebars.js/issues/1639 + // We try to make the wrapper least-invasive by not wrapping it, if the helper is not a function. + return helper; + } + const lookupProperty = container.lookupProperty; + return function invokeHelper(/* dynamic arguments */) { + const options = arguments[arguments.length - 1]; + options.lookupProperty = lookupProperty; + return helper.apply(this, arguments); + }; +} diff --git a/lib/handlebars/internal/wrapHelper.js b/lib/handlebars/internal/wrapHelper.js deleted file mode 100644 index 29d65b033..000000000 --- a/lib/handlebars/internal/wrapHelper.js +++ /dev/null @@ -1,13 +0,0 @@ -export function wrapHelper(helper, transformOptionsFn) { - if (typeof helper !== 'function') { - // This should not happen, but apparently it does in https://github.com/wycats/handlebars.js/issues/1639 - // We try to make the wrapper least-invasive by not wrapping it, if the helper is not a function. - return helper; - } - let wrapper = function(/* dynamic arguments */) { - const options = arguments[arguments.length - 1]; - arguments[arguments.length - 1] = transformOptionsFn(options); - return helper.apply(this, arguments); - }; - return wrapper; -} diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js index e6b3f9c84..6ca114962 100644 --- a/lib/handlebars/runtime.js +++ b/lib/handlebars/runtime.js @@ -6,8 +6,7 @@ import { LAST_COMPATIBLE_COMPILER_REVISION, REVISION_CHANGES } from './base'; -import { moveHelperToHooks } from './helpers'; -import { wrapHelper } from './internal/wrapHelper'; +import { mergeHelpers, moveHelperToHooks } from './helpers'; import { createProtoAccessControl, resultIsAllowed @@ -240,10 +239,7 @@ export function template(templateSpec, env) { ret._setup = function(options) { if (!options.partial) { - let mergedHelpers = {}; - addHelpers(mergedHelpers, env.helpers, container); - addHelpers(mergedHelpers, options.helpers, container); - container.helpers = mergedHelpers; + container.helpers = mergeHelpers(env, options, container); if (templateSpec.usePartial) { // Use mergeIfNeeded here to prevent compiling global partials multiple times @@ -421,19 +417,3 @@ function executeDecorators(fn, prog, container, depths, data, blockParams) { } return prog; } - -function addHelpers(mergedHelpers, helpers, container) { - if (!helpers) return; - Object.keys(helpers).forEach(helperName => { - let helper = helpers[helperName]; - mergedHelpers[helperName] = passLookupPropertyOption(helper, container); - }); -} - -function passLookupPropertyOption(helper, container) { - const lookupProperty = container.lookupProperty; - return wrapHelper(helper, options => { - options.lookupProperty = lookupProperty; - return options; - }); -}