EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeRequestedModules(ExecState* exec) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(vm, exec->argument(0)); if (!moduleRecord) { scope.release(); return JSValue::encode(constructEmptyArray(exec, nullptr)); } JSArray* result = constructEmptyArray(exec, nullptr, moduleRecord->requestedModules().size()); RETURN_IF_EXCEPTION(scope, encodedJSValue()); size_t i = 0; for (auto& key : moduleRecord->requestedModules()) { result->putDirectIndex(exec, i++, jsString(exec, key.get())); RETURN_IF_EXCEPTION(scope, encodedJSValue()); } return JSValue::encode(result); }
EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState* exec) { JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee()); ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true! JSArray* boundArgs = asArray(boundFunction->boundArgs()); MarkedArgumentBuffer args; for (unsigned i = 0; i < boundArgs->length(); ++i) args.append(boundArgs->getIndex(i)); for (unsigned i = 0; i < exec->argumentCount(); ++i) args.append(exec->argument(i)); JSObject* targetFunction = boundFunction->targetFunction(); CallData callData; CallType callType = getCallData(targetFunction, callData); ASSERT(callType != CallTypeNone); return JSValue::encode(call(exec, targetFunction, callType, callData, boundFunction->boundThis(), args)); }
void finishCreation(JSGlobalData& globalData, const Vector<String>& arguments) { Base::finishCreation(globalData); addFunction(globalData, "debug", functionDebug, 1); addFunction(globalData, "describe", functionDescribe, 1); addFunction(globalData, "print", functionPrint, 1); addFunction(globalData, "quit", functionQuit, 0); addFunction(globalData, "gc", functionGC, 0); #ifndef NDEBUG addFunction(globalData, "dumpCallFrame", functionDumpCallFrame, 0); addFunction(globalData, "releaseExecutableMemory", functionReleaseExecutableMemory, 0); #endif addFunction(globalData, "version", functionVersion, 1); addFunction(globalData, "run", functionRun, 1); addFunction(globalData, "load", functionLoad, 1); addFunction(globalData, "checkSyntax", functionCheckSyntax, 1); addFunction(globalData, "jscStack", functionJSCStack, 1); #if !defined(__LB_SHELL__) addFunction(globalData, "readline", functionReadline, 0); #endif addFunction(globalData, "preciseTime", functionPreciseTime, 0); #if ENABLE(SAMPLING_FLAGS) addFunction(globalData, "setSamplingFlags", functionSetSamplingFlags, 1); addFunction(globalData, "clearSamplingFlags", functionClearSamplingFlags, 1); #endif addConstructableFunction(globalData, "Uint8Array", constructJSUint8Array, 1); addConstructableFunction(globalData, "Uint8ClampedArray", constructJSUint8ClampedArray, 1); addConstructableFunction(globalData, "Uint16Array", constructJSUint16Array, 1); addConstructableFunction(globalData, "Uint32Array", constructJSUint32Array, 1); addConstructableFunction(globalData, "Int8Array", constructJSInt8Array, 1); addConstructableFunction(globalData, "Int16Array", constructJSInt16Array, 1); addConstructableFunction(globalData, "Int32Array", constructJSInt32Array, 1); addConstructableFunction(globalData, "Float32Array", constructJSFloat32Array, 1); addConstructableFunction(globalData, "Float64Array", constructJSFloat64Array, 1); JSArray* array = constructEmptyArray(globalExec(), 0); for (size_t i = 0; i < arguments.size(); ++i) array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i])); putDirect(globalData, Identifier(globalExec(), "arguments"), array); }
// 15.3.4.5 Function.prototype.bind (thisArg [, arg1 [, arg2, ...]]) EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec) { JSGlobalObject* globalObject = exec->callee()->globalObject(); // Let Target be the this value. JSValue target = exec->hostThisValue(); // If IsCallable(Target) is false, throw a TypeError exception. CallData callData; CallType callType = getCallData(target, callData); if (callType == CallTypeNone) return throwVMTypeError(exec); // 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 = JSArray::tryCreateUninitialized(exec->globalData(), globalObject->arrayStructure(), numBoundArgs); if (!boundArgs) return JSValue::encode(throwOutOfMemoryError(exec)); for (size_t i = 0; i < numBoundArgs; ++i) boundArgs->initializeIndex(exec->globalData(), i, exec->argument(i + 1)); boundArgs->completeInitialization(numBoundArgs); // 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->inherits(&JSFunction::s_info)) { ASSERT(target.get(exec, exec->propertyNames().length).isNumber()); // 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. unsigned targetLength = (unsigned)target.get(exec, exec->propertyNames().length).asNumber(); if (targetLength > numBoundArgs) length = targetLength - numBoundArgs; } Identifier name(exec, target.get(exec, exec->propertyNames().name).toString(exec)->value(exec)); return JSValue::encode(JSBoundFunction::create(exec, globalObject, targetObject, exec->argument(0), boundArgs, length, name)); }
EncodedJSValue JSC_HOST_CALL boundFunctionConstruct(ExecState* exec) { JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->jsCallee()); JSArray* boundArgs = boundFunction->boundArgs(); MarkedArgumentBuffer args; if (boundArgs) { for (unsigned i = 0; i < boundArgs->length(); ++i) args.append(boundArgs->getIndexQuickly(i)); } for (unsigned i = 0; i < exec->argumentCount(); ++i) args.append(exec->uncheckedArgument(i)); JSObject* targetFunction = boundFunction->targetFunction(); ConstructData constructData; ConstructType constructType = getConstructData(targetFunction, constructData); ASSERT(constructType != ConstructType::None); return JSValue::encode(construct(exec, targetFunction, constructType, constructData, args)); }
static EncodedJSValue JSC_HOST_CALL promiseAllCountdownFunction(ExecState* exec) { JSValue x = exec->argument(0); VM& vm = exec->vm(); JSObject* F = exec->callee(); // 1. Let 'index' be the value of F's [[Index]] internal slot. uint32_t index = F->get(exec, vm.propertyNames->indexPrivateName).asUInt32(); // 2. Let 'values' be the value of F's [[Values]] internal slot.. JSArray* values = jsCast<JSArray*>(F->get(exec, vm.propertyNames->valuesPrivateName)); // 3. Let 'deferred' be the value of F's [[Deferred]] internal slot. JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(F->get(exec, vm.propertyNames->deferredPrivateName)); // 4. Let 'countdownHolder' be the value of F's [[CountdownHolder]] internal slot. NumberObject* countdownHolder = jsCast<NumberObject*>(F->get(exec, vm.propertyNames->countdownHolderPrivateName)); // 5. Let 'result' be the result of calling the [[DefineOwnProperty]] internal method // of 'values' with arguments 'index' and Property Descriptor { [[Value]]: x, // [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }. values->putDirectIndex(exec, index, x); // 6. RejectIfAbrupt(result, deferred). if (exec->hadException()) abruptRejection(exec, deferred); // 7. Set countdownHolder.[[Countdown]] to countdownHolder.[[Countdown]] - 1. uint32_t newCountdownValue = countdownHolder->internalValue().asUInt32() - 1; countdownHolder->setInternalValue(vm, JSValue(newCountdownValue)); // 8. If countdownHolder.[[Countdown]] is 0, if (!newCountdownValue) { // i. Return the result of calling the [[Call]] internal method of deferred.[[Resolve]] // with undefined as thisArgument and a List containing 'values' as argumentsList. performDeferredResolve(exec, deferred, values); } // 9. Return. return JSValue::encode(jsUndefined()); }
static JSArray* getJSListenerFunctions(ExecState* exec, Document* document, const EventListenerInfo& listenerInfo) { JSArray* result = constructEmptyArray(exec); size_t handlersCount = listenerInfo.eventListenerVector.size(); for (size_t i = 0, outputIndex = 0; i < handlersCount; ++i) { const JSEventListener* jsListener = JSEventListener::cast(listenerInfo.eventListenerVector[i].listener.get()); if (!jsListener) { ASSERT_NOT_REACHED(); continue; } // Hide listeners from other contexts. if (jsListener->isolatedWorld() != currentWorld(exec)) continue; JSObject* function = jsListener->jsFunction(document); JSObject* listenerEntry = constructEmptyObject(exec); listenerEntry->putDirect(exec->globalData(), Identifier(exec, "listener"), function); listenerEntry->putDirect(exec->globalData(), Identifier(exec, "useCapture"), jsBoolean(listenerInfo.eventListenerVector[i].useCapture)); result->putDirectIndex(exec, outputIndex++, JSValue(listenerEntry)); } return result; }
JSArray* createRegExpMatchesArray(ExecState* exec, JSString* input, RegExp* regExp, MatchResult result) { ASSERT(result); VM& vm = exec->vm(); JSArray* array = JSArray::tryCreateUninitialized(vm, exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), regExp->numSubpatterns() + 1); RELEASE_ASSERT(array); SamplingRegion samplingRegion("Reifying substring properties"); array->initializeIndex(vm, 0, jsSubstring(exec, input, result.start, result.end - result.start), ArrayWithContiguous); if (unsigned numSubpatterns = regExp->numSubpatterns()) { Vector<int, 32> subpatternResults; int position = regExp->match(vm, input->value(exec), result.start, subpatternResults); ASSERT_UNUSED(position, position >= 0 && static_cast<size_t>(position) == result.start); ASSERT(result.start == static_cast<size_t>(subpatternResults[0])); ASSERT(result.end == static_cast<size_t>(subpatternResults[1])); for (unsigned i = 1; i <= numSubpatterns; ++i) { int start = subpatternResults[2 * i]; if (start >= 0) array->initializeIndex(vm, i, jsSubstring(exec, input, start, subpatternResults[2 * i + 1] - start), ArrayWithContiguous); else array->initializeIndex(vm, i, jsUndefined(), ArrayWithContiguous); } } array->putDirect(vm, vm.propertyNames->index, jsNumber(result.start)); array->putDirect(vm, vm.propertyNames->input, input); return array; }
JSValue Database::toJS(ExecState* exec) const { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSObject* result = constructEmptyObject(exec); JSArray* bytecodes = constructEmptyArray(exec, 0); RETURN_IF_EXCEPTION(scope, JSValue()); for (unsigned i = 0; i < m_bytecodes.size(); ++i) bytecodes->putDirectIndex(exec, i, m_bytecodes[i].toJS(exec)); result->putDirect(vm, exec->propertyNames().bytecodes, bytecodes); JSArray* compilations = constructEmptyArray(exec, 0); RETURN_IF_EXCEPTION(scope, JSValue()); for (unsigned i = 0; i < m_compilations.size(); ++i) compilations->putDirectIndex(exec, i, m_compilations[i]->toJS(exec)); result->putDirect(vm, exec->propertyNames().compilations, compilations); JSArray* events = constructEmptyArray(exec, 0); RETURN_IF_EXCEPTION(scope, JSValue()); for (unsigned i = 0; i < m_events.size(); ++i) events->putDirectIndex(exec, i, m_events[i].toJS(exec)); result->putDirect(vm, exec->propertyNames().events, events); return result; }
JSValue JSInspectorFrontendHost::showContextMenu(ExecState* exec) { if (exec->argumentCount() < 2) return jsUndefined(); #if ENABLE(CONTEXT_MENUS) Event* event = toEvent(exec->argument(0)); JSArray* array = asArray(exec->argument(1)); Vector<ContextMenuItem*> items; for (size_t i = 0; i < array->length(); ++i) { JSObject* item = asObject(array->getIndex(i)); JSValue label = item->get(exec, Identifier(exec, "label")); JSValue type = item->get(exec, Identifier(exec, "type")); JSValue id = item->get(exec, Identifier(exec, "id")); JSValue enabled = item->get(exec, Identifier(exec, "enabled")); JSValue checked = item->get(exec, Identifier(exec, "checked")); if (!type.isString()) continue; String typeString = ustringToString(type.toString(exec)->value(exec)); if (typeString == "separator") { items.append(new ContextMenuItem(SeparatorType, ContextMenuItemCustomTagNoAction, String())); } else { ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id.toInt32(exec)); ContextMenuItem* menuItem = new ContextMenuItem((typeString == "checkbox" ? CheckableActionType : ActionType), typedId, ustringToString(label.toString(exec)->value(exec))); if (!enabled.isUndefined()) menuItem->setEnabled(enabled.toBoolean(exec)); if (!checked.isUndefined()) menuItem->setChecked(checked.toBoolean(exec)); items.append(menuItem); } } impl()->showContextMenu(event, items); #endif return jsUndefined(); }
EncodedJSValue JSC_HOST_CALL JSWebSocketConstructor::constructJSWebSocket(ExecState* exec) { JSWebSocketConstructor* jsConstructor = static_cast<JSWebSocketConstructor*>(exec->callee()); ScriptExecutionContext* context = jsConstructor->scriptExecutionContext(); if (!context) return throwVMError(exec, createReferenceError(exec, "WebSocket constructor associated document is unavailable")); if (!exec->argumentCount()) return throwVMError(exec, createSyntaxError(exec, "Not enough arguments")); String urlString = ustringToString(exec->argument(0).toString(exec)->value(exec)); if (exec->hadException()) return throwVMError(exec, createSyntaxError(exec, "wrong URL")); RefPtr<WebSocket> webSocket = WebSocket::create(context); ExceptionCode ec = 0; if (exec->argumentCount() < 2) webSocket->connect(urlString, ec); else { JSValue protocolsValue = exec->argument(1); if (isJSArray(protocolsValue)) { Vector<String> protocols; JSArray* protocolsArray = asArray(protocolsValue); for (unsigned i = 0; i < protocolsArray->length(); ++i) { String protocol = ustringToString(protocolsArray->getIndex(i).toString(exec)->value(exec)); if (exec->hadException()) return JSValue::encode(JSValue()); protocols.append(protocol); } webSocket->connect(urlString, protocols, ec); } else { String protocol = ustringToString(protocolsValue.toString(exec)->value(exec)); if (exec->hadException()) return JSValue::encode(JSValue()); webSocket->connect(urlString, protocol, ec); } } setDOMException(exec, ec); return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), WebSocket, webSocket.get())); }
void ArrayAllocationProfile::updateIndexingType() { // This is awkwardly racy but totally sound even when executed concurrently. The // worst cases go something like this: // // - Two threads race to execute this code; one of them succeeds in updating the // m_currentIndexingType and the other either updates it again, or sees a null // m_lastArray; if it updates it again then at worst it will cause the profile // to "forget" some array. That's still sound, since we don't promise that // this profile is a reflection of any kind of truth. // // - A concurrent thread reads m_lastArray, but that array is now dead. While // it's possible for that array to no longer be reachable, it cannot actually // be freed, since we require the GC to wait until all concurrent JITing // finishes. JSArray* lastArray = m_lastArray; if (!lastArray) return; m_currentIndexingType = leastUpperBoundOfIndexingTypes(m_currentIndexingType, lastArray->structure()->indexingType()); m_lastArray = 0; }
JSValue Compilation::toJS(ExecState* exec) const { JSObject* result = constructEmptyObject(exec); result->putDirect(exec->globalData(), exec->propertyNames().bytecodesID, jsNumber(m_bytecodes->id())); result->putDirect(exec->globalData(), exec->propertyNames().compilationKind, jsString(exec, String::fromUTF8(toCString(m_kind)))); JSArray* profiledBytecodes = constructEmptyArray(exec, 0); for (unsigned i = 0; i < m_profiledBytecodes.size(); ++i) profiledBytecodes->putDirectIndex(exec, i, m_profiledBytecodes[i].toJS(exec)); result->putDirect(exec->globalData(), exec->propertyNames().profiledBytecodes, profiledBytecodes); JSArray* descriptions = constructEmptyArray(exec, 0); for (unsigned i = 0; i < m_descriptions.size(); ++i) descriptions->putDirectIndex(exec, i, m_descriptions[i].toJS(exec)); result->putDirect(exec->globalData(), exec->propertyNames().descriptions, descriptions); JSArray* counters = constructEmptyArray(exec, 0); HashMap<OriginStack, OwnPtr<ExecutionCounter> >::const_iterator end = m_counters.end(); for (HashMap<OriginStack, OwnPtr<ExecutionCounter> >::const_iterator iter = m_counters.begin(); iter != end; ++iter) { JSObject* counterEntry = constructEmptyObject(exec); counterEntry->putDirect(exec->globalData(), exec->propertyNames().origin, iter->key.toJS(exec)); counterEntry->putDirect(exec->globalData(), exec->propertyNames().executionCount, jsNumber(iter->value->count())); counters->push(exec, counterEntry); } result->putDirect(exec->globalData(), exec->propertyNames().counters, counters); JSArray* exitSites = constructEmptyArray(exec, 0); for (unsigned i = 0; i < m_osrExitSites.size(); ++i) exitSites->putDirectIndex(exec, i, m_osrExitSites[i].toJS(exec)); result->putDirect(exec->globalData(), exec->propertyNames().osrExitSites, exitSites); JSArray* exits = constructEmptyArray(exec, 0); for (unsigned i = 0; i < m_osrExits.size(); ++i) exits->putDirectIndex(exec, i, m_osrExits[i].toJS(exec)); result->putDirect(exec->globalData(), exec->propertyNames().osrExits, exits); return result; }
static JSValue idbKeyToJSValue(ExecState* exec, JSGlobalObject* globalObject, IDBKey* key) { if (!key || !exec) { // This should be undefined, not null. // Spec: http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBKeyRange return jsUndefined(); } Locker<JSLock> locker(exec->vm().apiLock()); switch (key->type()) { case KeyType::Array: { const Vector<RefPtr<IDBKey>>& inArray = key->array(); size_t size = inArray.size(); JSArray* outArray = constructEmptyArray(exec, 0, globalObject, size); for (size_t i = 0; i < size; ++i) { IDBKey* arrayKey = inArray.at(i).get(); outArray->putDirectIndex(exec, i, idbKeyToJSValue(exec, globalObject, arrayKey)); } return JSValue(outArray); } case KeyType::String: return jsStringWithCache(exec, key->string()); case KeyType::Date: return jsDateOrNull(exec, key->date()); case KeyType::Number: return jsNumber(key->number()); case KeyType::Min: case KeyType::Max: case KeyType::Invalid: ASSERT_NOT_REACHED(); return jsUndefined(); } ASSERT_NOT_REACHED(); return jsUndefined(); }
static RefPtr<IDBKey> createIDBKeyFromValue(ExecState* exec, JSValue value, Vector<JSArray*>& stack) { if (value.isNumber() && !std::isnan(value.toNumber(exec))) return IDBKey::createNumber(value.toNumber(exec)); if (value.isString()) return IDBKey::createString(value.toString(exec)->value(exec)); if (value.inherits(DateInstance::info()) && !std::isnan(valueToDate(exec, value))) return IDBKey::createDate(valueToDate(exec, value)); if (value.isObject()) { JSObject* object = asObject(value); if (isJSArray(object) || object->inherits(JSArray::info())) { JSArray* array = asArray(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); } } return nullptr; }
static bool cryptoKeyUsagesFromJSValue(ExecState& state, JSValue value, CryptoKeyUsageBitmap& result) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (!isJSArray(value)) { throwTypeError(&state, scope); return false; } result = 0; JSArray* array = asArray(value); for (size_t i = 0; i < array->length(); ++i) { JSValue element = array->getIndex(&state, i); String usageString = element.toString(&state)->value(&state); RETURN_IF_EXCEPTION(scope, false); if (usageString == "encrypt") result |= CryptoKeyUsageEncrypt; else if (usageString == "decrypt") result |= CryptoKeyUsageDecrypt; else if (usageString == "sign") result |= CryptoKeyUsageSign; else if (usageString == "verify") result |= CryptoKeyUsageVerify; else if (usageString == "deriveKey") result |= CryptoKeyUsageDeriveKey; else if (usageString == "deriveBits") result |= CryptoKeyUsageDeriveBits; else if (usageString == "wrapKey") result |= CryptoKeyUsageWrapKey; else if (usageString == "unwrapKey") result |= CryptoKeyUsageUnwrapKey; } return true; }
void C_AwesomiumBrowserManager::DispatchJavaScriptMethod(C_AwesomiumBrowserInstance* pBrowserInstance, std::string objectName, std::string objectMethod, std::vector<std::string> methodArguments) { //WebView* pWebView = m_webViews[pWebTab]; JSValue response = pBrowserInstance->GetWebView()->ExecuteJavascriptWithResult(WSLit(objectName.c_str()), WSLit("")); if (response.IsObject()) { JSObject object = response.ToObject(); JSArray arguments; for (auto argument : methodArguments) arguments.Push(WSLit(argument.c_str())); object.InvokeAsync(WSLit(objectMethod.c_str()), arguments); } //m_pWebBrowser->DispatchJavaScriptMethod(pWebTab, objectName, objectMethod, methodArguments); /* for (auto arg : args) { DevMsg("Argument: %s\n", arg->text.c_str()); } */ }
JSValue idbKeyDataToJSValue(JSC::ExecState& exec, const IDBKeyData& keyData) { if (keyData.isNull()) return jsUndefined(); Locker<JSLock> locker(exec.vm().apiLock()); switch (keyData.type()) { case KeyType::Array: { const Vector<IDBKeyData>& inArray = keyData.array(); size_t size = inArray.size(); JSArray* outArray = constructEmptyArray(&exec, 0, exec.lexicalGlobalObject(), size); for (size_t i = 0; i < size; ++i) { auto& arrayKey = inArray.at(i); outArray->putDirectIndex(&exec, i, idbKeyDataToJSValue(exec, arrayKey)); } return JSValue(outArray); } case KeyType::String: return jsStringWithCache(&exec, keyData.string()); case KeyType::Date: return jsDateOrNull(&exec, keyData.date()); case KeyType::Number: return jsNumber(keyData.number()); case KeyType::Min: case KeyType::Max: case KeyType::Invalid: ASSERT_NOT_REACHED(); return jsUndefined(); } ASSERT_NOT_REACHED(); return jsUndefined(); }
JSValue LiteralParser::parseArray() { StackGuard guard(this); if (!guard.isSafe()) return abortParse(); JSArray* array = constructEmptyArray(m_exec); while (true) { m_lexer.next(); JSValue value = parseExpression(); if (m_aborted) return JSValue(); if (!value) break; array->push(m_exec, value); if (m_lexer.currentToken().type != TokComma) break; } if (m_lexer.currentToken().type != TokRBracket) return abortParse(); m_lexer.next(); return array; }
static void addUsagesToJSON(ExecState* exec, JSObject* json, CryptoKeyUsage usages) { JSArray* keyOps = constructEmptyArray(exec, 0, exec->lexicalGlobalObject(), 0); unsigned index = 0; if (usages & CryptoKeyUsageSign) keyOps->putDirectIndex(exec, index++, jsString(exec, ASCIILiteral("sign"))); if (usages & CryptoKeyUsageVerify) keyOps->putDirectIndex(exec, index++, jsString(exec, ASCIILiteral("verify"))); if (usages & CryptoKeyUsageEncrypt) keyOps->putDirectIndex(exec, index++, jsString(exec, ASCIILiteral("encrypt"))); if (usages & CryptoKeyUsageDecrypt) keyOps->putDirectIndex(exec, index++, jsString(exec, ASCIILiteral("decrypt"))); if (usages & CryptoKeyUsageWrapKey) keyOps->putDirectIndex(exec, index++, jsString(exec, ASCIILiteral("wrapKey"))); if (usages & CryptoKeyUsageUnwrapKey) keyOps->putDirectIndex(exec, index++, jsString(exec, ASCIILiteral("unwrapKey"))); if (usages & CryptoKeyUsageDeriveKey) keyOps->putDirectIndex(exec, index++, jsString(exec, ASCIILiteral("deriveKey"))); if (usages & CryptoKeyUsageDeriveBits) keyOps->putDirectIndex(exec, index++, jsString(exec, ASCIILiteral("deriveBits"))); json->putDirect(exec->vm(), Identifier(exec, "key_ops"), keyOps); }
// Defined in ES5.1 15.4.5.1 bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException) { JSArray* array = jsCast<JSArray*>(object); // 3. If P is "length", then if (propertyName == exec->propertyNames().length) { // All paths through length definition call the default [[DefineOwnProperty]], hence: // from ES5.1 8.12.9 7.a. if (descriptor.configurablePresent() && descriptor.configurable()) return reject(exec, throwException, "Attempting to change configurable attribute of unconfigurable property."); // from ES5.1 8.12.9 7.b. if (descriptor.enumerablePresent() && descriptor.enumerable()) return reject(exec, throwException, "Attempting to change enumerable attribute of unconfigurable property."); // a. If the [[Value]] field of Desc is absent, then // a.i. Return the result of calling the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", Desc, and Throw as arguments. if (descriptor.isAccessorDescriptor()) return reject(exec, throwException, "Attempting to change access mechanism for an unconfigurable property."); // from ES5.1 8.12.9 10.a. if (!array->isLengthWritable() && descriptor.writablePresent() && descriptor.writable()) return reject(exec, throwException, "Attempting to change writable attribute of unconfigurable property."); // This descriptor is either just making length read-only, or changing nothing! if (!descriptor.value()) { if (descriptor.writablePresent()) array->setLengthWritable(exec, descriptor.writable()); return true; } // b. Let newLenDesc be a copy of Desc. // c. Let newLen be ToUint32(Desc.[[Value]]). unsigned newLen = descriptor.value().toUInt32(exec); // d. If newLen is not equal to ToNumber( Desc.[[Value]]), throw a RangeError exception. if (newLen != descriptor.value().toNumber(exec)) { exec->vm().throwException(exec, createRangeError(exec, ASCIILiteral("Invalid array length"))); return false; } // Based on SameValue check in 8.12.9, this is always okay. // FIXME: Nothing prevents this from being called on a RuntimeArray, and the length function will always return 0 in that case. if (newLen == array->length()) { if (descriptor.writablePresent()) array->setLengthWritable(exec, descriptor.writable()); return true; } // e. Set newLenDesc.[[Value] to newLen. // f. If newLen >= oldLen, then // f.i. Return the result of calling the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", newLenDesc, and Throw as arguments. // g. Reject if oldLenDesc.[[Writable]] is false. if (!array->isLengthWritable()) return reject(exec, throwException, "Attempting to change value of a readonly property."); // h. If newLenDesc.[[Writable]] is absent or has the value true, let newWritable be true. // i. Else, // i.i. Need to defer setting the [[Writable]] attribute to false in case any elements cannot be deleted. // i.ii. Let newWritable be false. // i.iii. Set newLenDesc.[[Writable] to true. // j. Let succeeded be the result of calling the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", newLenDesc, and Throw as arguments. // k. If succeeded is false, return false. // l. While newLen < oldLen repeat, // l.i. Set oldLen to oldLen – 1. // l.ii. Let deleteSucceeded be the result of calling the [[Delete]] internal method of A passing ToString(oldLen) and false as arguments. // l.iii. If deleteSucceeded is false, then if (!array->setLength(exec, newLen, throwException)) { // 1. Set newLenDesc.[[Value] to oldLen+1. // 2. If newWritable is false, set newLenDesc.[[Writable] to false. // 3. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", newLenDesc, and false as arguments. // 4. Reject. if (descriptor.writablePresent()) array->setLengthWritable(exec, descriptor.writable()); return false; } // m. If newWritable is false, then // i. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", // Property Descriptor{[[Writable]]: false}, and false as arguments. This call will always // return true. if (descriptor.writablePresent()) array->setLengthWritable(exec, descriptor.writable()); // n. Return true. return true; } // 4. Else if P is an array index (15.4), then // a. Let index be ToUint32(P). if (Optional<uint32_t> optionalIndex = parseIndex(propertyName)) { // b. Reject if index >= oldLen and oldLenDesc.[[Writable]] is false. uint32_t index = optionalIndex.value(); // FIXME: Nothing prevents this from being called on a RuntimeArray, and the length function will always return 0 in that case. if (index >= array->length() && !array->isLengthWritable()) return reject(exec, throwException, "Attempting to define numeric property on array with non-writable length property."); // c. Let succeeded be the result of calling the default [[DefineOwnProperty]] internal method (8.12.9) on A passing P, Desc, and false as arguments. // d. Reject if succeeded is false. // e. If index >= oldLen // e.i. Set oldLenDesc.[[Value]] to index + 1. // e.ii. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", oldLenDesc, and false as arguments. This call will always return true. // f. Return true. return array->defineOwnIndexedProperty(exec, index, descriptor, throwException); } return array->JSObject::defineOwnNonIndexProperty(exec, propertyName, descriptor, throwException); }
JSValue collectMatches(VM& vm, ExecState* exec, JSString* string, const String& s, RegExpConstructor* constructor, RegExp* regExp, const FixEndFunc& fixEnd) { auto scope = DECLARE_THROW_SCOPE(vm); MatchResult result = constructor->performMatch(vm, regExp, string, s, 0); if (!result) return jsNull(); static unsigned maxSizeForDirectPath = 100000; JSArray* array = constructEmptyArray(exec, nullptr); if (UNLIKELY(vm.exception())) return jsUndefined(); auto iterate = [&] () { size_t end = result.end; size_t length = end - result.start; array->push(exec, JSRopeString::createSubstringOfResolved(vm, string, result.start, length)); if (!length) end = fixEnd(end); result = constructor->performMatch(vm, regExp, string, s, end); }; do { if (array->length() >= maxSizeForDirectPath) { // First do a throw-away match to see how many matches we'll get. unsigned matchCount = 0; MatchResult savedResult = result; do { if (array->length() + matchCount >= MAX_STORAGE_VECTOR_LENGTH) { throwOutOfMemoryError(exec, scope); return jsUndefined(); } size_t end = result.end; matchCount++; if (result.empty()) end = fixEnd(end); // Using RegExpConstructor::performMatch() instead of calling RegExp::match() // directly is a surprising but profitable choice: it means that when we do OOM, we // will leave the cached result in the state it ought to have had just before the // OOM! On the other hand, if this loop concludes that the result is small enough, // then the iterate() loop below will overwrite the cached result anyway. result = constructor->performMatch(vm, regExp, string, s, end); } while (result); // OK, we have a sensible number of matches. Now we can create them for reals. result = savedResult; do iterate(); while (result); return array; } iterate(); } while (result); return array; }
JSValue IntlNumberFormat::formatToParts(ExecState& exec, double value) { VM& vm = exec.vm(); auto scope = DECLARE_THROW_SCOPE(vm); // FormatNumberToParts (ECMA-402) // https://tc39.github.io/ecma402/#sec-formatnumbertoparts // https://tc39.github.io/ecma402/#sec-partitionnumberpattern if (!m_initializedNumberFormat) return throwTypeError(&exec, scope, "Intl.NumberFormat.prototype.formatToParts called on value that's not an object initialized as a NumberFormat"_s); UErrorCode status = U_ZERO_ERROR; auto fieldItr = std::unique_ptr<UFieldPositionIterator, UFieldPositionIteratorDeleter>(ufieldpositer_open(&status)); if (U_FAILURE(status)) return throwTypeError(&exec, scope, "failed to open field position iterator"_s); status = U_ZERO_ERROR; Vector<UChar, 32> result(32); auto resultLength = unum_formatDoubleForFields(m_numberFormat.get(), value, result.data(), result.size(), fieldItr.get(), &status); if (status == U_BUFFER_OVERFLOW_ERROR) { status = U_ZERO_ERROR; result.grow(resultLength); unum_formatDoubleForFields(m_numberFormat.get(), value, result.data(), resultLength, fieldItr.get(), &status); } if (U_FAILURE(status)) return throwTypeError(&exec, scope, "failed to format a number."_s); int32_t literalFieldType = -1; auto literalField = IntlNumberFormatField(literalFieldType, resultLength); Vector<IntlNumberFormatField> fields(resultLength, literalField); int32_t beginIndex = 0; int32_t endIndex = 0; auto fieldType = ufieldpositer_next(fieldItr.get(), &beginIndex, &endIndex); while (fieldType >= 0) { auto size = endIndex - beginIndex; for (auto i = beginIndex; i < endIndex; ++i) { // Only override previous value if new value is more specific. if (fields[i].size >= size) fields[i] = IntlNumberFormatField(fieldType, size); } fieldType = ufieldpositer_next(fieldItr.get(), &beginIndex, &endIndex); } JSGlobalObject* globalObject = exec.jsCallee()->globalObject(vm); JSArray* parts = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0); if (!parts) return throwOutOfMemoryError(&exec, scope); unsigned index = 0; auto resultString = String(result.data(), resultLength); auto typePropertyName = Identifier::fromString(&vm, "type"); auto literalString = jsString(&exec, "literal"_s); int32_t currentIndex = 0; while (currentIndex < resultLength) { auto startIndex = currentIndex; auto fieldType = fields[currentIndex].type; while (currentIndex < resultLength && fields[currentIndex].type == fieldType) ++currentIndex; auto partType = fieldType == literalFieldType ? literalString : jsString(&exec, partTypeString(UNumberFormatFields(fieldType), value)); auto partValue = jsSubstring(&vm, resultString, startIndex, currentIndex - startIndex); JSObject* part = constructEmptyObject(&exec); part->putDirect(vm, typePropertyName, partType); part->putDirect(vm, vm.propertyNames->value, partValue); parts->putDirectIndex(&exec, index++, part); RETURN_IF_EXCEPTION(scope, { }); } return parts; }
JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); JSValue a1 = args.at(1); JSArray* result = constructEmptyArray(exec); unsigned i = 0; int p0 = 0; unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec); if (a0.isObject(&RegExpObject::info)) { RegExp* reg = asRegExpObject(a0)->regExp(); if (s.isEmpty() && reg->match(s, 0) >= 0) { // empty string matched by regexp -> empty array return result; } int pos = 0; while (i != limit && pos < s.size()) { OwnArrayPtr<int> ovector; int mpos = reg->match(s, pos, &ovector); if (mpos < 0) break; int mlen = ovector[1] - ovector[0]; pos = mpos + (mlen == 0 ? 1 : mlen); if (mpos != p0 || mlen) { result->put(exec, i++, jsSubstring(exec, s, p0, mpos - p0)); p0 = mpos + mlen; } for (unsigned si = 1; si <= reg->numSubpatterns(); ++si) { int spos = ovector[si * 2]; if (spos < 0) result->put(exec, i++, jsUndefined()); else result->put(exec, i++, jsSubstring(exec, s, spos, ovector[si * 2 + 1] - spos)); } } } else { UString u2 = a0.toString(exec); if (u2.isEmpty()) { if (s.isEmpty()) { // empty separator matches empty string -> empty array return result; } while (i != limit && p0 < s.size() - 1) result->put(exec, i++, jsSingleCharacterSubstring(exec, s, p0++)); } else { int pos; while (i != limit && (pos = s.find(u2, p0)) >= 0) { result->put(exec, i++, jsSubstring(exec, s, p0, pos - p0)); p0 = pos + u2.size(); } } } // add remaining string if (i != limit) result->put(exec, i++, jsSubstring(exec, s, p0, s.size() - p0)); return result; }
EncodedJSValue JSC_HOST_CALL JSBlobConstructor::constructJSBlob(ExecState* exec) { JSBlobConstructor* jsConstructor = jsCast<JSBlobConstructor*>(exec->callee()); ScriptExecutionContext* context = jsConstructor->scriptExecutionContext(); if (!context) return throwVMError(exec, createReferenceError(exec, "Blob constructor associated document is unavailable")); if (!exec->argumentCount()) { RefPtr<Blob> blob = Blob::create(); return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), Blob, blob.get())); } JSValue firstArg = exec->argument(0); if (!isJSArray(firstArg)) return throwVMError(exec, createTypeError(exec, "First argument of the constructor is not of type Array")); String type; String endings = "transparent"; if (exec->argumentCount() > 1) { JSValue blobPropertyBagValue = exec->argument(1); if (!blobPropertyBagValue.isObject()) return throwVMError(exec, createTypeError(exec, "Second argument of the constructor is not of type Object")); // Given the above test, this will always yield an object. JSObject* blobPropertyBagObject = blobPropertyBagValue.toObject(exec); // Create the dictionary wrapper from the initializer object. JSDictionary dictionary(exec, blobPropertyBagObject); // Attempt to get the endings property and validate it. bool containsEndings = dictionary.get("endings", endings); if (exec->hadException()) return JSValue::encode(jsUndefined()); if (containsEndings) { if (endings != "transparent" && endings != "native") return throwVMError(exec, createTypeError(exec, "The endings property must be either \"transparent\" or \"native\"")); } // Attempt to get the type property. dictionary.get("type", type); if (exec->hadException()) return JSValue::encode(jsUndefined()); } ASSERT(endings == "transparent" || endings == "native"); // FIXME: this would be better if the WebKitBlobBuilder were a stack object to avoid the allocation. RefPtr<WebKitBlobBuilder> blobBuilder = WebKitBlobBuilder::create(); JSArray* array = asArray(firstArg); unsigned length = array->length(); for (unsigned i = 0; i < length; ++i) { JSValue item = array->getIndex(i); #if ENABLE(BLOB) if (item.inherits(&JSArrayBuffer::s_info)) blobBuilder->append(toArrayBuffer(item)); else #endif if (item.inherits(&JSBlob::s_info)) blobBuilder->append(toBlob(item)); else { String string = ustringToString(item.toString(exec)->value(exec)); if (exec->hadException()) return JSValue::encode(jsUndefined()); blobBuilder->append(string, endings, ASSERT_NO_EXCEPTION); } } RefPtr<Blob> blob = blobBuilder->getBlob(type); return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), Blob, blob.get())); }
std::unique_ptr<CryptoKeyData> JSCryptoKeySerializationJWK::keyDataRSAComponents() const { Vector<uint8_t> modulus; Vector<uint8_t> exponent; Vector<uint8_t> privateExponent; if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "n", modulus)) { if (!m_exec->hadException()) throwTypeError(m_exec, "Required JWK \"n\" member is missing"); return nullptr; } if (!keySizeIsValid(modulus.size() * 8)) { throwTypeError(m_exec, "Key size is not valid for " + m_jwkAlgorithmName); return nullptr; } if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "e", exponent)) { if (!m_exec->hadException()) throwTypeError(m_exec, "Required JWK \"e\" member is missing"); return nullptr; } if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "d", modulus)) { if (m_exec->hadException()) return nullptr; return CryptoKeyDataRSAComponents::createPublic(modulus, exponent); } CryptoKeyDataRSAComponents::PrimeInfo firstPrimeInfo; CryptoKeyDataRSAComponents::PrimeInfo secondPrimeInfo; Vector<CryptoKeyDataRSAComponents::PrimeInfo> otherPrimeInfos; if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "p", firstPrimeInfo.primeFactor)) { if (m_exec->hadException()) return nullptr; return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent); } if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "dp", firstPrimeInfo.factorCRTExponent)) { if (m_exec->hadException()) return nullptr; return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent); } if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "q", secondPrimeInfo.primeFactor)) { if (m_exec->hadException()) return nullptr; return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent); } if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "dq", secondPrimeInfo.factorCRTExponent)) { if (m_exec->hadException()) return nullptr; return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent); } if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "qi", secondPrimeInfo.factorCRTCoefficient)) { if (m_exec->hadException()) return nullptr; return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent); } JSArray* otherPrimeInfoJSArray; if (!getJSArrayFromJSON(m_exec, m_json.get(), "oth", otherPrimeInfoJSArray)) { if (m_exec->hadException()) return nullptr; return CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos); } for (size_t i = 0; i < otherPrimeInfoJSArray->length(); ++i) { CryptoKeyDataRSAComponents::PrimeInfo info; JSValue element = otherPrimeInfoJSArray->getIndex(m_exec, i); if (m_exec->hadException()) return nullptr; if (!element.isObject()) { throwTypeError(m_exec, "JWK \"oth\" array member is not an object"); return nullptr; } if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "r", info.primeFactor)) { if (!m_exec->hadException()) throwTypeError(m_exec, "Cannot get prime factor for a prime in \"oth\" dictionary"); return nullptr; } if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "d", info.factorCRTExponent)) { if (!m_exec->hadException()) throwTypeError(m_exec, "Cannot get factor CRT exponent for a prime in \"oth\" dictionary"); return nullptr; } if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "t", info.factorCRTCoefficient)) { if (!m_exec->hadException()) throwTypeError(m_exec, "Cannot get factor CRT coefficient for a prime in \"oth\" dictionary"); return nullptr; } otherPrimeInfos.append(info); } return CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos); }
JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec) { if (exec->argumentCount() < 1) return jsUndefined(); VM& vm = exec->vm(); JSValue value = exec->uncheckedArgument(0); if (JSPromise* promise = jsDynamicCast<JSPromise*>(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr); if (UNLIKELY(vm.exception())) return jsUndefined(); switch (promise->status(exec->vm())) { case JSPromise::Status::Pending: array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("status"), jsNontrivialString(exec, ASCIILiteral("pending")))); break; case JSPromise::Status::Fulfilled: array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("status"), jsNontrivialString(exec, ASCIILiteral("resolved")))); array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("result"), promise->result(exec->vm()))); break; case JSPromise::Status::Rejected: array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("status"), jsNontrivialString(exec, ASCIILiteral("rejected")))); array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("result"), promise->result(exec->vm()))); break; } // FIXME: <https://webkit.org/b/141664> Web Inspector: ES6: Improved Support for Promises - Promise Reactions return array; } if (JSBoundFunction* boundFunction = jsDynamicCast<JSBoundFunction*>(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr); if (UNLIKELY(vm.exception())) return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "targetFunction", boundFunction->targetFunction())); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "boundThis", boundFunction->boundThis())); if (boundFunction->boundArgs()) array->putDirectIndex(exec, index++, constructInternalProperty(exec, "boundArgs", boundFunction->boundArgs())); return array; } if (ProxyObject* proxy = jsDynamicCast<ProxyObject*>(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 2); if (UNLIKELY(vm.exception())) return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("target"), proxy->target())); array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("handler"), proxy->handler())); return array; } if (JSObject* iteratorObject = jsDynamicCast<JSObject*>(value)) { if (iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())) { JSValue iteratedValue = iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().iteratedObjectPrivateName()); JSValue kind = iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().arrayIteratorKindPrivateName()); unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 2); if (UNLIKELY(vm.exception())) return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "array", iteratedValue)); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", kind)); return array; } } if (JSArrayIterator* arrayIterator = jsDynamicCast<JSArrayIterator*>(value)) { String kind; switch (arrayIterator->kind(exec)) { case ArrayIterateKey: kind = ASCIILiteral("key"); break; case ArrayIterateValue: kind = ASCIILiteral("value"); break; case ArrayIterateKeyValue: kind = ASCIILiteral("key+value"); break; } unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 2); if (UNLIKELY(vm.exception())) return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "array", arrayIterator->iteratedValue(exec))); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); return array; } if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(value)) { String kind; switch (mapIterator->kind()) { case MapIterateKey: kind = ASCIILiteral("key"); break; case MapIterateValue: kind = ASCIILiteral("value"); break; case MapIterateKeyValue: kind = ASCIILiteral("key+value"); break; } unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 2); if (UNLIKELY(vm.exception())) return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "map", mapIterator->iteratedValue())); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); return array; } if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(value)) { String kind; switch (setIterator->kind()) { case SetIterateKey: kind = ASCIILiteral("key"); break; case SetIterateValue: kind = ASCIILiteral("value"); break; case SetIterateKeyValue: kind = ASCIILiteral("key+value"); break; } unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 2); if (UNLIKELY(vm.exception())) return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "set", setIterator->iteratedValue())); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); return array; } if (JSStringIterator* stringIterator = jsDynamicCast<JSStringIterator*>(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 1); if (UNLIKELY(vm.exception())) return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "string", stringIterator->iteratedValue(exec))); return array; } if (JSPropertyNameIterator* propertyNameIterator = jsDynamicCast<JSPropertyNameIterator*>(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 1); if (UNLIKELY(vm.exception())) return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "object", propertyNameIterator->iteratedValue())); return array; } return jsUndefined(); }
JSValue Compilation::toJS(ExecState* exec) const { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSObject* result = constructEmptyObject(exec); RETURN_IF_EXCEPTION(scope, { }); result->putDirect(vm, exec->propertyNames().bytecodesID, jsNumber(m_bytecodes->id())); result->putDirect(vm, exec->propertyNames().compilationKind, jsString(exec, String::fromUTF8(toCString(m_kind)))); JSArray* profiledBytecodes = constructEmptyArray(exec, 0); RETURN_IF_EXCEPTION(scope, { }); for (unsigned i = 0; i < m_profiledBytecodes.size(); ++i) { auto value = m_profiledBytecodes[i].toJS(exec); RETURN_IF_EXCEPTION(scope, { }); profiledBytecodes->putDirectIndex(exec, i, value); RETURN_IF_EXCEPTION(scope, { }); } result->putDirect(vm, exec->propertyNames().profiledBytecodes, profiledBytecodes); JSArray* descriptions = constructEmptyArray(exec, 0); RETURN_IF_EXCEPTION(scope, { }); for (unsigned i = 0; i < m_descriptions.size(); ++i) { auto value = m_descriptions[i].toJS(exec); RETURN_IF_EXCEPTION(scope, { }); descriptions->putDirectIndex(exec, i, value); RETURN_IF_EXCEPTION(scope, { }); } result->putDirect(vm, exec->propertyNames().descriptions, descriptions); JSArray* counters = constructEmptyArray(exec, 0); RETURN_IF_EXCEPTION(scope, { }); for (auto it = m_counters.begin(), end = m_counters.end(); it != end; ++it) { JSObject* counterEntry = constructEmptyObject(exec); RETURN_IF_EXCEPTION(scope, { }); auto value = it->key.toJS(exec); RETURN_IF_EXCEPTION(scope, { }); counterEntry->putDirect(vm, exec->propertyNames().origin, value); counterEntry->putDirect(vm, exec->propertyNames().executionCount, jsNumber(it->value->count())); counters->push(exec, counterEntry); RETURN_IF_EXCEPTION(scope, { }); } result->putDirect(vm, exec->propertyNames().counters, counters); JSArray* exitSites = constructEmptyArray(exec, 0); RETURN_IF_EXCEPTION(scope, { }); for (unsigned i = 0; i < m_osrExitSites.size(); ++i) { auto value = m_osrExitSites[i].toJS(exec); RETURN_IF_EXCEPTION(scope, { }); exitSites->putDirectIndex(exec, i, value); RETURN_IF_EXCEPTION(scope, { }); } result->putDirect(vm, exec->propertyNames().osrExitSites, exitSites); JSArray* exits = constructEmptyArray(exec, 0); RETURN_IF_EXCEPTION(scope, { }); for (unsigned i = 0; i < m_osrExits.size(); ++i) { exits->putDirectIndex(exec, i, m_osrExits[i].toJS(exec)); RETURN_IF_EXCEPTION(scope, { }); } result->putDirect(vm, exec->propertyNames().osrExits, exits); result->putDirect(vm, exec->propertyNames().numInlinedGetByIds, jsNumber(m_numInlinedGetByIds)); result->putDirect(vm, exec->propertyNames().numInlinedPutByIds, jsNumber(m_numInlinedPutByIds)); result->putDirect(vm, exec->propertyNames().numInlinedCalls, jsNumber(m_numInlinedCalls)); result->putDirect(vm, exec->propertyNames().jettisonReason, jsString(exec, String::fromUTF8(toCString(m_jettisonReason)))); if (!m_additionalJettisonReason.isNull()) result->putDirect(vm, exec->propertyNames().additionalJettisonReason, jsString(exec, String::fromUTF8(m_additionalJettisonReason))); result->putDirect(vm, exec->propertyNames().uid, m_uid.toJS(exec)); return result; }
JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec) { if (exec->argumentCount() < 1) return jsUndefined(); JSValue value = exec->uncheckedArgument(0); #if ENABLE(PROMISES) if (JSPromise* promise = jsDynamicCast<JSPromise*>(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr); switch (promise->status(exec->vm())) { case JSPromise::Status::Pending: array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("status"), jsNontrivialString(exec, ASCIILiteral("pending")))); break; case JSPromise::Status::Fulfilled: array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("status"), jsNontrivialString(exec, ASCIILiteral("resolved")))); array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("result"), promise->result(exec->vm()))); break; case JSPromise::Status::Rejected: array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("status"), jsNontrivialString(exec, ASCIILiteral("rejected")))); array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("result"), promise->result(exec->vm()))); break; } // FIXME: <https://webkit.org/b/141664> Web Inspector: ES6: Improved Support for Promises - Promise Reactions return array; } #endif if (JSBoundFunction* boundFunction = jsDynamicCast<JSBoundFunction*>(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 3); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "targetFunction", boundFunction->targetFunction())); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "boundThis", boundFunction->boundThis())); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "boundArgs", boundFunction->boundArgs())); return array; } if (JSArrayIterator* arrayIterator = jsDynamicCast<JSArrayIterator*>(value)) { String kind; switch (arrayIterator->kind(exec)) { case ArrayIterateKey: kind = ASCIILiteral("key"); break; case ArrayIterateValue: kind = ASCIILiteral("value"); break; case ArrayIterateKeyValue: kind = ASCIILiteral("key+value"); break; } unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 2); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "array", arrayIterator->iteratedValue(exec))); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); return array; } if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(value)) { String kind; switch (mapIterator->kind()) { case MapIterateKey: kind = ASCIILiteral("key"); break; case MapIterateValue: kind = ASCIILiteral("value"); break; case MapIterateKeyValue: kind = ASCIILiteral("key+value"); break; } unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 2); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "map", mapIterator->iteratedValue())); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); return array; } if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(value)) { String kind; switch (setIterator->kind()) { case SetIterateKey: kind = ASCIILiteral("key"); break; case SetIterateValue: kind = ASCIILiteral("value"); break; case SetIterateKeyValue: kind = ASCIILiteral("key+value"); break; } unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 2); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "set", setIterator->iteratedValue())); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); return array; } if (JSStringIterator* stringIterator = jsDynamicCast<JSStringIterator*>(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 1); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "string", stringIterator->iteratedValue(exec))); return array; } return jsUndefined(); }
void MenuListener::OnShowPopupMenu(WebView *caller, const WebPopupMenuInfo &menu_info) { // DevMsg("DISABLED FOR TESTING!\n"); // return; //C_WebTab* pWebTab = g_pAnarchyManager->GetWebManager()->GetWebBrowser()->FindWebTab(caller); //C_WebTab* pHudWebTab = g_pAnarchyManager->GetWebManager()->GetHudWebTab(); //WebView* pHudWebView = g_pAnarchyManager->GetWebManager()->GetWebBrowser()->FindWebView(pHudWebTab); C_AwesomiumBrowserInstance* pAwesomiumBrowserInstance = g_pAnarchyManager->GetAwesomiumBrowserManager()->FindAwesomiumBrowserInstance(caller); // FIXME: This should be a general EmbeddedInstance of any type. C_AwesomiumBrowserInstance* pHudBrowserInstance = g_pAnarchyManager->GetAwesomiumBrowserManager()->FindAwesomiumBrowserInstance("hud"); WebView* pHudWebView = pHudBrowserInstance->GetWebView(); DevMsg("Pop menu detected!\n"); std::vector<std::string> methodArguments; methodArguments.push_back(pAwesomiumBrowserInstance->GetId()); methodArguments.push_back(VarArgs("%i", menu_info.bounds.x)); methodArguments.push_back(VarArgs("%i", menu_info.bounds.y)); methodArguments.push_back(VarArgs("%i", menu_info.bounds.width)); methodArguments.push_back(VarArgs("%i", menu_info.bounds.height)); methodArguments.push_back(VarArgs("%i", menu_info.item_height)); methodArguments.push_back(VarArgs("%f", menu_info.item_font_size)); methodArguments.push_back(VarArgs("%i", menu_info.selected_item)); methodArguments.push_back(VarArgs("%i", menu_info.right_aligned)); for (int i = 0; i < menu_info.items.size(); i++) { if (menu_info.items[i].type == kWebMenuItemType_Option) methodArguments.push_back("Option"); else if (menu_info.items[i].type == kWebMenuItemType_CheckableOption) methodArguments.push_back("CheckableOption"); else if (menu_info.items[i].type == kWebMenuItemType_Group) methodArguments.push_back("Group"); else if (menu_info.items[i].type == kWebMenuItemType_Separator) methodArguments.push_back("Separator"); methodArguments.push_back(WebStringToCharString(menu_info.items[i].label)); methodArguments.push_back(WebStringToCharString(menu_info.items[i].tooltip)); methodArguments.push_back(VarArgs("%i", menu_info.items[i].action)); methodArguments.push_back(VarArgs("%i", menu_info.items[i].right_to_left)); methodArguments.push_back(VarArgs("%i", menu_info.items[i].has_directional_override)); methodArguments.push_back(VarArgs("%i", menu_info.items[i].enabled)); methodArguments.push_back(VarArgs("%i", menu_info.items[i].checked)); } std::string objectName = "window.arcadeHud"; std::string objectMethod = "showPopupMenu"; JSValue response = pHudWebView->ExecuteJavascriptWithResult(WSLit(objectName.c_str()), WSLit("")); if (response.IsObject()) { JSObject object = response.ToObject(); JSArray arguments; for (auto argument : methodArguments) arguments.Push(WSLit(argument.c_str())); object.InvokeAsync(WSLit(objectMethod.c_str()), arguments); } }