diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/runtime/JSONObject.cpp | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSONObject.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSONObject.cpp | 166 |
1 files changed, 111 insertions, 55 deletions
diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp index 20244652f..982628917 100644 --- a/Source/JavaScriptCore/runtime/JSONObject.cpp +++ b/Source/JavaScriptCore/runtime/JSONObject.cpp @@ -36,7 +36,7 @@ #include "LocalScope.h" #include "Lookup.h" #include "ObjectConstructor.h" -#include "JSCInlines.h" +#include "Operations.h" #include "PropertyNameArray.h" #include <wtf/MathExtras.h> #include <wtf/text/StringBuilder.h> @@ -45,8 +45,8 @@ namespace JSC { STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSONObject); -EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState*); -EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*); +static EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState*); +static EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*); } @@ -63,8 +63,6 @@ void JSONObject::finishCreation(VM& vm) { Base::finishCreation(vm); ASSERT(inherits(info())); - - putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "JSON"), DontEnum | ReadOnly); } // PropertyNameForFunctionCall objects must be on the stack, since the JSValue that they create is not marked. @@ -109,10 +107,11 @@ private: friend class Holder; + static void appendQuotedString(StringBuilder&, const String&); + JSValue toJSON(JSValue, const PropertyNameForFunctionCall&); - JSValue toJSONImpl(JSValue, const PropertyNameForFunctionCall&); - enum StringifyResult { StringifyFailed, StringifySucceeded, StringifyFailedDueToUndefinedOrSymbolValue }; + enum StringifyResult { StringifyFailed, StringifySucceeded, StringifyFailedDueToUndefinedValue }; StringifyResult appendStringifiedValue(StringBuilder&, JSValue, JSObject* holder, const PropertyNameForFunctionCall&); bool willIndent() const; @@ -146,9 +145,6 @@ static inline JSValue unwrapBoxedPrimitive(ExecState* exec, JSValue value) return object->toString(exec); if (object->inherits(BooleanObject::info())) return object->toPrimitive(exec); - - // Do not unwrap SymbolObject to Symbol. It is not performed in the spec. - // http://www.ecma-international.org/ecma-262/6.0/#sec-serializejsonproperty return value; } @@ -211,7 +207,7 @@ Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const : m_exec(exec) , m_replacer(replacer) , m_usingArrayReplacer(false) - , m_arrayReplacerPropertyNames(exec, PropertyNameMode::Strings) + , m_arrayReplacerPropertyNames(exec) , m_replacerCallType(CallTypeNone) , m_gap(gap(exec, space.get())) { @@ -230,10 +226,9 @@ Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const if (name.isObject()) { if (!asObject(name)->inherits(NumberObject::info()) && !asObject(name)->inherits(StringObject::info())) continue; - } else if (!name.isNumber() && !name.isString()) - continue; + } - m_arrayReplacerPropertyNames.add(name.toString(exec)->toIdentifier(exec)); + m_arrayReplacerPropertyNames.add(Identifier(exec, name.toString(exec)->value(exec))); } return; } @@ -259,16 +254,83 @@ Local<Unknown> Stringifier::stringify(Handle<Unknown> value) return Local<Unknown>(m_exec->vm(), jsString(m_exec, result.toString())); } -ALWAYS_INLINE JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFunctionCall& propertyName) +template <typename CharType> +static void appendStringToStringBuilder(StringBuilder& builder, const CharType* data, int length) +{ + for (int i = 0; i < length; ++i) { + int start = i; + while (i < length && (data[i] > 0x1F && data[i] != '"' && data[i] != '\\')) + ++i; + builder.append(data + start, i - start); + if (i >= length) + break; + switch (data[i]) { + case '\t': + builder.append('\\'); + builder.append('t'); + break; + case '\r': + builder.append('\\'); + builder.append('r'); + break; + case '\n': + builder.append('\\'); + builder.append('n'); + break; + case '\f': + builder.append('\\'); + builder.append('f'); + break; + case '\b': + builder.append('\\'); + builder.append('b'); + break; + case '"': + builder.append('\\'); + builder.append('"'); + break; + case '\\': + builder.append('\\'); + builder.append('\\'); + break; + default: + static const char hexDigits[] = "0123456789abcdef"; + UChar ch = data[i]; + LChar hex[] = { '\\', 'u', static_cast<LChar>(hexDigits[(ch >> 12) & 0xF]), static_cast<LChar>(hexDigits[(ch >> 8) & 0xF]), static_cast<LChar>(hexDigits[(ch >> 4) & 0xF]), static_cast<LChar>(hexDigits[ch & 0xF]) }; + builder.append(hex, WTF_ARRAY_LENGTH(hex)); + break; + } + } +} + +void escapeStringToBuilder(StringBuilder& builder, const String& message) +{ + if (message.is8Bit()) + appendStringToStringBuilder(builder, message.characters8(), message.length()); + else + appendStringToStringBuilder(builder, message.characters16(), message.length()); +} + +void Stringifier::appendQuotedString(StringBuilder& builder, const String& value) +{ + int length = value.length(); + + builder.append('"'); + + if (value.is8Bit()) + appendStringToStringBuilder<LChar>(builder, value.characters8(), length); + else + appendStringToStringBuilder<UChar>(builder, value.characters16(), length); + + builder.append('"'); +} + +inline JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFunctionCall& propertyName) { ASSERT(!m_exec->hadException()); if (!value.isObject() || !asObject(value)->hasProperty(m_exec, m_exec->vm().propertyNames->toJSON)) return value; - return toJSONImpl(value, propertyName); -} -JSValue Stringifier::toJSONImpl(JSValue value, const PropertyNameForFunctionCall& propertyName) -{ JSValue toJSONFunction = asObject(value)->get(m_exec, m_exec->vm().propertyNames->toJSON); if (m_exec->hadException()) return jsNull(); @@ -304,8 +366,8 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& return StringifyFailed; } - if ((value.isUndefined() || value.isSymbol()) && !holder->inherits(JSArray::info())) - return StringifyFailedDueToUndefinedOrSymbolValue; + if (value.isUndefined() && !holder->inherits(JSArray::info())) + return StringifyFailedDueToUndefinedValue; if (value.isNull()) { builder.appendLiteral("null"); @@ -325,21 +387,18 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& return StringifySucceeded; } - if (value.isString()) { - builder.appendQuotedJSONString(asString(value)->value(m_exec)); + String stringValue; + if (value.getString(m_exec, stringValue)) { + appendQuotedString(builder, stringValue); return StringifySucceeded; } if (value.isNumber()) { - if (value.isInt32()) - builder.appendNumber(value.asInt32()); - else { - double number = value.asNumber(); - if (!std::isfinite(number)) - builder.appendLiteral("null"); - else - builder.appendECMAScriptNumber(number); - } + double number = value.asNumber(); + if (!std::isfinite(number)) + builder.appendLiteral("null"); + else + builder.append(String::numberToStringECMAScript(number)); return StringifySucceeded; } @@ -354,7 +413,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& builder.appendLiteral("null"); return StringifySucceeded; } - return StringifyFailedDueToUndefinedOrSymbolValue; + return StringifyFailedDueToUndefinedValue; } // Handle cycle detection, and put the holder on the stack. @@ -428,17 +487,14 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui if (!m_index) { if (m_isArray) { m_isJSArray = isJSArray(m_object.get()); - if (m_isJSArray) - m_size = asArray(m_object.get())->length(); - else - m_size = m_object->get(exec, exec->vm().propertyNames->length).toUInt32(exec); + m_size = m_object->get(exec, exec->vm().propertyNames->length).toUInt32(exec); builder.append('['); } else { if (stringifier.m_usingArrayReplacer) m_propertyNames = stringifier.m_arrayReplacerPropertyNames.data(); else { - PropertyNameArray objectPropertyNames(exec, PropertyNameMode::Strings); - m_object->methodTable()->getOwnPropertyNames(m_object.get(), exec, objectPropertyNames, EnumerationMode()); + PropertyNameArray objectPropertyNames(exec); + m_object->methodTable()->getOwnPropertyNames(m_object.get(), exec, objectPropertyNames, ExcludeDontEnumProperties); m_propertyNames = objectPropertyNames.releaseData(); } m_size = m_propertyNames->propertyNameVector().size(); @@ -466,7 +522,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui if (m_isJSArray && asArray(m_object.get())->canGetIndexQuickly(index)) value = asArray(m_object.get())->getIndexQuickly(index); else { - PropertySlot slot(m_object.get(), PropertySlot::InternalMethodType::Get); + PropertySlot slot(m_object.get()); if (m_object->methodTable()->getOwnPropertySlotByIndex(m_object.get(), exec, index, slot)) { value = slot.getValue(exec, index); if (exec->hadException()) @@ -484,7 +540,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object.get(), index); } else { // Get the value. - PropertySlot slot(m_object.get(), PropertySlot::InternalMethodType::Get); + PropertySlot slot(m_object.get()); Identifier& propertyName = m_propertyNames->propertyNameVector()[index]; if (!m_object->methodTable()->getOwnPropertySlot(m_object.get(), exec, propertyName, slot)) return true; @@ -500,7 +556,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui stringifier.startNewLine(builder); // Append the property name. - builder.appendQuotedJSONString(propertyName.string()); + appendQuotedString(builder, propertyName.string()); builder.append(':'); if (stringifier.willIndent()) builder.append(' '); @@ -519,10 +575,10 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui break; case StringifySucceeded: break; - case StringifyFailedDueToUndefinedOrSymbolValue: - // This only occurs when get an undefined value or a symbol value for - // an object property. In this case we don't want the separator and - // property name that we already appended, so roll back. + case StringifyFailedDueToUndefinedValue: + // This only occurs when get an undefined value for an object property. + // In this case we don't want the separator and property name that we + // already appended, so roll back. builder.resize(rollBackPoint); break; } @@ -532,7 +588,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui // ------------------------------ JSONObject -------------------------------- -const ClassInfo JSONObject::s_info = { "JSON", &JSNonFinalObject::s_info, &jsonTable, CREATE_METHOD_TABLE(JSONObject) }; +const ClassInfo JSONObject::s_info = { "JSON", &JSNonFinalObject::s_info, 0, ExecState::jsonTable, CREATE_METHOD_TABLE(JSONObject) }; /* Source for JSONObject.lut.h @begin jsonTable @@ -545,7 +601,7 @@ const ClassInfo JSONObject::s_info = { "JSON", &JSNonFinalObject::s_info, &jsonT bool JSONObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) { - return getStaticFunctionSlot<JSObject>(exec, jsonTable, jsCast<JSONObject*>(object), propertyName, slot); + return getStaticFunctionSlot<JSObject>(exec, ExecState::jsonTable(exec->vm()), jsCast<JSONObject*>(object), propertyName, slot); } class Walker { @@ -598,7 +654,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) ASSERT(inValue.isObject()); ASSERT(isJSArray(asObject(inValue)) || asObject(inValue)->inherits(JSArray::info())); if (objectStack.size() + arrayStack.size() > maximumFilterRecursion) - return throwStackOverflowError(m_exec); + return m_exec->vm().throwException(m_exec, createStackOverflowError(m_exec)); JSArray* array = asArray(inValue); arrayStack.push(array); @@ -618,7 +674,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) if (isJSArray(array) && array->canGetIndexQuickly(index)) inValue = array->getIndexQuickly(index); else { - PropertySlot slot(array, PropertySlot::InternalMethodType::Get); + PropertySlot slot(array); if (array->methodTable()->getOwnPropertySlotByIndex(array, m_exec, index, slot)) inValue = slot.getValue(m_exec, index); else @@ -649,13 +705,13 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) ASSERT(inValue.isObject()); ASSERT(!isJSArray(asObject(inValue)) && !asObject(inValue)->inherits(JSArray::info())); if (objectStack.size() + arrayStack.size() > maximumFilterRecursion) - return throwStackOverflowError(m_exec); + return m_exec->vm().throwException(m_exec, createStackOverflowError(m_exec)); JSObject* object = asObject(inValue); objectStack.push(object); indexStack.append(0); - propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings)); - object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode()); + propertyStack.append(PropertyNameArray(m_exec)); + object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), ExcludeDontEnumProperties); } objectStartVisitMember: FALLTHROUGH; @@ -670,7 +726,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) propertyStack.removeLast(); break; } - PropertySlot slot(object, PropertySlot::InternalMethodType::Get); + PropertySlot slot(object); if (object->methodTable()->getOwnPropertySlot(object, m_exec, properties[index], slot)) inValue = slot.getValue(m_exec, properties[index]); else @@ -729,7 +785,7 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec) { if (!exec->argumentCount()) return throwVMError(exec, createError(exec, ASCIILiteral("JSON.parse requires at least one parameter"))); - JSString::SafeView source = exec->uncheckedArgument(0).toString(exec)->view(exec); + String source = exec->uncheckedArgument(0).toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsNull()); |