\enabletrackers[system.callbacks]

\def\tasktype{processors}
\startluacode
  thirddata = thirddata or { foo = { } } --- namespace
  local ncalls, nnodes = 0, 0
  --- main callback; third arg is head
  local do_cbk = function (_, _, head)
    ncalls = ncalls + 1
    print("···············[" .. ncalls .. "]···············")
    for n in node.traverse(head) do
      nnodes = nnodes + 1
      local nid = n.id
      print(n, (nid == node.id"glyph" and unicode.utf8.char(n.char) or false))
    end
    return head
  end
  --- context wrapper
  thirddata.foo.cbk = nodes.installattributehandler{
    namespace = thirddata.foo,
    processor = do_cbk,
  }
  --- registration
  nodes.tasks.appendaction ("\tasktype","before","thirddata.foo.cbk")
  nodes.tasks.disableaction("\tasktype",         "thirddata.foo.cbk")
  --- display counters
  thirddata.foo.dumpstats = function (head)
    print(string.rep("·", 71))
    print(string.format("callback invoked %d times, %d nodes inspected", ncalls, nnodes))
    print(string.rep("·", 71))
  end
\stopluacode

%% wrapper macros
\def\startfoo{\par\ctxlua{nodes.tasks. enableaction("\tasktype","thirddata.foo.cbk")}}
\def \stopfoo{\par\ctxlua{nodes.tasks.disableaction("\tasktype","thirddata.foo.cbk")}}

%% invoke counter on exit
\appendtoks \ctxlua{thirddata.foo.dumpstats()} \to \everystoptext

\starttext
  \startfoo
    foo \vbox{\hbox{bar}} baz
  \stopfoo
\stoptext \endinput

