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

v8.Value becomes manually releaseable #361

Merged
merged 7 commits into from Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions context.go
Expand Up @@ -81,6 +81,12 @@ func (c *Context) Isolate() *Isolate {
return c.iso
}

func (c *Context) RetainedValueCount() int {
ctxMutex.Lock()
defer ctxMutex.Unlock()
return int(C.ContextRetainedValueCount(c.ptr))
}

// RunScript executes the source JavaScript; origin (a.k.a. filename) provides a
// reference for the script and used in the stack trace if there is an error.
// error will be of type `JSError` if not nil.
Expand Down
4 changes: 2 additions & 2 deletions context_test.go
Expand Up @@ -104,8 +104,8 @@ func TestMemoryLeak(t *testing.T) {

for i := 0; i < 6000; i++ {
ctx := v8.NewContext(iso)
obj := ctx.Global()
_ = obj.String()
_ = ctx.Global()
// _ = obj.String()
_, _ = ctx.RunScript("2", "")
ctx.Close()
}
Expand Down
7 changes: 7 additions & 0 deletions function_template.go
Expand Up @@ -37,6 +37,13 @@ func (i *FunctionCallbackInfo) Args() []*Value {
return i.args
}

func (i *FunctionCallbackInfo) Release() {
for _, arg := range i.args {
arg.Release()
}
i.this.Release()
}

// FunctionTemplate is used to create functions at runtime.
// There can only be one function created from a FunctionTemplate in a context.
// The lifetime of the created function is equal to the lifetime of the context.
Expand Down
39 changes: 39 additions & 0 deletions function_template_test.go
Expand Up @@ -48,6 +48,45 @@ func TestFunctionTemplate_panic_on_nil_callback(t *testing.T) {
defer iso.Dispose()
v8.NewFunctionTemplate(iso, nil)
}
func TestFunctionTemplate_generates_values(t *testing.T) {
t.Parallel()

iso := v8.NewIsolate()
defer iso.Dispose()
global := v8.NewObjectTemplate(iso)
printfn := v8.NewFunctionTemplate(iso, func(info *v8.FunctionCallbackInfo) *v8.Value {
fmt.Printf("%+v\n", info.Args())

Choose a reason for hiding this comment

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

Just to keep the test output clean, please consider removing any unneeded print statements here. I know the test is trying to show a print implementation but we should probably check the value here, not print it out. Same thing below.

return nil
})
global.Set("print", printfn, v8.ReadOnly)
ctx := v8.NewContext(iso, global)
defer ctx.Close()
ctx.RunScript("print('foo', 'bar', 0, 1)", "")
if ctx.RetainedValueCount() != 6 {
t.Errorf("expected 6 retained values, got: %d", ctx.RetainedValueCount())
}
}

func TestFunctionTemplate_releases_values(t *testing.T) {
t.Parallel()

iso := v8.NewIsolate()
defer iso.Dispose()
global := v8.NewObjectTemplate(iso)
printfn := v8.NewFunctionTemplate(iso, func(info *v8.FunctionCallbackInfo) *v8.Value {
defer info.Release()
fmt.Printf("%+v\n", info.Args())
return nil
})
global.Set("print", printfn, v8.ReadOnly)
ctx := v8.NewContext(iso, global)
defer ctx.Close()
ctx.RunScript("print('foo', 'bar', 0, 1)", "")
// there is a constant factor associated with the global.
if ctx.RetainedValueCount() != 1 {
t.Errorf("expected 1 retained values, got: %d", ctx.RetainedValueCount())
}
}

func TestFunctionTemplateGetFunction(t *testing.T) {
t.Parallel()
Expand Down