Skip to content

Commit

Permalink
_attachContext
Browse files Browse the repository at this point in the history
  • Loading branch information
kurkle committed Feb 6, 2021
1 parent 1651f73 commit 87d9d9a
Showing 1 changed file with 40 additions and 34 deletions.
74 changes: 40 additions & 34 deletions src/helpers/helpers.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,8 @@ export function _createResolver(scopes, prefixes = ['']) {
* @private
*/
export function _attachContext(proxy, context, subProxy) {
const cache = {};
const cache = {_proxy: proxy, _context: context, _subProxy: subProxy, _stack: new Set()};
const {isScriptable, isIndexable} = _descriptors(proxy);
const stack = new Set();
return new Proxy(cache, {
// eslint-disable-next-line complexity
get(target, prop, receiver) {
Expand All @@ -62,31 +61,10 @@ export function _attachContext(proxy, context, subProxy) {

if (isPublicOptionValue(prop, value)) {
if (isFunction(value) && isScriptable(prop)) {
if (stack.has(prop)) {
// @ts-ignore
throw new Error('Recursion detected: ' + [...stack].join('->') + '->' + prop);
}
stack.add(prop);
value = value(context, subProxy || receiver);
stack.delete(prop);
if (isObject(value)) {
// When scriptable option returns an object, create a resolver on that.
value = createSubResolver([value].concat(proxy._scopes), prop, value); // _createResolver([value].concat(subscopes(proxy._scopes, prop)));
}
value = _resolveScriptable(prop, value, target, receiver);
}
if (isArray(value) && value.length) {
if (defined(context.index) && isIndexable(prop)) {
value = value[context.index % value.length];
} else if (isObject(value[0])) {
// Array of objects, return array or resolvers
const arr = value;
const scopes = proxy._scopes.filter(s => s !== arr);
value = [];
for (const item of arr) {
const resolver = createSubResolver([item].concat(scopes), prop, item);
value.push(_attachContext(resolver, context, subProxy && subProxy[prop]));
}
}
value = _resolveArray(prop, value, target, isIndexable);
}
if (defined(value)) {
if (needsSubResolver(prop, value)) {
Expand All @@ -99,22 +77,50 @@ export function _attachContext(proxy, context, subProxy) {
return value;
},

ownKeys() {
return Reflect.ownKeys(proxy);
},

getOwnPropertyDescriptor(target, prop) {
return Reflect.getOwnPropertyDescriptor(proxy._scopes[0], prop);
},
ownKeys: () => Reflect.ownKeys(proxy),
getOwnPropertyDescriptor: (target, prop) => Reflect.getOwnPropertyDescriptor(proxy._scopes[0], prop),

set(target, prop, value) {
delete target[prop];
proxy[prop] = value;
return true;
return delete target[prop];
}
});
}

function _resolveScriptable(prop, value, target, receiver) {
const {_proxy, _context, _subProxy, _stack} = target;
if (_stack.has(prop)) {
// @ts-ignore
throw new Error('Recursion detected: ' + [..._stack].join('->') + '->' + prop);
}
_stack.add(prop);
value = value(_context, _subProxy || receiver);
_stack.delete(prop);
if (isObject(value)) {
// When scriptable option returns an object, create a resolver on that.
value = createSubResolver([value].concat(_proxy._scopes), prop, value);
}
return value;
}

function _resolveArray(prop, value, target, isIndexable) {
const {_proxy, _context, _subProxy} = target;

if (defined(_context.index) && isIndexable(prop)) {
value = value[_context.index % value.length];
} else if (isObject(value[0])) {
// Array of objects, return array or resolvers
const arr = value;
const scopes = _proxy._scopes.filter(s => s !== arr);
value = [];
for (const item of arr) {
const resolver = createSubResolver([item].concat(scopes), prop, item);
value.push(_attachContext(resolver, _context, _subProxy && _subProxy[prop]));
}
}
return value;
}

/**
* @private
*/
Expand Down

0 comments on commit 87d9d9a

Please sign in to comment.