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;
}
Exemple #2
0
// ECMA 15.9.3
JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, JSValue newTarget, const ArgList& args)
{
    VM& vm = exec->vm();
    int numArgs = args.size();

    double value;

    if (numArgs == 0) // new Date() ECMA 15.9.3.3
        value = NORMAL_OR_DETERMINISTIC_FUNCTION(jsCurrentTime(), deterministicCurrentTime(globalObject));
    else if (numArgs == 1) {
        if (args.at(0).inherits(DateInstance::info()))
            value = asDateInstance(args.at(0))->internalNumber();
        else {
            JSValue primitive = args.at(0).toPrimitive(exec);
            if (primitive.isString())
                value = parseDate(vm, primitive.getString(exec));
            else
                value = primitive.toNumber(exec);
        }
    } else
        value = millisecondsFromComponents(exec, args, WTF::LocalTime);

    Structure* dateStructure = InternalFunction::createSubclassStructure(exec, newTarget, globalObject->dateStructure());

    return DateInstance::create(vm, dateStructure, value);
}
static RefPtr<InspectorValue> jsToInspectorValue(ExecState* scriptState, JSValue value, int maxDepth)
{
    if (!value) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }

    if (!maxDepth)
        return nullptr;

    maxDepth--;

    if (value.isNull() || value.isUndefined())
        return InspectorValue::null();
    if (value.isBoolean())
        return InspectorValue::create(value.asBoolean());
    if (value.isNumber() && value.isDouble())
        return InspectorValue::create(value.asNumber());
    if (value.isNumber() && value.isMachineInt())
        return InspectorValue::create(static_cast<int>(value.asMachineInt()));
    if (value.isString())
        return InspectorValue::create(value.getString(scriptState));

    if (value.isObject()) {
        if (isJSArray(value)) {
            Ref<InspectorArray> inspectorArray = InspectorArray::create();
            JSArray* array = asArray(value);
            unsigned length = array->length();
            for (unsigned i = 0; i < length; i++) {
                JSValue element = array->getIndex(scriptState, i);
                RefPtr<InspectorValue> elementValue = jsToInspectorValue(scriptState, element, maxDepth);
                if (!elementValue)
                    return nullptr;
                inspectorArray->pushValue(WTFMove(elementValue));
            }
            return WTFMove(inspectorArray);
        }
        Ref<InspectorObject> inspectorObject = InspectorObject::create();
        JSObject* object = value.getObject();
        PropertyNameArray propertyNames(scriptState, PropertyNameMode::Strings);
        object->methodTable()->getOwnPropertyNames(object, scriptState, propertyNames, EnumerationMode());
        for (size_t i = 0; i < propertyNames.size(); i++) {
            const Identifier& name = propertyNames[i];
            JSValue propertyValue = object->get(scriptState, name);
            RefPtr<InspectorValue> inspectorValue = jsToInspectorValue(scriptState, propertyValue, maxDepth);
            if (!inspectorValue)
                return nullptr;
            inspectorObject->setValue(name.string(), WTFMove(inspectorValue));
        }
        return WTFMove(inspectorObject);
    }

    ASSERT_NOT_REACHED();
    return nullptr;
}
// ECMA 15.9.3
JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
{
    VM& vm = exec->vm();
    int numArgs = args.size();

    double value;

    if (numArgs == 0) // new Date() ECMA 15.9.3.3
        value = jsCurrentTime();
    else if (numArgs == 1) {
        if (args.at(0).inherits(DateInstance::info()))
            value = asDateInstance(args.at(0))->internalNumber();
        else {
            JSValue primitive = args.at(0).toPrimitive(exec);
            if (primitive.isString())
                value = parseDate(vm, primitive.getString(exec));
            else
                value = primitive.toNumber(exec);
        }
    } else {
        double doubleArguments[7] = {
            args.at(0).toNumber(exec), 
            args.at(1).toNumber(exec), 
            args.at(2).toNumber(exec), 
            args.at(3).toNumber(exec), 
            args.at(4).toNumber(exec), 
            args.at(5).toNumber(exec), 
            args.at(6).toNumber(exec)
        };
        if (!std::isfinite(doubleArguments[0])
            || !std::isfinite(doubleArguments[1])
            || (numArgs >= 3 && !std::isfinite(doubleArguments[2]))
            || (numArgs >= 4 && !std::isfinite(doubleArguments[3]))
            || (numArgs >= 5 && !std::isfinite(doubleArguments[4]))
            || (numArgs >= 6 && !std::isfinite(doubleArguments[5]))
            || (numArgs >= 7 && !std::isfinite(doubleArguments[6])))
            value = QNaN;
        else {
            GregorianDateTime t;
            int year = JSC::toInt32(doubleArguments[0]);
            t.setYear((year >= 0 && year <= 99) ? (year + 1900) : year);
            t.setMonth(JSC::toInt32(doubleArguments[1]));
            t.setMonthDay((numArgs >= 3) ? JSC::toInt32(doubleArguments[2]) : 1);
            t.setHour(JSC::toInt32(doubleArguments[3]));
            t.setMinute(JSC::toInt32(doubleArguments[4]));
            t.setSecond(JSC::toInt32(doubleArguments[5]));
            t.setIsDST(-1);
            double ms = (numArgs >= 7) ? doubleArguments[6] : 0;
            value = gregorianDateTimeToMS(vm, t, ms, false);
        }
    }

    return DateInstance::create(vm, globalObject->dateStructure(), value);
}
// ECMA 15.9.3
JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
{
    int numArgs = args.size();

    double value;

    if (numArgs == 0) // new Date() ECMA 15.9.3.3
        value = jsCurrentTime();
    else if (numArgs == 1) {
        if (args.at(0).inherits(&DateInstance::s_info))
            value = asDateInstance(args.at(0))->internalNumber();
        else {
            JSValue primitive = args.at(0).toPrimitive(exec);
            if (primitive.isString())
                value = parseDate(exec, primitive.getString(exec));
            else
                value = primitive.toNumber(exec);
        }
    } else {
        double doubleArguments[7] = {
            args.at(0).toNumber(exec),
            args.at(1).toNumber(exec),
            args.at(2).toNumber(exec),
            args.at(3).toNumber(exec),
            args.at(4).toNumber(exec),
            args.at(5).toNumber(exec),
            args.at(6).toNumber(exec)
        };
        if (isnan(doubleArguments[0])
                || isnan(doubleArguments[1])
                || (numArgs >= 3 && isnan(doubleArguments[2]))
                || (numArgs >= 4 && isnan(doubleArguments[3]))
                || (numArgs >= 5 && isnan(doubleArguments[4]))
                || (numArgs >= 6 && isnan(doubleArguments[5]))
                || (numArgs >= 7 && isnan(doubleArguments[6])))
            value = NaN;
        else {
            GregorianDateTime t;
            int year = JSC::toInt32(doubleArguments[0]);
            t.year = (year >= 0 && year <= 99) ? year : year - 1900;
            t.month = JSC::toInt32(doubleArguments[1]);
            t.monthDay = (numArgs >= 3) ? JSC::toInt32(doubleArguments[2]) : 1;
            t.hour = JSC::toInt32(doubleArguments[3]);
            t.minute = JSC::toInt32(doubleArguments[4]);
            t.second = JSC::toInt32(doubleArguments[5]);
            t.isDST = -1;
            double ms = (numArgs >= 7) ? doubleArguments[6] : 0;
            value = gregorianDateTimeToMS(exec, t, ms, false);
        }
    }

    return new (exec) DateInstance(exec, globalObject->dateStructure(), value);
}
static PassRefPtr<InspectorValue> jsToInspectorValue(ScriptState* scriptState, JSValue value, int maxDepth)
{
    if (!value) {
        ASSERT_NOT_REACHED();
        return 0;
    }

    if (!maxDepth)
        return 0;
    maxDepth--;

    if (value.isNull() || value.isUndefined())
        return InspectorValue::null();
    if (value.isBoolean())
        return InspectorBasicValue::create(value.asBoolean());
    if (value.isNumber())
        return InspectorBasicValue::create(value.asNumber());
    if (value.isString()) {
        String s = value.getString(scriptState);
        return InspectorString::create(String(s.characters(), s.length()));
    }
    if (value.isObject()) {
        if (isJSArray(value)) {
            RefPtr<InspectorArray> inspectorArray = InspectorArray::create();
            JSArray* array = asArray(value);
            unsigned length = array->length();
            for (unsigned i = 0; i < length; i++) {
                // FIXME: What if the array is in sparse mode? https://bugs.webkit.org/show_bug.cgi?id=95610
                JSValue element = array->getIndexQuickly(i);
                RefPtr<InspectorValue> elementValue = jsToInspectorValue(scriptState, element, maxDepth);
                if (!elementValue)
                    return 0;
                inspectorArray->pushValue(elementValue);
            }
            return inspectorArray;
        }
        RefPtr<InspectorObject> inspectorObject = InspectorObject::create();
        JSObject* object = value.getObject();
        PropertyNameArray propertyNames(scriptState);
        object->methodTable()->getOwnPropertyNames(object, scriptState, propertyNames, ExcludeDontEnumProperties);
        for (size_t i = 0; i < propertyNames.size(); i++) {
            const Identifier& name =  propertyNames[i];
            JSValue propertyValue = object->get(scriptState, name);
            RefPtr<InspectorValue> inspectorValue = jsToInspectorValue(scriptState, propertyValue, maxDepth);
            if (!inspectorValue)
                return 0;
            inspectorObject->setValue(String(name.characters(), name.length()), inspectorValue);
        }
        return inspectorObject;
    }
    ASSERT_NOT_REACHED();
    return 0;
}
void JSCryptoKeySerializationJWK::reconcileUsages(CryptoKeyUsage& suggestedUsages) const
{
    CryptoKeyUsage jwkUsages = 0;

    JSArray* keyOps;
    if (getJSArrayFromJSON(m_exec, m_json.get(), "key_ops", keyOps)) {
        for (size_t i = 0; i < keyOps->length(); ++i) {
            JSValue jsValue = keyOps->getIndex(m_exec, i);
            String operation;
            if (!jsValue.getString(m_exec, operation)) {
                if (!m_exec->hadException())
                    throwTypeError(m_exec, "JWK key_ops attribute could not be processed");
                return;
            }
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("sign"), CryptoKeyUsageSign))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("verify"), CryptoKeyUsageVerify))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("encrypt"), CryptoKeyUsageEncrypt))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("decrypt"), CryptoKeyUsageDecrypt))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("wrapKey"), CryptoKeyUsageWrapKey))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("unwrapKey"), CryptoKeyUsageUnwrapKey))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("deriveKey"), CryptoKeyUsageDeriveKey))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("deriveBits"), CryptoKeyUsageDeriveBits))
                return;
        }
    } else {
        if (m_exec->hadException())
            return;

        String jwkUseString;
        if (!getStringFromJSON(m_exec, m_json.get(), "use", jwkUseString)) {
            // We have neither key_ops nor use.
            return;
        }

        if (jwkUseString == "enc")
            jwkUsages |= (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey);
        else if (jwkUseString == "sig")
            jwkUsages |= (CryptoKeyUsageSign | CryptoKeyUsageVerify);
        else {
            throwTypeError(m_exec, "Unsupported JWK key use value \"" + jwkUseString + "\"");
            return;
        }
    }

    suggestedUsages = suggestedUsages & jwkUsages;
}
static PassRefPtr<InspectorValue> jsToInspectorValue(ScriptState* scriptState, JSValue value)
{
    if (!value) {
        ASSERT_NOT_REACHED();
        return 0;
    }
    if (value.isNull() || value.isUndefined())
        return InspectorValue::null();
    if (value.isBoolean())
        return InspectorBasicValue::create(value.getBoolean());
    if (value.isNumber())
        return InspectorBasicValue::create(value.uncheckedGetNumber());
    if (value.isString()) {
        UString s = value.getString(scriptState);
        return InspectorString::create(String(s.characters(), s.length()));
    }
    if (value.isObject()) {
        if (isJSArray(&scriptState->globalData(), value)) {
            RefPtr<InspectorArray> inspectorArray = InspectorArray::create();
            JSArray* array = asArray(value);
            unsigned length = array->length();
            for (unsigned i = 0; i < length; i++) {
                JSValue element = array->getIndex(i);
                RefPtr<InspectorValue> elementValue = jsToInspectorValue(scriptState, element);
                if (!elementValue) {
                    ASSERT_NOT_REACHED();
                    elementValue = InspectorValue::null();
                }
                inspectorArray->pushValue(elementValue);
            }
            return inspectorArray;
        }
        RefPtr<InspectorObject> inspectorObject = InspectorObject::create();
        JSObject* object = value.getObject();
        PropertyNameArray propertyNames(scriptState);
        object->getOwnPropertyNames(scriptState, propertyNames);
        for (size_t i = 0; i < propertyNames.size(); i++) {
            const Identifier& name =  propertyNames[i];
            JSValue propertyValue = object->get(scriptState, name);
            RefPtr<InspectorValue> inspectorValue = jsToInspectorValue(scriptState, propertyValue);
            if (!inspectorValue) {
                ASSERT_NOT_REACHED();
                inspectorValue = InspectorValue::null();
            }
            inspectorObject->setValue(String(name.characters(), name.length()), inspectorValue);
        }
        return inspectorObject;
    }
    ASSERT_NOT_REACHED();
    return 0;
}
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);
}
// ECMA 15.9.3
JSObject* constructDate(ExecState* exec, const ArgList& args)
{
    int numArgs = args.size();

    double value;

    if (numArgs == 0) // new Date() ECMA 15.9.3.3
        value = getCurrentUTCTime();
    else if (numArgs == 1) {
        if (args.at(exec, 0)->isObject(&DateInstance::info))
            value = asDateInstance(args.at(exec, 0))->internalNumber();
        else {
            JSValue* primitive = args.at(exec, 0)->toPrimitive(exec);
            if (primitive->isString())
                value = parseDate(primitive->getString());
            else
                value = primitive->toNumber(exec);
        }
    } else {
        if (isnan(args.at(exec, 0)->toNumber(exec))
                || isnan(args.at(exec, 1)->toNumber(exec))
                || (numArgs >= 3 && isnan(args.at(exec, 2)->toNumber(exec)))
                || (numArgs >= 4 && isnan(args.at(exec, 3)->toNumber(exec)))
                || (numArgs >= 5 && isnan(args.at(exec, 4)->toNumber(exec)))
                || (numArgs >= 6 && isnan(args.at(exec, 5)->toNumber(exec)))
                || (numArgs >= 7 && isnan(args.at(exec, 6)->toNumber(exec))))
            value = NaN;
        else {
          GregorianDateTime t;
          int year = args.at(exec, 0)->toInt32(exec);
          t.year = (year >= 0 && year <= 99) ? year : year - 1900;
          t.month = args.at(exec, 1)->toInt32(exec);
          t.monthDay = (numArgs >= 3) ? args.at(exec, 2)->toInt32(exec) : 1;
          t.hour = args.at(exec, 3)->toInt32(exec);
          t.minute = args.at(exec, 4)->toInt32(exec);
          t.second = args.at(exec, 5)->toInt32(exec);
          t.isDST = -1;
          double ms = (numArgs >= 7) ? args.at(exec, 6)->toNumber(exec) : 0;
          value = gregorianDateTimeToMS(t, ms, false);
        }
    }

    DateInstance* result = new (exec) DateInstance(exec->lexicalGlobalObject()->dateStructure());
    result->setInternalValue(jsNumber(exec, timeClip(value)));
    return result;
}
Exemple #11
0
static bool getStringFromJSON(ExecState* exec, JSObject* json, const char* key, String& result)
{
    Identifier identifier(exec, key);
    PropertySlot slot(json);

    if (!json->getPropertySlot(exec, identifier, slot))
        return false;

    JSValue jsValue = slot.getValue(exec, identifier);
    ASSERT(!exec->hadException());
    if (!jsValue.getString(exec, result)) {
        // Can get an out of memory exception.
        if (exec->hadException())
            return false;
        throwTypeError(exec, String::format("Expected a string value for \"%s\" JSON key",  key));
        return false;
    }

    return true;
}