summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/JSONObject.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/runtime/JSONObject.cpp
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-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.cpp166
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());