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 };