void fxBuildFunction(txMachine* the) { mxPush(mxGlobal); mxPush(mxObjectPrototype); fxNewFunctionInstance(the); fxNewHostFunction(the, fx_Function_get_length, 0); fxQueueID(the, the->lengthID, XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG | XS_GETTER_FLAG); fxNewHostFunction(the, fx_Function_get_prototype, 0); fxQueueID(the, the->prototypeID, XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_GETTER_FLAG); fxNewHostFunction(the, fx_Function_set_prototype, 1); fxQueueID(the, the->prototypeID, XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_SETTER_FLAG); fxNewHostFunction(the, fx_Function_apply, 2); fxQueueID(the, fxID(the, "apply"), XS_DONT_ENUM_FLAG); fxNewHostFunction(the, fx_Function_bind, 1); fxQueueID(the, fxID(the, "bind"), XS_DONT_ENUM_FLAG); fxNewHostFunction(the, fx_Function_call, 1); fxQueueID(the, fxID(the, "call"), XS_DONT_ENUM_FLAG); fxAliasInstance(the, the->stack); mxFunctionPrototype = *the->stack; fxNewHostConstructor(the, fx_Function, 1); the->stack->value.reference->next->next->next->flag |= XS_DONT_SET_FLAG; *(--the->stack) = mxFunctionPrototype; fxPutID(the, fxID(the, "constructor"), XS_DONT_ENUM_FLAG, XS_DONT_ENUM_FLAG); fxQueueID(the, fxID(the, "Function"), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); the->stack++; }
void fx_Function_bind(txMachine* the) { txSlot* aFunction; txSlot* aProperty; txSlot* anArray; txSlot* anItem; txSize aCount, anIndex; aFunction = fxGetInstance(the, mxThis); if (!mxIsFunction(aFunction)) mxDebug0(the, XS_TYPE_ERROR, "this is no Function"); if (mxArgc < 1) mxDebug0(the, XS_SYNTAX_ERROR, "Function.prototype.bind: no this parameter"); aProperty = aFunction->next; if (aProperty->kind == XS_CODE_KIND) aCount = *(aProperty->value.code + 4); else aCount = aProperty->value.callback.length; aCount -= mxArgc - 1; if (aCount < 0) aCount = 0; mxPush(mxFunctionPrototype); aFunction = fxNewFunctionInstance(the); *mxResult = *(the->stack++); aProperty = aFunction->next; aProperty->kind = XS_CALLBACK_KIND; aProperty->value.callback.address = fx_Function_bound; aProperty->value.callback.length = aCount; aProperty = fxSetProperty(the, aFunction, fxID(the, "boundFunction"), C_NULL); aProperty->kind = mxThis->kind; aProperty->value = mxThis->value; aProperty = fxSetProperty(the, aFunction, fxID(the, "boundThis"), C_NULL); aProperty->kind = mxArgv(0)->kind; aProperty->value = mxArgv(0)->value; aProperty = fxSetProperty(the, aFunction, fxID(the, "boundArguments"), C_NULL); mxPush(mxArrayPrototype); anArray = fxNewArrayInstance(the); aProperty->kind = the->stack->kind; aProperty->value = the->stack->value; the->stack++; anItem = anArray->next; for (anIndex = 1; anIndex < mxArgc; anIndex++) { anItem->next = fxNewSlot(the); anItem = anItem->next; anItem->kind = mxArgv(anIndex)->kind; anItem->value = mxArgv(anIndex)->value; } anArray->next->value.array.length = mxArgc - 1; fxCacheArray(the, anArray); }
void fxBuildGlobal(txMachine* the) { static const txHostFunctionBuilder gx_global_builders[] = { { fx_decodeURI, 1, _decodeURI }, { fx_decodeURIComponent, 1, _decodeURIComponent }, { fx_encodeURI, 1, _encodeURI }, { fx_encodeURIComponent, 1, _encodeURIComponent }, { fx_escape, 1, _escape }, { fx_eval, 1, _eval }, { fx_trace, 1, _trace }, { fx_unescape, 1, _unescape }, { C_NULL, 0, 0 }, }; const txHostFunctionBuilder* builder; txSlot* slot; fxNewGlobalInstance(the); mxPull(mxGlobal); fxNewInstance(the); mxPull(mxObjectPrototype); mxPush(mxObjectPrototype); fxNewFunctionInstance(the, XS_NO_ID); mxPull(mxFunctionPrototype); for (builder = gx_global_builders; builder->callback; builder++) { fxNewHostFunctionGlobal(the, builder->callback, builder->length, mxID(builder->id), XS_DONT_ENUM_FLAG); the->stack++; } slot = fxSetGlobalProperty(the, mxGlobal.value.reference, mxID(_undefined), C_NULL); slot->flag = XS_GET_ONLY; mxPush(mxObjectPrototype); slot = fxNewObjectInstance(the); slot = fxNextHostFunctionProperty(the, slot, fx_Iterator_iterator, 0, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG); mxPull(mxIteratorPrototype); mxPush(mxIteratorPrototype); slot = fxLastProperty(the, fxNewObjectInstance(the)); slot = fxNextHostFunctionProperty(the, slot, fx_Enumerator_next, 0, mxID(_next), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG); fxNewHostConstructor(the, fx_Enumerator, 0, XS_NO_ID); mxPull(mxEnumeratorFunction); }
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); } }
void fx_Function(txMachine* the) { txSlot* aFunction; txInteger aCount, anIndex, aFileIndex, aLineIndex; txFlag aFlag; txSlot* aSlot; txStringStream aStream; txByte* aCode; txSlot* aProperty; if (mxResult->kind == XS_UNDEFINED_KIND) { mxPush(mxFunctionPrototype); aFunction = fxNewFunctionInstance(the); *mxResult = *(the->stack++); } else aFunction = fxGetOwnInstance(the, mxResult); mxCheckFunction(aFunction); aCount = mxArgc; anIndex = 0; aFileIndex = aCount - 2; aLineIndex = aCount - 1; aFlag = XS_NO_FLAG; if ((aCount >= 4) && (mxArgv(aLineIndex)->kind == XS_INTEGER_KIND)) { aCount -= 2; aFlag |= XS_DEBUG_FLAG; } aSlot = fxGetInstance(the, mxThis); if (aSlot && (aSlot->flag & XS_SANDBOX_FLAG)) aFlag |= XS_SANDBOX_FLAG; else aFlag |= the->frame->next->flag & XS_SANDBOX_FLAG; mxZeroSlot(--the->stack); fxCopyStringC(the, the->stack, "("); while (aCount > 1) { fxToString(the, mxArgv(anIndex)); fxConcatString(the, the->stack, mxArgv(anIndex)); if (aCount > 2) fxConcatStringC(the, the->stack, ", "); aCount--; anIndex++; } fxConcatStringC(the, the->stack, "){"); if (aCount > 0) { fxToString(the, mxArgv(anIndex)); fxConcatString(the, the->stack, mxArgv(anIndex)); } fxConcatStringC(the, the->stack, "}"); aStream.slot = the->stack; aStream.offset = 0; aStream.size = c_strlen(the->stack->value.string); #ifdef mxDebug if (aFlag & XS_DEBUG_FLAG) aCode = fxParseScript(the, &aStream, fxStringGetter, fxNewFile(the, mxArgv(aFileIndex)), mxArgv(aLineIndex)->value.integer, aFlag, C_NULL); else #endif aCode = fxParseScript(the, &aStream, fxStringGetter, C_NULL, 0, aFlag, C_NULL); aFunction->next->value.code = aCode; aProperty = fxSetProperty(the, aFunction, the->bodyID, C_NULL); aProperty->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG; aProperty->value.string = mxArgv(anIndex)->value.string; aProperty->kind = mxArgv(anIndex)->kind; the->stack++; }