JSValue JSInspectorFrontendHost::showContextMenu(ExecState* execState, const ArgList& args) { if (args.size() < 2) return jsUndefined(); Event* event = toEvent(args.at(0)); JSArray* array = asArray(args.at(1)); Vector<ContextMenuItem*> items; for (size_t i = 0; i < array->length(); ++i) { JSObject* item = asObject(array->getIndex(i)); JSValue label = item->get(execState, Identifier(execState, "label")); JSValue id = item->get(execState, Identifier(execState, "id")); if (label.isUndefined() || id.isUndefined()) items.append(new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String())); else { ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id.toInt32(execState)); items.append(new ContextMenuItem(ActionType, typedId, label.toString(execState))); } } impl()->showContextMenu(event, items); return jsUndefined(); }
static void populateContextMenuItems(ExecState* exec, JSArray* array, ContextMenu& menu) { for (size_t i = 0; i < array->length(); ++i) { JSObject* item = asObject(array->getIndex(exec, i)); JSValue label = item->get(exec, Identifier::fromString(exec, "label")); JSValue type = item->get(exec, Identifier::fromString(exec, "type")); JSValue id = item->get(exec, Identifier::fromString(exec, "id")); JSValue enabled = item->get(exec, Identifier::fromString(exec, "enabled")); JSValue checked = item->get(exec, Identifier::fromString(exec, "checked")); JSValue subItems = item->get(exec, Identifier::fromString(exec, "subItems")); if (!type.isString()) continue; String typeString = type.toWTFString(exec); if (typeString == "separator") { ContextMenuItem item(SeparatorType, ContextMenuItemTagNoAction, String()); menu.appendItem(item); } else if (typeString == "subMenu" && subItems.inherits(JSArray::info())) { ContextMenu subMenu; JSArray* subItemsArray = asArray(subItems); populateContextMenuItems(exec, subItemsArray, subMenu); ContextMenuItem item(SubmenuType, ContextMenuItemTagNoAction, label.toWTFString(exec), &subMenu); menu.appendItem(item); } else { ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id.toInt32(exec)); ContextMenuItem menuItem((typeString == "checkbox" ? CheckableActionType : ActionType), typedId, label.toWTFString(exec)); if (!enabled.isUndefined()) menuItem.setEnabled(enabled.toBoolean(exec)); if (!checked.isUndefined()) menuItem.setChecked(checked.toBoolean(exec)); menu.appendItem(menuItem); } } }
// ECMA-262 5.1, 15.11.4.4 EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); // 1. Let O be the this value. JSValue thisValue = exec->thisValue(); // 2. If Type(O) is not Object, throw a TypeError exception. if (!thisValue.isObject()) return throwVMTypeError(exec, scope); JSObject* thisObj = asObject(thisValue); // Guard against recursion! StringRecursionChecker checker(exec, thisObj); ASSERT(!scope.exception() || checker.earlyReturnValue()); if (JSValue earlyReturnValue = checker.earlyReturnValue()) return JSValue::encode(earlyReturnValue); // 3. Let name be the result of calling the [[Get]] internal method of O with argument "name". JSValue name = thisObj->get(exec, exec->propertyNames().name); RETURN_IF_EXCEPTION(scope, encodedJSValue()); // 4. If name is undefined, then let name be "Error"; else let name be ToString(name). String nameString; if (name.isUndefined()) nameString = ASCIILiteral("Error"); else { nameString = name.toWTFString(exec); RETURN_IF_EXCEPTION(scope, encodedJSValue()); } // 5. Let msg be the result of calling the [[Get]] internal method of O with argument "message". JSValue message = thisObj->get(exec, exec->propertyNames().message); RETURN_IF_EXCEPTION(scope, encodedJSValue()); // (sic) // 6. If msg is undefined, then let msg be the empty String; else let msg be ToString(msg). // 7. If msg is undefined, then let msg be the empty String; else let msg be ToString(msg). String messageString; if (message.isUndefined()) messageString = String(); else { messageString = message.toWTFString(exec); RETURN_IF_EXCEPTION(scope, encodedJSValue()); } // 8. If name is the empty String, return msg. if (!nameString.length()) return JSValue::encode(message.isString() ? message : jsString(exec, messageString)); // 9. If msg is the empty String, return name. if (!messageString.length()) return JSValue::encode(name.isString() ? name : jsString(exec, nameString)); // 10. Return the result of concatenating name, ":", a single space character, and msg. scope.release(); return JSValue::encode(jsMakeNontrivialString(exec, nameString, ": ", messageString)); }
template<> DictionaryImplName convertDictionary<DictionaryImplName>(ExecState& state, JSValue value) { VM& vm = state.vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); if (UNLIKELY(!isNullOrUndefined && !object)) { throwTypeError(&state, throwScope); return { }; } DictionaryImplName result; JSValue boolMemberValue; if (isNullOrUndefined) boolMemberValue = jsUndefined(); else { boolMemberValue = object->get(&state, Identifier::fromString(&state, "boolMember")); RETURN_IF_EXCEPTION(throwScope, { }); } if (!boolMemberValue.isUndefined()) { result.boolMember = convert<IDLBoolean>(state, boolMemberValue); RETURN_IF_EXCEPTION(throwScope, { }); } JSValue callbackMemberValue; if (isNullOrUndefined) callbackMemberValue = jsUndefined(); else { callbackMemberValue = object->get(&state, Identifier::fromString(&state, "callbackMember")); RETURN_IF_EXCEPTION(throwScope, { }); } if (!callbackMemberValue.isUndefined()) { result.callbackMember = convert<IDLCallbackFunction<JSVoidCallback>>(state, callbackMemberValue, *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject())); RETURN_IF_EXCEPTION(throwScope, { }); } JSValue enumMemberValue; if (isNullOrUndefined) enumMemberValue = jsUndefined(); else { enumMemberValue = object->get(&state, Identifier::fromString(&state, "enumMember")); RETURN_IF_EXCEPTION(throwScope, { }); } if (!enumMemberValue.isUndefined()) { result.enumMember = convert<IDLEnumeration<TestStandaloneDictionary::EnumInStandaloneDictionaryFile>>(state, enumMemberValue); RETURN_IF_EXCEPTION(throwScope, { }); } JSValue stringMemberValue; if (isNullOrUndefined) stringMemberValue = jsUndefined(); else { stringMemberValue = object->get(&state, Identifier::fromString(&state, "stringMember")); RETURN_IF_EXCEPTION(throwScope, { }); } if (!stringMemberValue.isUndefined()) { result.stringMember = convert<IDLDOMString>(state, stringMemberValue); RETURN_IF_EXCEPTION(throwScope, { }); } return result; }
JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i) { JSArray* array = m_cachedResult.lastResult(exec, this); if (i < array->length()) { JSValue result = JSValue(array).get(exec, i); ASSERT(result.isString() || result.isUndefined()); if (!result.isUndefined()) return result; } return jsEmptyString(exec); }
JSValue RegExpConstructor::getLastParen(ExecState* exec) { JSArray* array = m_cachedResult.lastResult(exec, this); unsigned length = array->length(); if (length > 1) { JSValue result = JSValue(array).get(exec, length - 1); ASSERT(result.isString() || result.isUndefined()); if (!result.isUndefined()) return result; } return jsEmptyString(exec); }
static int compareByStringForQSort(const void *a, const void *b) { ExecState *exec = execForCompareByStringForQSort; JSValue *va = *(JSValue **)a; JSValue *vb = *(JSValue **)b; if (va->isUndefined()) { return vb->isUndefined() ? 0 : 1; } if (vb->isUndefined()) { return -1; } return compare(va->toString(exec), vb->toString(exec)); }
JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, JSObject* callee, JSValue newTarget) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSValue patternArg = args.at(0); JSValue flagsArg = args.at(1); bool isPatternRegExp = patternArg.inherits(vm, RegExpObject::info()); bool constructAsRegexp = isRegExp(vm, exec, patternArg); RETURN_IF_EXCEPTION(scope, nullptr); if (newTarget.isUndefined() && constructAsRegexp && flagsArg.isUndefined()) { JSValue constructor = patternArg.get(exec, vm.propertyNames->constructor); RETURN_IF_EXCEPTION(scope, nullptr); if (callee == constructor) { // We know that patternArg is a object otherwise constructAsRegexp would be false. return patternArg.getObject(); } } if (isPatternRegExp) { RegExp* regExp = jsCast<RegExpObject*>(patternArg)->regExp(); Structure* structure = getRegExpStructure(exec, globalObject, newTarget); RETURN_IF_EXCEPTION(scope, nullptr); if (!flagsArg.isUndefined()) { RegExpFlags flags = toFlags(exec, flagsArg); ASSERT(!!scope.exception() == (flags == InvalidFlags)); if (flags == InvalidFlags) return nullptr; regExp = RegExp::create(vm, regExp->pattern(), flags); } return RegExpObject::create(vm, structure, regExp); } if (constructAsRegexp) { JSValue pattern = patternArg.get(exec, vm.propertyNames->source); RETURN_IF_EXCEPTION(scope, nullptr); if (flagsArg.isUndefined()) { flagsArg = patternArg.get(exec, vm.propertyNames->flags); RETURN_IF_EXCEPTION(scope, nullptr); } patternArg = pattern; } scope.release(); return regExpCreate(exec, globalObject, newTarget, patternArg, flagsArg); }
static EncodedJSValue JSC_HOST_CALL callSymbol(ExecState* exec) { JSValue description = exec->argument(0); if (description.isUndefined()) return JSValue::encode(Symbol::create(exec->vm())); return JSValue::encode(Symbol::create(exec, description.toString(exec))); }
static EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatFuncFormatDateTime(ExecState* state) { // 12.3.4 DateTime Format Functions (ECMA-402 2.0) // 1. Let dtf be the this value. // 2. Assert: Type(dtf) is Object and dtf has an [[initializedDateTimeFormat]] internal slot whose value is true. IntlDateTimeFormat* format = jsCast<IntlDateTimeFormat*>(state->thisValue()); JSValue date = state->argument(0); double value; // 3. If date is not provided or is undefined, then if (date.isUndefined()) { // a. Let x be %Date_now%(). value = JSValue::decode(dateNow(state)).toNumber(state); } else { // 4. Else // a. Let x be ToNumber(date). value = date.toNumber(state); // b. ReturnIfAbrupt(x). if (state->hadException()) return JSValue::encode(jsUndefined()); } // 5. Return FormatDateTime(dtf, x). return JSValue::encode(format->format(*state, value)); }
static inline double normalizeHighWaterMark(ExecState& exec, JSObject& strategy) { JSValue jsHighWaterMark = getPropertyFromObject(exec, strategy, "highWaterMark"); if (exec.hadException()) return 0; if (jsHighWaterMark.isUndefined()) return 1; double highWaterMark = jsHighWaterMark.toNumber(&exec); if (exec.hadException()) return 0; if (std::isnan(highWaterMark)) { throwVMError(&exec, createTypeError(&exec, ASCIILiteral("Value is NaN"))); return 0; } if (highWaterMark < 0) { throwVMError(&exec, createRangeError(&exec, ASCIILiteral("Not a positive value"))); return 0; } return highWaterMark; }
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 _NPN_HasMethod(NPP, NPObject* o, NPIdentifier methodName) { if (o->_class == NPScriptObjectClass) { JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o); PrivateIdentifier* i = static_cast<PrivateIdentifier*>(methodName); if (!i->isString) return false; RootObject* rootObject = obj->rootObject; if (!rootObject || !rootObject->isValid()) return false; ExecState* exec = rootObject->globalObject()->globalExec(); JSLock lock(false); JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string)); exec->clearException(); return !func->isUndefined(); } if (o->_class->hasMethod) return o->_class->hasMethod(o, methodName); return false; }
bool injectIDBKeyIntoScriptValue(JSC::ExecState& exec, const IDBKeyData& keyData, JSC::JSValue value, const IDBKeyPath& keyPath) { LOG(IndexedDB, "injectIDBKeyIntoScriptValue"); ASSERT(keyPath.type() == IndexedDB::KeyPathType::String); Vector<String> keyPathElements; IDBKeyPathParseError error; IDBParseKeyPath(keyPath.string(), keyPathElements, error); ASSERT(error == IDBKeyPathParseError::None); if (keyPathElements.isEmpty()) return false; JSValue parent = ensureNthValueOnKeyPath(&exec, value, keyPathElements, keyPathElements.size() - 1); if (parent.isUndefined()) return false; auto key = keyData.maybeCreateIDBKey(); if (!key) return false; if (!set(&exec, parent, keyPathElements.last(), idbKeyToJSValue(&exec, exec.lexicalGlobalObject(), key.get()))) return false; return true; }
bool _NPN_HasMethod(NPP, NPObject* o, NPIdentifier methodName) { if (o->_class == NPScriptObjectClass) { JavaScriptObject* obj = (JavaScriptObject*)o; if (!_isSafeScript(obj)) return false; PrivateIdentifier* i = (PrivateIdentifier*)methodName; if (!i->isString) return false; RootObject* rootObject = obj->rootObject; if (!rootObject || !rootObject->isValid()) return false; ExecState* exec = rootObject->interpreter()->globalExec(); JSLock lock; JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string)); return !func->isUndefined(); } if (o->_class->hasMethod) return o->_class->hasMethod(o, methodName); return false; }
EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec) { VM& vm = exec->vm(); JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); if (thisValue.isUndefinedOrNull()) return JSValue::encode(thisValue.isUndefined() ? vm.smallStrings.undefinedObjectString() : vm.smallStrings.nullObjectString()); JSObject* thisObject = thisValue.toObject(exec); JSValue stringTag = thisObject->get(exec, exec->propertyNames().toStringTagSymbol); if (stringTag.isString()) { JSRopeString::RopeBuilder<RecordOverflow> ropeBuilder(vm); ropeBuilder.append(vm.smallStrings.objectStringStart()); ropeBuilder.append(jsCast<JSString*>(stringTag)); ropeBuilder.append(vm.smallStrings.singleCharacterString(']')); if(ropeBuilder.hasOverflowed()) return JSValue::encode(throwOutOfMemoryError(exec)); return JSValue::encode(ropeBuilder.release()); } JSString* result = thisObject->structure(vm)->objectToStringValue(); if (!result) { RefPtr<StringImpl> newString = WTF::tryMakeString("[object ", thisObject->methodTable(exec->vm())->className(thisObject), "]"); if (!newString) return JSValue::encode(throwOutOfMemoryError(exec)); result = jsNontrivialString(&vm, newString.release()); thisObject->structure(vm)->setObjectToStringValue(vm, result); } return JSValue::encode(result); }
RefPtr<IDBRequest> IDBObjectStore::put(ExecState& execState, JSValue value, JSValue key, ExceptionCodeWithMessage& ec) { RefPtr<IDBKey> idbKey; if (!key.isUndefined()) idbKey = scriptValueToIDBKey(execState, key); return putOrAdd(execState, value, idbKey, IndexedDB::ObjectStoreOverwriteMode::Overwrite, InlineKeyCheck::Perform, ec); }
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; }
bool injectIDBKeyIntoScriptValue(DOMRequestState* requestState, PassRefPtr<IDBKey> key, Deprecated::ScriptValue& value, const IDBKeyPath& keyPath) { LOG(StorageAPI, "injectIDBKeyIntoScriptValue"); ASSERT(keyPath.type() == IndexedDB::KeyPathType::String); Vector<String> keyPathElements; IDBKeyPathParseError error; IDBParseKeyPath(keyPath.string(), keyPathElements, error); ASSERT(error == IDBKeyPathParseError::None); if (keyPathElements.isEmpty()) return false; ExecState* exec = requestState->exec(); JSValue parent = ensureNthValueOnKeyPath(exec, value.jsValue(), keyPathElements, keyPathElements.size() - 1); if (parent.isUndefined()) return false; if (!set(exec, parent, keyPathElements.last(), idbKeyToJSValue(exec, exec->lexicalGlobalObject(), key.get()))) return false; return true; }
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(); }
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); } }
bool injectIDBKeyIntoScriptValue(ExecState& exec, const IDBKeyData& keyData, JSValue value, const IDBKeyPath& keyPath) { LOG(IndexedDB, "injectIDBKeyIntoScriptValue"); ASSERT(WTF::holds_alternative<String>(keyPath)); Vector<String> keyPathElements; IDBKeyPathParseError error; IDBParseKeyPath(WTF::get<String>(keyPath), keyPathElements, error); ASSERT(error == IDBKeyPathParseError::None); if (keyPathElements.isEmpty()) return false; JSValue parent = ensureNthValueOnKeyPath(exec, value, keyPathElements, keyPathElements.size() - 1); if (parent.isUndefined()) return false; auto key = keyData.maybeCreateIDBKey(); if (!key) return false; if (!set(exec, parent, keyPathElements.last(), toJS(exec, *exec.lexicalGlobalObject(), key.get()))) return false; return true; }
static EncodedJSValue JSC_HOST_CALL constructIntlDateTimeFormat(ExecState* state) { // 12.1.2 Intl.DateTimeFormat ([locales [, options]]) (ECMA-402 2.0) // 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget. JSValue newTarget = state->newTarget(); if (newTarget.isUndefined()) newTarget = state->callee(); // 2. Let dateTimeFormat be OrdinaryCreateFromConstructor(newTarget, %DateTimeFormatPrototype%). VM& vm = state->vm(); IntlDateTimeFormat* dateTimeFormat = IntlDateTimeFormat::create(vm, jsCast<IntlDateTimeFormatConstructor*>(state->callee())); if (dateTimeFormat && !jsDynamicCast<IntlDateTimeFormatConstructor*>(newTarget)) { JSValue proto = asObject(newTarget)->getDirect(vm, vm.propertyNames->prototype); asObject(dateTimeFormat)->setPrototype(vm, state, proto); if (vm.exception()) return JSValue::encode(JSValue()); } // 3. ReturnIfAbrupt(dateTimeFormat). ASSERT(dateTimeFormat); // 4. Return InitializeDateTimeFormat(dateTimeFormat, locales, options). JSValue locales = state->argument(0); JSValue options = state->argument(1); dateTimeFormat->initializeDateTimeFormat(*state, locales, options); return JSValue::encode(dateTimeFormat); }
template<> TestEventConstructor::Init convertDictionary<TestEventConstructor::Init>(ExecState& state, JSValue value) { VM& vm = state.vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); if (UNLIKELY(!isNullOrUndefined && !object)) { throwTypeError(&state, throwScope); return { }; } if (UNLIKELY(object && object->type() == RegExpObjectType)) { throwTypeError(&state, throwScope); return { }; } TestEventConstructor::Init result; JSValue bubblesValue = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "bubbles")); if (!bubblesValue.isUndefined()) { result.bubbles = convert<IDLBoolean>(state, bubblesValue); RETURN_IF_EXCEPTION(throwScope, { }); } else result.bubbles = false; JSValue cancelableValue = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "cancelable")); if (!cancelableValue.isUndefined()) { result.cancelable = convert<IDLBoolean>(state, cancelableValue); RETURN_IF_EXCEPTION(throwScope, { }); } else result.cancelable = false; JSValue composedValue = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "composed")); if (!composedValue.isUndefined()) { result.composed = convert<IDLBoolean>(state, composedValue); RETURN_IF_EXCEPTION(throwScope, { }); } else result.composed = false; JSValue attr2Value = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "attr2")); if (!attr2Value.isUndefined()) { result.attr2 = convert<IDLDOMString>(state, attr2Value); RETURN_IF_EXCEPTION(throwScope, { }); } else result.attr2 = ""; JSValue attr3Value = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "attr3")); if (!attr3Value.isUndefined()) { result.attr3 = convert<IDLDOMString>(state, attr3Value); RETURN_IF_EXCEPTION(throwScope, { }); } else result.attr3 = ""; return result; }
void JSArray::sort(ExecState* exec) { unsigned lengthNotIncludingUndefined = compactForSorting(); if (m_storage->m_sparseValueMap) { throwOutOfMemoryError(exec); return; } if (!lengthNotIncludingUndefined) return; // Converting JavaScript values to strings can be expensive, so we do it once up front and sort based on that. // This is a considerable improvement over doing it twice per comparison, though it requires a large temporary // buffer. Besides, this protects us from crashing if some objects have custom toString methods that return // random or otherwise changing results, effectively making compare function inconsistent. Vector<ValueStringPair> values(lengthNotIncludingUndefined); if (!values.begin()) { throwOutOfMemoryError(exec); return; } for (size_t i = 0; i < lengthNotIncludingUndefined; i++) { JSValue value = m_storage->m_vector[i]; Q_ASSERT(!value.isUndefined()); values[i].first = value; } // FIXME: While calling these toString functions, the array could be mutated. // In that case, objects pointed to by values in this vector might get garbage-collected! // FIXME: The following loop continues to call toString on subsequent values even after // a toString call raises an exception. for (size_t i = 0; i < lengthNotIncludingUndefined; i++) values[i].second = values[i].first.toString(exec); if (exec->hadException()) return; // FIXME: Since we sort by string value, a fast algorithm might be to use a radix sort. That would be O(N) rather // than O(N log N). #if HAVE(MERGESORT) mergesort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort); #else // FIXME: The qsort library function is likely to not be a stable sort. // ECMAScript-262 does not specify a stable sort, but in practice, browsers perform a stable sort. qsort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort); #endif // FIXME: If the toString function changed the length of the array, this might be // modifying the vector incorrectly. for (size_t i = 0; i < lengthNotIncludingUndefined; i++) m_storage->m_vector[i] = values[i].first; checkConsistency(SortConsistencyCheck); }
EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); JSValue name = thisObj->get(exec, exec->propertyNames().name); JSValue message = thisObj->get(exec, exec->propertyNames().message); // Mozilla-compatible format. if (!name.isUndefined()) { if (!message.isUndefined()) return JSValue::encode(jsMakeNontrivialString(exec, name.toString(exec), ": ", message.toString(exec))); return JSValue::encode(jsNontrivialString(exec, name.toString(exec))); } if (!message.isUndefined()) return JSValue::encode(jsMakeNontrivialString(exec, "Error: ", message.toString(exec))); return JSValue::encode(jsNontrivialString(exec, "Error")); }
bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isUndefined(); }
JSValue* ErrorProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List &/*args*/) { // toString() UString s = "Error"; JSValue* v = thisObj->get(exec, exec->propertyNames().name); if (!v->isUndefined()) { s = v->toString(exec); } v = thisObj->get(exec, exec->propertyNames().message); if (!v->isUndefined()) { s += ": " + v->toString(exec); // Mozilla compatible format } return jsString(s); }
EncodedJSValue JSC_HOST_CALL JSPromisePrototypeFuncThen(ExecState* exec) { JSPromise* thisObject = jsDynamicCast<JSPromise*>(exec->thisValue()); if (!thisObject) return throwVMError(exec, createTypeError(exec, "Receiver of then must be a Promise")); JSValue fulfillCallback = exec->argument(0); if (!fulfillCallback.isUndefined()) { CallData callData; CallType callType = getCallData(fulfillCallback, callData); if (callType == CallTypeNone) return throwVMError(exec, createTypeError(exec, "Expected function or undefined as as first argument")); } JSValue rejectCallback = exec->argument(1); if (!rejectCallback.isUndefined()) { CallData callData; CallType callType = getCallData(rejectCallback, callData); if (callType == CallTypeNone) return throwVMError(exec, createTypeError(exec, "Expected function or undefined as as second argument")); } JSFunction* callee = jsCast<JSFunction*>(exec->callee()); JSGlobalObject* globalObject = callee->globalObject(); // 1. Let promise be a new promise. JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject); // 2. Let resolver be promise's associated resolver. JSPromiseResolver* resolver = promise->resolver(); // 3. Let fulfillWrapper be a promise wrapper callback for resolver and fulfillCallback if fulfillCallback is // not omitted and a promise callback for resolver and its fulfill algorithm otherwise. InternalFunction* fulfillWrapper = wrapCallback(exec, globalObject, fulfillCallback, resolver, JSPromiseCallback::Fulfill); // 4. Let rejectWrapper be a promise wrapper callback for resolver and rejectCallback if rejectCallback is // not omitted and a promise callback for resolver and its reject algorithm otherwise. InternalFunction* rejectWrapper = wrapCallback(exec, globalObject, rejectCallback, resolver, JSPromiseCallback::Reject); // 5. Append fulfillWrapper and rejectWrapper to the context object. thisObject->appendCallbacks(exec, fulfillWrapper, rejectWrapper); // 6. Return promise. return JSValue::encode(promise); }
bool JSHTMLAllCollection::nameGetter(ExecState* state, PropertyName propertyName, JSValue& value) { JSValue items = namedItems(*state, this, propertyName); if (items.isUndefined()) return false; value = items; return true; }