diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/DocServer.ts | 11 | ||||
-rw-r--r-- | src/client/util/SerializationHelper.ts | 15 | ||||
-rw-r--r-- | src/client/views/InkingControl.tsx | 4 | ||||
-rw-r--r-- | src/new_fields/Doc.ts | 13 | ||||
-rw-r--r-- | src/new_fields/Proxy.ts | 4 | ||||
-rw-r--r-- | src/new_fields/ScriptField.ts | 22 |
6 files changed, 48 insertions, 21 deletions
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index 8c64d2b2f..077c8e5ba 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -126,12 +126,11 @@ export namespace DocServer { // future .proto calls on the Doc won't have to go farther than the cache to get their actual value. const deserializeField = getSerializedField.then(async fieldJson => { // deserialize - const field = SerializationHelper.Deserialize(fieldJson); + const field = await SerializationHelper.Deserialize(fieldJson); // either way, overwrite or delete any promises cached at this id (that we inserted as flags // to indicate that the field was in the process of being fetched). Now everything // should be an actual value within or entirely absent from the cache. if (field !== undefined) { - await field.proto; _cache[id] = field; } else { delete _cache[id]; @@ -202,18 +201,18 @@ export namespace DocServer { // future .proto calls on the Doc won't have to go farther than the cache to get their actual value. const deserializeFields = getSerializedFields.then(async fields => { const fieldMap: { [id: string]: RefField } = {}; - const protosToLoad: any = []; + // const protosToLoad: any = []; for (const field of fields) { if (field !== undefined) { // deserialize - let deserialized: any = SerializationHelper.Deserialize(field); + let deserialized = await SerializationHelper.Deserialize(field); fieldMap[field.id] = deserialized; // adds to a list of promises that will be awaited asynchronously - protosToLoad.push(deserialized.proto); + // protosToLoad.push(deserialized.proto); } } // this actually handles the loading of prototypes - await Promise.all(protosToLoad); + // await Promise.all(protosToLoad); return fieldMap; }); diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts index dca539f3b..692d07c74 100644 --- a/src/client/util/SerializationHelper.ts +++ b/src/client/util/SerializationHelper.ts @@ -28,7 +28,7 @@ export namespace SerializationHelper { return json; } - export function Deserialize(obj: any): any { + export async function Deserialize(obj: any): Promise<any> { if (obj === undefined || obj === null) { return undefined; } @@ -52,16 +52,19 @@ export namespace SerializationHelper { } const type = serializationTypes[obj.__type]; - const value = deserialize(type.ctor, obj); + const value = await new Promise(res => deserialize(type.ctor, obj, (err, result) => res(result))); if (type.afterDeserialize) { - type.afterDeserialize(value); + const currentSerialization = serializing; + serializing = 0; + await type.afterDeserialize(value); + serializing = currentSerialization; } serializing -= 1; return value; } } -let serializationTypes: { [name: string]: { ctor: { new(): any }, afterDeserialize?: (obj: any) => void } } = {}; +let serializationTypes: { [name: string]: { ctor: { new(): any }, afterDeserialize?: (obj: any) => void | Promise<any> } } = {}; let reverseMap: { [ctor: string]: string } = {}; export interface DeserializableOpts { @@ -69,7 +72,7 @@ export interface DeserializableOpts { withFields(fields: string[]): Function; } -export function Deserializable(name: string, afterDeserialize?: (obj: any) => void): DeserializableOpts; +export function Deserializable(name: string, afterDeserialize?: (obj: any) => void | Promise<any>): DeserializableOpts; export function Deserializable(constructor: { new(...args: any[]): any }): void; export function Deserializable(constructor: { new(...args: any[]): any } | string, afterDeserialize?: (obj: any) => void): DeserializableOpts | void { function addToMap(name: string, ctor: { new(...args: any[]): any }) { @@ -135,6 +138,6 @@ export namespace Deserializable { export function autoObject(): PropSchema { return custom( (s) => SerializationHelper.Serialize(s), - (s) => SerializationHelper.Deserialize(s) + (json: any, context: any, oldValue: any, cb: (err: any, result: any) => void) => SerializationHelper.Deserialize(json).then(res => cb(null, res)) ); }
\ No newline at end of file diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index c7f7bdb66..1910e409b 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -1,5 +1,5 @@ import { observable, action, computed, runInAction } from "mobx"; -import { ColorResult } from 'react-color'; +import { ColorState } from 'react-color'; import React = require("react"); import { observer } from "mobx-react"; import "./InkingControl.scss"; @@ -41,7 +41,7 @@ export class InkingControl extends React.Component { } @undoBatch - switchColor = action((color: ColorResult): void => { + switchColor = action((color: ColorState): void => { this._selectedColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff"); if (InkingControl.Instance.selectedTool === InkTool.None) { if (MainOverlayTextBox.Instance.SetColor(color.hex)) return; diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 59e61023f..45eb2e514 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -67,8 +67,15 @@ export function DocListCast(field: FieldResult): Doc[] { export const WidthSym = Symbol("Width"); export const HeightSym = Symbol("Height"); +function fetchProto(doc: Doc) { + const proto = doc.proto; + if (proto instanceof Promise) { + return proto; + } +} + @scriptingGlobal -@Deserializable("doc").withFields(["id"]) +@Deserializable("doc", fetchProto).withFields(["id"]) export class Doc extends RefField { constructor(id?: FieldId, forceSave?: boolean) { super(id); @@ -133,14 +140,14 @@ export class Doc extends RefField { return "invalid"; } - public [HandleUpdate](diff: any) { + public async [HandleUpdate](diff: any) { const set = diff.$set; if (set) { for (const key in set) { if (!key.startsWith("fields.")) { continue; } - const value = SerializationHelper.Deserialize(set[key]); + const value = await SerializationHelper.Deserialize(set[key]); const fKey = key.substring(7); this[fKey] = value; } diff --git a/src/new_fields/Proxy.ts b/src/new_fields/Proxy.ts index 38d874a68..14f08814e 100644 --- a/src/new_fields/Proxy.ts +++ b/src/new_fields/Proxy.ts @@ -48,7 +48,7 @@ export class ProxyField<T extends RefField> extends ObjectField { private failed = false; private promise?: Promise<any>; - value(): T | undefined | FieldWaiting { + value(): T | undefined | FieldWaiting<T> { if (this.cache) { return this.cache; } @@ -63,6 +63,6 @@ export class ProxyField<T extends RefField> extends ObjectField { return field; })); } - return this.promise; + return this.promise as any; } } diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts index e8a1ea28a..e1f65fc9c 100644 --- a/src/new_fields/ScriptField.ts +++ b/src/new_fields/ScriptField.ts @@ -2,10 +2,11 @@ import { ObjectField } from "./ObjectField"; import { CompiledScript, CompileScript, scriptingGlobal } from "../client/util/Scripting"; import { Copy, ToScriptString, Parent, SelfProxy } from "./FieldSymbols"; import { serializable, createSimpleSchema, map, primitive, object, deserialize, PropSchema, custom, SKIP } from "serializr"; -import { Deserializable } from "../client/util/SerializationHelper"; +import { Deserializable, autoObject } from "../client/util/SerializationHelper"; import { Doc } from "../new_fields/Doc"; import { Plugins } from "./util"; import { computedFn } from "mobx-utils"; +import { ProxyField } from "./Proxy"; function optional(propSchema: PropSchema) { return custom(value => { @@ -34,7 +35,16 @@ const scriptSchema = createSimpleSchema({ originalScript: true }); -function deserializeScript(script: ScriptField) { +async function deserializeScript(script: ScriptField) { + const captures: ProxyField<Doc> = (script as any).captures; + if (captures) { + const doc = (await captures.value())!; + const captured: any = {}; + const keys = Object.keys(doc); + const vals = await Promise.all(keys.map(key => doc[key]) as any); + keys.forEach((key, i) => captured[key] = vals[i]); + (script.script.options as any).capturedVariables = captured; + } const comp = CompileScript(script.script.originalScript, script.script.options); if (!comp.compiled) { throw new Error("Couldn't compile loaded script"); @@ -48,9 +58,17 @@ export class ScriptField extends ObjectField { @serializable(object(scriptSchema)) readonly script: CompiledScript; + @serializable(autoObject()) + private captures?: ProxyField<Doc>; + constructor(script: CompiledScript) { super(); + if (script && script.options.capturedVariables) { + const doc = Doc.assign(new Doc, script.options.capturedVariables); + this.captures = new ProxyField(doc); + } + this.script = script; } |