[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdelibs/khtml/ecma
From:       Maks Orlovich <maksim () kde ! org>
Date:       2010-05-11 20:09:05
Message-ID: 20100511200905.76433AC8B5 () svn ! kde ! org
[Download RAW message or body]

SVN commit 1125604 by orlovich:

Implement binding for some more operations..
Next few steps will be ultra-tricky, though.


 M  +152 -38   kjs_scriptable.cpp  
 M  +20 -7     kjs_scriptable.h  


--- trunk/KDE/kdelibs/khtml/ecma/kjs_scriptable.cpp #1125603:1125604
@@ -45,7 +45,7 @@
 
 static bool isFuncRef(const QVariant& v)
 {
-    return v.canConvert<ScriptableExtension::Exception>();
+    return v.canConvert<ScriptableExtension::FunctionRef>();
 }
 
 static bool isForeignObject(const QVariant& v)
@@ -177,20 +177,65 @@
 
 JSValue* WrapScriptableObject::callAsFunction(ExecState *exec, JSObject *thisObj, \
const List &args)  {
-    if (type == Object) {
-        // if ()
-        // callAsFunction
+    QVariant res;
+
+    if (ScriptableExtension* base = objExtension.data()) {
+        ScriptableExtension::ArgList sargs = exportArgs(args);
+        if (type == Object)
+            res = base->callAsFunction(principal(exec), objId, sargs);
+        else
+            res = base->callFunctionReference(principal(exec), objId, field, sargs);
+    }
+
+    // Problem. Throw an exception.
+    if (!res.isValid() || isException(res))
+        return throwError(exec, GeneralError, "Call to plugin function failed");
+    else
+        return KHTMLScriptable::importValue(exec, res);
+}
+
+JSObject* WrapScriptableObject::construct(ExecState* exec, const List& args)
+{
+    QVariant res;
+
+    bool ok;
+    ScriptableExtension::Object actualObj = resolveAnyReferences(exec, &ok);
+    if (ok) {
+        res = actualObj.owner->callAsConstructor(principal(exec), actualObj.objId,
+                                                 exportArgs(args));
+    }
+
+    if (!res.isValid() || isException(res)) {
+        return throwError(exec, GeneralError, "Call to plugin ctor failed");
     } else {
-        // callFunctionRefence.
+        JSValue* v = KHTMLScriptable::importValue(exec, res);
+        return v->toObject(exec);
     }
 }
 
+void WrapScriptableObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& \
a) +{
+    JSObject::getOwnPropertyNames(exec, a);
+
+    bool ok;
+    ScriptableExtension::Object actualObj = resolveAnyReferences(exec, &ok);
+    if (ok) {
+        QStringList out;
+        if (actualObj.owner->enumerateProperties(principal(exec), actualObj.objId, \
&out)) { +            foreach (const QString& s, out)
+                a.add(Identifier(s));
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+// conversion stuff
+
 /**
    SECURITY: For the conversion helpers, it is assumed that 'exec' corresponds
    to the appropriate principal.
 */
 
-
 JSObject* KHTMLScriptable::importObject(ExecState* exec, const QVariant& v)
 {
     ScriptableExtension::Object obj = v.value<ScriptableExtension::Object>();
@@ -220,7 +265,7 @@
     ScriptableExtension::FunctionRef fr = \
v.value<ScriptableExtension::FunctionRef>();  
     if (JSObject* base = tryGetNativeObject(fr.base)) {
-        return base->get(exec, fr.field);
+        return base->get(exec, Identifier(fr.field));
     } else {
         if (WrapScriptableObject* old = importedFunctions()->value(fr)) {
             return old;
@@ -250,24 +295,52 @@
         return jsString(v.toString());
     if (v.canConvert<double>())
         return jsNumber(v.toDouble());
-    kWarning() << "conversion from " << v << "failed";
+    kWarning(6031) << "conversion from " << v << "failed";
     return jsNull();
 }
 
-QVariant exportObject(JSObject* o)
+List KHTMLScriptable::importArgs(ExecState* exec, const ArgList& args)
 {
+    List out;
+    for (int i = 0; i < args.size(); ++i)
+        out.append(importValue(exec, args[i]));
+    return out;
+}
+
+ScriptableExtension::Object KHTMLScriptable::exportNativeObject(JSObject* o)
+{
+    assert (!o->inherits(&WrapScriptableObject::info));
+    // We're exporting our own. Add to export table if needed.
+    // Use the pointer as an ID.
+    if (!exportedObjects()->contains(o))
+        exportedObjects()->insert(o, 0);
+    return ScriptableExtension::Object(this, reinterpret_cast<quint64>(o);
+}
+
+QVariant KHTMLScriptable::exportObject(JSObject* o)
+{
     // XSS checks are done at get time, so if we have a value here, we can
     // export it.
-
     if (o->inherits(&WrapScriptableObject::info)) {
-        // Re-exporting external one
+        // Re-exporting external one. That's easy.
+        WrapScriptableObject* wo = static_cast<WrapScriptableObject*>(o);
+        if (ScriptableExtension* owner = wo->objExtension.data()) {
+            return ScriptableExtension::Object(owner, wo->objId);
     } else {
-        // Add to export table if needed. Use the pointer
-        // as an ID.
-        //TODO
+            kWarning(6031) << "export of an object of a destroyed extension. \
Returning null"; +            return scriptableNull();
     }
+    } else {
+        return exportNativeObject(o);
 }
+}
 
+QVariant KHTMLScriptable::exportFuncRef(JSObject* base, const QString& field)
+{
+    ScriptableExtension::Object base = exportNativeObject(base);
+    return ScriptableExtension::FunctionRef(base, field);
+}
+
 QVariant KHTMLScriptable::exportValue(JSValue* v)
 {
     switch (v->type()) {
@@ -287,25 +360,42 @@
     }
 }
 
-#if 0
-exportValue ones.
+//-----------------------------------------------------------------------------
+// letting outsiders use us.
 
 
+KHTMLScriptable::KHTMLScriptable(KHTMLPart* part):
+    ScriptableExtension(part), m_part(part)
+{
+}
 
+KJS::Interpreter* KHTMLScriptable::interpreter()
+{
+{
+    KJSProxy* proxy = m_part->jScript();
+    if (!proxy)
+        return 0;
 
+    return proxy->interpreter();
+}
 
+QVariant KHTMLScriptable::rootObject()
+{
+    if (KJS::Interpreter* i = interpreter()) {
+        return exportObject(i->globalObject());    
+    }
 
-get, etc --- check for part for extension, do XSS check on that?
-#endif
+    return scriptableNull();
+}
 
-KHTMLScriptable::KHTMLScriptable(KHTMLPart* part):
-    ScriptableExtension(part), m_part(part)
+QVariant KHTMLScriptable::encloserForKid(KParts::ScriptableExtension* kid)
 {
-}
+    ReadOnlyPart* childPart = qobject_cast<ReadOnlyPart*>(kid->parentObject());
 
+    KJS::Interpreter* i = interpreter();
+    if (!childPart || !i)
+        return scriptableNull();
 
-QVariant KHTMLScriptable::enclosingObject(KParts::ReadOnlyPart* childPart)
-{
     khtml::ChildFrame* f = m_part->frame(childPart);
 
     if (!f) {
@@ -313,16 +403,45 @@
         return scriptableNull();
     }
 
-    // ### Note: this should never actually get an iframe once iframes are fixed
-    // TODO
+    // ### should this deal with fake window objects for iframes? 
+    // ### this should never actually get an iframe once iframes are fixed
+    if (!f->m_partContainerElement.isNull()) {
+        return exportObject(getDOMNode(i->globalExec(), f->m_partContainerElement));
 }
 
+    kWarning(6031) << "could not find the part container";
+    return scriptableNull();
+}
+
+QVariant KHTMLScriptable::handleReturn(ExecState* exec, JSValue* v)
+{
+    if (exec->hadException()) {
+        JSValue* e = exec->exception();
+        exec->classException();
+        
+        QString msg = QLatin1String("KJS exception");
+        
+        if (JSObject* eo = e->getObject()) {
+            JSValue* msgVal = eo->get(exec, exec->propertyNames().message);
+            if (!msgVal->isUndefined())
+                msg = msgVal->toString(exec);
+            
+            // in case the get failed too.
+            exec->classException();
+        }
+
+        return ScriptableExtension::Exception(msg);
+    }
+
+    return exportValue(v);
+}
+
 QVariant KHTMLScriptable::callAsFunction(ScriptableExtension* caller,
                                                   quint64 objId, const ArgList& \
args)  {
-    KHTMLPart* ctx = partForPrincipal(caller);
-    KJSProxy*  kjs = ctx ? ctx->jScript() : 0;
-    if (!kjs) {
+    ExecState* exec = execStateForPrincipal(caller);
+
+    if (!exec) {
         kWarning(6031) << "Trying to script the unscriptable";
         return exception("No scripting context or frame");
     }
@@ -333,9 +452,13 @@
         return exception("Not a function");
     }
 
-    //fn->callAsFunction(
+    JSValue* res = fn->callAsFunction(exec, \
exec->dynamicInterpreter()->globalObject(), +                                      \
importArgs(exec, args); +
+    return handleReturn(exec, res);
 }
 
+
 KHTMLPart* KHTMLScriptable::partForPrincipal(ScriptableExtension* caller)
 {
     // We implement our security checks by delegating to the KHTMLPart corresponding
@@ -349,15 +472,6 @@
     }
 }
 
-
-List KHTMLScriptable::decodeArgs(const ArgList& args)
-{
-    List out;
-    for (int i = 0; i < args.size(); ++i)
-        out.append(importValue(args[i]));
-    return out;
-}
-
 // ::get() {
 //
 //     if result is a function... return function reference instead..
--- trunk/KDE/kdelibs/khtml/ecma/kjs_scriptable.h #1125603:1125604
@@ -35,13 +35,14 @@
 
 class KHTMLScriptable: public ScriptableExtension
 {
+    Q_OBJECT
 public:
     KHTMLScriptable(KHTMLPart* part);
 
 
     // ScriptableExtension API
     virtual QVariant rootObject();
-    virtual QVariant enclosingObject(KParts::ReadOnlyPart* childPart);
+    virtual QVariant encloserForKid(KParts::ScriptableExtension* kid);
     virtual QVariant callAsFunction(ScriptableExtension* callerPrincipal, quint64 \
                objId, const ArgList& args);
     virtual QVariant callFunctionReference(ScriptableExtension* callerPrincipal, \
                quint64 objId,
                                            const QString& f, const ArgList& args);
@@ -66,33 +67,45 @@
     static QHash<Object,      WrapScriptableObject*>* importedObjects();
     static QHash<FunctionRef, WrapScriptableObject*>* importedFunctions();
 
+    // For exported objects, we keep refcounts, and mark them
+    static QHash<JSObject*, int>* exportedObjects();
+
     static JSValue* importValue(ExecState* exec, const QVariant& v);
     static JSValue* importFunctionRef(ExecState* exec, const QVariant& v);
     static JSObject* importObject(ExecState* exec, const QVariant& v);
+    static List importArgs(ExecState* exec, const ArgList& args);
 
     static QVariant exportValue (JSValue* v);
-    static QVariant exportObject(JSValue* v);
+    static QVariant exportObject(JSObject* o);
+    static QVariant exportFuncRef(JSObject* base, const QString& field);
 private:
-    // May return 0. Used for security checks!
+    // input should not be a WrapScriptableObject.
+    static ScriptableExtension::Object exportNativeObject(JSObject* o);
+
+    // Checks exception state before handling conversion
+    QVariant handleReturn(ExecState* exec, JSValue* v);
+
+    // Both methods ay return 0. Used for security checks!
     KHTMLPart* partForPrincipal(ScriptableExtension* callerPrincipal);
+    ExecState* execStateForPrincipal(ScriptableExtension* callerPrincipal);
 
     // May return null.
     JSObject* objectForId(quint64 objId);
 
-    List decodeArgs(const ArgList& args);
 
-
     QVariant exception(const char* msg);
     QVariant scriptableNull();
 
+    KJS::Interpreter* interpreter();
+    KHTMLPart* m_part;
+
     // If the given object is owned by a KHTMLScriptable, return the
     // JS object for it. If not, return 0.
     static JSObject* tryGetNativeObject(const Object& sObj);
 
+    static QHash<JSValue*, int> s_exportedObjects;
     static QHash<Object,      WrapScriptableObject*>* s_importedObjects;
     static QHash<FunctionRef, WrapScriptableObject*>* s_importedFunctions;
-    KHTMLPart* m_part;
-
 };
 
 // This represents an object we imported from a foreign ScriptableExtension


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic