Skip to content

Commit 28e102c

Browse files
committed
compiler/natives/src/reflect: Override Value.assignTo method, drop v.Kind() == Interface && v.IsNil().
This change adds a copy of Value.assignTo method to reflect package, identical to upstream, except with golang/go@eafa29b not applied. That commit adds a short-circuit check to that skips ifaceE2I, in order to avoid a panic that occurs in ifaceE2I under that condition in gc and gccgo compilers. GopherJS implements a custom version of ifaceE2I which needs to run and does not panic in that condition. So, there's no need skip it. Fixes: $ gopherjs test --short reflect html/template --- FAIL: TestCallConvert (0.01s) all_test.go:1639: expected [nil], got [<io.Reader Value>] FAIL FAIL reflect 3.084s --- FAIL: TestEscapingNilNonemptyInterfaces (0.01s) go/src/github.com/shurcooL/play/241/test.243863553:9608 if (!(($parseInt(methodSet.length) === 0)) || !!(typ.named)) { ^ TypeError: Cannot read property 'length' of undefined at reflectType (go/src/github.com/shurcooL/play/241/test.243863553:9608:31) at Object.TypeOf (go/src/github.com/shurcooL/play/241/reflect.go:312:3) at indirect (/html/template/content.go:119:6) at stringify (/html/template/content.go:153:4) at htmlEscaper (/html/template/html.go:43:3) at $call (go/src/github.com/shurcooL/play/241/test.243863553:30:50) at go/src/github.com/shurcooL/play/241/test.243863553:1948:22 at Object.$packages.reflect.Value.ptr.call (go/src/github.com/shurcooL/play/241/reflect.go:880:3) at Object.$packages.reflect.Value.ptr.Call (/reflect/value.go:308:3) at Object.$packages.text/template.state.ptr.evalCall (/text/template/exec.go:667:3) at Object.$packages.text/template.state.ptr.evalFunction (/text/template/exec.go:535:3) at Object.$packages.text/template.state.ptr.evalCommand (/text/template/exec.go:432:4) at Object.$packages.text/template.state.ptr.evalPipeline (/text/template/exec.go:405:4) at Object.$packages.text/template.state.ptr.walk (/text/template/exec.go:231:4) at Object.$packages.text/template.state.ptr.walk (/text/template/exec.go:239:5) at Object.$packages.text/template.Template.ptr.execute (/text/template/exec.go:194:3) at Object.$packages.text/template.Template.ptr.Execute (/text/template/exec.go:177:3) at Object.$packages.html/template.Template.ptr.Execute (/html/template/template.go:122:3) at Object.TestEscapingNilNonemptyInterfaces [as $blk] (/html/template/content_test.go:448:3) at Object.tRunner [as $blk] (/testing/testing.go:777:3) at fun (go/src/github.com/shurcooL/play/241/test.243863553:1479:37) at $goroutine (go/src/github.com/shurcooL/play/241/test.243863553:1477:19) at $runScheduled (go/src/github.com/shurcooL/play/241/test.243863553:1517:7) at $schedule (go/src/github.com/shurcooL/play/241/test.243863553:1533:5) at $go (go/src/github.com/shurcooL/play/241/test.243863553:1509:3) at Object.<anonymous> (go/src/github.com/shurcooL/play/241/test.243863553:55363:1) at Object.<anonymous> (go/src/github.com/shurcooL/play/241/test.243863553:55366:4) at Module._compile (module.js:660:30) at Object.Module._extensions..js (module.js:671:10) at Module.load (module.js:573:32) at tryModuleLoad (module.js:513:12) at Function.Module._load (module.js:505:3) at Function.Module.runMain (module.js:701:10) at startup (bootstrap_node.js:190:16) at bootstrap_node.js:662:3 FAIL html/template 1.079s
1 parent 5e5d2d2 commit 28e102c

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

compiler/natives/src/reflect/reflect.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,39 @@ func (v Value) object() *js.Object {
792792
return js.InternalObject(v.ptr)
793793
}
794794

795+
func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value {
796+
if v.flag&flagMethod != 0 {
797+
v = makeMethodValue(context, v)
798+
}
799+
800+
switch {
801+
case directlyAssignable(dst, v.typ):
802+
// Overwrite type so that they match.
803+
// Same memory layout, so no harm done.
804+
fl := v.flag&(flagAddr|flagIndir) | v.flag.ro()
805+
fl |= flag(dst.Kind())
806+
return Value{dst, v.ptr, fl}
807+
808+
case implements(dst, v.typ):
809+
if target == nil {
810+
target = unsafe_New(dst)
811+
}
812+
// GopherJS: Skip the v.Kind() == Interface && v.IsNil() if statement
813+
// from upstream. ifaceE2I below does not panic, and it needs
814+
// to run, given its custom implementation.
815+
x := valueInterface(v, false)
816+
if dst.NumMethod() == 0 {
817+
*(*interface{})(target) = x
818+
} else {
819+
ifaceE2I(dst, x, target)
820+
}
821+
return Value{dst, target, flagIndir | flag(Interface)}
822+
}
823+
824+
// Failed.
825+
panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
826+
}
827+
795828
var callHelper = js.Global.Get("$call").Interface().(func(...interface{}) *js.Object)
796829

797830
func (v Value) call(op string, in []Value) []Value {

0 commit comments

Comments
 (0)