UNPKG

slightning-coco-widget

Version:

SLIGHTNING 的 CoCo 控件框架。

220 lines (219 loc) 10.3 kB
import { capitalize } from "../../utils"; import { AnyType, InstanceOfClassType, ObjectType, StringEnumType, VoidType } from "../type"; import { BlockType } from "../types"; import { emit } from "../utils"; import { methodParamNeedsTransformToEvent, traverseTypes } from "./utils"; export function addTransformMethodsCallbackFunctionsToEvents(types, widget) { traverseTypes(types, { MethodTypes(node) { if (!node.value.block.some(methodParamNeedsTransformToEvent)) { return; } const argumentsTransformers = []; const transformedMethod = Object.assign(Object.assign({}, node.value), { key: `__slightning_coco_widget_transformed_callback_function_to_events__${node.value.key}`, block: [...node.value.block] }); for (let i = 0; i < transformedMethod.block.length; i++) { const part = transformedMethod.block[i]; if (part == undefined) { continue; } if (typeof part != "object") { continue; } if (!methodParamNeedsTransformToEvent(part)) { argumentsTransformers.push((arg) => arg); continue; } const key = `${transformedMethod.key}${capitalize(part.key)}`; const label = `${transformedMethod.label}·${part.label}`; const type = part.type; class ResolveRef { constructor() { this.name = "解决函数引用"; } } class RejectRef { constructor() { this.name = "拒绝函数引用"; } } const resolveMap = new WeakMap(); const rejectMap = new WeakMap(); const callDataType = new ObjectType({ propertiesType: { state: new StringEnumType([ ["未完成", "undone"], ["已解决", "resolved"], ["已拒绝", "rejected"] ]), resolve: new InstanceOfClassType({ theClass: ResolveRef }), reject: new InstanceOfClassType({ theClass: RejectRef }) }, defaultValue: label }); const eventParams = [ { key: "__slightning_coco_widget_call_data__", label: part.label, type: callDataType }, { key: "__slightning_coco_widget_call_context__", label: "上下文", type: new AnyType() } ]; for (const part of type.block) { if (typeof part != "object") { continue; } eventParams.push({ key: part.key, label: part.label, type: part.type }); } transformedMethod.block.splice(i, 1, part.label, "(上下文", { key: `__slightning_coco_widget_call_context__${part.key}`, label: `${part.label}(上下文)`, type: new AnyType({ defaultValue: `${part.label}上下文` }) }, ")"); i++; argumentsTransformers.push(function (context) { const widget = this; return function (...args) { let promiseResolve = null; let promiseReject = null; function resolve(result) { if (callData.state == "undone") { callData.state = "resolved"; callData.value = result; promiseResolve === null || promiseResolve === void 0 ? void 0 : promiseResolve(result); } } function reject(reason) { if (callData.state == "undone") { callData.state = "rejected"; callData.value = reason; promiseReject === null || promiseReject === void 0 ? void 0 : promiseReject(reason); } } const resolveRef = new ResolveRef(); const rejectRef = new RejectRef(); resolveMap.set(resolveRef, resolve); rejectMap.set(rejectRef, reject); const callData = { state: "undone", resolve: resolveRef, reject: rejectRef }; emit.call(widget, key, callData, context, ...args); if (callData.state == "resolved") { return callData.value; } else if (callData.state == "rejected") { throw callData.value; } return new Promise((resolve, reject) => { promiseResolve = resolve; promiseReject = reject; }); }; }); if (type.throws != null && !(type.throws.isVoid())) { node.insertAfter({ space: 8 }, { type: BlockType.METHOD, key: `__slightning_coco_widget_throw__${key}`, label: `${label}抛出`, block: [ { key: "__slightning_coco_widget_call_data__", label, type: callDataType }, "抛出", { key: "exception", label: "异常", type: type.throws } ], returns: new VoidType(), blockOptions: Object.assign(Object.assign({}, transformedMethod.blockOptions), { inline: true, previousStatement: true, nextStatement: false }) }); Object.defineProperty(widget.prototype, `__slightning_coco_widget_throw__${key}`, { value: function (callData, exception) { const reject = rejectMap.get(callData.reject); if (reject == null) { throw new Error("拒绝函数不存在"); } reject(exception); }, writable: true, enumerable: false, configurable: true }); } if (type.returns != null) { node.insertAfter({ space: 8 }, { type: BlockType.METHOD, key: `__slightning_coco_widget_return__${key}`, label: `${label}返回`, block: [ { key: "__slightning_coco_widget_call_data__", label, type: callDataType }, "返回", ...(type.returns.isVoid() ? [] : [{ key: "returnValue", label: "返回值", type: type.returns }]) ], returns: new VoidType(), blockOptions: Object.assign(Object.assign({}, transformedMethod.blockOptions), { inline: true, previousStatement: true, nextStatement: false }) }); Object.defineProperty(widget.prototype, `__slightning_coco_widget_return__${key}`, { value: function (callData, returnValue) { const resolve = resolveMap.get(callData.resolve); if (resolve == null) { throw new Error("解决函数不存在"); } resolve(returnValue); }, writable: true, enumerable: false, configurable: true }); } node.insertAfter({ type: BlockType.EVENT, key, label: `${label}被调用`, params: eventParams }); } Object.defineProperty(widget.prototype, transformedMethod.key, { value: function (...args) { var _a; const transformedArgs = []; for (let i = 0; i < args.length; i++) { transformedArgs.push((_a = argumentsTransformers[i]) === null || _a === void 0 ? void 0 : _a.call(this, args[i])); } return this[node.value.key].apply(this, transformedArgs); }, writable: true, enumerable: false, configurable: true }); node.insertAfter(transformedMethod); } }); return [types, widget]; }