feat(bindable): allow "global" context for expressions inside bindings (#9734)

This commit is contained in:
Dimitris - Rafail Katsampas
2022-01-14 07:35:56 +02:00
committed by Nathan Walker
parent 65eb4e2add
commit 2cbb135250

View File

@ -82,20 +82,23 @@ const expressionParsers = {
object = getContext(expression.callee.name, model, changedModel); object = getContext(expression.callee.name, model, changedModel);
property = expression.callee?.name; property = expression.callee?.name;
} }
const callback = expression.callee.optional ? object?.[property] : object[property]; const callback = expression.callee.optional ? object?.[property] : object[property];
if (isNullOrUndefined(callback)) {
throw new Error('Cannot perform a call using a null or undefined property');
}
const isConverter = isObject(callback) && (isFunction(callback.toModel) || isFunction(callback.toView)); const isConverter = isObject(callback) && (isFunction(callback.toModel) || isFunction(callback.toView));
if (!isFunction(callback) && !isConverter) {
throw new Error('Cannot perform a call using a non-callable property');
}
const parsedArgs = []; const parsedArgs = [];
for (let argument of expression.arguments) { for (let argument of expression.arguments) {
let value = convertExpressionToValue(argument, model, isBackConvert, changedModel); let value = convertExpressionToValue(argument, model, isBackConvert, changedModel);
argument.type == 'SpreadElement' ? parsedArgs.push(...value) : parsedArgs.push(value); argument.type == 'SpreadElement' ? parsedArgs.push(...value) : parsedArgs.push(value);
} }
return isConverter ? getConverter(callback, object, parsedArgs, isBackConvert) : callback.apply(object, parsedArgs);
if (isNullOrUndefined(callback) || (!isFunction(callback) && !isConverter)) {
throw new Error('Cannot perform a call using a non-function property');
}
return isConverter ? getConverter(callback, parsedArgs, isBackConvert) : callback.apply(object, parsedArgs);
}, },
'ChainExpression': (expression: ASTExpression, model, isBackConvert: boolean, changedModel) => { 'ChainExpression': (expression: ASTExpression, model, isBackConvert: boolean, changedModel) => {
return convertExpressionToValue(expression.expression, model, isBackConvert, changedModel); return convertExpressionToValue(expression.expression, model, isBackConvert, changedModel);
@ -174,12 +177,16 @@ const expressionParsers = {
}; };
function getContext(key, model, changedModel) { function getContext(key, model, changedModel) {
return key in changedModel ? changedModel : model; let context = key in changedModel ? changedModel : model;
if (!(key in context)) {
context = global;
}
return context;
} }
function getConverter(context, args, isBackConvert: boolean) { function getConverter(converterSchema, context, args, isBackConvert: boolean) {
const converter = { callback: null, context, args }; const converter = { callback: null, context, args };
let callback = isBackConvert ? context.toModel : context.toView; let callback = isBackConvert ? converterSchema.toModel : converterSchema.toView;
if (callback == null) { if (callback == null) {
callback = Function.prototype; callback = Function.prototype;
} }