github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/prelude/jsmapping.js (about)

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