Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Assignment of externalized array doesn't work #1302

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

Open
grantnelson-wf opened this issue Apr 30, 2024 · 2 comments
Open

Assignment of externalized array doesn't work #1302

grantnelson-wf opened this issue Apr 30, 2024 · 2 comments

Comments

@grantnelson-wf
Copy link
Collaborator

Problem

In the following code, the assignment of b.V doesn't work:

type Bar struct {
	*js.Object
	V [3]int `js:"V"`
}

func main() {
	b := Bar{Object: js.Global.Get("Object").New()}
	b.V = [3]int{4, 5, 6}
	fmt.Printf("%v\n", b.V)
}

This is because the code translates into:

arrayType.copy($internalize(b.Object.V, arrayType), $toNativeArray($kindInt, [4, 5, 6]));

The $internalize creates a new array that is written to, but that new array is never set back to b.Object.V meaning b.V is not updated.

This isn't a problem with slices because the value is assigned to the externalized value instead. The following is the same example code above expect with [3] changed to [] in both locations then translated into JS:

b.Object.V = $externalize(new sliceType([4, 5, 6, 7]), sliceType);

Possible Fixes

The compiler code, at statements.go:737, generating this code could do one of the following:

  1. Pass in a flag to translateExpr to indicate that the result is the left hand side of an assignment. In this case the expression must reference the actual data being assigned or create a proxy to perform the conversion when a value is set (if such a thing is possible in JS). If the flag simply prevents internalization, then the copy method would have to be updated to also handle assigning to an externalized array.

  2. The returned *expression needs to indicate the result is internalized. This is similar to how the expression can have "paren" or not and has StringWithParens() string. The idea would be that it indicates that the normal String() would internalize the value and we'd add a StringWithoutInternalize() that either returns the expression without the internalization or the same thing as String() if there is no internalization. This would allow us to use the internalize flag on *expression to know we need to create a variable for the internalized instance, then we perform the array copy, then we add the code to assign the "un-internalized" value to the externalization of the newly updated internalized instance.

These two ideas aren't the only solution, they were just the two that came to my head first. We should look into what causes the slice not to use the copy in the assignment and try to get a whole picture of how externalized arrays work before coming up with a fix.

@grantnelson-wf
Copy link
Collaborator Author

Another issue that is very similar and might be fixed as part of this issue is the initialization of V in the following:

type Bar struct {
	*js.Object
	V [3]int `js:"V"`
}

func main() {
	b := Bar{
		Object: js.Global.Get("Object").New()
		V:      [3]int{4, 5, 6},
	}
	fmt.Printf("%v\n", b.V)
}

The creation of b translates to:

b = new Bar.ptr(new ($global.Object)(), $clone($toNativeArray($kindInt, [4, 5, 6]), arrayType));

That $clone is directly above the statement.go code which does the $copy. For some reason this doesn't function either but it seems like it should be externalizing the initial value set to V. Whatever is happening, when internalizing b.V for the print it outputs [0 0 0] instead of the expected [4 5 6].

I haven't dug into this problem too far so this may be unrelated or require changes somewhere else in code. If that's the case, please move this part to it's own issue to track this as a separate issue.

@nevkontakte
Copy link
Member

The second problem is a case of #236, I think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants