JsObject constructor

JsObject(JsFunction constructor, [ List arguments ])

Constructs a JavaScript object from its native constructor and returns a proxy to it.

Implementation

factory JsObject(JsFunction constructor, [List arguments]) {
  var ctor = _convertToJS(constructor);
  if (arguments == null) {
    return _wrapToDart(JS('', 'new #()', ctor));
  }

  if (JS('bool', '# instanceof Array', arguments)) {
    int argumentCount = JS('int', '#.length', arguments);
    switch (argumentCount) {
      case 0:
        return _wrapToDart(JS('', 'new #()', ctor));

      case 1:
        var arg0 = _convertToJS(JS('', '#[0]', arguments));
        return _wrapToDart(JS('', 'new #(#)', ctor, arg0));

      case 2:
        var arg0 = _convertToJS(JS('', '#[0]', arguments));
        var arg1 = _convertToJS(JS('', '#[1]', arguments));
        return _wrapToDart(JS('', 'new #(#, #)', ctor, arg0, arg1));

      case 3:
        var arg0 = _convertToJS(JS('', '#[0]', arguments));
        var arg1 = _convertToJS(JS('', '#[1]', arguments));
        var arg2 = _convertToJS(JS('', '#[2]', arguments));
        return _wrapToDart(JS('', 'new #(#, #, #)', ctor, arg0, arg1, arg2));

      case 4:
        var arg0 = _convertToJS(JS('', '#[0]', arguments));
        var arg1 = _convertToJS(JS('', '#[1]', arguments));
        var arg2 = _convertToJS(JS('', '#[2]', arguments));
        var arg3 = _convertToJS(JS('', '#[3]', arguments));
        return _wrapToDart(
            JS('', 'new #(#, #, #, #)', ctor, arg0, arg1, arg2, arg3));
    }
  }

  // The following code solves the problem of invoking a JavaScript
  // constructor with an unknown number arguments.
  // First bind the constructor to the argument list using bind.apply().
  // The first argument to bind() is the binding of 'this', so add 'null' to
  // the arguments list passed to apply().
  // After that, use the JavaScript 'new' operator which overrides any binding
  // of 'this' with the new instance.
  var args = <dynamic>[null]..addAll(arguments.map(_convertToJS));
  var factoryFunction = JS('', '#.bind.apply(#, #)', ctor, ctor, args);
  // Without this line, calling factoryFunction as a constructor throws
  JS('String', 'String(#)', factoryFunction);
  // This could return an UnknownJavaScriptObject, or a native
  // object for which there is an interceptor
  var jsObj = JS('', 'new #()', factoryFunction);

  return _wrapToDart(jsObj);

  // TODO(sra): Investigate:
  //
  //     var jsObj = JS('', 'Object.create(#.prototype)', ctor);
  //     JS('', '#.apply(#, #)', ctor, jsObj,
  //         []..addAll(arguments.map(_convertToJS)));
  //     return _wrapToDart(jsObj);
}