-
Notifications
You must be signed in to change notification settings - Fork 570
Fields of embedded structs are not set correctly #640
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@theclapp there's two issues/bugs here that are related. It appears that fields of embedded structs are not being correctly transpiled. Given: package main
import (
"github.com/gopherjs/gopherjs/js"
)
type T1 struct {
*js.Object
F1 string `js:"f1"`
}
type T2 struct {
*js.Object
*T1 `js:"t1"`
}
func main() {
s := &T2{Object: js.Global.Get("Object").New()}
s.T1 = &T1{Object: js.Global.Get("Object").New()}
_ = s.F1
} the transpiled result of the $unused($internalize(s.Object.t1, $String)); which is clearly wrong. If we then change the assignment to explicitly dereference via the $unused($internalize($internalize(s.Object.t1, ptrType).Object.f1, $String)); i.e. the superfluous
// EDIT: IGNORE THIS...
// t := s.T1
// _ = t.F1
// EDIT: IGNORE THIS
// t = $internalize(s.Object.t1, ptrType);
// $unused($internalize(t.Object.f1, $String)); The desired result here is (I think) which removes the redundant _ = s.F1 transpiles to: $unused($internalize(s.Object.t1.f1, $String)); |
I'll have to trust you that that's a bug. :) FWIW, it does seem to work.
I'm not sure I understand. So, do we have any ETA on those? |
In case anyone's wondering (I was :), access of regular Go embedded fields works fine, e.g. type T3 struct {
F3 string
}
type T4 struct {
T3
}
t4 := T4{T3{"foo"}}
println(t4.F3) works fine and transpiles to t4 = new T4.ptr(new T3.ptr("foo"));
console.log(t4.T3.F3); As an aside, I've seen several recent issues saying |
You're right; to confirm, whilst suboptimal, this does work. I was conflating two things here (edited my comment above). The point I failed to make was that in making this optimal we will also solve #639 when it comes to comparison of values of pointer to
Not a specific one from my side, no. But they are issues that are also blocking me in https://github.com/myitcv/react so I have incentive to work on them asap. We have explicit agreement from @neelance and @shurcooL on the major points (and @flimzy has offered some helpful feedback too); I'll ping a few others to see if they have anything to add into the mix. |
Thanks, @myitcv, for your comments and feedback. I forgot to mention, re:
This isn't quite right. We want it to transpile to ... |
Actually I think that's what I intended because:
(if you run https://gopherjs.github.io/playground/#/_9Zv0-b_lc locally and set a breakpoint on the The |
Possibly related to this and other issues mentioned: https://gopherjs.github.io/playground/#/J4t4vqRaj2 Seems to crash the playground, when
|
On re-reading my own initial bug report, I think this is, in fact, wrong (Edit: But see later comment): type T1 struct {
*js.Object
F1 string `js:"f1"`
}
s := &struct {
*js.Object
*T1 `js:"t1"` // <- shouldn't have this `js:"t1"` tag
}{Object: hvue.NewObject()} That should be type T1 struct {
*js.Object
F1 string `js:"f1"`
}
s := &struct {
*js.Object
*T1 // <- no js tag here
}{Object: hvue.NewObject()} with no I'm inclined to close this bug as "user error / don't do that then". (Edit: Again, see later comment.) |
So I tried this again in my actual app, and it does seem like it should work and doesn't. The core problem is that Here's the full code and the full transpiled Javascript: type StyleObject struct {
*js.Object
Color string `js:"color"`
FontSize string `js:"fontSize"`
}
data4 := &struct {
*js.Object
*StyleObject `js:"styleObject"`
}{Object: hvue.NewObject()}
data4.StyleObject = &StyleObject{Object: hvue.NewObject()}
println("assigning Color & FontSize")
data4.Color = "red"
data4.FontSize = "13px"
println("Color:", data4.Color) // => Color: 13px
println("FontSize:", data4.FontSize) // => FontSize: 13px
println("data4.StyleObject.Color:", data4.StyleObject.Color) // => data4.StyleObject.Color: undefined
println("data4.StyleObject.FontSize:", data4.StyleObject.FontSize) // => data4.StyleObject.FontSize: undefined
println("data4 json:", js.Global.Get("JSON").Call("stringify", data4)) // => data4 json: {"styleObject":"13px"}
data4.StyleObject = &StyleObject{Object: hvue.NewObject()}
data4.StyleObject.Color = "blue"
data4.StyleObject.FontSize = "14px"
println("reassinged")
println("Color:", data4.Color) // => Color: [object Object]
println("FontSize:", data4.FontSize) // => FontSize: [object Object]
println("data4.StyleObject.Color:", data4.StyleObject.Color) // => data4.StyleObject.Color: blue
println("data4.StyleObject.FontSize:", data4.StyleObject.FontSize) // => data4.StyleObject.FontSize: 14px And here's the transpiled JS: console.log("assigning Color & FontSize");
data4.Object.styleObject = $externalize("red", $String);
data4.Object.styleObject = $externalize("13px", $String);
console.log("Color:", $internalize(data4.Object.styleObject, $String));
console.log("FontSize:", $internalize(data4.Object.styleObject, $String));
console.log("data4.StyleObject.Color:", $internalize($internalize(data4.Object.styleObject, ptrType$3).Object.color, $String));
console.log("data4.StyleObject.FontSize:", $internalize($internalize(data4.Object.styleObject, ptrType$3).Object.fontSize, $String));
console.log("data4 json:", $global.JSON.stringify($externalize(data4, ptrType$4)));
data4.Object.styleObject = $externalize(new StyleObject.ptr(hvue.NewObject(), "", ""), ptrType$3);
$internalize(data4.Object.styleObject, ptrType$3).Object.color = $externalize("blue", $String);
$internalize(data4.Object.styleObject, ptrType$3).Object.fontSize = $externalize("14px", $String);
console.log("reassinged");
console.log("Color:", $internalize(data4.Object.styleObject, $String));
console.log("FontSize:", $internalize(data4.Object.styleObject, $String));
console.log("data4.StyleObject.Color:", $internalize($internalize(data4.Object.styleObject, ptrType$3).Object.color, $String));
console.log("data4.StyleObject.FontSize:", $internalize($internalize(data4.Object.styleObject, ptrType$3).Object.fontSize, $String)); |
As near as I can tell, this is still broken. If you embed a struct type, and DO NOT give it a type T1 struct {
*js.Object
F1 string `js:"f1"`
}
s := &struct {
*js.Object
*T1 // <- no js tag here
}{Object: hvue.NewObject()} then you can reference But only in Go. If you need to reference |
In the below I'd expect
s.F1 = "foo"
to compile tos.Object.t1.Object.f1 = "foo"
, but instead it seems to compile tos.Object.t1 = "foo"
. In the marked assignment ("error here"), running in Node I get "TypeError: Cannot create property 'f1' on string 'foo'"; in Chrome with similar code I get a similar error. (The playground behaves differently -- it doesn't error, but it doesn't get it right, either).This code compiles as
Am I doing something wrong and/or unsupported?
The text was updated successfully, but these errors were encountered: