void fx_Function_prototype_get_length(txMachine* the) { txSlot* instance = fxCheckFunctionInstance(the, mxThis); txSlot* code = mxFunctionInstanceCode(instance); if ((code->kind == XS_CODE_KIND) || (code->kind == XS_CODE_X_KIND)) mxResult->value.integer = *(code->value.code + 1); else mxResult->value.integer = mxFunctionInstanceInfo(instance)->value.info.length; mxResult->kind = XS_INTEGER_KIND; }
void fx_Function(txMachine* the) { txInteger c, i; txStringStream stream; c = mxArgc; i = 0; mxPushStringC("(function anonymous("); while (c > 1) { fxToString(the, mxArgv(i)); fxConcatString(the, the->stack, mxArgv(i)); if (c > 2) fxConcatStringC(the, the->stack, ", "); c--; i++; } fxConcatStringC(the, the->stack, "){"); if (c > 0) { fxToString(the, mxArgv(i)); fxConcatString(the, the->stack, mxArgv(i)); } fxConcatStringC(the, the->stack, "})"); stream.slot = the->stack; stream.offset = 0; stream.size = c_strlen(the->stack->value.string); fxRunScript(the, fxParseScript(the, &stream, fxStringGetter, mxProgramFlag), C_NULL, C_NULL, C_NULL, C_NULL); if (mxTarget->kind == XS_UNDEFINED_KIND) mxPullSlot(mxResult); else { txSlot* from = fxGetInstance(the, the->stack++); txSlot* to = fxGetInstance(the, mxThis); txSlot* fromProperty; txSlot* toProperty; to->next->value.code = from->next->value.code; fromProperty = mxFunctionInstancePrototype(from); toProperty = mxFunctionInstancePrototype(to); *toProperty = *fromProperty; fromProperty = mxFunctionInstanceInfo(from); toProperty = mxFunctionInstanceInfo(to); *toProperty = *fromProperty; } }
void fx_Function_prototype_get_name(txMachine* the) { txSlot* instance = fxCheckFunctionInstance(the, mxThis); txSlot* info = mxFunctionInstanceInfo(instance); txSlot* key = fxGetKey(the, info->value.info.name); if (key) { if (key->kind == XS_KEY_KIND) { mxResult->kind = XS_STRING_KIND; mxResult->value.string = key->value.key.string; } else if (key->kind == XS_KEY_X_KIND) { mxResult->kind = XS_STRING_X_KIND; mxResult->value.string = key->value.key.string; } else { fxCopyStringC(the, mxResult, "["); fxConcatStringC(the, mxResult, key->value.string); fxConcatStringC(the, mxResult, "]"); } return; } *mxResult = mxEmptyString; }
void fx_Function_prototype_bind(txMachine* the) { txSlot* instance = fxToInstance(the, mxThis); txSize length; txSlot* slot; txID id; txSlot* arguments; txSlot* argument; txSize c = mxArgc, i; if (!fxIsFunction(the, instance)) mxTypeError("this is no Function instance"); if (fxHasOwnProperty(the, instance, mxID(_length))) { mxPushSlot(mxThis); fxGetID(the, mxID(_length)); length = fxToInteger(the, the->stack++); if (c > 1) length -= c - 1; if (length < 0) length = 0; mxPop(); } else length = 0; mxPushSlot(mxThis); fxGetID(the, mxID(_name)); mxPushStringC("bound "); fxConcatString(the, the->stack, the->stack + 1); slot = fxNewName(the, the->stack); id = slot->ID; mxPop(); mxPop(); mxPushReference(instance->value.instance.prototype); instance = fxNewFunctionInstance(the, id); mxPullSlot(mxResult); slot = mxFunctionInstanceCode(instance); slot->kind = XS_CALLBACK_KIND; slot->value.callback.address = fx_Function_prototype_bound; slot->value.callback.IDs = (txID*)mxIDs.value.code; slot = mxFunctionInstanceInfo(instance); slot->value.info.length = (txID)length; slot = fxLastProperty(the, instance); slot = fxNextSlotProperty(the, slot, mxThis, mxID(_boundFunction), XS_GET_ONLY); if (c > 0) slot = fxNextSlotProperty(the, slot, mxArgv(0), mxID(_boundThis), XS_GET_ONLY); else slot = fxNextUndefinedProperty(the, slot, mxID(_boundThis), XS_GET_ONLY); mxPush(mxArrayPrototype); arguments = fxNewArrayInstance(the); argument = arguments->next; for (i = 1; i < c; i++) { argument->next = fxNewSlot(the); argument = argument->next; argument->kind = mxArgv(i)->kind; argument->value = mxArgv(i)->value; } arguments->next->value.array.length = mxArgc - 1; fxCacheArray(the, arguments); slot = fxNextSlotProperty(the, slot, the->stack, mxID(_boundArguments), XS_GET_ONLY); mxPop(); }
txBoolean fxNewProperty(txMachine* the, txSlot* instance, txInteger ID, txFlag flag, txSlot* slot) { txSlot** address = &(instance->next); txSlot* property; if (ID >= 0) { txSlot* array = C_NULL; while ((property = *address)) { if (property->ID == XS_NO_ID) { if (property->kind == XS_ARRAY_KIND) { array = property; break; } } else break; address = &(property->next); } if (!array) { array = *address = fxNewSlot(the); array->next = property; array->kind = XS_ARRAY_KIND; array->value.array.address = C_NULL; array->value.array.length = 0; } property = fxSetArrayProperty(the, array, ID); property->kind = slot->kind; property->value = slot->value; return 1; } while ((property = *address)) { if (property->ID == ID) break; address = &(property->next); } if (property) { if (property->flag & XS_DONT_DELETE_FLAG) { if (!(flag & XS_DONT_DELETE_FLAG)) return 0; if ((property->flag & XS_DONT_ENUM_FLAG) != (flag & XS_DONT_ENUM_FLAG)) return 0; if (flag & XS_ACCESSOR_FLAG) { if (property->kind != XS_ACCESSOR_KIND) return 0; if (flag & XS_GETTER_FLAG) { if (property->value.accessor.getter != slot->value.reference) return 0; } if (flag & XS_SETTER_FLAG) { if (property->value.accessor.setter != slot->value.reference) return 0; } } else { if (property->kind == XS_ACCESSOR_KIND) return 0; if (property->flag & XS_DONT_SET_FLAG) { if (!(flag & XS_DONT_DELETE_FLAG)) return 0; if (!fxIsSameSlot(the, property, slot)) return 0; } } } } else { if (instance->flag & XS_DONT_PATCH_FLAG) return 0; *address = property = fxNewSlot(the); property->ID = (txID)ID; } if (flag & XS_ACCESSOR_FLAG) { if (property->kind != XS_ACCESSOR_KIND) { property->kind = XS_ACCESSOR_KIND; property->value.accessor.getter = C_NULL; property->value.accessor.setter = C_NULL; } property->flag = flag & ~XS_ACCESSOR_FLAG; if (flag & XS_GETTER_FLAG) property->value.accessor.getter = slot->value.reference; else property->value.accessor.setter = slot->value.reference; slot = mxFunctionInstancePrototype(slot->value.reference); slot->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; } else { property->flag = flag; property->kind = slot->kind; property->value = slot->value; if (slot->kind == XS_REFERENCE_KIND) { slot = slot->value.reference; if (mxIsFunction(slot)) { property = mxFunctionInstanceInfo(slot); if (property->value.info.name == XS_NO_ID) property->value.info.name = (txID)ID; } } } return 1; }