File indexing completed on 2024-05-12 15:43:24
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 2012 Bernd Buschinski (b.buschinski@googlemail.com) 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 * 0020 */ 0021 0022 #include "json_object.h" 0023 0024 #include "jsonlexer.h" 0025 #include "lookup.h" 0026 #include "array_instance.h" 0027 #include "jsonstringify.h" 0028 0029 #include "json_object.lut.h" 0030 0031 using namespace KJS; 0032 0033 // ------------------------------ JSONObjectImp -------------------------------- 0034 0035 const ClassInfo JSONObjectImp::info = { "JSON", nullptr, &jsonTable, nullptr }; 0036 0037 /* Source for json_object.lut.h 0038 @begin jsonTable 2 0039 parse JSONObjectImp::Parse DontEnum|Function 2 0040 stringify JSONObjectImp::Stringify DontEnum|Function 3 0041 @end 0042 */ 0043 0044 JSONObjectImp::JSONObjectImp(ExecState *, ObjectPrototype *objProto) 0045 : JSObject(objProto) 0046 { 0047 } 0048 0049 bool JSONObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 0050 { 0051 // As of ECMA 5.1r6 JSON only has 2 functions, so only functionSlot is needed 0052 return getStaticFunctionSlot<JSONFuncImp, JSObject>(exec, &jsonTable, this, propertyName, slot); 0053 } 0054 0055 // ------------------------------ JSONFuncImp -------------------------------- 0056 0057 JSONFuncImp::JSONFuncImp(ExecState *exec, int i, int l, const Identifier &name) 0058 : InternalFunctionImp(static_cast<FunctionPrototype *>(exec->lexicalInterpreter()->builtinFunctionPrototype()), name), 0059 id(i) 0060 { 0061 putDirect(exec->propertyNames().length, l, DontDelete | ReadOnly | DontEnum); 0062 } 0063 0064 static void reviver(ExecState *exec, JSValue *value, JSObject *func) 0065 { 0066 if (exec->hadException()) { 0067 return; 0068 } 0069 0070 JSType type = JSValue::type(value); 0071 switch (type) { 0072 case ObjectType: { 0073 JSObject *obj = JSValue::getObject(value); 0074 bool isArray = obj->inherits(&ArrayInstance::info); 0075 bool validArrayIndex = false; 0076 0077 PropertyNameArray names; 0078 obj->getOwnPropertyNames(exec, names, KJS::PropertyMap::ExcludeDontEnumProperties); 0079 const int nameSize = names.size(); 0080 for (int i = 0; i < nameSize; ++i) { 0081 // For Array only take properties that are valid Array indexes 0082 if (isArray) { 0083 names[i].toArrayIndex(&validArrayIndex); 0084 if (!validArrayIndex) { 0085 continue; 0086 } 0087 } 0088 0089 JSValue *val = obj->get(exec, names[i]); 0090 0091 List args; 0092 args.append(jsString(names[i].ustring())); 0093 args.append(val); 0094 0095 JSValue *ret = func->call(exec, obj, args); 0096 if (exec->hadException()) { 0097 return; 0098 } 0099 if (JSValue::isUndefined(ret)) { 0100 obj->deleteProperty(exec, names[i]); 0101 } else { 0102 obj->put(exec, names[i], ret); 0103 reviver(exec, ret, func); 0104 } 0105 } 0106 break; 0107 } 0108 case NullType: 0109 case NumberType: 0110 case BooleanType: 0111 case StringType: 0112 break; 0113 case UnspecifiedType: 0114 case GetterSetterType: 0115 case UndefinedType: 0116 // should never be reached, as JSON doesn't know them 0117 // and we only have json data here 0118 ASSERT_NOT_REACHED(); 0119 break; 0120 } 0121 } 0122 0123 JSValue *JSONFuncImp::callAsFunction(ExecState *exec, JSObject * /*thisObj*/, const List &args) 0124 { 0125 switch (id) { 0126 case JSONObjectImp::Parse: { 0127 if (args.size() < 1) { 0128 return throwError(exec, SyntaxError, "Invalid JSON Syntax"); 0129 } 0130 0131 JSONParser parser(JSValue::toString(args[0], exec)); 0132 if (exec->hadException()) { 0133 return jsUndefined(); 0134 } 0135 JSValue *val = parser.tryParse(exec); 0136 0137 if (!val) { 0138 return throwError(exec, SyntaxError, "Invalid JSON Syntax"); 0139 } 0140 0141 if (args.size() < 2) { 0142 return val; 0143 } 0144 0145 JSValue *func = args[1]; 0146 if (JSValue::implementsCall(func)) { 0147 JSObject *function = JSValue::getObject(func); 0148 0149 List args; 0150 args.append(jsString("")); 0151 args.append(val); 0152 0153 JSObject *jsobjectArg = JSValue::toObject(val, exec); 0154 if (exec->hadException()) { 0155 return jsUndefined(); 0156 } 0157 JSValue *ret = function->call(exec, jsobjectArg, args); 0158 if (JSValue::isUndefined(ret)) { 0159 return ret; 0160 } else { 0161 reviver(exec, ret, function); 0162 if (exec->hadException()) { 0163 return jsUndefined(); 0164 } 0165 } 0166 } 0167 0168 return val; 0169 } 0170 case JSONObjectImp::Stringify: { 0171 JSValue *object = args[0]; 0172 JSONStringify stringifier(exec, args[1], args[2]); 0173 0174 JSONStringify::StringifyState state; 0175 JSValue *ret = stringifier.stringify(exec, object, state); 0176 switch (state) { 0177 case JSONStringify::Success: 0178 return ret; 0179 case JSONStringify::FailedCyclic: 0180 return throwError(exec, TypeError, "cyclic object value"); 0181 case JSONStringify::FailedStackLimitExceeded: 0182 return throwError(exec, TypeError, "object stack limit exceeded"); 0183 case JSONStringify::FailedException: 0184 //stringify already got an exception 0185 return jsUndefined(); 0186 } 0187 } 0188 default: 0189 ASSERT_NOT_REACHED(); 0190 } 0191 0192 return jsUndefined(); 0193 }