/* * Copyright (C) 2010-2015 Marvell International Ltd. * Copyright (C) 2002-2010 Kinoma, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ void fxBuildJSON(txMachine* the) { txSlot* xs; mxPush(mxGlobal); mxPush(mxObjectPrototype); fxNewObjectInstance(the); fxNewHostFunction(the, fx_JSON_parse, 2); fxQueueID(the, fxID(the, "parse"), XS_DONT_ENUM_FLAG); fxNewHostFunction(the, fx_JSON_stringify, 3); fxQueueID(the, fxID(the, "stringify"), XS_DONT_ENUM_FLAG); fxQueueID(the, fxID(the, "JSON"), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); the->stack++; xs = fxGetProperty(the, mxGlobal.value.reference, fxID(the, "xs")); mxPush(*xs); mxPush(mxObjectPrototype); fxNewObjectInstance(the); fxNewHostFunction(the, fx_JSON_parse, 1); fxQueueID(the, fxID(the, "parse"), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); fxNewHostFunction(the, fx_JSON_stringify, 1); fxQueueID(the, fxID(the, "serialize"), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); fxQueueID(the, fxID(the, "json"), XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); the->stack++; }
void fxBufferFunctionName(txMachine* the, txString buffer, txSize size, txSlot* function, txString suffix) { txSlot* slot = fxGetProperty(the, function, mxID(_name)); if (slot && ((slot->kind == XS_STRING_KIND) || (slot->kind == XS_STRING_X_KIND))) { c_strncat(buffer, slot->value.string, size - c_strlen(buffer) - 1); c_strncat(buffer, suffix, size - c_strlen(buffer) - 1); } }
void fxBufferObjectName(txMachine* the, txString buffer, txSize size, txSlot* object, txString suffix) { txSlot* slot = fxGetProperty(the, object, mxID(_Symbol_toStringTag)); if (slot && ((slot->kind == XS_STRING_KIND) || (slot->kind == XS_STRING_X_KIND))) { c_strncat(buffer, slot->value.string, size - c_strlen(buffer) - 1); c_strncat(buffer, suffix, size - c_strlen(buffer) - 1); } }
void fx_Error_toString(txMachine* the) { txSlot* anError; txSlot* aProperty; txInteger aLength; anError = fxGetInstance(the, mxThis); aProperty = fxGetProperty(the, anError, fxID(the, "name")); --the->stack; the->stack->kind = aProperty->kind; the->stack->value = aProperty->value; if (the->stack->kind == XS_UNDEFINED_KIND) fxCopyStringC(the, the->stack, "Error"); else fxToString(the, the->stack); aProperty = fxGetProperty(the, anError, fxID(the, "message")); --the->stack; the->stack->kind = aProperty->kind; the->stack->value = aProperty->value; if (the->stack->kind == XS_UNDEFINED_KIND) fxCopyStringC(the, the->stack, ""); else fxToString(the, the->stack); aLength = c_strlen(the->stack->value.string); if (aLength) { aLength += c_strlen((the->stack + 1)->value.string) + 2; mxResult->value.string = (txString)fxNewChunk(the, aLength + 1); mxResult->kind = XS_STRING_KIND; c_strcpy(mxResult->value.string, (the->stack + 1)->value.string); c_strcat(mxResult->value.string, ": "); c_strcat(mxResult->value.string, the->stack->value.string); the->stack++; the->stack++; } else { the->stack++; *mxResult = *(the->stack++); } }
txBoolean fxHasID(txMachine* the, txInteger theID) { txSlot* anInstance; txSlot* aProperty; fxToInstance(the, the->stack); anInstance = fxGetInstance(the, the->stack); aProperty = fxGetProperty(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 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 fxSerializeJSONProperty(txMachine* the, txJSONSerializer* theSerializer, txFlag* theFlag) { txSlot* aWrapper = the->stack + 2; txSlot* aValue = the->stack + 1; txSlot* aKey = the->stack; txSlot* anInstance; txSlot* aProperty; txFlag aFlag; txIndex aLength, anIndex; txFlag aMask; if (mxIsReference(aValue)) { anInstance = fxGetInstance(the, aValue); if (anInstance->flag & XS_LEVEL_FLAG) fxSerializeJSONError(the, theSerializer, XS_TYPE_ERROR); aProperty = fxGetProperty(the, anInstance, the->toJSONID); if (aProperty && mxIsReference(aProperty) && mxIsFunction(fxGetInstance(the, aProperty))) { *(--the->stack) = *aKey; mxInitSlot(--the->stack, XS_INTEGER_KIND); the->stack->value.integer = 1; /* THIS */ *(--the->stack) = *aValue; /* FUNCTION */ *(--the->stack) = *aProperty; /* RESULT */ mxZeroSlot(--the->stack); fxRunID(the, the->toJSONID); *aValue = *(the->stack++); } } else anInstance = C_NULL; if (theSerializer->replacer) { *(--the->stack) = *aKey; *(--the->stack) = *aValue; mxInitSlot(--the->stack, XS_INTEGER_KIND); the->stack->value.integer = 2; /* THIS */ *(--the->stack) = *aWrapper; /* FUNCTION */ *(--the->stack) = *theSerializer->replacer; /* RESULT */ mxZeroSlot(--the->stack); fxRunID(the, XS_NO_ID); *aValue = *(the->stack++); } again: switch (aValue->kind) { case XS_NULL_KIND: fxSerializeJSONName(the, theSerializer, theFlag); fxSerializeJSONChars(the, theSerializer, "null"); break; case XS_BOOLEAN_KIND: fxSerializeJSONName(the, theSerializer, theFlag); fxSerializeJSONChars(the, theSerializer, aValue->value.boolean ? "true" : "false"); break; case XS_INTEGER_KIND: fxSerializeJSONName(the, theSerializer, theFlag); fxSerializeJSONInteger(the, theSerializer, aValue->value.integer); break; case XS_NUMBER_KIND: fxSerializeJSONName(the, theSerializer, theFlag); fxSerializeJSONNumber(the, theSerializer, aValue->value.number); break; case XS_STRING_KIND: fxSerializeJSONName(the, theSerializer, theFlag); fxSerializeJSONString(the, theSerializer, aValue->value.string); break; case XS_ARRAY_KIND: fxSerializeJSONName(the, theSerializer, theFlag); anInstance->flag |= XS_LEVEL_FLAG; fxSerializeJSONChar(the, theSerializer, '['); theSerializer->level++; fxSerializeJSONIndent(the, theSerializer); aFlag = 4; aLength = aValue->value.array.length; for (anIndex = 0; anIndex < aLength; anIndex++) { aProperty = aValue->value.array.address + anIndex; mxInitSlot(--the->stack, aProperty->kind); the->stack->value = aProperty->value; mxInitSlot(--the->stack, XS_INTEGER_KIND); the->stack->value.integer = anIndex; fxSerializeJSONProperty(the, theSerializer, &aFlag); } theSerializer->level--; fxSerializeJSONIndent(the, theSerializer); fxSerializeJSONChar(the, theSerializer, ']'); anInstance->flag &= ~XS_LEVEL_FLAG; break; case XS_REFERENCE_KIND: case XS_ALIAS_KIND: anInstance = fxGetInstance(the, aValue); if (anInstance->flag & XS_VALUE_FLAG) { aValue = anInstance->next; goto again; } fxSerializeJSONName(the, theSerializer, theFlag); fxSerializeJSONChar(the, theSerializer, '{'); theSerializer->level++; fxSerializeJSONIndent(the, theSerializer); aFlag = 2; if ((the->frame->flag & XS_SANDBOX_FLAG) || (anInstance->flag & XS_SANDBOX_FLAG)) { if (anInstance->flag & XS_SANDBOX_FLAG) anInstance = anInstance->value.instance.prototype; aMask = XS_DONT_ENUM_FLAG | XS_DONT_SCRIPT_FLAG; } else aMask = XS_DONT_ENUM_FLAG | XS_SANDBOX_FLAG; anInstance->flag |= XS_LEVEL_FLAG; aProperty = anInstance->next; while (aProperty) { if (!(aProperty->flag & aMask)) { txID anID = aProperty->ID; if (anID != XS_NO_ID) { mxInitSlot(--the->stack, aProperty->kind); the->stack->value = aProperty->value; if (anID < 0) { txSlot *aSymbol = fxGetSymbol(the, aProperty->ID); mxInitSlot(--the->stack, XS_STRING_KIND); the->stack->value.string = aSymbol->value.symbol.string; } else { mxInitSlot(--the->stack, XS_INTEGER_KIND); the->stack->value.integer = anID; } fxSerializeJSONProperty(the, theSerializer, &aFlag); } } aProperty = aProperty->next; } theSerializer->level--; fxSerializeJSONIndent(the, theSerializer); fxSerializeJSONChar(the, theSerializer, '}'); anInstance->flag &= ~XS_LEVEL_FLAG; break; default: if (*theFlag & 4) { if (*theFlag & 1) { fxSerializeJSONChars(the, theSerializer, ","); fxSerializeJSONIndent(the, theSerializer); } else *theFlag |= 1; fxSerializeJSONChars(the, theSerializer, "null"); } break; } the->stack++; // POP VALUE }
txSlot* fxSetProperty(txMachine* the, txSlot* theInstance, txInteger theID, txFlag* theFlag) { txSlot* result; txSlot** instanceAddress; txSlot* prototype; txSlot* aProperty; mxCheck(the, theInstance->kind == XS_INSTANCE_KIND); if (theInstance->flag & XS_SHARED_FLAG) { txSlot* alias = the->aliasArray[theInstance->ID]; txSlot** aliasAddress = C_NULL; if (alias) { aliasAddress = &(alias->next); while ((result = *aliasAddress)) { if (result->ID == theID) return result; aliasAddress = &(result->next); } } aProperty = fxGetProperty(the, theInstance, theID); if (!theFlag && aProperty) { if (aProperty->kind == XS_ACCESSOR_KIND) return aProperty; if (aProperty->flag & XS_DONT_SET_FLAG) return aProperty; } if (theInstance->flag & XS_DONT_PATCH_FLAG) return C_NULL; if (!aliasAddress) { alias = fxNewSlot(the); alias->kind = XS_INSTANCE_KIND; alias->value.instance.garbage = C_NULL; alias->value.instance.prototype = C_NULL; the->aliasArray[theInstance->ID] = alias; aliasAddress = &(alias->next); } *aliasAddress = result = fxNewSlot(the); result->ID = (txID)theID; if (aProperty) { result->flag = aProperty->flag; result->kind = aProperty->kind; result->value = aProperty->value; } else { if (theFlag) result->flag = *theFlag; } return result; } if (theInstance->flag & XS_VALUE_FLAG) { if (theID < 0) { if (theInstance->next->kind == XS_GLOBAL_KIND) return fxSetGlobalProperty(the, theInstance, theID, theFlag); if (theInstance->next->kind == XS_STAR_KIND) return fxSetStarProperty(the, theInstance, theID); if (theInstance->next->kind == XS_PROXY_KIND) return fxSetProxyProperty(the, theInstance, theID); } else { if (theInstance->next->kind == XS_TYPED_ARRAY_KIND) return fxSetTypedArrayProperty(the, theInstance, theID); if (theInstance->next->kind == XS_STRING_KIND) return fxSetStringProperty(the, theInstance, theID); if (theInstance->next->kind == XS_PARAMETERS_KIND) return fxSetParametersProperty(the, theInstance, theID); if (theInstance->next->kind == XS_PROXY_KIND) return fxSetProxyProperty(the, theInstance, theID); } } if (theID >= 0) { instanceAddress = &(theInstance->next); while ((aProperty = *instanceAddress)) { if (aProperty->ID == XS_NO_ID) { if (aProperty->kind == XS_ARRAY_KIND) { return fxSetArrayProperty(the, aProperty, theID); } } else break; instanceAddress = &(aProperty->next); } *instanceAddress = result = fxNewSlot(the); result->next = aProperty; result->kind = XS_ARRAY_KIND; result->value.array.address = C_NULL; result->value.array.length = 0; return fxSetArrayProperty(the, result, theID); } instanceAddress = &(theInstance->next); while ((result = *instanceAddress)) { if (result->ID == theID) return result; instanceAddress = &(result->next); } prototype = theInstance->value.instance.prototype; if (prototype) aProperty = fxGetProperty(the, prototype, theID); else aProperty = C_NULL; if (!theFlag && aProperty) { if (aProperty->kind == XS_ACCESSOR_KIND) return aProperty; if (aProperty->flag & XS_DONT_SET_FLAG) return aProperty; } if (theInstance->flag & XS_DONT_PATCH_FLAG) return C_NULL; *instanceAddress = result = fxNewSlot(the); result->ID = (txID)theID; if (aProperty) { result->flag = aProperty->flag; result->kind = aProperty->kind; result->value = aProperty->value; } else { if (theFlag) result->flag = *theFlag; } return result; }
txBoolean fxHasProperty(txMachine* the, txSlot* theInstance, txInteger theID) { if ((theInstance->flag & XS_VALUE_FLAG) && (theInstance->next->kind == XS_PROXY_KIND)) return fxHasProxyProperty(the, theInstance, theID); return (fxGetProperty(the, theInstance, theID)) ? 1 : 0; }