Permalink
Browse files

Do not reuse JS-owned wrapper values.

JavaScript-owned wrapper values cannot be reused because the
QML runtime may choose to destroy the value right after it
is handed a new reference to the same value.

Fixes #68.
  • Loading branch information...
1 parent ab659ec commit 364da65db2c6a8b3d74c6e060d95f5bd9e4858a0 @niemeyer niemeyer committed Sep 10, 2014
Showing with 24 additions and 5 deletions.
  1. +9 −5 bridge.go
  2. +15 −0 qml_test.go
View
@@ -230,8 +230,11 @@ func wrapGoValue(engine *Engine, gvalue interface{}, owner valueOwner) (cvalue u
painting := cdata.Ref() == atomic.LoadUintptr(&guiPaintRef)
+ // Cannot reuse a jsOwner because the QML runtime may choose to destroy
+ // the value _after_ we hand it a new reference to the same value.
+ // See issue #68 for details.
prev, ok := engine.values[gvalue]
- if ok && (prev.owner == owner || owner != cppOwner || painting) {
+ if ok && (prev.owner == cppOwner || painting) {
return prev.cvalue
}
@@ -250,11 +253,12 @@ func wrapGoValue(engine *Engine, gvalue interface{}, owner valueOwner) (cvalue u
}
fold.cvalue = C.newGoValue(unsafe.Pointer(fold), typeInfo(gvalue), parent)
if prev != nil {
- prev.next = fold
- fold.prev = prev
- } else {
- engine.values[gvalue] = fold
+ // Put new fold first so the single cppOwner, if any, is always the first entry.
+ fold.next = prev
+ prev.prev = fold
}
+ engine.values[gvalue] = fold
+
//fmt.Printf("[DEBUG] value alive (wrapped): cvalue=%x gvalue=%x/%#v\n", fold.cvalue, addrOf(fold.gvalue), fold.gvalue)
stats.valuesAlive(+1)
C.engineSetContextForObject(engine.addr, fold.cvalue)
View
@@ -1213,6 +1213,21 @@ var tests = []struct {
},
DoneLog: "Signal has run.",
},
+ {
+ Summary: "References handed out must not be GCd (issue #68)",
+ Init: func(c *TestData) {
+ type B struct{ S string }
+ type A struct{ B *B }
+ c.context.SetVar("a", &A{&B{}})
+ },
+ QML: `Item { function f() { var x = [[],[],[]]; gc(); if (!a.b) console.log("BUG"); } }`,
+ Done: func(c *TestData) {
+ for i := 0; i < 100; i++ {
+ c.root.Call("f")
+ }
+ },
+ DoneLog: "!BUG",
+ },
}
var tablef = flag.String("tablef", "", "if provided, TestTable only runs tests with a summary matching the regexp")

0 comments on commit 364da65

Please sign in to comment.