github.com/goplusjs/gopherjs@v1.2.6-0.20211206034512-f187917453b8/compiler/prelude/jsmapping.go (about)

     1  package prelude
     2  
     3  const jsmapping = `
     4  var $jsObjectPtr, $jsErrorPtr;
     5  
     6  var $needsExternalization = function(t) {
     7    switch (t.kind) {
     8      case $kindBool:
     9      case $kindInt:
    10      case $kindInt8:
    11      case $kindInt16:
    12      case $kindInt32:
    13      case $kindUint:
    14      case $kindUint8:
    15      case $kindUint16:
    16      case $kindUint32:
    17      case $kindUintptr:
    18      case $kindFloat32:
    19      case $kindFloat64:
    20        return false;
    21      default:
    22        return t !== $jsObjectPtr;
    23    }
    24  };
    25  
    26  var $externalize = function(v, t) {
    27    if (t === $jsObjectPtr) {
    28      return v;
    29    }
    30    switch (t.kind) {
    31    case $kindBool:
    32    case $kindInt:
    33    case $kindInt8:
    34    case $kindInt16:
    35    case $kindInt32:
    36    case $kindUint:
    37    case $kindUint8:
    38    case $kindUint16:
    39    case $kindUint32:
    40    case $kindUintptr:
    41    case $kindFloat32:
    42    case $kindFloat64:
    43      return v;
    44    case $kindInt64:
    45    case $kindUint64:
    46      return $flatten64(v);
    47    case $kindArray:
    48      if ($needsExternalization(t.elem)) {
    49        return $mapArray(v, function(e) { return $externalize(e, t.elem); });
    50      }
    51      return v;
    52    case $kindFunc:
    53      return $externalizeFunction(v, t, false);
    54    case $kindInterface:
    55      if (v === $ifaceNil) {
    56        return null;
    57      }
    58      if (v.constructor === $jsObjectPtr) {
    59        return v.$val.object;
    60      }
    61      return $externalize(v.$val, v.constructor);
    62    case $kindMap:
    63      var m = {};
    64      var keys = $keys(v);
    65      for (var i = 0; i < keys.length; i++) {
    66        var entry = v[keys[i]];
    67        m[$externalize(entry.k, t.key)] = $externalize(entry.v, t.elem);
    68      }
    69      return m;
    70    case $kindPtr:
    71      if (v === t.nil) {
    72        return null;
    73      }
    74      return $externalize(v.$get(), t.elem);
    75    case $kindSlice:
    76      if ($needsExternalization(t.elem)) {
    77        return $mapArray($sliceToArray(v), function(e) { return $externalize(e, t.elem); });
    78      }
    79      return $sliceToArray(v);
    80    case $kindString:
    81      if ($isASCII(v)) {
    82        return v;
    83      }
    84      var s = "", r;
    85      for (var i = 0; i < v.length; i += r[1]) {
    86        r = $decodeRune(v, i);
    87        var c = r[0];
    88        if (c > 0xFFFF) {
    89          var h = Math.floor((c - 0x10000) / 0x400) + 0xD800;
    90          var l = (c - 0x10000) % 0x400 + 0xDC00;
    91          s += String.fromCharCode(h, l);
    92          continue;
    93        }
    94        s += String.fromCharCode(c);
    95      }
    96      return s;
    97    case $kindStruct:
    98      var timePkg = $packages["time"];
    99      if (timePkg !== undefined && v.constructor === timePkg.Time.ptr) {
   100        var milli = $div64(v.UnixNano(), new $Int64(0, 1000000));
   101        return new Date($flatten64(milli));
   102      }
   103  
   104      var noJsObject = {};
   105      var searchJsObject = function(v, t) {
   106        if (t === $jsObjectPtr) {
   107          return v;
   108        }
   109        switch (t.kind) {
   110        case $kindPtr:
   111          if (v === t.nil) {
   112            return noJsObject;
   113          }
   114          return searchJsObject(v.$get(), t.elem);
   115        case $kindStruct:
   116          var f = t.fields[0];
   117          return searchJsObject(v[f.prop], f.typ);
   118        case $kindInterface:
   119          return searchJsObject(v.$val, v.constructor);
   120        default:
   121          return noJsObject;
   122        }
   123      };
   124      var o = searchJsObject(v, t);
   125      if (o !== noJsObject) {
   126        return o;
   127      }
   128  
   129      o = {};
   130      for (var i = 0; i < t.fields.length; i++) {
   131        var f = t.fields[i];
   132        if (!f.exported) {
   133          continue;
   134        }
   135        o[f.name] = $externalize(v[f.prop], f.typ);
   136      }
   137      return o;
   138    }
   139    $throwRuntimeError("cannot externalize " + t.string);
   140  };
   141  
   142  var $externalizeFunction = function(v, t, passThis) {
   143    if (v === $throwNilPointerError) {
   144      return null;
   145    }
   146    if (v.$externalizeWrapper === undefined) {
   147      $checkForDeadlock = false;
   148      v.$externalizeWrapper = function() {
   149        var args = [];
   150        for (var i = 0; i < t.params.length; i++) {
   151          if (t.variadic && i === t.params.length - 1) {
   152            var vt = t.params[i].elem, varargs = [];
   153            for (var j = i; j < arguments.length; j++) {
   154              varargs.push($internalize(arguments[j], vt));
   155            }
   156            args.push(new (t.params[i])(varargs));
   157            break;
   158          }
   159          args.push($internalize(arguments[i], t.params[i]));
   160        }
   161        var result = v.apply(passThis ? this : undefined, args);
   162        switch (t.results.length) {
   163        case 0:
   164          return;
   165        case 1:
   166          return $externalize(result, t.results[0]);
   167        default:
   168          for (var i = 0; i < t.results.length; i++) {
   169            result[i] = $externalize(result[i], t.results[i]);
   170          }
   171          return result;
   172        }
   173      };
   174    }
   175    return v.$externalizeWrapper;
   176  };
   177  
   178  var $internalize = function(v, t, recv) {
   179    if (t === $jsObjectPtr) {
   180      return v;
   181    }
   182    if (t === $jsObjectPtr.elem) {
   183      $throwRuntimeError("cannot internalize js.Object, use *js.Object instead");
   184    }
   185    if (v && v.__internal_object__ !== undefined) {
   186      return $assertType(v.__internal_object__, t, false);
   187    }
   188    var timePkg = $packages["time"];
   189    if (timePkg !== undefined && t === timePkg.Time) {
   190      if (!(v !== null && v !== undefined && v.constructor === Date)) {
   191        $throwRuntimeError("cannot internalize time.Time from " + typeof v + ", must be Date");
   192      }
   193      return timePkg.Unix(new $Int64(0, 0), new $Int64(0, v.getTime() * 1000000));
   194    }
   195    switch (t.kind) {
   196    case $kindBool:
   197      return !!v;
   198    case $kindInt:
   199      return parseInt(v);
   200    case $kindInt8:
   201      return parseInt(v) << 24 >> 24;
   202    case $kindInt16:
   203      return parseInt(v) << 16 >> 16;
   204    case $kindInt32:
   205      return parseInt(v) >> 0;
   206    case $kindUint:
   207      return parseInt(v);
   208    case $kindUint8:
   209      return parseInt(v) << 24 >>> 24;
   210    case $kindUint16:
   211      return parseInt(v) << 16 >>> 16;
   212    case $kindUint32:
   213    case $kindUintptr:
   214      return parseInt(v) >>> 0;
   215    case $kindInt64:
   216    case $kindUint64:
   217      return new t(0, v);
   218    case $kindFloat32:
   219    case $kindFloat64:
   220      return parseFloat(v);
   221    case $kindArray:
   222      if (v.length !== t.len) {
   223        $throwRuntimeError("got array with wrong size from JavaScript native");
   224      }
   225      return $mapArray(v, function(e) { return $internalize(e, t.elem); });
   226    case $kindFunc:
   227      return function() {
   228        var args = [];
   229        for (var i = 0; i < t.params.length; i++) {
   230          if (t.variadic && i === t.params.length - 1) {
   231            var vt = t.params[i].elem, varargs = arguments[i];
   232            for (var j = 0; j < varargs.$length; j++) {
   233              args.push($externalize(varargs.$array[varargs.$offset + j], vt));
   234            }
   235            break;
   236          }
   237          args.push($externalize(arguments[i], t.params[i]));
   238        }
   239        var result = v.apply(recv, args);
   240        switch (t.results.length) {
   241        case 0:
   242          return;
   243        case 1:
   244          return $internalize(result, t.results[0]);
   245        default:
   246          for (var i = 0; i < t.results.length; i++) {
   247            result[i] = $internalize(result[i], t.results[i]);
   248          }
   249          return result;
   250        }
   251      };
   252    case $kindInterface:
   253      if (t.methods.length !== 0) {
   254        $throwRuntimeError("cannot internalize " + t.string);
   255      }
   256      if (v === null) {
   257        return $ifaceNil;
   258      }
   259      if (v === undefined) {
   260        return new $jsObjectPtr(undefined);
   261      }
   262      switch (v.constructor) {
   263      case Int8Array:
   264        return new ($sliceType($Int8))(v);
   265      case Int16Array:
   266        return new ($sliceType($Int16))(v);
   267      case Int32Array:
   268        return new ($sliceType($Int))(v);
   269      case Uint8Array:
   270        return new ($sliceType($Uint8))(v);
   271      case Uint16Array:
   272        return new ($sliceType($Uint16))(v);
   273      case Uint32Array:
   274        return new ($sliceType($Uint))(v);
   275      case Float32Array:
   276        return new ($sliceType($Float32))(v);
   277      case Float64Array:
   278        return new ($sliceType($Float64))(v);
   279      case Array:
   280        return $internalize(v, $sliceType($emptyInterface));
   281      case Boolean:
   282        return new $Bool(!!v);
   283      case Date:
   284        if (timePkg === undefined) {
   285          /* time package is not present, internalize as &js.Object{Date} so it can be externalized into original Date. */
   286          return new $jsObjectPtr(v);
   287        }
   288        return new timePkg.Time($internalize(v, timePkg.Time));
   289      case Function:
   290        var funcType = $funcType([$sliceType($emptyInterface)], [$jsObjectPtr], true);
   291        return new funcType($internalize(v, funcType));
   292      case Number:
   293        return new $Float64(parseFloat(v));
   294      case String:
   295        return new $String($internalize(v, $String));
   296      default:
   297        if ($global.Node && v instanceof $global.Node) {
   298          return new $jsObjectPtr(v);
   299        }
   300        var mapType = $mapType($String, $emptyInterface);
   301        return new mapType($internalize(v, mapType));
   302      }
   303    case $kindMap:
   304      var m = {};
   305      var keys = $keys(v);
   306      for (var i = 0; i < keys.length; i++) {
   307        var k = $internalize(keys[i], t.key);
   308        m[t.key.keyFor(k)] = { k: k, v: $internalize(v[keys[i]], t.elem) };
   309      }
   310      return m;
   311    case $kindPtr:
   312      if (t.elem.kind === $kindStruct) {
   313        return $internalize(v, t.elem);
   314      }
   315    case $kindSlice:
   316      return new t($mapArray(v, function(e) { return $internalize(e, t.elem); }));
   317    case $kindString:
   318      v = String(v);
   319      if ($isASCII(v)) {
   320        return v;
   321      }
   322      var s = "";
   323      var i = 0;
   324      while (i < v.length) {
   325        var h = v.charCodeAt(i);
   326        if (0xD800 <= h && h <= 0xDBFF) {
   327          var l = v.charCodeAt(i + 1);
   328          var c = (h - 0xD800) * 0x400 + l - 0xDC00 + 0x10000;
   329          s += $encodeRune(c);
   330          i += 2;
   331          continue;
   332        }
   333        s += $encodeRune(h);
   334        i++;
   335      }
   336      return s;
   337    case $kindStruct:
   338      var noJsObject = {};
   339      var searchJsObject = function(t) {
   340        if (t === $jsObjectPtr) {
   341          return v;
   342        }
   343        if (t === $jsObjectPtr.elem) {
   344          $throwRuntimeError("cannot internalize js.Object, use *js.Object instead");
   345        }
   346        switch (t.kind) {
   347        case $kindPtr:
   348          return searchJsObject(t.elem);
   349        case $kindStruct:
   350          var f = t.fields[0];
   351          var o = searchJsObject(f.typ);
   352          if (o !== noJsObject) {
   353            var n = new t.ptr();
   354            n[f.prop] = o;
   355            return n;
   356          }
   357          return noJsObject;
   358        default:
   359          return noJsObject;
   360        }
   361      };
   362      var o = searchJsObject(t);
   363      if (o !== noJsObject) {
   364        return o;
   365      }
   366    }
   367    $throwRuntimeError("cannot internalize " + t.string);
   368  };
   369  
   370  /* $isASCII reports whether string s contains only ASCII characters. */
   371  var $isASCII = function(s) {
   372    for (var i = 0; i < s.length; i++) {
   373      if (s.charCodeAt(i) >= 128) {
   374        return false;
   375      }
   376    }
   377    return true;
   378  };
   379  `