static bool extractSourceInformationFromException(JSC::ExecState* exec, JSObject* exceptionObject, int* lineNumber, int* columnNumber, String* sourceURL) { VM& vm = exec->vm(); auto scope = DECLARE_CATCH_SCOPE(vm); // FIXME: <http://webkit.org/b/115087> Web Inspector: Should not need to evaluate JavaScript handling exceptions JSValue lineValue = exceptionObject->getDirect(vm, Identifier::fromString(exec, "line")); JSValue columnValue = exceptionObject->getDirect(vm, Identifier::fromString(exec, "column")); JSValue sourceURLValue = exceptionObject->getDirect(vm, Identifier::fromString(exec, "sourceURL")); bool result = false; if (lineValue && lineValue.isNumber() && sourceURLValue && sourceURLValue.isString()) { *lineNumber = int(lineValue.toNumber(exec)); *columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0; *sourceURL = sourceURLValue.toWTFString(exec); result = true; } else if (ErrorInstance* error = jsDynamicCast<ErrorInstance*>(vm, exceptionObject)) { unsigned unsignedLine; unsigned unsignedColumn; result = getLineColumnAndSource(error->stackTrace(), unsignedLine, unsignedColumn, *sourceURL); *lineNumber = static_cast<int>(unsignedLine); *columnNumber = static_cast<int>(unsignedColumn); } if (sourceURL->isEmpty()) *sourceURL = "undefined"_s; scope.clearException(); return result; }
PassRefPtr<ScriptCallStack> createScriptCallStackFromException(JSC::ExecState* exec, JSC::JSValue& exception, size_t maxStackSize) { Vector<ScriptCallFrame> frames; RefCountedArray<StackFrame> stackTrace = exec->vm().exceptionStack(); for (size_t i = 0; i < stackTrace.size() && i < maxStackSize; i++) { if (!stackTrace[i].callee && frames.size()) break; unsigned line; unsigned column; stackTrace[i].computeLineAndColumn(line, column); String functionName = stackTrace[i].friendlyFunctionName(exec); frames.append(ScriptCallFrame(functionName, stackTrace[i].sourceURL, line, column)); } // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions // Fallback to getting at least the line and sourceURL from the exception if it has values and the exceptionStack doesn't. if (frames.size() > 0) { const ScriptCallFrame& firstCallFrame = frames.first(); JSObject* exceptionObject = exception.toObject(exec); if (exception.isObject() && firstCallFrame.sourceURL().isEmpty()) { JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "line")); int lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0; JSValue columnValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "column")); int columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0; JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "sourceURL")); String exceptionSourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : ASCIILiteral("undefined"); frames[0] = ScriptCallFrame(firstCallFrame.functionName(), exceptionSourceURL, lineNumber, columnNumber); } } return ScriptCallStack::create(frames); }
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; }
// See ES5.1 9.12 bool sameValue(ExecState* exec, JSValue a, JSValue b) { if (!a.isNumber()) return JSValue::strictEqual(exec, a, b); if (!b.isNumber()) return false; double x = a.asNumber(); double y = b.asNumber(); if (isnan(x)) return isnan(y); return bitwise_cast<uint64_t>(x) == bitwise_cast<uint64_t>(y); }
void reportException(ExecState* exec, JSValue exception, CachedScript* cachedScript) { if (isTerminatedExecutionException(exception)) return; Interpreter::ErrorHandlingMode mode(exec); RefPtr<ScriptCallStack> callStack(createScriptCallStackFromException(exec, exception, ScriptCallStack::maxCallStackSizeToCapture)); exec->clearException(); exec->clearSupplementaryExceptionInfo(); JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()); if (JSDOMWindow* window = jsDynamicCast<JSDOMWindow*>(globalObject)) { if (!window->impl()->isCurrentlyDisplayedInFrame()) return; } int lineNumber = 0; int columnNumber = 0; String exceptionSourceURL; if (callStack->size()) { const ScriptCallFrame& frame = callStack->at(0); lineNumber = frame.lineNumber(); columnNumber = frame.columnNumber(); exceptionSourceURL = frame.sourceURL(); } else { // There may not be an exceptionStack for a <script> SyntaxError. Fallback to getting at least the line and sourceURL from the exception. JSObject* exceptionObject = exception.toObject(exec); JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "line")); lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0; JSValue columnValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "column")); columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0; JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "sourceURL")); exceptionSourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : ASCIILiteral("undefined"); } String errorMessage; if (ExceptionBase* exceptionBase = toExceptionBase(exception)) errorMessage = exceptionBase->message() + ": " + exceptionBase->description(); else { // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions // If this is a custon exception object, call toString on it to try and get a nice string representation for the exception. errorMessage = exception.toString(exec)->value(exec); exec->clearException(); exec->clearSupplementaryExceptionInfo(); } ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext(); scriptExecutionContext->reportException(errorMessage, lineNumber, columnNumber, exceptionSourceURL, callStack->size() ? callStack : 0, cachedScript); }
JSValue JSInjectedScriptHost::subtype(ExecState* exec) { if (exec->argumentCount() < 1) return jsUndefined(); JSValue value = exec->uncheckedArgument(0); if (value.isString()) return exec->vm().smallStrings.stringString(); if (value.isBoolean()) return exec->vm().smallStrings.booleanString(); if (value.isNumber()) return exec->vm().smallStrings.numberString(); if (value.isSymbol()) return exec->vm().smallStrings.symbolString(); JSObject* object = asObject(value); if (object) { if (object->isErrorInstance()) return jsNontrivialString(exec, ASCIILiteral("error")); // Consider class constructor functions class objects. JSFunction* function = jsDynamicCast<JSFunction*>(value); if (function && function->isClassConstructorFunction()) return jsNontrivialString(exec, ASCIILiteral("class")); } if (value.inherits(JSArray::info())) return jsNontrivialString(exec, ASCIILiteral("array")); if (value.inherits(DirectArguments::info()) || value.inherits(ScopedArguments::info())) return jsNontrivialString(exec, ASCIILiteral("array")); if (value.inherits(DateInstance::info())) return jsNontrivialString(exec, ASCIILiteral("date")); if (value.inherits(RegExpObject::info())) return jsNontrivialString(exec, ASCIILiteral("regexp")); if (value.inherits(JSMap::info())) return jsNontrivialString(exec, ASCIILiteral("map")); if (value.inherits(JSSet::info())) return jsNontrivialString(exec, ASCIILiteral("set")); if (value.inherits(JSWeakMap::info())) return jsNontrivialString(exec, ASCIILiteral("weakmap")); if (value.inherits(JSWeakSet::info())) return jsNontrivialString(exec, ASCIILiteral("weakset")); if (value.inherits(JSArrayIterator::info()) || value.inherits(JSMapIterator::info()) || value.inherits(JSSetIterator::info()) || value.inherits(JSStringIterator::info())) return jsNontrivialString(exec, ASCIILiteral("iterator")); if (value.inherits(JSInt8Array::info()) || value.inherits(JSInt16Array::info()) || value.inherits(JSInt32Array::info())) return jsNontrivialString(exec, ASCIILiteral("array")); if (value.inherits(JSUint8Array::info()) || value.inherits(JSUint16Array::info()) || value.inherits(JSUint32Array::info())) return jsNontrivialString(exec, ASCIILiteral("array")); if (value.inherits(JSFloat32Array::info()) || value.inherits(JSFloat64Array::info())) return jsNontrivialString(exec, ASCIILiteral("array")); return impl().subtype(exec, value); }
RuntimeType runtimeTypeForValue(JSValue value) { if (UNLIKELY(!value)) return TypeNothing; if (value.isUndefined()) return TypeUndefined; if (value.isNull()) return TypeNull; if (value.isAnyInt()) return TypeAnyInt; if (value.isNumber()) return TypeNumber; if (value.isString()) return TypeString; if (value.isBoolean()) return TypeBoolean; if (value.isObject()) return TypeObject; if (value.isFunction()) return TypeFunction; if (value.isSymbol()) return TypeSymbol; return TypeNothing; }
void dumpImmediate(JSValue value) { if (value.isNull()) write(NullTag); else if (value.isUndefined()) write(UndefinedTag); else if (value.isNumber()) { if (value.isInt32()) { if (!value.asInt32()) write(ZeroTag); else if (value.asInt32() == 1) write(OneTag); else { write(IntTag); write(static_cast<uint32_t>(value.asInt32())); } } else { write(DoubleTag); write(value.asDouble()); } } else if (value.isBoolean()) { if (value.isTrue()) write(TrueTag); else write(FalseTag); } }
static void updateResultProfileForBinaryArithOp(ExecState* exec, Instruction* pc, JSValue result, JSValue left, JSValue right) { CodeBlock* codeBlock = exec->codeBlock(); unsigned bytecodeOffset = codeBlock->bytecodeOffset(pc); ResultProfile* profile = codeBlock->ensureResultProfile(bytecodeOffset); if (result.isNumber()) { if (!result.isInt32()) { if (left.isInt32() && right.isInt32()) profile->setObservedInt32Overflow(); double doubleVal = result.asNumber(); if (!doubleVal && std::signbit(doubleVal)) profile->setObservedNegZeroDouble(); else { profile->setObservedNonNegZeroDouble(); // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value. // Therefore, we will get a false positive if the result is that value. This is intentionally // done to simplify the checking algorithm. static const int64_t int52OverflowPoint = (1ll << 51); int64_t int64Val = static_cast<int64_t>(std::abs(doubleVal)); if (int64Val >= int52OverflowPoint) profile->setObservedInt52Overflow(); } } } else profile->setObservedNonNumber(); }
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. if (space.isNumber()) { double spaceCount = space.asNumber(); 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; }
static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value) { JSGlobalData* globalData = &exec->globalData(); if (isJSArray(baseValue)) { JSArray* array = asArray(baseValue); if (array->canSetIndex(index)) { array->setIndex(*globalData, index, value); return; } JSArray::putByIndex(array, exec, index, value, strict); return; } if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(index)) { JSByteArray* byteArray = asByteArray(baseValue); // FIXME: the JITstub used to relink this to an optimized form! if (value.isInt32()) { byteArray->setIndex(index, value.asInt32()); return; } if (value.isNumber()) { byteArray->setIndex(index, value.asNumber()); return; } } baseValue.putByIndex(exec, index, value, strict); }
static void updateArithProfileForUnaryArithOp(Instruction* pc, JSValue result, JSValue operand) { ArithProfile& profile = *bitwise_cast<ArithProfile*>(&pc[3].u.operand); profile.observeLHS(operand); ASSERT(result.isNumber()); if (!result.isInt32()) { if (operand.isInt32()) profile.setObservedInt32Overflow(); double doubleVal = result.asNumber(); if (!doubleVal && std::signbit(doubleVal)) profile.setObservedNegZeroDouble(); else { profile.setObservedNonNegZeroDouble(); // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value. // Therefore, we will get a false positive if the result is that value. This is intentionally // done to simplify the checking algorithm. static const int64_t int52OverflowPoint = (1ll << 51); int64_t int64Val = static_cast<int64_t>(std::abs(doubleVal)); if (int64Val >= int52OverflowPoint) profile.setObservedInt52Overflow(); } } }
JSValue JSInjectedScriptHost::type(ExecState* exec) { if (exec->argumentCount() < 1) return jsUndefined(); JSValue value = exec->argument(0); if (value.isString()) return jsString(exec, String("string")); if (value.inherits(&JSArray::s_info)) return jsString(exec, String("array")); if (value.isBoolean()) return jsString(exec, String("boolean")); if (value.isNumber()) return jsString(exec, String("number")); if (value.inherits(&DateInstance::s_info)) return jsString(exec, String("date")); if (value.inherits(&RegExpObject::s_info)) return jsString(exec, String("regexp")); if (value.inherits(&JSNode::s_info)) return jsString(exec, String("node")); if (value.inherits(&JSNodeList::s_info)) return jsString(exec, String("array")); if (value.inherits(&JSHTMLCollection::s_info)) return jsString(exec, String("array")); if (value.inherits(&JSInt8Array::s_info) || value.inherits(&JSInt16Array::s_info) || value.inherits(&JSInt32Array::s_info)) return jsString(exec, String("array")); if (value.inherits(&JSUint8Array::s_info) || value.inherits(&JSUint16Array::s_info) || value.inherits(&JSUint32Array::s_info)) return jsString(exec, String("array")); if (value.inherits(&JSFloat32Array::s_info) || value.inherits(&JSFloat64Array::s_info)) return jsString(exec, String("array")); return jsUndefined(); }
JSValue jsTypeStringForValue(VM& vm, JSGlobalObject* globalObject, JSValue v) { if (v.isUndefined()) return vm.smallStrings.undefinedString(); if (v.isBoolean()) return vm.smallStrings.booleanString(); if (v.isNumber()) return vm.smallStrings.numberString(); if (v.isString()) return vm.smallStrings.stringString(); if (v.isSymbol()) return vm.smallStrings.symbolString(); if (v.isObject()) { JSObject* object = asObject(v); // Return "undefined" for objects that should be treated // as null when doing comparisons. if (object->structure(vm)->masqueradesAsUndefined(globalObject)) return vm.smallStrings.undefinedString(); if (object->type() == JSFunctionType) return vm.smallStrings.functionString(); if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) { CallData callData; JSObject* object = asObject(v); if (object->methodTable(vm)->getCallData(object, callData) != CallTypeNone) return vm.smallStrings.functionString(); } } return vm.smallStrings.objectString(); }
RuntimeType TypeSet::getRuntimeTypeForValue(JSValue v) { RuntimeType ret; if (v.isFunction()) ret = TypeFunction; else if (v.isUndefined()) ret = TypeUndefined; else if (v.isNull()) ret = TypeNull; else if (v.isBoolean()) ret = TypeBoolean; else if (v.isMachineInt()) ret = TypeMachineInt; else if (v.isNumber()) ret = TypeNumber; else if (v.isString()) ret = TypeString; else if (v.isPrimitive()) ret = TypePrimitive; else if (v.isObject()) ret = TypeObject; else CRASH(); return ret; }
bool isWithinPowerOfTwoForConstant(Node* node) { JSValue immediateValue = node->asJSValue(); if (!immediateValue.isNumber()) return false; double immediate = immediateValue.asNumber(); return immediate > -(static_cast<int64_t>(1) << power) && immediate < (static_cast<int64_t>(1) << power); }
double valueToDate(ExecState* exec, JSValue value) { if (value.isNumber()) return value.asNumber(); if (!value.inherits(DateInstance::info())) return std::numeric_limits<double>::quiet_NaN(); return static_cast<DateInstance*>(value.toObject(exec))->internalNumber(); }
bool JSValueIsNumber(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isNumber(); }
bool JSValueIsNumber(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); exec->globalData().heap.registerThread(); JSLock lock(exec); JSValue jsValue = toJS(exec, value); return jsValue.isNumber(); }
char* newTypedArrayWithOneArgument( ExecState* exec, Structure* structure, EncodedJSValue encodedValue) { VM& vm = exec->vm(); NativeCallFrameTracer tracer(&vm, exec); JSValue value = JSValue::decode(encodedValue); if (JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(value)) { RefPtr<ArrayBuffer> buffer = jsBuffer->impl(); if (buffer->byteLength() % ViewClass::elementSize) { vm.throwException(exec, createRangeError(exec, ASCIILiteral("ArrayBuffer length minus the byteOffset is not a multiple of the element size"))); return 0; } return bitwise_cast<char*>( ViewClass::create( exec, structure, buffer, 0, buffer->byteLength() / ViewClass::elementSize)); } if (JSObject* object = jsDynamicCast<JSObject*>(value)) { unsigned length = object->get(exec, vm.propertyNames->length).toUInt32(exec); if (exec->hadException()) return 0; ViewClass* result = ViewClass::createUninitialized(exec, structure, length); if (!result) return 0; if (!result->set(exec, object, 0, length)) return 0; return bitwise_cast<char*>(result); } int length; if (value.isInt32()) length = value.asInt32(); else if (!value.isNumber()) { vm.throwException(exec, createTypeError(exec, ASCIILiteral("Invalid array length argument"))); return 0; } else { length = static_cast<int>(value.asNumber()); if (length != value.asNumber()) { vm.throwException(exec, createTypeError(exec, ASCIILiteral("Invalid array length argument (fractional lengths not allowed)"))); return 0; } } if (length < 0) { vm.throwException(exec, createRangeError(exec, ASCIILiteral("Requested length is negative"))); return 0; } return bitwise_cast<char*>(ViewClass::create(exec, structure, length)); }
JSLR_API bool _cdecl JSTryConvertToNumber(JSContextRef ctx, JSValueRef value, double* result) { ExecState* exec = toJS(ctx); JSValue jsValue = toJS(exec, value); if (jsValue.isNumber()) { *result = jsValue.toNumber(exec); return true; } return false; }
bool JSValueIsNumber(JSContextRef ctx, JSValueRef value) { if (!ctx) { ASSERT_NOT_REACHED(); return false; } ExecState* exec = toJS(ctx); JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); return jsValue.isNumber(); }
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; }
// 15.3.4.5 Function.prototype.bind (thisArg [, arg1 [, arg2, ...]]) EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSGlobalObject* globalObject = exec->callee()->globalObject(); // Let Target be the this value. JSValue target = exec->thisValue(); // If IsCallable(Target) is false, throw a TypeError exception. CallData callData; CallType callType = getCallData(target, callData); if (callType == CallType::None) return throwVMTypeError(exec, scope); // Primitive values are not callable. ASSERT(target.isObject()); JSObject* targetObject = asObject(target); // Let A be a new (possibly empty) internal list of all of the argument values provided after thisArg (arg1, arg2 etc), in order. size_t numBoundArgs = exec->argumentCount() > 1 ? exec->argumentCount() - 1 : 0; JSArray* boundArgs; if (numBoundArgs) { boundArgs = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), numBoundArgs); if (!boundArgs) return JSValue::encode(throwOutOfMemoryError(exec, scope)); for (size_t i = 0; i < numBoundArgs; ++i) boundArgs->initializeIndex(vm, i, exec->argument(i + 1)); } else boundArgs = nullptr; // If the [[Class]] internal property of Target is "Function", then ... // Else set the length own property of F to 0. unsigned length = 0; if (targetObject->hasOwnProperty(exec, exec->propertyNames().length)) { if (exec->hadException()) return JSValue::encode(jsUndefined()); // a. Let L be the length property of Target minus the length of A. // b. Set the length own property of F to either 0 or L, whichever is larger. JSValue lengthValue = target.get(exec, exec->propertyNames().length); if (lengthValue.isNumber()) { unsigned targetLength = (unsigned)lengthValue.asNumber(); if (targetLength > numBoundArgs) length = targetLength - numBoundArgs; } } JSValue nameProp = target.get(exec, exec->propertyNames().name); JSString* name = nameProp.isString() ? nameProp.toString(exec) : jsEmptyString(exec); return JSValue::encode(JSBoundFunction::create(vm, exec, globalObject, targetObject, exec->argument(0), boundArgs, length, name->value(exec))); }
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; }
JSValue JSSQLTransactionSync::executeSql(ExecState* exec) { if (!exec->argumentCount()) { setDOMException(exec, SYNTAX_ERR); return jsUndefined(); } String sqlStatement = ustringToString(exec->argument(0).toString(exec)); if (exec->hadException()) return jsUndefined(); // Now assemble the list of SQL arguments Vector<SQLValue> sqlValues; if (!exec->argument(1).isUndefinedOrNull()) { JSObject* object = exec->argument(1).getObject(); if (!object) { setDOMException(exec, TYPE_MISMATCH_ERR); return jsUndefined(); } JSValue lengthValue = object->get(exec, exec->propertyNames().length); if (exec->hadException()) return jsUndefined(); unsigned length = lengthValue.toUInt32(exec); if (exec->hadException()) return jsUndefined(); for (unsigned i = 0 ; i < length; ++i) { JSValue value = object->get(exec, i); if (exec->hadException()) return jsUndefined(); if (value.isUndefinedOrNull()) sqlValues.append(SQLValue()); else if (value.isNumber()) sqlValues.append(value.uncheckedGetNumber()); else { // Convert the argument to a string and append it sqlValues.append(ustringToString(value.toString(exec))); if (exec->hadException()) return jsUndefined(); } } } ExceptionCode ec = 0; JSValue result = toJS(exec, globalObject(), WTF::getPtr(m_impl->executeSQL(sqlStatement, sqlValues, ec))); setDOMException(exec, ec); return result; }
static RefPtr<IDBKey> createIDBKeyFromValue(ExecState& exec, JSValue value, Vector<JSArray*>& stack) { VM& vm = exec.vm(); if (value.isNumber() && !std::isnan(value.toNumber(&exec))) return IDBKey::createNumber(value.toNumber(&exec)); if (value.isString()) return IDBKey::createString(asString(value)->value(&exec)); if (value.inherits<DateInstance>(vm)) { auto dateValue = valueToDate(exec, value); if (!std::isnan(dateValue)) return IDBKey::createDate(dateValue); } if (value.isObject()) { JSObject* object = asObject(value); if (auto* array = jsDynamicCast<JSArray*>(vm, object)) { size_t length = array->length(); if (stack.contains(array)) return nullptr; if (stack.size() >= maximumDepth) return nullptr; stack.append(array); Vector<RefPtr<IDBKey>> subkeys; for (size_t i = 0; i < length; i++) { JSValue item = array->getIndex(&exec, i); RefPtr<IDBKey> subkey = createIDBKeyFromValue(exec, item, stack); if (!subkey) subkeys.append(IDBKey::createInvalid()); else subkeys.append(subkey); } stack.removeLast(); return IDBKey::createArray(subkeys); } if (auto* arrayBuffer = jsDynamicCast<JSArrayBuffer*>(vm, value)) return IDBKey::createBinary(*arrayBuffer); if (auto* arrayBufferView = jsDynamicCast<JSArrayBufferView*>(vm, value)) return IDBKey::createBinary(*arrayBufferView); } return nullptr; }
void NPRuntimeObjectMap::convertJSValueToNPVariant(ExecState* exec, JSValue value, NPVariant& variant) { JSLock lock(SilenceAssertionsOnly); VOID_TO_NPVARIANT(variant); if (value.isNull()) { NULL_TO_NPVARIANT(variant); return; } if (value.isUndefined()) { VOID_TO_NPVARIANT(variant); return; } if (value.isBoolean()) { BOOLEAN_TO_NPVARIANT(value.toBoolean(exec), variant); return; } if (value.isNumber()) { DOUBLE_TO_NPVARIANT(value.toNumber(exec), variant); return; } if (value.isString()) { CString utf8String = value.toString(exec).utf8(); // This should use NPN_MemAlloc, but we know that it uses malloc under the hood. char* utf8Characters = static_cast<char*>(malloc(utf8String.length())); memcpy(utf8Characters, utf8String.data(), utf8String.length()); STRINGN_TO_NPVARIANT(utf8Characters, utf8String.length(), variant); return; } if (value.isObject()) { NPObject* npObject = getOrCreateNPObject(asObject(value)); OBJECT_TO_NPVARIANT(npObject, variant); return; } ASSERT_NOT_REACHED(); }
// Variant value must be released with NPReleaseVariantValue() void convertValueToNPVariant(ExecState* exec, JSValue value, NPVariant* result) { JSLock lock(SilenceAssertionsOnly); VOID_TO_NPVARIANT(*result); if (value.isString()) { UString ustring = value.toString(exec); CString cstring = ustring.utf8(); NPString string = { (const NPUTF8*)cstring.data(), static_cast<uint32_t>(cstring.length()) }; NPN_InitializeVariantWithStringCopy(result, &string); } else if (value.isNumber()) { DOUBLE_TO_NPVARIANT(value.toNumber(exec), *result); } else if (value.isBoolean()) { BOOLEAN_TO_NPVARIANT(value.toBoolean(exec), *result); } else if (value.isNull()) { NULL_TO_NPVARIANT(*result); } else if (value.isObject()) { JSObject* object = asObject(value); if (object->classInfo() == &CRuntimeObject::s_info) { CRuntimeObject* runtimeObject = static_cast<CRuntimeObject*>(object); CInstance* instance = runtimeObject->getInternalCInstance(); if (instance) { NPObject* obj = instance->getObject(); _NPN_RetainObject(obj); OBJECT_TO_NPVARIANT(obj, *result); } } else { #ifdef ANDROID RootObject* rootObject = findRootObject(exec->dynamicGlobalObject()); if (!rootObject) rootObject = findRootObject(exec->lexicalGlobalObject()); #else JSGlobalObject* globalObject = exec->dynamicGlobalObject(); RootObject* rootObject = findRootObject(globalObject); #endif if (rootObject) { NPObject* npObject = _NPN_CreateScriptObject(0, object, rootObject); OBJECT_TO_NPVARIANT(npObject, *result); } } } }
JSLR_API bool _cdecl JSTryConvertToNumbers(JSContextRef ctx, JSValueRef** value, size_t length, int** indices, double** result) { auto values = *value; auto res = *result; auto ind = *indices; ExecState* exec = toJS(ctx); for (unsigned int i = 0; i < length; i++) { auto ptr = values[ind[i]]; JSValueRef js_value = *&ptr; JSValue jsValue = toJS(exec, js_value); if (!jsValue.isNumber()) { return false; } *&res[i] = jsValue.toNumber(exec); } return true; }