void fxPutID(txMachine* the, txInteger theID, txFlag theFlag, txFlag theMask) { txSlot* anInstance; txSlot* aProperty; txFlag aFlag = theFlag & ~XS_ACCESSOR_FLAG; txFlag aMask = theMask & ~XS_ACCESSOR_FLAG; fxToInstance(the, the->stack); anInstance = fxGetInstance(the, the->stack); if (!anInstance) mxDebugID(XS_TYPE_ERROR, "set %s: shared instance", theID); aProperty = fxSetProperty(the, anInstance, theID, &aFlag); the->stack++; aProperty->flag = (aProperty->flag & ~aMask) | aFlag; if (theFlag & XS_ACCESSOR_FLAG) { if (aProperty->kind != XS_ACCESSOR_KIND) { aProperty->kind = XS_ACCESSOR_KIND; aProperty->value.accessor.getter = C_NULL; aProperty->value.accessor.setter = C_NULL; } if (theFlag & XS_GETTER_FLAG) aProperty->value.accessor.getter = the->stack->value.reference; else aProperty->value.accessor.setter = the->stack->value.reference; } else { aProperty->kind = the->stack->kind; aProperty->value = the->stack->value; } }
void fx_Function_prototype_apply(txMachine* the) { txInteger c, i; if ((mxArgc < 2) || (mxArgv(1)->kind == XS_UNDEFINED_KIND) || (mxArgv(1)->kind == XS_NULL_KIND)) c = 0; else { fxToInstance(the, mxArgv(1)); mxPushSlot(mxArgv(1)); fxGetID(the, mxID(_length)); c = fxToInteger(the, the->stack); the->stack++; for (i = 0; i < c; i++) { mxPushSlot(mxArgv(1)); fxGetID(the, (txID)i); } } /* ARGC */ mxPushInteger(c); /* THIS */ if (mxArgc < 1) mxPushUndefined(); else mxPushSlot(mxArgv(0)); /* FUNCTION */ mxPushSlot(mxThis); fxCall(the); mxPullSlot(mxResult); }
void fxSetID(txMachine* the, txInteger theID) { txSlot* anInstance; txSlot* aProperty; txSlot* aFunction; fxToInstance(the, the->stack); anInstance = fxGetInstance(the, the->stack); if (!anInstance) mxDebugID(XS_TYPE_ERROR, "C: xsSet %s: shared instance", theID); aProperty = fxSetProperty(the, anInstance, theID, C_NULL); if (!aProperty) mxDebugID(XS_TYPE_ERROR, "C: xsSet %s: not extensible", theID); if (aProperty->kind == XS_ACCESSOR_KIND) { mxPushInteger(1); /* SWAP THIS */ the->scratch = *(the->stack); *(the->stack) = *(the->stack + 1); *(the->stack + 1) = the->scratch; /* FUNCTION */ aFunction = aProperty->value.accessor.setter; if (!mxIsFunction(aFunction)) mxDebugID(XS_TYPE_ERROR, "C: xsCall set %s: no function", theID); mxPushReference(aFunction); fxCall(the); } else { the->stack++; if (aProperty->flag & XS_DONT_SET_FLAG) mxDebugID(XS_TYPE_ERROR, "C: xsSet %s: no permission", theID); aProperty->kind = the->stack->kind; aProperty->value = the->stack->value; } }
txSlot* fxCoerceToArray(txMachine* the, txSlot* slot) { txSlot* instance = fxToInstance(the, slot); txSlot** address = &(instance->next); txSlot* array = C_NULL; txSlot* property; while ((property = *address)) { if (property->ID == XS_NO_ID) { if ((property->kind == XS_ARRAY_KIND) || (property->kind == XS_PARAMETERS_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; } return array; }
void fxRunForIn(txMachine* the) { txSlot* limit = the->stack; txSlot* slot = fxToInstance(the, limit); while (slot) { fxEachInstanceProperty(the, slot, XS_EACH_ENUMERABLE_FLAG | XS_EACH_STRING_FLAG, fxRunForInProperty, limit, slot); slot = fxGetParent(the, slot); } slot = the->stack; while (slot < limit) { txInteger id = slot->value.integer; if (id < 0) { txSlot* key = fxGetKey(the, (txID)id); if (key && (key->flag & XS_DONT_ENUM_FLAG)) { if (key->kind == XS_KEY_KIND) { slot->kind = XS_STRING_KIND; slot->value.string = key->value.key.string; } else { slot->kind = XS_STRING_X_KIND; slot->value.string = key->value.key.string; } } else { slot->kind = XS_SYMBOL_KIND; slot->value.ID = (txID)id; } } slot++; } limit->kind = XS_NULL_KIND; }
void fx_Function_apply(txMachine* the) { txInteger aCount, anIndex; if ((mxArgc < 2) || (mxArgv(1)->kind == XS_UNDEFINED_KIND) || (mxArgv(1)->kind == XS_NULL_KIND)) aCount = 0; else { fxToInstance(the, mxArgv(1)); *(--the->stack) = *mxArgv(1); fxGetID(the, the->lengthID); aCount = fxToInteger(the, the->stack); the->stack++; for (anIndex = 0; anIndex < aCount; anIndex++) { *(--the->stack) = *mxArgv(1); fxGetID(the, (txID)anIndex); } } /* #PARAM */ mxZeroSlot(--the->stack); the->stack->kind = XS_INTEGER_KIND; the->stack->value.integer = aCount; /* THIS */ if (mxArgc < 1) { mxZeroSlot(--the->stack); } else *(--the->stack) = *mxArgv(0); /* FUNCTION */ *(--the->stack) = *mxThis; /* RESULT */ mxZeroSlot(--the->stack); fxRunID(the, XS_NO_ID); *mxResult = *(the->stack++); }
void fxCopyObject(txMachine* the) { txSlot* toInstance; txSlot* fromInstance; txSlot* toProperty; txSlot* fromProperty; txSlot** firstAddress; txSlot** lastAddress; fxToInstance(the, the->stack + 1); toInstance = fxGetInstance(the, the->stack + 1); fxToInstance(the, the->stack); fromInstance = fxGetInstance(the, the->stack); firstAddress = &toInstance->next; while ((toProperty = *firstAddress)) firstAddress = &toProperty->next; lastAddress = firstAddress; fromProperty = fromInstance->next; while (fromProperty) { if (fromProperty->ID != XS_NO_ID) { toProperty = toInstance->next; while (toProperty != *firstAddress) { if (toProperty->ID == fromProperty->ID) break; toProperty = toProperty->next; } if (toProperty != *firstAddress) { toProperty->kind = fromProperty->kind; toProperty->value = fromProperty->value; } else { *lastAddress = toProperty = fxNewSlot(the); toProperty->ID = fromProperty->ID; toProperty->flag = fromProperty->flag; toProperty->kind = fromProperty->kind; toProperty->value = fromProperty->value; lastAddress = &toProperty->next; } } fromProperty = fromProperty->next; } the->stack++; }
txBoolean fxHasOwnID(txMachine* the, txInteger theID) { txSlot* anInstance; txSlot* aProperty; fxToInstance(the, the->stack); anInstance = fxGetInstance(the, the->stack); aProperty = fxGetOwnProperty(the, anInstance, theID); the->stack++; if (aProperty) { the->scratch.kind = aProperty->kind; the->scratch.value = aProperty->value; return 1; } the->scratch.kind = XS_UNDEFINED_KIND; return 0; }
void fx_Function_set_prototype(txMachine* the) { txSlot* aFunction; txSlot* aSlot; aFunction = fxGetInstance(the, mxThis); mxCheckFunction(aFunction); aSlot = aFunction->next->next->next; if (aSlot->flag & XS_DONT_SET_FLAG) mxDebug0(the, XS_NO_ERROR, "set prototype: no permission"); else { if (aFunction->flag & XS_SHARED_FLAG) mxDebug0(the, XS_TYPE_ERROR, "Function.set prototype: this is shared"); fxToInstance(the, mxArgv(0)); aSlot->value = mxArgv(0)->value; aSlot->kind = mxArgv(0)->kind; } }
txSlot* fxNewHostConstructor(txMachine* the, txCallback theCallback, txInteger theLength, txInteger name) { txSlot* aStack; txSlot* instance; txSlot* property; fxToInstance(the, the->stack); aStack = the->stack; instance = fxNewHostFunction(the, theCallback, theLength, name); property = fxLastProperty(the, instance); fxNextSlotProperty(the, property, aStack, mxID(_prototype), XS_GET_ONLY); property = fxSetProperty(the, fxGetInstance(the, aStack), mxID(_constructor), C_NULL); property->flag = XS_DONT_ENUM_FLAG; property->kind = the->stack->kind; property->value = the->stack->value; *aStack = *the->stack; the->stack++; return instance; }
void fx_Function_prototype_set_prototype(txMachine* the) { txSlot* instance = fxCheckFunctionInstance(the, mxThis); txSlot* slot = mxFunctionInstancePrototype(instance); if (slot->flag & XS_DONT_SET_FLAG) { if (the->frame->next->flag & XS_STRICT_FLAG) mxTypeError("set \"prototype\": const"); return; } if (instance->flag & XS_SHARED_FLAG) mxTypeError("set \"prototype\": shared"); if ((mxArgc == 0) || (mxArgv(0)->kind == XS_UNDEFINED_KIND) || (mxArgv(0)->kind == XS_NULL_KIND)) { slot->kind = XS_NULL_KIND; } else { fxToInstance(the, mxArgv(0)); slot->value = mxArgv(0)->value; slot->kind = mxArgv(0)->kind; } }
void fxGetID(txMachine* the, txInteger theID) { txSlot* anInstance; txSlot* aProperty; txSlot* aFunction; fxToInstance(the, the->stack); anInstance = fxGetInstance(the, the->stack); aProperty = fxGetProperty(the, anInstance, theID); if (!aProperty) { the->stack->kind = XS_UNDEFINED_KIND; //mxDebugID(XS_NO_ERROR, "C: xsGet %s: no property", theID); } else if (aProperty->kind == XS_ACCESSOR_KIND) { aFunction = aProperty->value.accessor.getter; if (mxIsFunction(aFunction)) { mxPushInteger(0); /* SWAP THIS */ the->scratch = *(the->stack); *(the->stack) = *(the->stack + 1); *(the->stack + 1) = the->scratch; /* FUNCTION */ aFunction = aProperty->value.accessor.getter; if (!mxIsFunction(aFunction)) mxDebugID(XS_TYPE_ERROR, "C: xsCall get %s: no function", theID); mxPushReference(aFunction); fxCall(the); } else the->stack->kind = XS_UNDEFINED_KIND; } else { the->stack->kind = aProperty->kind; the->stack->value = aProperty->value; } }
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(); }
void fxNewInstanceOf(txMachine* the) { txSlot* aParent; if (the->stack->kind == XS_NULL_KIND) { txSlot* instance = fxNewSlot(the); instance->kind = XS_INSTANCE_KIND; instance->value.instance.garbage = C_NULL; instance->value.instance.prototype = C_NULL; the->stack->value.reference = instance; the->stack->kind = XS_REFERENCE_KIND; } else { fxToInstance(the, the->stack); aParent = fxGetInstance(the, the->stack); if (aParent->flag & XS_VALUE_FLAG) { switch (aParent->next->kind) { case XS_CALLBACK_KIND: case XS_CODE_KIND: fxNewFunctionInstance(the, XS_NO_ID); break; case XS_ARRAY_KIND: fxNewArrayInstance(the); break; case XS_STRING_KIND: case XS_STRING_X_KIND: fxNewStringInstance(the); break; case XS_BOOLEAN_KIND: fxNewBooleanInstance(the); break; case XS_NUMBER_KIND: fxNewNumberInstance(the); break; case XS_DATE_KIND: fxNewDateInstance(the); break; case XS_REGEXP_KIND: fxNewRegExpInstance(the); break; case XS_SYMBOL_KIND: fxNewSymbolInstance(the); break; case XS_HOST_KIND: fxNewHostInstance(the); break; case XS_PROMISE_KIND: fxNewPromiseInstance(the); break; case XS_PROXY_KIND: fxNewProxyInstance(the); break; case XS_MAP_KIND: fxNewMapInstance(the); break; case XS_SET_KIND: fxNewSetInstance(the); break; case XS_WEAK_MAP_KIND: fxNewWeakMapInstance(the); break; case XS_WEAK_SET_KIND: fxNewWeakSetInstance(the); break; case XS_ARRAY_BUFFER_KIND: fxNewArrayBufferInstance(the); break; case XS_DATA_VIEW_KIND: fxNewDataViewInstance(the); break; case XS_TYPED_ARRAY_KIND: fxNewTypedArrayInstance(the, aParent->next->value.typedArray); break; case XS_STACK_KIND: fxNewGeneratorInstance(the); break; default: mxSyntaxError("C: xsNewInstanceOf: invalid prototype"); break; } } else fxNewObjectInstance(the); } }