UNPKG

@openui5/sap.ui.core

Version:

OpenUI5 Core Library sap.ui.core

152 lines (137 loc) 6.56 kB
/*! * OpenUI5 * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ sap.ui.define(["sap/base/util/ObjectPath"], function(ObjectPath) { "use strict"; // indicator if the reference can't be resolved var oNotFound = Object.create(null); /** * Resolve the path segments under the given root context * * @param {array} aParts The path segments * @param {object} oRoot The root context * @param {object} [mOptions] Options * @param {boolean} [mOptions.bindContext] When the resolved value is a * function, whether the resolved function is bound to a context * @param {boolean} [mOptions.rootContext] When the resolved value is a * function and a rootContext is given, the resolved function is bound * to this context instead of the object to which it belongs. If * <code>mOptions.bindContext=false</code>, this option has no effect * @return {any} The resolved value. If the value can't be resolved under the * given root context, it returns <code>oNotFound</code>. */ function _resolve(aParts, oRoot, mOptions) { var vRef, oContext; if (oRoot && (aParts[0] in oRoot)) { // the path consists of at least two segments // e.g. key "Module.namespace.function" -> function() {...} oContext = aParts.length > 1 ? ObjectPath.get(aParts.slice(0, -1), oRoot) : oRoot; vRef = oContext && oContext[aParts[aParts.length - 1]]; if (typeof vRef === "function" && mOptions.bindContext) { vRef = vRef.bind(mOptions.rootContext || oContext); } return vRef; } return oNotFound; } /** * Returns a value located in the provided path using the given * <code>mVariables</code> object. * * If the provided path cannot be resolved completely, <code>undefined</code> is returned. * * How <code>mVariables</code> are checked for resolving the path depends on * the syntax of the path: * <ul> * <li><i>absolute</i>: paths not starting with a dot ('.') are checked through * <code>mVariables</code>.</li> * <li><i>relative</i>: paths starting with a dot ('.') are only checked through the * dot variable <code>mVariables["."]</code> and don't fallback to global scope * <code>window</code>.</li> * <li><i>legacy</i>: when <code>mOptions.preferDotContext=true</code>, paths not starting * with a dot ('.') are first checked through the dot Variable * <code>mVariables["."]</code> and then - if nothing is found - through the other * Variables in <code>mVariables</code> and eventually fallback to global scope * <code>window</code>.</li> * </ul> * * When the resolved value is a function, a context may be bound to it with the following * conditions: * <ul> * <li><i>No bound</i>: if the function is resolved from the global scope (not from any * given variables in <code>mVariables</code>, it's not bound to any context. If the * function exists directly under <code>mVariables</code>, nothing is bound.</li> * <li><i>Bound</i>: otherwise, the resolved function is bound to the object to which it * belongs</li> * <li><i>mOptions.bindContext</i>: when this option is set to <code>false</code>, no * context is bound to the resolved function regardless where the function is resolved * </li> * <li><i>mOptions.bindDotContext</i>: for paths starting with a dot ('.'), * <code>mOptions.bindDotContext=false</code> turns off the automatic binding to the * dot variable <code>mVariables["."]</code>. <code>mOptions.bindDotContext</code> has * no effect when <code>mOptions.bindContext=false</code>.</li> * </ul> * * @function * @private * @ui5-restricted sap.ui.core * @since 1.69 * * @param {string} sPath Path * @param {object} [mVariables] An object containing the mapping of variable name to object or function * @param {object} [mOptions] Options * @param {boolean} [mOptions.preferDotContext=false] Whether the path not starting with a dot ('.') is * resolved under the dot variable when it can not be resolved through the given variables object. * @param {boolean} [mOptions.bindContext=true] When the resolved value is a function, whether the * resolved function is bound to a context. When this property is set to false, the * mOptions.bindDotContext has no effect anymore. * @param {boolean} [mOptions.bindDotContext=true] When the resolved value is a function, whether the * resolved function from a path which starts with a dot ('.') should be bound to the dot context * @returns {any} Returns the value located in the provided path, or <code>undefined</code> if the path * does not exist completely. * @alias module:sap/base/util/resolveReference */ var resolveReference = function(sPath, mVariables, mOptions) { // fill the default values mVariables = mVariables || {}; mOptions = mOptions || {}; mOptions.bindContext = mOptions.bindContext !== false; mOptions.bindDotContext = mOptions.bindDotContext !== false; var aParts = sPath.split("."), // if sPath starts with ".", split returns an empty string // at the first position and the dot is used as variable sVariable = aParts.shift() || ".", bDotCase = sVariable === ".", vRef = oNotFound; // push the first part back to the array aParts.unshift(sVariable); // if preferDotContext, resolve the sPath under the dot context first for sPath which doesn't begin with "." if (mOptions.preferDotContext && !bDotCase) { vRef = _resolve(aParts, mVariables["."], { bindContext: mOptions.bindContext && mOptions.bindDotContext, // resolve function in dot variable should always bind the dot variable rootContext: mVariables["."] }); } // If sPath isn't resolved yet, resolve the path under mVariables if (vRef === oNotFound) { vRef = _resolve(aParts, mVariables, { bindContext: mOptions.bindContext // dot case: mOptions.bindDotContext determins whether context should be bound // non dot case: bind context if sPath contains more than one segment && (bDotCase ? mOptions.bindDotContext : (aParts.length > 1)), rootContext: bDotCase ? mVariables["."] : undefined }); } // resolve the path under global scope, only when it can't be resolved under mVariables if (vRef === oNotFound) { // fallback if no value could be found under the given sPath's first segment // otherwise resolve under global namespace vRef = ObjectPath.get(sPath); } return vRef; }; return resolveReference; });