Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DartObject not unwrapped when passed into JsObject.callMethod

I'm writing a Dart wrapper for a JS library, but hitting on this problem:

I'm calling a JS method with a MediaStream (Dart)Object as a parameter. The problem is, that inside the JS lib, this parameter is a DartObject, and causes an error because it's not a MediaStream anymore.

JsObject.jsify works only on Maps and Lists, is there a way to jsify this object for JS usage?

like image 840
SkaveRat Avatar asked Oct 20 '22 07:10

SkaveRat


1 Answers

after a few time to think about your problem, i get a solution with mirror API. It's possible to create a JsObject, so my approach has been to create a "binding" object that will make the interface between the Js and the dart. Thanks to the mirror api i was able to analyze object instance to create dynamicly the binding. i hope it will be usefull

the dart file :

import 'dart:js';
import 'dart:mirrors';

typedef dynamic OnCall(List);

class VarargsFunction extends Function {
  OnCall _onCall;

  VarargsFunction(this._onCall);

  call() => _onCall([]);

  noSuchMethod(Invocation invocation) {
    final arguments = invocation.positionalArguments;
    return _onCall(arguments);
  }
}

JsObject toJsObject(var inst) {
  InstanceMirror im = reflect(inst);
  ClassMirror classMirror = im.type;
  JsObject jsObj = new JsObject(context["Object"]);

  classMirror.declarations.values.where((dm) => dm is MethodMirror && dm.isRegularMethod).forEach((MethodMirror method) {
        jsObj[MirrorSystem.getName(method.simpleName)] = new VarargsFunction((args) {
           return im.invoke(method.simpleName, args).reflectee;
        });
  });
  return jsObj;
}

class TestClass {
  String str;


  TestClass(this.str);

  String getStr() {
    return this.str;
  }

  String toString() {
    return '[Myclass Instance str: "${this.str}"]';
  }

  JsObject toJs() {
    var jsobj = new JsObject(context['Object']);
    jsobj["getStr"] = this.getStr;
    return jsobj;
  }
}

void main() {
    JsObject jsInst = context['jsInst'];
    print(jsInst);
    TestClass tmp = new TestClass(jsInst.callMethod("getMyAttr"));
    toJsObject(tmp);
    jsInst.callMethod("printDartObj", [toJsObject(tmp)]);
}

the js file :

function MyJsClass() {
    this.my_attr = "Salut";
}

MyJsClass.prototype.getMyAttr = function() {
    return this.my_attr;
}

MyJsClass.prototype.printDartObj = function(obj) {
    console.log(obj.toString());
    console.log(obj.getStr());
}

var jsInst = new MyJsClass();
console.log(jsInst);

the output :

[object Object]

[Myclass Instance str: "Salut"]

Salut

like image 111
Vink Avatar answered Oct 27 '22 09:10

Vink