Namespaces:
  sys: io.murano.system
  std: io.murano

Name: TestGCNode
Extends: Node

Properties:
  runtimeProperty:
    Usage: Runtime
    Contract: $

Methods:
  .init:
    Body:
      - $this.runtimeProperty: new(Node)
  foo:
    Body:
      - trace(foo)

  destructionHandler:
    Arguments:
      - obj:
          Contract: $.class(TestGCNode).notNull()
    Body:
      - trace('Destruction of {0}'.format($obj.value))

  .destroy:
    Body:
      - trace($.value)


---

Name: TestGCNode2
Extends: TestGCNode

Methods:
  .destroy:
    Body:
      - trace(list($.nodes.select(sys:GC.isDoomed($))))
      - $owner: $.find(std:Object)
      - trace(sys:GC.isDoomed($owner))

---

Name: TestGCNode3
Extends: TestGCNode

Methods:
  .init:
    Body:
      - $this.undeclaredProp: new(TestGCNode, value => C)

---

Name: TestGC

Properties:
  outNode:
    Usage: Out
    Contract: $.class(TestGCNode)

  staticPropertyNode:
    Usage: Static
    Contract: $.class(TestGCNode)

Methods:
  testObjectsCollect:
    Body:
      - $model:
          :TestGCNode:
            value: A
            nodes:
              - :TestGCNode:
                  value: B
      - new($model)
      - $localAssignedVariable: new($model)
      - sys:GC.collect()

  testObjectsCollectWithSubscription:
    Body:
      - $model:
          :TestGCNode:
            value: A
            nodes:
              :TestGCNode:
                value: B
      - $x: new($model)
      - sys:GC.subscribeDestruction($x, $this, _handler)
      - sys:GC.subscribeDestruction($x.nodes[0], $this, _handler)
      - sys:GC.subscribeDestruction($x.nodes[0], $x, destructionHandler)
      - $x: null
      - sys:GC.collect()

  _handler:
    Arguments:
      - obj:
          Contract: $.class(TestGCNode).notNull()
    Body:
      - trace('Destroy ' + $obj.value)

  testCallOnDestroyedObject:
    Body:
      - $val: new(TestGCNode, value => X)
      - sys:GC.subscribeDestruction($val, $this, _handler2)
      - $val: null
      - sys:GC.collect()
      - $this.destroyed.foo()

  _handler2:
    Arguments:
      - obj:
          Contract: $.class(TestGCNode).notNull()
    Body:
      - $obj.foo()
      - $this.destroyed: $obj

  testIsDoomed:
    Body:
      - $model:
          :TestGCNode2:
            value: A
            nodes:
              - :TestGCNode2:
                  value: B
      - new($model, $this)
      - sys:GC.collect()

  testIsDestroyed:
    Body:
      - $val: new(Node, value => X)
      - sys:GC.subscribeDestruction($val, $this, _handler3)
      - $val: null
      - sys:GC.collect()
      - trace(sys:GC.isDestroyed($this.destroyed))

  _handler3:
    Arguments:
      - obj:
          Contract: $.class(Node).notNull()
    Body:
      - trace(sys:GC.isDestroyed($obj))
      - $this.destroyed: $obj

  testDestructionDependencySerialization:
    Body:
      - $model:
          :TestGCNode:
            value: A
            nodes:
              :TestGCNode:
                value: B
      - $.outNode: new($model)
      - sys:GC.subscribeDestruction($.outNode, $this, _handler)
      - sys:GC.subscribeDestruction($.outNode.nodes[0], $this, _handler)

  testStaticProperties:
    Body:
      - :TestGC.staticPropertyNode: new(TestGCNode, value => A)
      - sys:GC.collect()

  methodWithArgs:
    Arguments:
      - obj:
          Contract: $.class(TestGCNode).notNull()
    Body:
      - sys:GC.collect()

  testDestroyArgs:
    Body:
      - $.methodWithArgs(new(TestGCNode, value => A))

  testReachableRuntimeProperties:
    Body:
      - $node: new(TestGCNode3, value => A)
      - sys:GC.collect()
      - trace(sys:GC.isDestroyed($node.runtimeProperty))


