static inline UString gap(ExecState* exec, JSValue space) { const unsigned maxGapLength = 10; space = unwrapBoxedPrimitive(exec, space); // If the space value is a number, create a gap string with that number of spaces. double spaceCount; if (space.getNumber(spaceCount)) { int count; if (spaceCount > maxGapLength) count = maxGapLength; else if (!(spaceCount > 0)) count = 0; else count = static_cast<int>(spaceCount); UChar spaces[maxGapLength]; for (int i = 0; i < count; ++i) spaces[i] = ' '; return UString(spaces, count); } // If the space value is a string, use it as the gap string, otherwise use no gap string. UString spaces = space.getString(exec); if (spaces.length() > maxGapLength) { spaces = spaces.substringSharingImpl(0, maxGapLength); } return spaces; }
Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space) : m_nextStringifierToMark(exec->globalData().firstStringifierToMark) , m_exec(exec) , m_replacer(replacer) , m_usingArrayReplacer(false) , m_arrayReplacerPropertyNames(exec) , m_replacerCallType(CallTypeNone) , m_gap(gap(exec, space)) { exec->globalData().firstStringifierToMark = this; if (!m_replacer.isObject()) return; if (asObject(m_replacer)->inherits(&JSArray::info)) { m_usingArrayReplacer = true; JSObject* array = asObject(m_replacer); unsigned length = array->get(exec, exec->globalData().propertyNames->length).toUInt32(exec); for (unsigned i = 0; i < length; ++i) { JSValue name = array->get(exec, i); if (exec->hadException()) break; UString propertyName; if (name.getString(exec, propertyName)) { m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName)); continue; } double value = 0; if (name.getNumber(value)) { m_arrayReplacerPropertyNames.add(Identifier::from(exec, value)); continue; } if (name.isObject()) { if (!asObject(name)->inherits(&NumberObject::info) && !asObject(name)->inherits(&StringObject::info)) continue; propertyName = name.toString(exec); if (exec->hadException()) break; m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName)); } } return; } m_replacerCallType = asObject(m_replacer)->getCallData(m_replacerCallData); }
ALWAYS_INLINE static void operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) { JSGlobalData* globalData = &exec->globalData(); JSValue baseValue = JSValue::decode(encodedBase); JSValue property = JSValue::decode(encodedProperty); JSValue value = JSValue::decode(encodedValue); if (LIKELY(property.isUInt32())) { uint32_t i = property.asUInt32(); if (isJSArray(globalData, baseValue)) { JSArray* jsArray = asArray(baseValue); if (jsArray->canSetIndex(i)) { jsArray->setIndex(*globalData, i, value); return; } jsArray->JSArray::put(exec, i, value); return; } if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { JSByteArray* jsByteArray = asByteArray(baseValue); // FIXME: the JITstub used to relink this to an optimized form! if (value.isInt32()) { jsByteArray->setIndex(i, value.asInt32()); return; } double dValue = 0; if (value.getNumber(dValue)) { jsByteArray->setIndex(i, dValue); return; } } baseValue.put(exec, i, value); return; } // Don't put to an object if toString throws an exception. Identifier ident(exec, property.toString(exec)); if (!globalData->exception) { PutPropertySlot slot(strict); baseValue.put(exec, ident, value, slot); } }