From 85fa802338b1baf6e4890be95c5724531e7c4e9f Mon Sep 17 00:00:00 2001 From: cha0s Date: Fri, 19 Jun 2020 15:28:02 -0500 Subject: [PATCH] chore: export structure --- packages/behavior/context/context.js | 165 +++++++++++++++++++++++++++ packages/behavior/context/index.js | 156 +------------------------ 2 files changed, 166 insertions(+), 155 deletions(-) create mode 100644 packages/behavior/context/context.js diff --git a/packages/behavior/context/context.js b/packages/behavior/context/context.js new file mode 100644 index 0000000..9bf4b73 --- /dev/null +++ b/packages/behavior/context/context.js @@ -0,0 +1,165 @@ +import D from 'debug'; +import {invokeHookFlat} from 'scwp'; + +import {fastApply, objectFromEntries} from '@avocado/core'; + +const debug = D('@avocado:behavior:context'); + +export class Context { + + constructor(defaults = {}) { + this.initialize(); + for (const key in defaults) { + this.add(key, defaults[key]); + } + } + + static describe(description, fn) { + const {type} = description; + fn.type = type; + return fn; + } + + static globals() { + if (!Context._globals) { + Context._globals = {}; + const globalss = invokeHookFlat('behaviorContextGlobals'); + for (let i = 0; i < globalss.length; i++) { + const globals = globalss[i]; + for (const key in globals) { + Context._globals[key] = globals[key]; + } + } + } + return Context._globals; + } + + add(key, value) { + this.map.set(key, value); + } + + all() { + return objectFromEntries(Array.from(this.map.entries())); + } + + initialize() { + this.map = new Map(); + this.add('context', this); + const globals = this.constructor.globals(); + for (const key in globals) { + this.add(key, globals[key]); + } + } + + clear() { + this.initialize(); + } + + destroy() { + this.map.clear(); + } + + static renderSteps(steps) { + return steps.reduce((rendered, step) => { + switch (step.type) { + case 'key': + if (rendered) { + rendered += '.'; + } + rendered += step.key; + break; + case 'invoke': + rendered += `(${step.args.length > 0 ? '...' : ''})`; + break; + } + return rendered; + }, ''); + } + + static renderStepsUntilNow(steps, step) { + const stepsUntilNow = steps.slice(0, steps.indexOf(step)); + return this.renderSteps(stepsUntilNow); + } + + takeStep(value, fn) { + if (value instanceof Promise) { + return value.then((value) => { + return fn(value); + }); + } + else { + return fn(value); + } + } + + traverse(traversal) { + const {steps, value} = traversal; + return this.traverseAndDo(steps, (node, previousNode, step, index) => { + const isLastStep = index === steps.length - 2; + // Traverse if we're not at the final step with a value. + if (!isLastStep || !value) { + return this.traverseOneStep(steps, previousNode, node, step); + } + // Try to set the value. + switch (step.type) { + case 'key': + if ('object' === typeof node) { + return node[step.key] = value.get(this); + } + case 'invoke': + const rendered = this.constructor.renderStepsUntilNow(steps, step); + debug(`invalid assignment to function "${rendered}"`); + return; + } + }); + } + + traverseAndDo(steps, fn) { + const [first, ...rest] = steps; + if ('key' !== first.type) { + throw new TypeError(`First step in a traversal must be type "key"`); + } + let previousNode = null; + return rest.reduce((node, step, index) => { + return this.takeStep(node, (node) => { + const result = fn(node, previousNode, step, index); + previousNode = node; + return result; + }); + }, this.map.get(first.key)); + } + + traverseOneStep(steps, previousNode, node, step) { + if ('undefined' === typeof node) { + const rendered = this.constructor.renderStepsUntilNow(steps, step); + debug(`"${rendered}" is traversed through but undefined`); + return; + } + switch (step.type) { + case 'key': + return node[step.key]; + case 'invoke': + const args = step.args.map((arg) => arg.get(this)); + // Pass the context itself as the last arg. + args.push(this); + // Any arg promises will be resolved; the arg values will be passed + // transparently to the invocation. + let hasPromise = false; + for (let i = 0; i < args.length; i++) { + if (args[i] instanceof Promise) { + hasPromise = true; + break; + } + } + if (hasPromise) { + return Promise.all(args).then((args) => { + return fastApply(previousNode, node, args); + }); + } + else { + return fastApply(previousNode, node, args); + } + } + } + +} diff --git a/packages/behavior/context/index.js b/packages/behavior/context/index.js index a260898..1a7fb45 100644 --- a/packages/behavior/context/index.js +++ b/packages/behavior/context/index.js @@ -1,155 +1 @@ -import D from 'debug'; -import {invokeHookFlat} from 'scwp'; - -import {fastApply} from '@avocado/core'; - -const debug = D('@avocado:behavior:context'); - -export class Context { - - constructor(defaults = {}) { - this.initialize(); - for (const key in defaults) { - this.add(key, defaults[key]); - } - } - - static globals() { - if (!Context._globals) { - Context._globals = {}; - const globalss = invokeHookFlat('behaviorContextGlobals'); - for (let i = 0; i < globalss.length; i++) { - const globals = globalss[i]; - for (const key in globals) { - Context._globals[key] = globals[key]; - } - } - } - return Context._globals; - } - - add(key, value) { - this.map.set(key, value); - } - - initialize() { - this.map = new Map(); - this.add('context', this); - const globals = this.constructor.globals(); - for (const key in globals) { - this.add(key, globals[key]); - } - } - - clear() { - this.initialize(); - } - - destroy() { - this.map.clear(); - } - - static renderSteps(steps) { - return steps.reduce((rendered, step) => { - switch (step.type) { - case 'key': - if (rendered) { - rendered += '.'; - } - rendered += step.key; - break; - case 'invoke': - rendered += `(${step.args.length > 0 ? '...' : ''})`; - break; - } - return rendered; - }, ''); - } - - static renderStepsUntilNow(steps, step) { - const stepsUntilNow = steps.slice(0, steps.indexOf(step)); - return this.renderSteps(stepsUntilNow); - } - - takeStep(value, fn) { - if (value instanceof Promise) { - return value.then((value) => { - return fn(value); - }); - } - else { - return fn(value); - } - } - - traverse(traversal) { - const {steps, value} = traversal; - return this.traverseAndDo(steps, (node, previousNode, step, index) => { - const isLastStep = index === steps.length - 2; - // Traverse if we're not at the final step with a value. - if (!isLastStep || !value) { - return this.traverseOneStep(steps, previousNode, node, step); - } - // Try to set the value. - switch (step.type) { - case 'key': - if ('object' === typeof node) { - return node[step.key] = value.get(this); - } - case 'invoke': - const rendered = this.constructor.renderStepsUntilNow(steps, step); - debug(`invalid assignment to function "${rendered}"`); - return; - } - }); - } - - traverseAndDo(steps, fn) { - const [first, ...rest] = steps; - if ('key' !== first.type) { - throw new TypeError(`First step in a traversal must be type "key"`); - } - let previousNode = null; - return rest.reduce((node, step, index) => { - return this.takeStep(node, (node) => { - const result = fn(node, previousNode, step, index); - previousNode = node; - return result; - }); - }, this.map.get(first.key)); - } - - traverseOneStep(steps, previousNode, node, step) { - if ('undefined' === typeof node) { - const rendered = this.constructor.renderStepsUntilNow(steps, step); - debug(`"${rendered}" is traversed through but undefined`); - return; - } - switch (step.type) { - case 'key': - return node[step.key]; - case 'invoke': - const args = step.args.map((arg) => arg.get(this)); - // Pass the context itself as the last arg. - args.push(this); - // Any arg promises will be resolved; the arg values will be passed - // transparently to the invocation. - let hasPromise = false; - for (let i = 0; i < args.length; i++) { - if (args[i] instanceof Promise) { - hasPromise = true; - break; - } - } - if (hasPromise) { - return Promise.all(args).then((args) => { - return fastApply(previousNode, node, args); - }); - } - else { - return fastApply(previousNode, node, args); - } - } - } - -} +export {Context} from './context';