/*! \internal \since 4.5 Adds the given \a object to the front of this context's scope chain. If \a object is not an object, this function does nothing. */ void QScriptContext::pushScope(const QScriptValue &object) { activationObject(); //ensure the creation of the normal scope for native context if (!object.isObject()) return; else if (object.engine() != engine()) { qWarning("QScriptContext::pushScope() failed: " "cannot push an object created in " "a different engine"); return; } JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); QScript::APIShim shim(engine); JSC::JSObject *jscObject = JSC::asObject(engine->scriptValueToJSCValue(object)); if (jscObject == engine->originalGlobalObjectProxy) jscObject = engine->originalGlobalObject(); JSC::ScopeChainNode *scope = frame->scopeChain(); Q_ASSERT(scope != 0); if (!scope->object) { // pushing to an "empty" chain if (!jscObject->isGlobalObject()) { qWarning("QScriptContext::pushScope() failed: initial object in scope chain has to be the Global Object"); return; } scope->object = jscObject; } else frame->setScopeChain(scope->push(jscObject)); }
String getEventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* scriptState, EventListener* eventListener) { const JSEventListener* jsListener = JSEventListener::cast(eventListener); if (!jsListener) return ""; JSC::JSObject* jsFunction = jsListener->jsFunction(context); if (!jsFunction) return ""; return jsFunction->toString(scriptState); }
String eventListenerHandlerBody(Document* document, EventListener* eventListener) { const JSEventListener* jsListener = JSEventListener::cast(eventListener); if (!jsListener) return ""; JSC::JSObject* jsFunction = jsListener->jsFunction(document); if (!jsFunction) return ""; return ustringToString(jsFunction->toString(scriptStateFromNode(jsListener->isolatedWorld(), document))); }
WebFrame* WebFrame::frameForContext(JSContextRef context) { JSObjectRef globalObjectRef = JSContextGetGlobalObject(context); JSC::JSObject* globalObjectObj = toJS(globalObjectRef); if (strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell") != 0) return 0; Frame* coreFrame = static_cast<JSDOMWindowShell*>(globalObjectObj)->window()->impl()->frame(); return static_cast<WebFrameLoaderClient*>(coreFrame->loader()->client())->webFrame(); }
WebFrame* WebFrame::frameForContext(JSContextRef context) { JSObjectRef globalObjectRef = JSContextGetGlobalObject(context); JSC::JSObject* globalObjectObj = toJS(globalObjectRef); if (strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell") != 0) return 0; Frame* frame = static_cast<JSDOMWindowShell*>(globalObjectObj)->window()->impl().frame(); return WebFrame::fromCoreFrame(*frame); }
String eventListenerHandlerBody(Document* document, EventListener* eventListener) { const JSEventListener* jsListener = JSEventListener::cast(eventListener); if (!jsListener) return ""; JSLock lock(SilenceAssertionsOnly); JSC::JSObject* jsFunction = jsListener->jsFunction(document); if (!jsFunction) return ""; ScriptState* scriptState = scriptStateFromNode(jsListener->isolatedWorld(), document); return ustringToString(jsFunction->toString(scriptState)->value(scriptState)); }
String eventListenerHandlerBody(Document* document, EventListener* eventListener) { const JSEventListener* jsListener = JSEventListener::cast(eventListener); ASSERT(jsListener); if (!jsListener) return ""; JSLockHolder lock(jsListener->isolatedWorld()->globalData()); JSC::JSObject* jsFunction = jsListener->jsFunction(document); if (!jsFunction) return ""; ScriptState* scriptState = scriptStateFromNode(jsListener->isolatedWorld(), document); return jsFunction->toString(scriptState)->value(scriptState); }
void HTMLPlugInImageElement::didAddUserAgentShadowRoot(ShadowRoot* root) { HTMLPlugInElement::didAddUserAgentShadowRoot(root); if (displayState() >= PreparingPluginReplacement) return; Page* page = document().page(); if (!page) return; // Reset any author styles that may apply as we only want explicit // styles defined in the injected user agents stylesheets to specify // the look-and-feel of the snapshotted plug-in overlay. root->setResetStyleInheritance(true); String mimeType = loadedMimeType(); DOMWrapperWorld& isolatedWorld = plugInImageElementIsolatedWorld(); document().ensurePlugInsInjectedScript(isolatedWorld); ScriptController& scriptController = document().frame()->script(); JSDOMGlobalObject* globalObject = JSC::jsCast<JSDOMGlobalObject*>(scriptController.globalObject(isolatedWorld)); JSC::ExecState* exec = globalObject->globalExec(); JSC::JSLockHolder lock(exec); JSC::MarkedArgumentBuffer argList; argList.append(toJS(exec, globalObject, root)); argList.append(jsString(exec, titleText(page, mimeType))); argList.append(jsString(exec, subtitleText(page, mimeType))); // This parameter determines whether or not the snapshot overlay should always be visible over the plugin snapshot. // If no snapshot was found then we want the overlay to be visible. argList.append(JSC::jsBoolean(!m_snapshotImage)); // It is expected the JS file provides a createOverlay(shadowRoot, title, subtitle) function. JSC::JSObject* overlay = globalObject->get(exec, JSC::Identifier::fromString(exec, "createOverlay")).toObject(exec); if (!overlay) { ASSERT(exec->hadException()); exec->clearException(); return; } JSC::CallData callData; JSC::CallType callType = overlay->methodTable()->getCallData(overlay, callData); if (callType == JSC::CallType::None) return; JSC::call(exec, overlay, callType, callData, globalObject, argList); exec->clearException(); }
QScriptValue QScriptContext::activationObject() const { JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this)); QScript::APIShim shim(QScript::scriptEngineFromExec(frame)); JSC::JSObject *result = 0; uint flags = QScriptEnginePrivate::contextFlags(frame); if ((flags & QScriptEnginePrivate::NativeContext) && !(flags & QScriptEnginePrivate::HasScopeContext)) { //For native functions, lazily create it if needed QScript::QScriptActivationObject *scope = new (frame) QScript::QScriptActivationObject(frame); frame->setScopeChain(frame->scopeChain()->copy()->push(scope)); result = scope; QScriptEnginePrivate::setContextFlags(frame, flags | QScriptEnginePrivate::HasScopeContext); } else { // look in scope chain JSC::ScopeChainNode *node = frame->scopeChain(); JSC::ScopeChainIterator it(node); for (it = node->begin(); it != node->end(); ++it) { if ((*it) && (*it)->isVariableObject()) { result = *it; break; } } } if (!result) { if (!parentContext()) return engine()->globalObject(); qWarning("QScriptContext::activationObject: could not get activation object for frame"); return QScriptValue(); /*JSC::CodeBlock *codeBlock = frame->codeBlock(); if (!codeBlock) { // non-Qt native function Q_ASSERT(true); //### this should in theorry not happen result = new (frame)QScript::QScriptActivationObject(frame); } else { // ### this is wrong JSC::FunctionBodyNode *body = static_cast<JSC::FunctionBodyNode*>(codeBlock->ownerNode()); result = new (frame)JSC::JSActivation(frame, body); }*/ } if (result && result->inherits(&QScript::QScriptActivationObject::info) && (static_cast<QScript::QScriptActivationObject*>(result)->delegate() != 0)) { // Return the object that property access is being delegated to result = static_cast<QScript::QScriptActivationObject*>(result)->delegate(); } return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); }
/*! Sets the activation object of this QScriptContext to be the given \a activation. If \a activation is not an object, this function does nothing. \note For a context corresponding to a JavaScript function, this is only guaranteed to work if there was an QScriptEngineAgent active on the engine while the function was evaluated. */ void QScriptContext::setActivationObject(const QScriptValue &activation) { if (!activation.isObject()) return; else if (activation.engine() != engine()) { qWarning("QScriptContext::setActivationObject() failed: " "cannot set an object created in " "a different engine"); return; } JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); QScript::APIShim shim(engine); JSC::JSObject *object = JSC::asObject(engine->scriptValueToJSCValue(activation)); if (object == engine->originalGlobalObjectProxy) object = engine->originalGlobalObject(); uint flags = QScriptEnginePrivate::contextFlags(frame); if ((flags & QScriptEnginePrivate::NativeContext) && !(flags & QScriptEnginePrivate::HasScopeContext)) { //For native functions, we create a scope node JSC::JSObject *scope = object; if (!scope->isVariableObject()) { // Create a QScriptActivationObject that acts as a proxy scope = new (frame) QScript::QScriptActivationObject(frame, scope); } frame->setScopeChain(frame->scopeChain()->copy()->push(scope)); QScriptEnginePrivate::setContextFlags(frame, flags | QScriptEnginePrivate::HasScopeContext); return; } // else replace the first activation object in the scope chain JSC::ScopeChainNode *node = frame->scopeChain(); while (node != 0) { if (node->object && node->object->isVariableObject()) { if (!object->isVariableObject()) { if (node->object->inherits(&QScript::QScriptActivationObject::info)) { static_cast<QScript::QScriptActivationObject*>(node->object)->setDelegate(object); } else { // Create a QScriptActivationObject that acts as a proxy node->object = new (frame) QScript::QScriptActivationObject(frame, object); } } else { node->object = object; } break; } node = node->next; } }
void setDocumentEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, HTMLElement& element, const AtomicString& eventType, JSC::JSValue value) { ASSERT(wrapper.globalObject()); auto& document = element.document(); auto* documentWrapper = jsDocumentCast(toJS(&state, JSC::jsCast<JSDOMGlobalObject*>(wrapper.globalObject()), document)); ASSERT(documentWrapper); document.setAttributeEventListener(eventType, createEventListenerForEventHandlerAttribute(state, value, *documentWrapper)); }
WebFrame* WebFrame::frameForContext(JSContextRef context) { #if USE(JSC) JSObjectRef globalObjectRef = JSContextGetGlobalObject(context); JSC::JSObject* globalObjectObj = toJS(globalObjectRef); if (strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell") != 0) return 0; Frame* coreFrame = static_cast<JSDOMWindowShell*>(globalObjectObj)->window()->impl()->frame(); #elif USE(V8) Frame* coreFrame = V8Proxy::retrieveFrame(toV8(context)); if (!coreFrame) return 0; #endif return static_cast<WebFrameLoaderClient*>(coreFrame->loader()->client())->webFrame(); }
bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector) { if (!value.isObject()) return false; JSC::JSObject* object = asObject(value); int32_t length = object->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); vector.resize(length); for (int32_t i = 0; i < length; ++i) { JSC::JSValue v = object->get(exec, i); if (exec->hadException()) return false; vector[i] = static_cast<T>(v.toNumber(exec)); } return true; }
/* Returns the scope chain entry at \a index. If index is less than 0, returns entries starting at the end. For example, scopeChainValue(context, -1) will return the value last in the scope chain. */ QScriptValue QScriptDeclarativeClass::scopeChainValue(QScriptContext *context, int index) { context->activationObject(); //ensure the creation of the normal scope for native context const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(context); QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); QScript::APIShim shim(engine); JSC::ScopeChainNode *node = frame->scopeChain(); JSC::ScopeChainIterator it(node); if (index < 0) { int count = 0; for (it = node->begin(); it != node->end(); ++it) ++count; index = qAbs(index); if (index > count) return QScriptValue(); else index = count - index; } for (it = node->begin(); it != node->end(); ++it) { if (index == 0) { JSC::JSObject *object = *it; if (!object) return QScriptValue(); if (object->inherits(&QScript::QScriptActivationObject::info) && (static_cast<QScript::QScriptActivationObject*>(object)->delegate() != 0)) { // Return the object that property access is being delegated to object = static_cast<QScript::QScriptActivationObject*>(object)->delegate(); } return engine->scriptValueFromJSCValue(object); } else { --index; } } return QScriptValue(); }
void DumpRenderTreeSupportEfl::evaluateScriptInIsolatedWorld(const Evas_Object* ewkFrame, int worldID, JSObjectRef globalObject, const String& script) { WebCore::Frame* coreFrame = EWKPrivate::coreFrame(ewkFrame); if (!coreFrame) return; // Comment from mac: Start off with some guess at a frame and a global object, we'll try to do better...! WebCore::JSDOMWindow* anyWorldGlobalObject = coreFrame->script()->globalObject(WebCore::mainThreadNormalWorld()); // Comment from mac: The global object is probably a shell object? - if so, we know how to use this! JSC::JSObject* globalObjectObj = toJS(globalObject); if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell")) anyWorldGlobalObject = static_cast<WebCore::JSDOMWindowShell*>(globalObjectObj)->window(); // Comment from mac: Get the frame from the global object we've settled on. WebCore::Frame* globalFrame = anyWorldGlobalObject->impl()->frame(); if (!globalFrame) return; WebCore::ScriptController* proxy = globalFrame->script(); if (!proxy) return; static WTF::HashMap<int, WTF::RefPtr<WebCore::DOMWrapperWorld > > worldMap; WTF::RefPtr<WebCore::DOMWrapperWorld> scriptWorld; if (!worldID) scriptWorld = WebCore::ScriptController::createWorld(); else { WTF::HashMap<int, RefPtr<WebCore::DOMWrapperWorld > >::const_iterator it = worldMap.find(worldID); if (it != worldMap.end()) scriptWorld = (*it).second; else { scriptWorld = WebCore::ScriptController::createWorld(); worldMap.set(worldID, scriptWorld); } } // The code below is only valid for JSC, V8 specific code is to be added // when V8 will be supported in EFL port. See Qt implemenation. proxy->executeScriptInWorld(scriptWorld.get(), script, true); }
bool toVector(JSC::ExecState& state, JSC::JSValue value, Vector<T, inlineCapacity>& vector) { if (!value.isObject()) return false; JSC::JSObject* object = asObject(value); int32_t length = object->get(&state, state.vm().propertyNames->length).toInt32(&state); if (!vector.tryReserveCapacity(length)) return false; vector.resize(length); for (int32_t i = 0; i < length; ++i) { JSC::JSValue v = object->get(&state, i); if (state.hadException()) return false; vector[i] = static_cast<T>(v.toNumber(&state)); } return true; }
/*! \internal \since 4.5 Returns the scope chain of this QScriptContext. */ QScriptValueList QScriptContext::scopeChain() const { activationObject(); //ensure the creation of the normal scope for native context const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); QScript::APIShim shim(engine); QScriptValueList result; JSC::ScopeChainNode *node = frame->scopeChain(); JSC::ScopeChainIterator it(node); for (it = node->begin(); it != node->end(); ++it) { JSC::JSObject *object = *it; if (!object) continue; if (object->inherits(&QScript::QScriptActivationObject::info) && (static_cast<QScript::QScriptActivationObject*>(object)->delegate() != 0)) { // Return the object that property access is being delegated to object = static_cast<QScript::QScriptActivationObject*>(object)->delegate(); } result.append(engine->scriptValueFromJSCValue(object)); } return result; }
bool WebFrame::stringByEvaluatingJavaScriptInScriptWorld(WebScriptWorld* world, void* jsGlobalObject, const char* script, const char** evaluationResult) { if (!world || !jsGlobalObject || !evaluationResult) return false; *evaluationResult = 0; Frame* coreFrame = core(this); JSObjectRef globalObjectRef = reinterpret_cast<JSObjectRef>(jsGlobalObject); String string = String(script); // Start off with some guess at a frame and a global object, we'll try to do better...! JSDOMWindow* anyWorldGlobalObject = coreFrame->script()->globalObject(mainThreadNormalWorld()); // The global object is probably a shell object? - if so, we know how to use this! JSC::JSObject* globalObjectObj = toJS(globalObjectRef); if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell")) anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window(); // Get the frame from the global object we've settled on. Frame* frame = anyWorldGlobalObject->impl()->frame(); ASSERT(frame->document()); JSC::JSValue result = frame->script()->executeScriptInWorld(world->world(), string, true).jsValue(); if (!frame) // In case the script removed our frame from the page. return true; // This bizarre set of rules matches behavior from WebKit for Safari 2.0. // If you don't like it, use -[WebScriptObject evaluateWebScript:] or // JSEvaluateScript instead, since they have less surprising semantics. if (!result || !result.isBoolean() && !result.isString() && !result.isNumber()) return true; JSC::JSLock lock(JSC::SilenceAssertionsOnly); String resultString = ustringToString(result.toString(anyWorldGlobalObject->globalExec())); *evaluationResult = strdup(resultString.utf8().data()); return true; }
void DragData::asFilenames(Vector<String>& result) const { bool success; JSC::JSValue data = m_platformDragData->getData(ClipboardApolloHelper::FILE_LIST_TYPE, success); JSC::ExecState *exec = m_platformDragData->execState(); if (success && data.isObject()) { JSC::JSObject* filenameArray = data.toObject(exec); uint32_t length = filenameArray->get(exec, JSC::Identifier(exec, "length")).toUInt32(exec); for (uint32_t i=0; i<length; i++) { JSC::JSValue fileValue = filenameArray->get(exec, i); if (fileValue.isObject()) { JSC::JSObject* file = fileValue.toObject(exec); JSC::JSValue pathValue = file->get(exec, JSC::Identifier(exec, "nativePath")); if (pathValue.isString()) { String path = ustringToString(pathValue.toString(exec)); result.append(path); } } } } if (exec->hadException()) exec->clearException(); }
void toArray(JSC::ExecState* exec, JSC::JSValue value, T*& array, int& size) { array = 0; if (!value.isObject()) return; JSC::JSObject* object = asObject(value); int length = object->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); void* tempValues; if (!tryFastMalloc(length * sizeof(T)).getValue(tempValues)) return; T* values = static_cast<T*>(tempValues); for (int i = 0; i < length; ++i) { JSC::JSValue v = object->get(exec, i); if (exec->hadException()) return; values[i] = static_cast<T>(v.toNumber(exec)); } array = values; size = length; }
void setWindowEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, HTMLElement& element, const AtomicString& eventType, JSC::JSValue value) { ASSERT(wrapper.globalObject()); element.document().setWindowAttributeEventListener(eventType, createEventListenerForEventHandlerAttribute(state, value, *wrapper.globalObject())); }
/*! \internal */ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *context) { Q_ASSERT(context); functionType = QScriptContextInfo::NativeFunction; functionMetaIndex = -1; functionStartLineNumber = -1; functionEndLineNumber = -1; scriptId = -1; lineNumber = -1; columnNumber = -1; JSC::CallFrame *frame = const_cast<JSC::CallFrame *>(QScriptEnginePrivate::frameForContext(context)); // Get the line number: //We need to know the context directly up in the backtrace, in order to get the line number, and adjust the global context JSC::CallFrame *rewindContext = QScriptEnginePrivate::get(context->engine())->currentFrame; if (QScriptEnginePrivate::contextForFrame(rewindContext) == context) { //top context frame = rewindContext; //for retreiving the global context's "fake" frame // An agent might have provided the line number. lineNumber = QScript::scriptEngineFromExec(frame)->agentLineNumber; if (lineNumber == -1) lineNumber = QScript::scriptEngineFromExec(frame)->uncaughtExceptionLineNumber; } else { // rewind the stack from the top in order to find the frame from the caller where the returnPC is stored while (rewindContext && QScriptEnginePrivate::contextForFrame(rewindContext->callerFrame()->removeHostCallFrameFlag()) != context) rewindContext = rewindContext->callerFrame()->removeHostCallFrameFlag(); if (rewindContext) { frame = rewindContext->callerFrame()->removeHostCallFrameFlag(); //for retreiving the global context's "fake" frame JSC::Instruction *returnPC = rewindContext->returnPC(); JSC::CodeBlock *codeBlock = frame->codeBlock(); if (returnPC && codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { #if ENABLE(JIT) JSC::JITCode code = codeBlock->getJITCode(); uintptr_t jitOffset = reinterpret_cast<uintptr_t>(JSC::ReturnAddressPtr(returnPC).value()) - reinterpret_cast<uintptr_t>(code.addressForCall().executableAddress()); // We can only use the JIT code offset if it's smaller than the JIT size; // otherwise calling getBytecodeIndex() is meaningless. if (jitOffset < code.size()) { unsigned bytecodeOffset = codeBlock->getBytecodeIndex(frame, JSC::ReturnAddressPtr(returnPC)); #else unsigned bytecodeOffset = returnPC - codeBlock->instructions().begin(); #endif bytecodeOffset--; //because returnPC is on the next instruction. We want the current one lineNumber = codeBlock->lineNumberForBytecodeOffset(const_cast<JSC::ExecState *>(frame), bytecodeOffset); #if ENABLE(JIT) } #endif } } } // Get the filename and the scriptId: JSC::CodeBlock *codeBlock = frame->codeBlock(); if (codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { JSC::SourceProvider *source = codeBlock->source(); scriptId = source->asID(); fileName = source->url(); } // Get the others information: JSC::JSObject *callee = frame->callee(); if (callee && callee->inherits(&JSC::InternalFunction::info)) functionName = JSC::asInternalFunction(callee)->name(frame); if (callee && callee->inherits(&JSC::JSFunction::info) && !JSC::asFunction(callee)->isHostFunction()) { functionType = QScriptContextInfo::ScriptFunction; JSC::FunctionExecutable *body = JSC::asFunction(callee)->jsExecutable(); functionStartLineNumber = body->lineNo(); functionEndLineNumber = body->lastLine(); for (size_t i = 0; i < body->parameterCount(); ++i) parameterNames.append(body->parameterName(i)); // ### get the function name from the AST } else if (callee && callee->inherits(&QScript::QtFunction::info)) { functionType = QScriptContextInfo::QtFunction; functionMetaIndex = static_cast<QScript::QtFunction*>(callee)->specificIndex(context); const QMetaObject *meta = static_cast<QScript::QtFunction*>(callee)->metaObject(); if (meta != 0) { QMetaMethod method = meta->method(functionMetaIndex); QList<QByteArray> formals = method.parameterNames(); for (int i = 0; i < formals.count(); ++i) parameterNames.append(QLatin1String(formals.at(i))); } } else if (callee && callee->inherits(&QScript::QtPropertyFunction::info)) { functionType = QScriptContextInfo::QtPropertyFunction; functionMetaIndex = static_cast<QScript::QtPropertyFunction*>(callee)->propertyIndex(); } }