KJS::JSValue *SlotProxy::callMethod(const QByteArray &methodName, void **_a) { #ifdef DEBUG_SLOTPROXY qDebug() << "SlotProxy::callMethod(" << methodName << ",_a) obj=" << this; #endif KJS::ExecState *exec = m_interpreter->globalExec(); exec->clearException(); // Crash // KJS::Interpreter::globalExec()->context().thisValue() KJS::List args = convertArguments(exec, _a); KJS::Identifier id = KJS::Identifier(KJS::UString(methodName.data())); KJS::JSObject *fun = m_object->get(exec, id)->toObject(exec); KJS::JSValue *retValue; if (!fun->implementsCall()) { #ifdef DEBUG_SLOTPROXY qDebug() << "SlotProxy::callMethod got bad handler"; #endif QString msg = i18n("Bad slot handler: Object %1 Identifier %2 Method %3 Signature: %4.", m_object->className().ascii(), id.ascii(), methodName.data(), QString(m_signature)); retValue = throwError(exec, KJS::TypeError, msg); } else { retValue = fun->call(exec, m_object, args); } if (exec->hadException()) { #ifdef DEBUG_SLOTPROXY qDebug() << "SlotProxy::callMethod had exception"; #endif if (m_interpreter->shouldPrintExceptions()) { KJS::JSLock lock; KJS::JSObject *exceptObj = exec->exception()->toObject(exec);//retValue->toObject(exec); QString message = toQString(exceptObj->toString(exec)); QString sourceURL = toQString(exceptObj->get(exec, "sourceURL")->toString(exec)); int sourceId = exceptObj->get(exec, "sourceId")->toUInt32(exec); // would include the line number, but it's always last line of file int line = exceptObj->get(exec, "line")->toUInt32(exec); (*KJSEmbed::conerr()) << i18n("Exception calling '%1' slot from %2:%3:%4", QString(methodName), !sourceURL.isEmpty() ? sourceURL : QString::number(sourceId), line, message) << endl; } // clear it so it doesn't stop other things exec->clearException(); return KJS::jsNull(); } else { if (retValue->type() == 1 || retValue->type() == 0) { return KJS::jsNull(); } } return retValue; }
bool EventProxy::callHandler( QEvent *e ) { // Be careful enabling this as if there are a lot of events then the event loop times // out and the app crashes with 'Alarm Clock'. // qDebug("JSObjectEventProxy::callHandler() event type %d" , e->type() ); KJS::ExecState *exec = m_interpreter->globalExec(); KJS::Identifier id = JSEventMapper::mapper()->findEventHandler( e->type() ); KJS::JSObject *jsobj(m_watch); KJS::JSObject *fun = jsobj->get(exec, id )->toObject( exec ); KJS::JSValue *retValue; if ( !fun->implementsCall() ) { QString msg = i18n( "Bad event handler: Object %1 Identifier %2 Method %3 Type: %4.", jsobj->className().ascii(), id.ascii(), fun->className().ascii(), e->type()); retValue = throwError(exec, KJS::TypeError, msg); } else { // Process args KJS::List args; args.append( JSEventUtils::event(exec, e) ); // Call handler retValue = fun->call( exec, jsobj, args ); } if ( exec->hadException() ) { if (m_interpreter->shouldPrintExceptions()) { KJS::JSLock lock; KJS::JSObject* exceptObj = retValue->toObject(exec); QString message = toQString(exceptObj->toString(exec)); QString sourceURL = toQString(exceptObj->get(exec, "sourceURL")->toString(exec)); int sourceId = exceptObj->get(exec, "sourceId")->toUInt32(exec); int line = exceptObj->get(exec, "line")->toUInt32(exec); (*KJSEmbed::conerr()) << i18n("Exception calling '%1' function from %2:%3:%4", id.ascii(), !sourceURL.isEmpty() ? sourceURL : QString::number(sourceId), line, message) << endl; } // clear it so it doesn't stop other things exec->clearException(); return false; } return true; }
void SVGScriptElement::executeScript(Document *document, StringImpl *jsCode) { if(!document || !jsCode) return; #if 0 Ecma *ecmaEngine = document->ecmaEngine(); if(!ecmaEngine) return; KJS::Interpreter::lock(); // Run script KJS::Completion comp = ecmaEngine->evaluate(jsCode.deprecatedString(), ecmaEngine->globalObject()); if(comp.complType() == KJS::Throw) { KJS::ExecState *exec = ecmaEngine->globalExec(); KJS::JSValue *exVal = comp.value(); int lineno = -1; if(exVal->isObject()) { KJS::JSValue *lineVal = static_cast<KJS::JSObject *>(exVal)->get(exec, "line"); if(lineVal->type() == KJS::NumberType) lineno = int(lineVal->toNumber(exec)); } // Fire ERROR_EVENT upon errors... SVGDocument *svgDocument = static_cast<SVGDocument *>(document); if(svgDocument && document->hasListenerType(ERROR_EVENT)) { RefPtr<Event> event = svgDocument->createEvent("SVGEvents"); event->initEvent(EventNames::errorEvent, false, false); svgDocument->dispatchRecursiveEvent(event.get(), svgDocument->lastChild()); } kdDebug() << "[SVGScriptElement] Evaluation error, line " << (lineno != -1 ? DeprecatedString::number(lineno) : DeprecatedString::fromLatin1("N/A")) << " " << exVal->toString(exec).deprecatedString() << endl; } else if(comp.complType() == KJS::ReturnValue) kdDebug() << "[SVGScriptElement] Return value: " << comp.value()->toString(ecmaEngine->globalExec()).deprecatedString() << endl; else if(comp.complType() == KJS::Normal) kdDebug() << "[SVGScriptElement] Evaluated ecma script!" << endl; KJS::Interpreter::unlock(); #else if (jsCode) // Hack to close memory leak due to #if 0 String(jsCode); #endif }
KJS::JSValue *GlobalObject::get(KJS::ExecState *exec, const KJS::Identifier &p) const { kdDebug(26004) << "WebCore::GlobalObject (" << this << ")::get " << p.deprecatedString() << endl; KJS::JSValue *ret = GlobalObject::get(exec, p); if(ret->type() != KJS::UndefinedType) return ret; const KJS::HashEntry *entry = KJS::Lookup::findEntry(&GlobalObject::s_hashTable, p); if(entry) { switch(entry->value) { case GlobalObjectConstants::SVGException: return getSVGExceptionConstructor(exec); case GlobalObjectConstants::SVGLength: return getSVGLengthConstructor(exec); case GlobalObjectConstants::SVGAngle: return getSVGAngleConstructor(exec); case GlobalObjectConstants::SVGColor: return getSVGColorConstructor(exec); case GlobalObjectConstants::SVGPaint: return getSVGPaintConstructor(exec); case GlobalObjectConstants::SVGUnitTypes: return getSVGUnitTypesConstructor(exec); case GlobalObjectConstants::SVGTransform: return getSVGTransformConstructor(exec); case GlobalObjectConstants::SVGGradientElement: return getSVGGradientElementConstructor(exec); case GlobalObjectConstants::SVGPreserveAspectRatio: return getSVGPreserveAspectRatioConstructor(exec); case GlobalObjectConstants::SVGZoomAndPan: return getSVGZoomAndPanConstructor(exec); case GlobalObjectConstants::SVGMarkerElement: return getSVGMarkerElementConstructor(exec); } } // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1 // But it can also mean something isn't loaded or implemented... kdDebug(26004) << "GlobalObject::get property not found: " << p.deprecatedString() << endl; return KJS::jsUndefined(); }
JavaScriptArrayType checkArray(KJS::ExecState *exec, KJS::JSValue *val) { KJS::JSObject *obj = val->toObject(exec); if (toQString(obj->className()) == "Array") { if (!obj->hasProperty(exec, KJS::Identifier("length"))) { return Map; } KJS::JSValue *jslen = obj->get(exec, KJS::Identifier("length")); const int len = jslen->toNumber(exec); if (len > 0) { QByteArray buff; buff.setNum(len - 1); if (!obj->hasProperty(exec, KJS::Identifier(buff.data()))) { return Map; } } return List; } else { return None; } }
JSType JSValueGetType(JSContextRef, JSValueRef value) { KJS::JSValue* jsValue = toJS(value); switch (jsValue->type()) { case KJS::UndefinedType: return kJSTypeUndefined; case KJS::NullType: return kJSTypeNull; case KJS::BooleanType: return kJSTypeBoolean; case KJS::NumberType: return kJSTypeNumber; case KJS::StringType: return kJSTypeString; case KJS::ObjectType: return kJSTypeObject; default: ASSERT(!"JSValueGetType: unknown type code.\n"); return kJSTypeUndefined; } }
bool JSDOMWindow::customGetOwnPropertySlot(KJS::ExecState* exec, const KJS::Identifier& propertyName, KJS::PropertySlot& slot) { // we don't want any properties other than "closed" on a closed window if (!impl()->frame()) { if (propertyName == "closed") { const KJS::HashEntry* entry = KJS::Lookup::findEntry(classInfo()->propHashTable, propertyName); ASSERT(entry); if (entry) { slot.setStaticEntry(this, entry, KJS::staticValueGetter<JSDOMWindow>); return true; } } if (propertyName == "close") { KJS::JSValue* proto = prototype(); if (proto->isObject()) { const KJS::HashEntry* entry = KJS::Lookup::findEntry(static_cast<KJS::JSObject*>(proto)->classInfo()->propHashTable, propertyName); ASSERT(entry); if (entry) { slot.setStaticEntry(this, entry, KJS::staticFunctionGetter<JSDOMWindowPrototypeFunction>); return true; } } } slot.setUndefined(this); return true; } // Look for overrides first KJS::JSValue** val = getDirectLocation(propertyName); if (val) { if (!isSafeScript(exec)) { slot.setUndefined(this); return true; } // FIXME: Come up with a way of having JavaScriptCore handle getters/setters in this case if (_prop.hasGetterSetterProperties() && val[0]->type() == KJS::GetterSetterType) fillGetterPropertySlot(slot, val); else slot.setValueSlot(this, val); return true; } // FIXME: We need this to work around the blanket isSafeScript check in KJS::Window. Once we remove that, we // can move this to JSDOMWindowPrototype. KJS::JSValue* proto = prototype(); if (proto->isObject()) { const KJS::HashEntry* entry = KJS::Lookup::findEntry(static_cast<KJS::JSObject*>(proto)->classInfo()->propHashTable, propertyName); if (entry) { if (entry->attr & KJS::Function) { switch (entry->value) { case FocusFuncNum: case BlurFuncNum: case CloseFuncNum: slot.setStaticEntry(this, entry, KJS::staticFunctionGetter<JSDOMWindowPrototypeFunction>); return true; default: if (!isSafeScript(exec)) slot.setUndefined(this); else slot.setStaticEntry(this, entry, KJS::staticFunctionGetter<JSDOMWindowPrototypeFunction>); return true; } } } } return false; }
KJS::JSValue *KJSEmbed::convertToValue(KJS::ExecState *exec, const QVariant &value) { #ifdef KJSEMBED_VARIANT_DEBUG qDebug() << "KJSEmbed::convertToValue typeid=" << value.type() << "typename=" << value.typeName() << "toString=" << value.toString(); #endif KJS::JSValue *returnValue; switch (value.type()) { case QVariant::Invalid: returnValue = KJS::jsNull(); break; case QVariant::Int: returnValue = KJS::jsNumber(value.value<int>()); break; case QVariant::UInt: returnValue = KJS::jsNumber(value.value<unsigned int>()); break; case QVariant::LongLong: returnValue = KJS::jsNumber(value.value<qlonglong>()); break; case QVariant::ULongLong: returnValue = KJS::jsNumber(value.value<qulonglong>()); break; case QVariant::Double: returnValue = KJS::jsNumber(value.value<double>()); break; case QVariant::Bool: returnValue = KJS::jsBoolean(value.value<bool>()); break; case QVariant::ByteArray: returnValue = KJS::jsString(QString(value.value<QByteArray>())); break; case QVariant::String: returnValue = KJS::jsString(value.value<QString>()); break; case QVariant::StringList: { KJS::List items; QStringList lst = value.value<QStringList>(); QStringList::Iterator idx = lst.begin(); for (; idx != lst.end(); ++idx) { items.append(KJS::jsString((*idx))); } returnValue = exec->lexicalInterpreter()->builtinArray()->construct(exec, items); break; } case QVariant::Date: // fall through case QVariant::DateTime: // fall through case QVariant::Time: { QDateTime dt = QDateTime::currentDateTime(); if (value.type() == QVariant::Date) { dt.setDate(value.toDate()); } else if (value.type() == QVariant::Time) { dt.setTime(value.toTime()); } else { dt = value.toDateTime(); } KJS::List items; items.append(KJS::jsNumber(dt.date().year())); items.append(KJS::jsNumber(dt.date().month() - 1)); items.append(KJS::jsNumber(dt.date().day())); items.append(KJS::jsNumber(dt.time().hour())); items.append(KJS::jsNumber(dt.time().minute())); items.append(KJS::jsNumber(dt.time().second())); items.append(KJS::jsNumber(dt.time().msec())); returnValue = exec->lexicalInterpreter()->builtinDate()->construct(exec, items); break; } case QVariant::List: { KJS::List items; QList<QVariant> lst = value.toList(); foreach (const QVariant &item, lst) { items.append(convertToValue(exec, item)); } returnValue = exec->lexicalInterpreter()->builtinArray()->construct(exec, items); break; } case QVariant::Map: { QMap<QString, QVariant> map = value.toMap(); QMap<QString, QVariant>::Iterator idx = map.begin(); KJS::JSObject *obj = exec->lexicalInterpreter()->builtinObject()->construct(exec, KJS::List()); for (; idx != map.end(); ++idx) { obj->put(exec, KJS::Identifier(toUString(idx.key())), convertToValue(exec, idx.value())); } returnValue = obj; break; } default: { if (value.canConvert< QWidget * >()) { QWidget *widget = qvariant_cast< QWidget * >(value); returnValue = widget ? createQObject(exec, widget, KJSEmbed::ObjectBinding::CPPOwned) : KJS::jsNull(); } else if (value.canConvert< QObject * >()) { QObject *object = qvariant_cast< QObject * >(value); returnValue = object ? createQObject(exec, object, KJSEmbed::ObjectBinding::CPPOwned) : KJS::jsNull(); } else { returnValue = createVariant(exec, value.typeName(), value); if (returnValue->isNull()) { returnValue = KJS::jsString(value.value<QString>()); } } break; } }
// from khtml/ecma/debugger/debugwindow.cpp static QString exceptionToString(KJS::ExecState* exec, KJS::JSValue* exceptionObj) { QString exceptionMsg = valueToString(exceptionObj); // Since we purposefully bypass toString, we need to figure out // string serialization ourselves. //### might be easier to export class info for ErrorInstance --- KJS::JSObject* valueObj = exceptionObj->getObject(); KJS::JSValue* protoObj = valueObj ? valueObj->prototype() : 0; bool exception = false; bool syntaxError = false; if (protoObj == exec->lexicalInterpreter()->builtinSyntaxErrorPrototype()) { exception = true; syntaxError = true; } if (protoObj == exec->lexicalInterpreter()->builtinErrorPrototype() || protoObj == exec->lexicalInterpreter()->builtinEvalErrorPrototype() || protoObj == exec->lexicalInterpreter()->builtinReferenceErrorPrototype() || protoObj == exec->lexicalInterpreter()->builtinRangeErrorPrototype() || protoObj == exec->lexicalInterpreter()->builtinTypeErrorPrototype() || protoObj == exec->lexicalInterpreter()->builtinURIErrorPrototype()) { exception = true; } if (!exception) return exceptionMsg; // Clear exceptions temporarily so we can get/call a few things. // We memorize the old exception first, of course. Note that // This is not always the same as exceptionObj since we may be // asked to translate a non-active exception KJS::JSValue* oldExceptionObj = exec->exception(); exec->clearException(); // We want to serialize the syntax errors ourselves, to provide the line number. // The URL is in "sourceURL" and the line is in "line" // ### TODO: Perhaps we want to use 'sourceId' in case of eval contexts. if (syntaxError) { KJS::JSValue* lineValue = valueObj->get(exec, "line"); KJS::JSValue* urlValue = valueObj->get(exec, "sourceURL"); int line = lineValue->toNumber(exec); QString url = urlValue->toString(exec).qstring(); exceptionMsg = i18n("Parse error at %1 line %2", url, line + 1); } else { // ### it's still not 100% safe to call toString here, even on // native exception objects, since someone might have changed the toString property // of the exception prototype, but I'll punt on this case for now. exceptionMsg = exceptionObj->toString(exec).qstring(); } exec->setException(oldExceptionObj); return exceptionMsg; }