UNPKG

@neo-one/smart-contract-compiler

Version:

NEO•ONE TypeScript smart contract compiler.

140 lines (138 loc) 6.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SmartContractForBase = void 0; const ts_utils_1 = require("@neo-one/ts-utils"); const utils_1 = require("@neo-one/utils"); const constants_1 = require("../../../constants"); const utils_2 = require("../../../utils"); const constants_2 = require("../../constants"); const BuiltinMemberCall_1 = require("../BuiltinMemberCall"); class SmartContractForBase extends BuiltinMemberCall_1.BuiltinMemberCall { emitCall(sb, func, node, optionsIn) { const options = sb.pushValueOptions(optionsIn); const returnType = sb.context.analysis.getType(node); if (returnType === undefined) { return; } const properties = ts_utils_1.tsUtils.type_.getProperties(returnType); const props = properties.map((prop) => { const propType = sb.context.analysis.getTypeOfSymbol(prop, node); if (propType === undefined) { return undefined; } const propName = ts_utils_1.tsUtils.symbol.getName(prop); if (constants_1.IGNORED_PROPERTIES.has(propName)) { return undefined; } if (constants_1.BUILTIN_PROPERTIES.has(propName)) { return undefined; } const propNode = ts_utils_1.tsUtils.symbol.getValueDeclarationOrThrow(prop); if (ts_utils_1.tsUtils.modifier.isStatic(propNode) || ts_utils_1.tsUtils.modifier.isProtected(propNode) || ts_utils_1.tsUtils.modifier.isPrivate(propNode)) { return undefined; } const result = sb.context.analysis.extractSignatureForType(propNode, propType, { error: true }); if (result === undefined) { return { paramDecls: [], paramTypes: new Map(), returnType: propType, prop: propNode, propName, accessor: true, isReadonly: ts_utils_1.tsUtils.modifier.isReadonly(propNode), }; } return Object.assign(Object.assign({}, result), { prop: propNode, propName, accessor: false, isReadonly: false }); }); const handleParams = (prop, paramDecls, paramTypes, innerOptions) => { sb.emitHelper(prop, innerOptions, sb.helpers.parameters({ params: paramDecls, asArgsArr: true, map: (param, innerInnerOptions, isRestElement) => { let type = paramTypes.get(param); if (type !== undefined && isRestElement) { type = ts_utils_1.tsUtils.type_.getArrayType(type); } sb.emitHelper(param, innerInnerOptions, sb.helpers.unwrapValRecursive({ type })); }, })); }; const addressName = sb.scope.addUnique(); this.emitInitial(sb, func, node, addressName, options); sb.emitHelper(node, options, sb.helpers.createObject); props .filter(utils_1.utils.notNull) .forEach(({ prop, propName, paramDecls, paramTypes, returnType: propReturnType, accessor, isReadonly }) => { sb.emitOp(prop, 'DUP'); sb.emitPushString(prop, propName); if (accessor && !isReadonly) { sb.emitHelper(prop, options, sb.helpers.createFunctionArray({ body: (innerOptionsIn) => { const innerOptions = sb.pushValueOptions(innerOptionsIn); sb.emitPushInt(prop, 0); sb.emitOp(prop, 'PICKITEM'); sb.emitHelper(prop, innerOptions, sb.helpers.unwrapValRecursive({ type: propReturnType })); sb.emitPushInt(prop, 1); sb.emitOp(prop, 'PACK'); sb.emitPushString(prop, utils_2.getSetterName(propName)); const callBuffer = Buffer.from([0, 2]); this.emitInvoke(sb, func, node, prop, addressName, callBuffer, sb.noPushValueOptions(innerOptions)); sb.emitHelper(prop, innerOptions, sb.helpers.wrapUndefined); sb.emitHelper(prop, innerOptions, sb.helpers.return); }, })); sb.emitHelper(prop, options, sb.helpers.createFunctionObject({ property: constants_2.InternalObjectProperty.Call, })); } sb.emitHelper(prop, options, sb.helpers.createFunctionArray({ body: (innerOptionsIn) => { const innerOptions = sb.pushValueOptions(innerOptionsIn); if (accessor) { sb.emitOp(prop, 'DROP'); sb.emitPushInt(prop, 0); sb.emitOp(prop, 'NEWARRAY'); } else { handleParams(prop, paramDecls, paramTypes, innerOptions); } sb.emitPushString(prop, propName); const isVoidReturn = propReturnType !== undefined && ts_utils_1.tsUtils.type_.isVoid(propReturnType); const callBuffer = Buffer.from([isVoidReturn ? 0 : 1, 2]); this.emitInvoke(sb, func, node, prop, addressName, callBuffer, innerOptions); if (isVoidReturn) { sb.emitHelper(prop, innerOptions, sb.helpers.wrapUndefined); } else { sb.emitHelper(prop, innerOptions, sb.helpers.wrapValRecursive({ type: propReturnType, })); } sb.emitHelper(prop, innerOptions, sb.helpers.return); }, })); sb.emitHelper(prop, options, sb.helpers.createFunctionObject({ property: constants_2.InternalObjectProperty.Call, })); if (accessor) { sb.emitHelper(prop, options, sb.helpers.setAccessorPropertyObjectProperty({ hasGet: true, hasSet: !isReadonly })); } else { sb.emitHelper(prop, options, sb.helpers.setDataPropertyObjectProperty); } }); this.emitAdditionalProperties(sb, func, node, options); if (!optionsIn.pushValue) { sb.emitOp(node, 'DROP'); } } emitInitial(_sb, _func, _node, _addressName, _options) { } emitAdditionalProperties(_sb, _func, _node, _options) { } } exports.SmartContractForBase = SmartContractForBase; //# sourceMappingURL=SmartContractForBase.js.map