Skip to content
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

fix(builtin): handle string pointer in fromJSON #751

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

thevilledev
Copy link
Contributor

@thevilledev thevilledev commented Jan 25, 2025

Support *string input in the fromJSON builtin function by runtime type handling. Type switch how to handle each case.

Added tests covering both direct string and pointer-to-string use cases, including toJSON function.

Fixes #739

Support *string input in fromJSON builtin function by
dereferencing pointer before JSON unmarshaling.

Added tests covering both direct string and pointer string
use cases, including toJSON, which already supports this.

Signed-off-by: Ville Vesilehto <[email protected]>
@@ -443,7 +443,11 @@ var Builtins = []*Function{
Name: "fromJSON",
Func: func(args ...any) (any, error) {
var v any
err := json.Unmarshal([]byte(args[0].(string)), &v)
jsonStr := args[0]
if strPtr, ok := jsonStr.(*string); ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Althoug this is a working solution, we need to understand why OpDeref was not added before calling fromJSON.

Compiler adds OpDeref for arguments before calling a function. But only if needed. Aperently the check is not perfect.

@antonmedv
Copy link
Member

We can merge this PR, and it will fix problem with *string and fromJSON. But we still can encounter those errors.

@thevilledev
Copy link
Contributor Author

I did a quick glance over the compiler earlier but maybe I missed something. Agree that this would ideally be fixed for other use cases as well than just JSON. I can take a look and keep this as a draft PR until then.

This commit enables fromJSON to accept both string and *string arguments by
performing a runtime check on the provided argument. It also refactors the
deref.Type function to preserve interface types, ensuring methods sets are
not lost when unwrapping pointers.

Changes:
- fromJSON now handles `string` and `*string` distinctly, returning an error
  if the pointer is nil or if an unsupported type is given.
- deref.Type preserves the Kind() == reflect.Interface immediately instead
  of unwrapping further, which prevents losing interface method sets.
- Updated unit tests to confirm that interface-wrapped pointers are unwrapped
  correctly (e.g., reflect.String) and interface types remain interfaces.

Signed-off-by: Ville Vesilehto <[email protected]>
@thevilledev thevilledev changed the title fix: handle string pointer in fromJSON builtin fix(builtin,deref): handle string pointer in fromJSON and preserve interfaces Jan 27, 2025
@thevilledev
Copy link
Contributor Author

thevilledev commented Jan 27, 2025

I think I found a way to do this at compile-time, with just a little type hinting at runtime in fromJSON builtin. Could be extended to other functions too. Let me know what you think :)

EDIT: simplified it even further, I don't think we need Deref changes after all

@thevilledev thevilledev marked this pull request as ready for review January 27, 2025 19:08
@thevilledev thevilledev changed the title fix(builtin,deref): handle string pointer in fromJSON and preserve interfaces fix(builtin): handle string pointer in fromJSON Jan 27, 2025
@thevilledev
Copy link
Contributor Author

Well shoot. Looks like my assumption was wrong. Back to the drawing board 😅

@thevilledev thevilledev marked this pull request as draft January 27, 2025 21:02
@thevilledev
Copy link
Contributor Author

Used this scenario when debugging:

  • &jsonString is stored in the env map map[string]any as interface{}
  • When fromJSON(json) is called, the value is mapped to interface{}, not as *string
  • No OpDeref is triggered
  • We get args[0] as interface{} in the builtin func
  • Only runtime fixes available, as visible in this PR

So the compiler can't see through the interface{} to know deref is required. During type checking/compilation, we could look up the actual value, use reflection for the real type and insert OpDeref

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

Successfully merging this pull request may close these issues.

Can we make the fromJSON function support string pointer?
2 participants