Skip to content

Commit

Permalink
give promises a reftracker prefix so we can exclude it. Don't track p…
Browse files Browse the repository at this point in the history
…romises and reftracker nodes.
  • Loading branch information
TwitchBronBron committed Oct 17, 2024
1 parent 024d0e9 commit f3d450d
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 32 deletions.
38 changes: 32 additions & 6 deletions lib/components/Reftracker.bs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import "pkg:/source/reftrackerLib.bs"
import "pkg:/source/roku_modules/promises/promises.brs"
import "pkg:/source/roku_modules/reftracker_promises/promises.brs"

' typecast m as ReftrackerM
interface ReftrackerM
Expand All @@ -25,26 +25,52 @@ function init()
m.top.runId = reftracker.internal.getRandomUUID()
end function

'@public
function discover(_ = invalid)
'seed the list of nodes with all roots (should be a good starting point)
for each root in m.top.getRoots() as roSGnode[]
registerNodeRef(`<${root.subtype()}>`, "", root)
end for

'process the nodes one-by-one
return promises.onThen(processNodes(), function(result)
return reftracker.promises.onThen(processNodes(), function(result)
printNodes()
end function)
end function

interface GetNodesByIdOptions
id as string
end interface

'@public
function getNodesById(options as GetNodesByIdOptions)
id = options.id
results = []
' for each node in m.allNodes
' if node.id <> id
' continue for
' end if
' reftrackerId = reftracker.internal.getReftrackerId(node)
' 'build a list of keypaths for this node
' results.push({
' id: id,
' node: node,
' keypaths: m.keypathsByNodeReftrackerId[reftrackerId],
' })
' end for
return results
end function

function printNodes()
print m.nodesByKeypath
end function

'Register a reference to a node so we can process it later. This
function registerNodeRef(parentKeypath as string, key as string, node as roSGNode) as void
'skip this node if it's a reftracker property
if reftracker.internal.isReftrackerProperty(key)
subtype = node.subtype()

'skip this node if it's a reftracker property, or one of the internal reftracker nodes (promise, reftracker itself)
if reftracker.internal.isReftrackerProperty(key) or subtype = "reftracker_promises_Promise" or subtype = "Reftracker"
return
end if
reftrackerId = reftracker.internal.getReftrackerId(node)
Expand Down Expand Up @@ -75,15 +101,15 @@ function processNodes()
'if we have no more nodes, we are done!
if m.nodeQueue.count() = 0
reftracker.internal.writeLog("All nodes have been processed. Exiting node process loop")
return promises.resolve(invalid)
return reftracker.promises.resolve(invalid)
end if

queueItem = m.nodeQueue.pop() as NodeQueueItem

reftracker.internal.writeLog("processing node", queueItem.keypath, queueItem.node.subtype())

'if this node supports reftracker functionality, process the node's internal `m`
return promises.chain(promises.resolve(true), queueItem).then(function(result, queueItem as NodeQueueItem)
return reftracker.promises.chain(reftracker.promises.resolve(true), queueItem).then(function(result, queueItem as NodeQueueItem)
reftracker.internal.writeLog("processing node's internal m properties", queueItem.keypath, queueItem.node.subtype())
promise = queueItem.node@.reftracker_internal_execute({
command: "discover",
Expand Down
39 changes: 23 additions & 16 deletions lib/source/reftrackerLib.bs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import "pkg:/source/roku_modules/promises/promises.brs"
import "pkg:/source/roku_modules/reftracker_promises/promises.brs"

const MAX_WORK_QUEUE_DURATION = 5000000000000
' typecast m as mm
Expand All @@ -13,14 +13,21 @@ end interface

namespace reftracker

' Find all references to a SceneGraph node by its ID
function findNodeById(id as string)
' Find all references to a SceneGraph node by its ID. Since multiple nodes can have the same ID, this function returns an array of results,
' where each entry includes all results for a specific node having that ID
function findNodeRefsById(id as string)
'build the reftracker
tracker = createObject("roSGNode", "Reftracker")
'store a reference to it so it doesn't get lost
reftracker.internal.registerReftracker(tracker)

'run it
return tracker@.discover()
discoverPromise = tracker@.discover()

return reftracker.promises.onThen(discoverPromise, function(result, tracker)
'return all nodes with the given id
return tracker@.findNodeRefsById(id)
end function, tracker)
end function
end namespace

Expand All @@ -34,7 +41,7 @@ namespace reftracker.internal
registerWorkItem(options.keypath, "m", m)
return processWorkItems(options)
else
return promises.reject({
return reftracker.promises.reject({
message: "Unknown command"
})
end if
Expand Down Expand Up @@ -66,7 +73,7 @@ namespace reftracker.internal
end if
end function

function processWorkItems(options as reftracker.internal.ProcessOptions) as roSGNodepromises_Promise
function processWorkItems(options as reftracker.internal.ProcessOptions) as roSGNodereftracker_promises_Promise
startTime = createObject("roTimeSpan")

workQueue = getWorkQueue()
Expand Down Expand Up @@ -127,11 +134,11 @@ namespace reftracker.internal
if workQueue[0] = invalid
writeLog("work queue is complete", options.keypath)
'TODO clean up
return promises.resolve(true)
return reftracker.promises.resolve(true)
end if

'small delay, then process work again
return promises.chain(reftracker.internal.delay(.01), options).then(function(result, options)
return reftracker.promises.chain(reftracker.internal.delay(.01), options).then(function(result, options)
'process work items again
return processWorkItems(options)
end function).toPromise()
Expand Down Expand Up @@ -203,13 +210,13 @@ namespace reftracker.internal
end function

' Get a promise that resolves after a given duration
sub delay(duration = 0.0001 as float) as roSGNodepromises_Promise
sub delay(duration = 0.0001 as float) as roSGNodereftracker_promises_Promise
timer = createObject("roSGNode", "Timer")
timer.duration = duration
timer.repeat = false
timer.id = "___reftracker_delay_" + getRandomUUID()

promise = promises.create()
promise = reftracker.promises.create()

m[timer.id] = {
timer: timer
Expand All @@ -220,7 +227,7 @@ namespace reftracker.internal
delayId = event.getNode()
options = m[delayId]
promise = options.promise
promises.resolve(promise, invalid)
reftracker.promises.resolve(promise, invalid)
m[delayId].timer.unobserveFieldScoped("fire")
m.delete(delayId)
end sub).toStr().mid(10))
Expand Down Expand Up @@ -256,7 +263,7 @@ namespace reftracker.internal

'All reftracker properties are prefixed with ___reftracker_ , so this method can be used to filter them out
function isReftrackerProperty(key as dynamic)
return isString(key) and key.left(14) = "___reftracker_"
return (isString(key) and key.left(14) = "___reftracker_")
end function

function writeLog(message as string, keypath = "" as string, typeInfo = "" as string)
Expand Down Expand Up @@ -292,10 +299,10 @@ namespace reftracker.internal
end function

function isNonEmptyAA(value as dynamic) as boolean
return type(value) = "roAssociativeArray" and not value.isEmpty()
end function
return type(value) = "roAssociativeArray" and not value.isEmpty()
end function

function isArray(value as dynamic) as boolean
return type(value) = "roArray"
end function
return type(value) = "roArray"
end function
end namespace
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,6 @@
"dependencies": {
"fast-glob": "^3.3.2",
"fs-extra": "^11.2.0",
"promises": "npm:@rokucommunity/[email protected]"
"reftracker_promises": "npm:@rokucommunity/[email protected]"
}
}
4 changes: 2 additions & 2 deletions test-app/components/MainScene.bs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ sub init()
m.mainLabel
]

promises.chain(reftracker.findNodeById("bob")).then(function(result, node)
print "found node"
reftracker.promises.chain(reftracker.findNodeRefsById("mainLabel")).then(function(result, node)
print result
end function)
end sub

0 comments on commit f3d450d

Please sign in to comment.