diff options
Diffstat (limited to 'src/fields/ScriptField.ts')
-rw-r--r-- | src/fields/ScriptField.ts | 101 |
1 files changed, 51 insertions, 50 deletions
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index 68fb45987..2b8750714 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -6,11 +6,10 @@ import { scriptingGlobal, ScriptingGlobals } from '../client/util/ScriptingGloba import { autoObject, Deserializable } from '../client/util/SerializationHelper'; import { numberRange } from '../Utils'; import { Doc, Field, Opt } from './Doc'; -import { Copy, Id, ToScriptString, ToString } from './FieldSymbols'; +import { Copy, Id, ToScriptString, ToString, ToValue } from './FieldSymbols'; import { List } from './List'; import { ObjectField } from './ObjectField'; -import { Cast, NumCast } from './Types'; -import { Plugins } from './util'; +import { Cast, StrCast } from './Types'; function optional(propSchema: PropSchema) { return custom( @@ -43,12 +42,11 @@ const scriptSchema = createSimpleSchema({ originalScript: true, }); -function finalizeScript(script: ScriptField, captures: boolean) { +function finalizeScript(script: ScriptField) { const comp = CompileScript(script.script.originalScript, script.script.options); if (!comp.compiled) { throw new Error("Couldn't compile loaded script"); } - !captures && ScriptField._scriptFieldCache.set(script.script.originalScript, comp); if (script.setterscript) { const compset = CompileScript(script.setterscript?.originalScript, script.setterscript.options); if (!compset.compiled) { @@ -72,9 +70,9 @@ async function deserializeScript(script: ScriptField) { else if (!isNaN(Number(val))) captured[key] = Number(val); else captured[key] = val; }) - ).then(() => ((script as any).script = finalizeScript(script, true))); + ).then(() => ((script as any).script = finalizeScript(script))); } else { - (script as any).script = ScriptField.GetScriptFieldCache(script.script.originalScript) ?? finalizeScript(script, false); + (script as any).script = ScriptField.GetScriptFieldCache(script.script.originalScript) ?? finalizeScript(script); } } @@ -105,30 +103,9 @@ export class ScriptField extends ObjectField { } this.rawscript = rawscript; this.setterscript = setterscript; - this.script = script ?? (CompileScript('false') as CompiledScript); + this.script = script ?? ScriptField.GetScriptFieldCache('false:') ?? (CompileScript('false', { addReturn: true }) as CompiledScript); } - // init(callback: (res: Field) => any) { - // const options = this.options!; - // const keys = Object.keys(options.options.capturedIds); - // Server.GetFields(keys).then(fields => { - // let captured: { [name: string]: Field } = {}; - // keys.forEach(key => captured[options.options.capturedIds[key]] = fields[key]); - // const opts: ScriptOptions = { - // addReturn: options.options.addReturn, - // params: options.options.params, - // requiredType: options.options.requiredType, - // capturedVariables: captured - // }; - // const script = CompileScript(options.script, opts); - // if (!script.compiled) { - // throw new Error("Can't compile script"); - // } - // this._script = script; - // callback(this); - // }); - // } - [Copy](): ObjectField { return new ScriptField(this.script, this.setterscript, this.rawscript); } @@ -137,13 +114,13 @@ export class ScriptField extends ObjectField { } [ToScriptString]() { - return 'script field'; + return this.script.originalScript; } [ToString]() { return this.script.originalScript; } public static CompileScript(script: string, params: object = {}, addReturn = false, capturedVariables?: { [name: string]: Doc | string | number | boolean }) { - const compiled = CompileScript(script, { + return CompileScript(script, { params: { this: Doc?.name || 'Doc', // this is the doc that executes the script self: Doc?.name || 'Doc', // self is the root doc of the doc that executes the script @@ -156,7 +133,6 @@ export class ScriptField extends ObjectField { addReturn: addReturn, capturedVariables, }); - return compiled; } public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Doc | string | number | boolean }) { const compiled = ScriptField.CompileScript(script, params, true, capturedVariables); @@ -175,30 +151,57 @@ export class ComputedField extends ScriptField { _lastComputedResult: any; //TODO maybe add an observable cache based on what is passed in for doc, considering there shouldn't really be that many possible values for doc value = computedFn((doc: Doc) => this._valueOutsideReaction(doc)); - _valueOutsideReaction = (doc: Doc) => (this._lastComputedResult = this.script.run({ this: doc, self: Cast(doc.rootDocument, Doc, null) || doc, _last_: this._lastComputedResult, _readOnly_: true }, console.log).result); + _valueOutsideReaction = (doc: Doc) => (this._lastComputedResult = this.script.run({ this: doc, self: Cast(doc.rootDocument, Doc, null) ?? doc, value: '', _last_: this._lastComputedResult, _readOnly_: true }, console.log).result); + [ToValue](doc: Doc) { + return ComputedField.toValue(doc, this); + } [Copy](): ObjectField { return new ComputedField(this.script, this.setterscript, this.rawscript); } - public static MakeScript(script: string, params: object = {}) { - const compiled = ScriptField.CompileScript(script, params, false); - return compiled.compiled ? new ComputedField(compiled) : undefined; - } - public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Doc | string | number | boolean }) { - const compiled = ScriptField.CompileScript(script, params, true, capturedVariables); - return compiled.compiled ? new ComputedField(compiled) : undefined; + public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Doc | string | number | boolean }, setterscript?: string) { + const compiled = ScriptField.CompileScript(script, params, true, { value: '', ...capturedVariables }); + const compiledsetter = setterscript ? ScriptField.CompileScript(setterscript, { ...params, value: 'any' }, false, capturedVariables) : undefined; + const compiledsetscript = compiledsetter?.compiled ? compiledsetter : undefined; + return compiled.compiled ? new ComputedField(compiled, compiledsetscript) : undefined; } - public static MakeInterpolated(fieldKey: string, interpolatorKey: string, doc: Doc, curTimecode: number) { + public static MakeInterpolatedNumber(fieldKey: string, interpolatorKey: string, doc: Doc, curTimecode: number, defaultVal: Opt<number>) { if (!doc[`${fieldKey}-indexed`]) { const flist = new List<number>(numberRange(curTimecode + 1).map(i => undefined) as any as number[]); - flist[curTimecode] = NumCast(doc[fieldKey]); + flist[curTimecode] = Cast(doc[fieldKey], 'number', null); + doc[`${fieldKey}-indexed`] = flist; + } + const getField = ScriptField.CompileScript(`getIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey}, ${defaultVal})`, {}, true, {}); + const setField = ScriptField.CompileScript(`setIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey}, value)`, { value: 'any' }, true, {}); + return getField.compiled ? new ComputedField(getField, setField?.compiled ? setField : undefined) : undefined; + } + public static MakeInterpolatedString(fieldKey: string, interpolatorKey: string, doc: Doc, curTimecode: number) { + if (!doc[`${fieldKey}-indexed`]) { + const flist = new List<string>(numberRange(curTimecode + 1).map(i => undefined) as any as string[]); + flist[curTimecode] = StrCast(doc[fieldKey]); doc[`${fieldKey}-indexed`] = flist; } const getField = ScriptField.CompileScript(`getIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey})`, {}, true, {}); const setField = ScriptField.CompileScript(`setIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey}, value)`, { value: 'any' }, true, {}); return getField.compiled ? new ComputedField(getField, setField?.compiled ? setField : undefined) : undefined; } + public static MakeInterpolatedDataField(fieldKey: string, interpolatorKey: string, doc: Doc, curTimecode: number) { + if (doc[`${fieldKey}`] instanceof List) return; + if (!doc[`${fieldKey}-indexed`]) { + const flist = new List<Field>(numberRange(curTimecode + 1).map(i => undefined) as any as Field[]); + flist[curTimecode] = Field.Copy(doc[fieldKey]); + doc[`${fieldKey}-indexed`] = flist; + } + const getField = ScriptField.CompileScript(`getIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey})`, {}, true, {}); + const setField = ScriptField.CompileScript( + `{setIndexVal (self['${fieldKey}-indexed'], self.${interpolatorKey}, value); console.log(self["${fieldKey}-indexed"][self.${interpolatorKey}],self.data,self["${fieldKey}-indexed"]))}`, + { value: 'any' }, + false, + {} + ); + return (doc[`${fieldKey}`] = getField.compiled ? new ComputedField(getField, setField?.compiled ? setField : undefined) : undefined); + } } export namespace ComputedField { let useComputed = true; @@ -221,12 +224,10 @@ export namespace ComputedField { } } - export function initPlugin() { - Plugins.addGetterPlugin((doc, _, value) => { - if (useComputed && value instanceof ComputedField) { - return { value: value._valueOutsideReaction(doc), shouldReturn: true }; - } - }); + export function toValue(doc: any, value: any) { + if (useComputed) { + return { value: value._valueOutsideReaction(doc) }; + } } } @@ -240,8 +241,8 @@ ScriptingGlobals.add( ); ScriptingGlobals.add( - function getIndexVal(list: any[], index: number) { - return list?.reduce((p, x, i) => ((i <= index && x !== undefined) || p === undefined ? x : p), undefined as any); + function getIndexVal(list: any[], index: number, defaultVal: Opt<number> = undefined) { + return list?.reduce((p, x, i) => ((i <= index && x !== undefined) || p === undefined ? x : p), defaultVal); }, 'returns the value at a given index of a list', '(list: any[], index: number)' |