github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/prelude/types.js (about) 1 var $kindBool = 1; 2 var $kindInt = 2; 3 var $kindInt8 = 3; 4 var $kindInt16 = 4; 5 var $kindInt32 = 5; 6 var $kindInt64 = 6; 7 var $kindUint = 7; 8 var $kindUint8 = 8; 9 var $kindUint16 = 9; 10 var $kindUint32 = 10; 11 var $kindUint64 = 11; 12 var $kindUintptr = 12; 13 var $kindFloat32 = 13; 14 var $kindFloat64 = 14; 15 var $kindComplex64 = 15; 16 var $kindComplex128 = 16; 17 var $kindArray = 17; 18 var $kindChan = 18; 19 var $kindFunc = 19; 20 var $kindInterface = 20; 21 var $kindMap = 21; 22 var $kindPtr = 22; 23 var $kindSlice = 23; 24 var $kindString = 24; 25 var $kindStruct = 25; 26 var $kindUnsafePointer = 26; 27 28 var $methodSynthesizers = []; 29 var $addMethodSynthesizer = f => { 30 if ($methodSynthesizers === null) { 31 f(); 32 return; 33 } 34 $methodSynthesizers.push(f); 35 }; 36 var $synthesizeMethods = () => { 37 $methodSynthesizers.forEach(f => { f(); }); 38 $methodSynthesizers = null; 39 }; 40 41 var $ifaceKeyFor = x => { 42 if (x === $ifaceNil) { 43 return 'nil'; 44 } 45 var c = x.constructor; 46 return c.string + '$' + c.keyFor(x.$val); 47 }; 48 49 var $identity = x => { return x; }; 50 51 var $typeIDCounter = 0; 52 53 var $idKey = x => { 54 if (x.$id === undefined) { 55 $idCounter++; 56 x.$id = $idCounter; 57 } 58 return String(x.$id); 59 }; 60 61 // Creates constructor functions for array pointer types. Returns a new function 62 // instance each time to make sure each type is independent of the other. 63 var $arrayPtrCtor = () => { 64 return function (array) { 65 this.$get = () => { return array; }; 66 this.$set = function (v) { typ.copy(this, v); }; 67 this.$val = array; 68 }; 69 } 70 71 var $newType = (size, kind, string, named, pkg, exported, constructor) => { 72 var typ; 73 switch (kind) { 74 case $kindBool: 75 case $kindInt: 76 case $kindInt8: 77 case $kindInt16: 78 case $kindInt32: 79 case $kindUint: 80 case $kindUint8: 81 case $kindUint16: 82 case $kindUint32: 83 case $kindUintptr: 84 case $kindUnsafePointer: 85 typ = function (v) { this.$val = v; }; 86 typ.wrapped = true; 87 typ.keyFor = $identity; 88 break; 89 90 case $kindString: 91 typ = function (v) { this.$val = v; }; 92 typ.wrapped = true; 93 typ.keyFor = x => { return "$" + x; }; 94 break; 95 96 case $kindFloat32: 97 case $kindFloat64: 98 typ = function (v) { this.$val = v; }; 99 typ.wrapped = true; 100 typ.keyFor = x => { return $floatKey(x); }; 101 break; 102 103 case $kindInt64: 104 typ = function (high, low) { 105 this.$high = (high + Math.floor(Math.ceil(low) / 4294967296)) >> 0; 106 this.$low = low >>> 0; 107 this.$val = this; 108 }; 109 typ.keyFor = x => { return x.$high + "$" + x.$low; }; 110 break; 111 112 case $kindUint64: 113 typ = function (high, low) { 114 this.$high = (high + Math.floor(Math.ceil(low) / 4294967296)) >>> 0; 115 this.$low = low >>> 0; 116 this.$val = this; 117 }; 118 typ.keyFor = x => { return x.$high + "$" + x.$low; }; 119 break; 120 121 case $kindComplex64: 122 typ = function (real, imag) { 123 this.$real = $fround(real); 124 this.$imag = $fround(imag); 125 this.$val = this; 126 }; 127 typ.keyFor = x => { return x.$real + "$" + x.$imag; }; 128 break; 129 130 case $kindComplex128: 131 typ = function (real, imag) { 132 this.$real = real; 133 this.$imag = imag; 134 this.$val = this; 135 }; 136 typ.keyFor = x => { return x.$real + "$" + x.$imag; }; 137 break; 138 139 case $kindArray: 140 typ = function (v) { this.$val = v; }; 141 typ.wrapped = true; 142 typ.ptr = $newType(4, $kindPtr, "*" + string, false, "", false, $arrayPtrCtor()); 143 typ.init = (elem, len) => { 144 typ.elem = elem; 145 typ.len = len; 146 typ.comparable = elem.comparable; 147 typ.keyFor = x => { 148 return Array.prototype.join.call($mapArray(x, e => { 149 return String(elem.keyFor(e)).replace(/\\/g, "\\\\").replace(/\$/g, "\\$"); 150 }), "$"); 151 }; 152 typ.copy = (dst, src) => { 153 $copyArray(dst, src, 0, 0, src.length, elem); 154 }; 155 typ.ptr.init(typ); 156 Object.defineProperty(typ.ptr.nil, "nilCheck", { get: $throwNilPointerError }); 157 }; 158 break; 159 160 case $kindChan: 161 typ = function (v) { this.$val = v; }; 162 typ.wrapped = true; 163 typ.keyFor = $idKey; 164 typ.init = (elem, sendOnly, recvOnly) => { 165 typ.elem = elem; 166 typ.sendOnly = sendOnly; 167 typ.recvOnly = recvOnly; 168 }; 169 break; 170 171 case $kindFunc: 172 typ = function (v) { this.$val = v; }; 173 typ.wrapped = true; 174 typ.init = (params, results, variadic) => { 175 typ.params = params; 176 typ.results = results; 177 typ.variadic = variadic; 178 typ.comparable = false; 179 }; 180 break; 181 182 case $kindInterface: 183 typ = { implementedBy: {}, missingMethodFor: {} }; 184 typ.keyFor = $ifaceKeyFor; 185 typ.init = methods => { 186 typ.methods = methods; 187 methods.forEach(m => { 188 $ifaceNil[m.prop] = $throwNilPointerError; 189 }); 190 }; 191 break; 192 193 case $kindMap: 194 typ = function (v) { this.$val = v; }; 195 typ.wrapped = true; 196 typ.init = (key, elem) => { 197 typ.key = key; 198 typ.elem = elem; 199 typ.comparable = false; 200 }; 201 break; 202 203 case $kindPtr: 204 typ = constructor || function (getter, setter, target) { 205 this.$get = getter; 206 this.$set = setter; 207 this.$target = target; 208 this.$val = this; 209 }; 210 typ.keyFor = $idKey; 211 typ.init = elem => { 212 typ.elem = elem; 213 typ.wrapped = (elem.kind === $kindArray); 214 typ.nil = new typ($throwNilPointerError, $throwNilPointerError); 215 }; 216 break; 217 218 case $kindSlice: 219 typ = function (array) { 220 if (array.constructor !== typ.nativeArray) { 221 array = new typ.nativeArray(array); 222 } 223 this.$array = array; 224 this.$offset = 0; 225 this.$length = array.length; 226 this.$capacity = array.length; 227 this.$val = this; 228 }; 229 typ.init = elem => { 230 typ.elem = elem; 231 typ.comparable = false; 232 typ.nativeArray = $nativeArray(elem.kind); 233 typ.nil = new typ([]); 234 }; 235 break; 236 237 case $kindStruct: 238 typ = function (v) { this.$val = v; }; 239 typ.wrapped = true; 240 typ.ptr = $newType(4, $kindPtr, "*" + string, false, pkg, exported, constructor); 241 typ.ptr.elem = typ; 242 typ.ptr.prototype.$get = function () { return this; }; 243 typ.ptr.prototype.$set = function (v) { typ.copy(this, v); }; 244 typ.init = (pkgPath, fields) => { 245 typ.pkgPath = pkgPath; 246 typ.fields = fields; 247 fields.forEach(f => { 248 if (!f.typ.comparable) { 249 typ.comparable = false; 250 } 251 }); 252 typ.keyFor = x => { 253 var val = x.$val; 254 return $mapArray(fields, f => { 255 return String(f.typ.keyFor(val[f.prop])).replace(/\\/g, "\\\\").replace(/\$/g, "\\$"); 256 }).join("$"); 257 }; 258 typ.copy = (dst, src) => { 259 for (var i = 0; i < fields.length; i++) { 260 var f = fields[i]; 261 switch (f.typ.kind) { 262 case $kindArray: 263 case $kindStruct: 264 f.typ.copy(dst[f.prop], src[f.prop]); 265 continue; 266 default: 267 dst[f.prop] = src[f.prop]; 268 continue; 269 } 270 } 271 }; 272 /* nil value */ 273 var properties = {}; 274 fields.forEach(f => { 275 properties[f.prop] = { get: $throwNilPointerError, set: $throwNilPointerError }; 276 }); 277 typ.ptr.nil = Object.create(constructor.prototype, properties); 278 typ.ptr.nil.$val = typ.ptr.nil; 279 /* methods for embedded fields */ 280 $addMethodSynthesizer(() => { 281 var synthesizeMethod = (target, m, f) => { 282 if (target.prototype[m.prop] !== undefined) { return; } 283 target.prototype[m.prop] = function(...args) { 284 var v = this.$val[f.prop]; 285 if (f.typ === $jsObjectPtr) { 286 v = new $jsObjectPtr(v); 287 } 288 if (v.$val === undefined) { 289 v = new f.typ(v); 290 } 291 return v[m.prop](...args); 292 }; 293 }; 294 fields.forEach(f => { 295 if (f.embedded) { 296 $methodSet(f.typ).forEach(m => { 297 synthesizeMethod(typ, m, f); 298 synthesizeMethod(typ.ptr, m, f); 299 }); 300 $methodSet($ptrType(f.typ)).forEach(m => { 301 synthesizeMethod(typ.ptr, m, f); 302 }); 303 } 304 }); 305 }); 306 }; 307 break; 308 309 default: 310 $panic(new $String("invalid kind: " + kind)); 311 } 312 313 switch (kind) { 314 case $kindBool: 315 case $kindMap: 316 typ.zero = () => { return false; }; 317 break; 318 319 case $kindInt: 320 case $kindInt8: 321 case $kindInt16: 322 case $kindInt32: 323 case $kindUint: 324 case $kindUint8: 325 case $kindUint16: 326 case $kindUint32: 327 case $kindUintptr: 328 case $kindUnsafePointer: 329 case $kindFloat32: 330 case $kindFloat64: 331 typ.zero = () => { return 0; }; 332 break; 333 334 case $kindString: 335 typ.zero = () => { return ""; }; 336 break; 337 338 case $kindInt64: 339 case $kindUint64: 340 case $kindComplex64: 341 case $kindComplex128: 342 var zero = new typ(0, 0); 343 typ.zero = () => { return zero; }; 344 break; 345 346 case $kindPtr: 347 case $kindSlice: 348 typ.zero = () => { return typ.nil; }; 349 break; 350 351 case $kindChan: 352 typ.zero = () => { return $chanNil; }; 353 break; 354 355 case $kindFunc: 356 typ.zero = () => { return $throwNilPointerError; }; 357 break; 358 359 case $kindInterface: 360 typ.zero = () => { return $ifaceNil; }; 361 break; 362 363 case $kindArray: 364 typ.zero = () => { 365 var arrayClass = $nativeArray(typ.elem.kind); 366 if (arrayClass !== Array) { 367 return new arrayClass(typ.len); 368 } 369 var array = new Array(typ.len); 370 for (var i = 0; i < typ.len; i++) { 371 array[i] = typ.elem.zero(); 372 } 373 return array; 374 }; 375 break; 376 377 case $kindStruct: 378 typ.zero = () => { return new typ.ptr(); }; 379 break; 380 381 default: 382 $panic(new $String("invalid kind: " + kind)); 383 } 384 385 typ.id = $typeIDCounter; 386 $typeIDCounter++; 387 typ.size = size; 388 typ.kind = kind; 389 typ.string = string; 390 typ.named = named; 391 typ.pkg = pkg; 392 typ.exported = exported; 393 typ.methods = []; 394 typ.methodSetCache = null; 395 typ.comparable = true; 396 return typ; 397 }; 398 399 var $methodSet = typ => { 400 if (typ.methodSetCache !== null) { 401 return typ.methodSetCache; 402 } 403 var base = {}; 404 405 var isPtr = (typ.kind === $kindPtr); 406 if (isPtr && typ.elem.kind === $kindInterface) { 407 typ.methodSetCache = []; 408 return []; 409 } 410 411 var current = [{ typ: isPtr ? typ.elem : typ, indirect: isPtr }]; 412 413 var seen = {}; 414 415 while (current.length > 0) { 416 var next = []; 417 var mset = []; 418 419 current.forEach(e => { 420 if (seen[e.typ.string]) { 421 return; 422 } 423 seen[e.typ.string] = true; 424 425 if (e.typ.named) { 426 mset = mset.concat(e.typ.methods); 427 if (e.indirect) { 428 mset = mset.concat($ptrType(e.typ).methods); 429 } 430 } 431 432 switch (e.typ.kind) { 433 case $kindStruct: 434 e.typ.fields.forEach(f => { 435 if (f.embedded) { 436 var fTyp = f.typ; 437 var fIsPtr = (fTyp.kind === $kindPtr); 438 next.push({ typ: fIsPtr ? fTyp.elem : fTyp, indirect: e.indirect || fIsPtr }); 439 } 440 }); 441 break; 442 443 case $kindInterface: 444 mset = mset.concat(e.typ.methods); 445 break; 446 } 447 }); 448 449 mset.forEach(m => { 450 if (base[m.name] === undefined) { 451 base[m.name] = m; 452 } 453 }); 454 455 current = next; 456 } 457 458 typ.methodSetCache = []; 459 Object.keys(base).sort().forEach(name => { 460 typ.methodSetCache.push(base[name]); 461 }); 462 return typ.methodSetCache; 463 }; 464 465 var $Bool = $newType(1, $kindBool, "bool", true, "", false, null); 466 var $Int = $newType(4, $kindInt, "int", true, "", false, null); 467 var $Int8 = $newType(1, $kindInt8, "int8", true, "", false, null); 468 var $Int16 = $newType(2, $kindInt16, "int16", true, "", false, null); 469 var $Int32 = $newType(4, $kindInt32, "int32", true, "", false, null); 470 var $Int64 = $newType(8, $kindInt64, "int64", true, "", false, null); 471 var $Uint = $newType(4, $kindUint, "uint", true, "", false, null); 472 var $Uint8 = $newType(1, $kindUint8, "uint8", true, "", false, null); 473 var $Uint16 = $newType(2, $kindUint16, "uint16", true, "", false, null); 474 var $Uint32 = $newType(4, $kindUint32, "uint32", true, "", false, null); 475 var $Uint64 = $newType(8, $kindUint64, "uint64", true, "", false, null); 476 var $Uintptr = $newType(4, $kindUintptr, "uintptr", true, "", false, null); 477 var $Float32 = $newType(4, $kindFloat32, "float32", true, "", false, null); 478 var $Float64 = $newType(8, $kindFloat64, "float64", true, "", false, null); 479 var $Complex64 = $newType(8, $kindComplex64, "complex64", true, "", false, null); 480 var $Complex128 = $newType(16, $kindComplex128, "complex128", true, "", false, null); 481 var $String = $newType(8, $kindString, "string", true, "", false, null); 482 var $UnsafePointer = $newType(4, $kindUnsafePointer, "unsafe.Pointer", true, "unsafe", false, null); 483 484 var $nativeArray = elemKind => { 485 switch (elemKind) { 486 case $kindInt: 487 return Int32Array; 488 case $kindInt8: 489 return Int8Array; 490 case $kindInt16: 491 return Int16Array; 492 case $kindInt32: 493 return Int32Array; 494 case $kindUint: 495 return Uint32Array; 496 case $kindUint8: 497 return Uint8Array; 498 case $kindUint16: 499 return Uint16Array; 500 case $kindUint32: 501 return Uint32Array; 502 case $kindUintptr: 503 return Uint32Array; 504 case $kindFloat32: 505 return Float32Array; 506 case $kindFloat64: 507 return Float64Array; 508 default: 509 return Array; 510 } 511 }; 512 var $toNativeArray = (elemKind, array) => { 513 var nativeArray = $nativeArray(elemKind); 514 if (nativeArray === Array) { 515 return array; 516 } 517 return new nativeArray(array); 518 }; 519 var $arrayTypes = {}; 520 var $arrayType = (elem, len) => { 521 var typeKey = elem.id + "$" + len; 522 var typ = $arrayTypes[typeKey]; 523 if (typ === undefined) { 524 typ = $newType(elem.size * len, $kindArray, "[" + len + "]" + elem.string, false, "", false, null); 525 $arrayTypes[typeKey] = typ; 526 typ.init(elem, len); 527 } 528 return typ; 529 }; 530 531 var $chanType = (elem, sendOnly, recvOnly) => { 532 var string = (recvOnly ? "<-" : "") + "chan" + (sendOnly ? "<- " : " "); 533 if (!sendOnly && !recvOnly && (elem.string[0] == "<")) { 534 string += "(" + elem.string + ")"; 535 } else { 536 string += elem.string; 537 } 538 var field = sendOnly ? "SendChan" : (recvOnly ? "RecvChan" : "Chan"); 539 var typ = elem[field]; 540 if (typ === undefined) { 541 typ = $newType(4, $kindChan, string, false, "", false, null); 542 elem[field] = typ; 543 typ.init(elem, sendOnly, recvOnly); 544 } 545 return typ; 546 }; 547 var $Chan = function (elem, capacity) { 548 if (capacity < 0 || capacity > 2147483647) { 549 $throwRuntimeError("makechan: size out of range"); 550 } 551 this.$elem = elem; 552 this.$capacity = capacity; 553 this.$buffer = []; 554 this.$sendQueue = []; 555 this.$recvQueue = []; 556 this.$closed = false; 557 }; 558 var $chanNil = new $Chan(null, 0); 559 $chanNil.$sendQueue = $chanNil.$recvQueue = { length: 0, push() { }, shift() { return undefined; }, indexOf() { return -1; } }; 560 561 var $funcTypes = {}; 562 var $funcType = (params, results, variadic) => { 563 var typeKey = $mapArray(params, p => { return p.id; }).join(",") + "$" + $mapArray(results, r => { return r.id; }).join(",") + "$" + variadic; 564 var typ = $funcTypes[typeKey]; 565 if (typ === undefined) { 566 var paramTypes = $mapArray(params, p => { return p.string; }); 567 if (variadic) { 568 paramTypes[paramTypes.length - 1] = "..." + paramTypes[paramTypes.length - 1].substr(2); 569 } 570 var string = "func(" + paramTypes.join(", ") + ")"; 571 if (results.length === 1) { 572 string += " " + results[0].string; 573 } else if (results.length > 1) { 574 string += " (" + $mapArray(results, r => { return r.string; }).join(", ") + ")"; 575 } 576 typ = $newType(4, $kindFunc, string, false, "", false, null); 577 $funcTypes[typeKey] = typ; 578 typ.init(params, results, variadic); 579 } 580 return typ; 581 }; 582 583 var $interfaceTypes = {}; 584 var $interfaceType = methods => { 585 var typeKey = $mapArray(methods, m => { return m.pkg + "," + m.name + "," + m.typ.id; }).join("$"); 586 var typ = $interfaceTypes[typeKey]; 587 if (typ === undefined) { 588 var string = "interface {}"; 589 if (methods.length !== 0) { 590 string = "interface { " + $mapArray(methods, m => { 591 return (m.pkg !== "" ? m.pkg + "." : "") + m.name + m.typ.string.substr(4); 592 }).join("; ") + " }"; 593 } 594 typ = $newType(8, $kindInterface, string, false, "", false, null); 595 $interfaceTypes[typeKey] = typ; 596 typ.init(methods); 597 } 598 return typ; 599 }; 600 var $emptyInterface = $interfaceType([]); 601 var $ifaceNil = {}; 602 var $error = $newType(8, $kindInterface, "error", true, "", false, null); 603 $error.init([{ prop: "Error", name: "Error", pkg: "", typ: $funcType([], [$String], false) }]); 604 605 var $mapTypes = {}; 606 var $mapType = (key, elem) => { 607 var typeKey = key.id + "$" + elem.id; 608 var typ = $mapTypes[typeKey]; 609 if (typ === undefined) { 610 typ = $newType(4, $kindMap, "map[" + key.string + "]" + elem.string, false, "", false, null); 611 $mapTypes[typeKey] = typ; 612 typ.init(key, elem); 613 } 614 return typ; 615 }; 616 var $makeMap = (keyForFunc, entries) => { 617 var m = new Map(); 618 for (var i = 0; i < entries.length; i++) { 619 var e = entries[i]; 620 m.set(keyForFunc(e.k), e); 621 } 622 return m; 623 }; 624 625 var $ptrType = elem => { 626 var typ = elem.ptr; 627 if (typ === undefined) { 628 typ = $newType(4, $kindPtr, "*" + elem.string, false, "", elem.exported, null); 629 elem.ptr = typ; 630 typ.init(elem); 631 } 632 return typ; 633 }; 634 635 var $newDataPointer = (data, constructor) => { 636 if (constructor.elem.kind === $kindStruct) { 637 return data; 638 } 639 return new constructor(() => { return data; }, v => { data = v; }); 640 }; 641 642 var $indexPtr = (array, index, constructor) => { 643 if (array.buffer) { 644 // Pointers to the same underlying ArrayBuffer share cache. 645 var cache = array.buffer.$ptr = array.buffer.$ptr || {}; 646 // Pointers of different primitive types are non-comparable and stored in different caches. 647 var typeCache = cache[array.name] = cache[array.name] || {}; 648 var cacheIdx = array.BYTES_PER_ELEMENT * index + array.byteOffset; 649 return typeCache[cacheIdx] || (typeCache[cacheIdx] = new constructor(() => { return array[index]; }, v => { array[index] = v; })); 650 } else { 651 array.$ptr = array.$ptr || {}; 652 return array.$ptr[index] || (array.$ptr[index] = new constructor(() => { return array[index]; }, v => { array[index] = v; })); 653 } 654 }; 655 656 var $sliceType = elem => { 657 var typ = elem.slice; 658 if (typ === undefined) { 659 typ = $newType(12, $kindSlice, "[]" + elem.string, false, "", false, null); 660 elem.slice = typ; 661 typ.init(elem); 662 } 663 return typ; 664 }; 665 var $makeSlice = (typ, length, capacity = length) => { 666 if (length < 0 || length > 2147483647) { 667 $throwRuntimeError("makeslice: len out of range"); 668 } 669 if (capacity < 0 || capacity < length || capacity > 2147483647) { 670 $throwRuntimeError("makeslice: cap out of range"); 671 } 672 var array = new typ.nativeArray(capacity); 673 if (typ.nativeArray === Array) { 674 for (var i = 0; i < capacity; i++) { 675 array[i] = typ.elem.zero(); 676 } 677 } 678 var slice = new typ(array); 679 slice.$length = length; 680 return slice; 681 }; 682 683 var $structTypes = {}; 684 var $structType = (pkgPath, fields) => { 685 var typeKey = $mapArray(fields, f => { return f.name + "," + f.typ.id + "," + f.tag; }).join("$"); 686 var typ = $structTypes[typeKey]; 687 if (typ === undefined) { 688 var string = "struct { " + $mapArray(fields, f => { 689 var str = f.typ.string + (f.tag !== "" ? (" \"" + f.tag.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\"") : ""); 690 if (f.embedded) { 691 return str; 692 } 693 return f.name + " " + str; 694 }).join("; ") + " }"; 695 if (fields.length === 0) { 696 string = "struct {}"; 697 } 698 typ = $newType(0, $kindStruct, string, false, "", false, function(...args) { 699 this.$val = this; 700 for (var i = 0; i < fields.length; i++) { 701 var f = fields[i]; 702 if (f.name == '_') { 703 continue; 704 } 705 var arg = args[i]; 706 this[f.prop] = arg !== undefined ? arg : f.typ.zero(); 707 } 708 }); 709 $structTypes[typeKey] = typ; 710 typ.init(pkgPath, fields); 711 } 712 return typ; 713 }; 714 715 var $assertType = (value, type, returnTuple) => { 716 var isInterface = (type.kind === $kindInterface), ok, missingMethod = ""; 717 if (value === $ifaceNil) { 718 ok = false; 719 } else if (!isInterface) { 720 ok = value.constructor === type; 721 } else { 722 var valueTypeString = value.constructor.string; 723 ok = type.implementedBy[valueTypeString]; 724 if (ok === undefined) { 725 ok = true; 726 var valueMethodSet = $methodSet(value.constructor); 727 var interfaceMethods = type.methods; 728 for (var i = 0; i < interfaceMethods.length; i++) { 729 var tm = interfaceMethods[i]; 730 var found = false; 731 for (var j = 0; j < valueMethodSet.length; j++) { 732 var vm = valueMethodSet[j]; 733 if (vm.name === tm.name && vm.pkg === tm.pkg && vm.typ === tm.typ) { 734 found = true; 735 break; 736 } 737 } 738 if (!found) { 739 ok = false; 740 type.missingMethodFor[valueTypeString] = tm.name; 741 break; 742 } 743 } 744 type.implementedBy[valueTypeString] = ok; 745 } 746 if (!ok) { 747 missingMethod = type.missingMethodFor[valueTypeString]; 748 } 749 } 750 751 if (!ok) { 752 if (returnTuple) { 753 return [type.zero(), false]; 754 } 755 $panic(new $packages["runtime"].TypeAssertionError.ptr( 756 $packages["runtime"]._type.ptr.nil, 757 (value === $ifaceNil ? $packages["runtime"]._type.ptr.nil : new $packages["runtime"]._type.ptr(value.constructor.string)), 758 new $packages["runtime"]._type.ptr(type.string), 759 missingMethod)); 760 } 761 762 if (!isInterface) { 763 value = value.$val; 764 } 765 if (type === $jsObjectPtr) { 766 value = value.object; 767 } 768 return returnTuple ? [value, true] : value; 769 };