<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Michael,<div class=""><br class=""></div><div class="">Very clear, and very helpful. Only thing I would suggest would be to have a minimum example in the documentation. The bare minimum required for an implementation of an object.</div><div class=""><br class=""></div><div class="">Reading through what you write, it seems the correct approach is:</div><div class=""><br class=""></div><div class=""><ul class="MailOutline"><li class="">Extend OvmsCommand to have a virtual ExecuteCommand method (same parameters as ‘m_execute’ callback).</li><li class="">Extend OvmsCommand::execute to check if m_execute is null, then call ‘ExecuteCommand’ instead.</li><li class="">Perhaps do the same for m_validate in OvmsCommand.</li><li class="">Then, the duktape implementation can be object (rather than callback function) based, as your DuktapeObject expects. The javascript would call a function to register a command, with a command object to be used for the callback.</li><li class="">Need to extend the DuktapeObject system to support a synchronous command (presumably implemented with a passed mutex like we do in several other parts of the system).</li></ul></div><div class=""><br class=""></div><div class="">Is that correct, and what you were expecting? Or any other suggestions?</div><div class=""><br class=""></div><div class="">Regards, Mark.</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 7 Sep 2020, at 2:55 AM, Michael Balzer <<a href="mailto:dexter@expeedo.de" class="">dexter@expeedo.de</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
  
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" class="">
  
  <div class="">
    Mark,<br class="">
    <br class="">
    <blockquote type="cite" class="">
      <div class="">Still struggling with this. It seems like your
        DuktapeObject will do this, but I can’t work out how it works.</div>
    </blockquote>
    <br class="">
    I admit my documentation has some shortcomings. I'll try to fill
    that gap first:<br class="">
    <br class="">
    <br class="">
    <b class=""><u class="">Concept #1: Reference counting</u></b><br class="">
    <br class="">
    A DuktapeObject is meant to be a C++/OS extension of a Javascript
    object, for example to hold some system binding associated with the
    JS object.<br class="">
    <br class="">
    The primary goal is to provide asynchronous operations on the system
    side, initiating JS callbacks when finishing/failing. For example a
    HTTP operation can be started by a script, passing some "done"
    callback. The system then starts the network operation
    asynchronously, the JS task can continue processing other scripts.
    Once the network operation is done, the DuktapeObject sends a
    request to the Duktape task to execute the "done" callback on
    itself.<br class="">
    <br class="">
    So the DuktapeObject is normally shared by multiple contexts and
    parallel operations. Asynchronous operation also means the JS object
    or context may already be gone when the operation finishes. So the
    DuktapeObject needs to stay locked in memory independent of the JS
    context.<br class="">
    <br class="">
    That's implemented by counting the active references to the
    DuktapeObject (methods Ref() / Unref()). The last Unref()
    automatically deletes the DuktapeObject instance.<br class="">
    <br class="">
    For example: JS requests a network operation. The initial JS binding
    (see coupling) sets the reference count to 1. The DuktapeObject
    starts the network request, increasing the ref count to 2. If the JS
    context now dies (decreasing the reference count), the DuktapeObject
    will still remain valid until the network operation returns.<br class="">
    <br class="">
    As the Ref/Unref operations need a (recursive) mutex, that's also
    part of the DuktapeObject and exposed by the API for other uses:
    Lock() / Unlock().<br class="">
    <br class="">
    <br class="">
    <b class=""><u class="">Concept #2: Coupling</u></b><br class="">
    <br class="">
    Javascript does not have a destructor concept. JS objects get
    deleted by heap destruction or by the garbage collector when no
    reference to the JS object is left. In both cases, the actual object
    deletion is called "finalization", and a special finalizer
    method/callback can be installed on a JS object to be called just
    before the object gets deallocated. That is done by the
    DuktapeObject::Couple() method (implicitly called when constructed
    directly with a JS object reference).<br class="">
    <br class="">
    There is no way to force finalization on a JS object. So a
    DuktapeObject cannot tell Duktape to delete it's coupled object,
    that means a DuktapeObject should normally not be deleted from
    outside the Duktape context, at least not if still coupled to the JS
    object. Coupling and decoupling can only be done in the Duktape
    context.<br class="">
    <br class="">
    The standard finalizer DuktapeObject::Finalizer() simply decouples,
    automatically deleting itself if the coupling was the last
    reference. This is a virtual method, so can be overridden as
    necessary.<br class="">
    <br class="">
    The coupling operation additionally adds a hidden pointer to the
    DuktapeObject instance in the JS object. That allows to check for
    and retreive associated DuktapeObject instances from any JS object,
    which is provided by the GetInstance() call.<br class="">
    <br class="">
    <br class="">
    <b class=""><u class="">Concept #3: Registration</u></b><br class="">
    <br class="">
    For asynchronous operations, it's normally very convenient to have a
    "fire & forget" API. Example from the documentation:<br class="">
    <pre id="codecell13" style="box-sizing: border-box; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", Courier, monospace; font-size: 12px; white-space: pre; margin: 0px; padding: 12px; display: block; overflow: auto; line-height: 1.4; color: rgb(64, 64, 64); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" class=""><span class="nx" style="box-sizing: border-box;">VFS</span><span class="p" style="box-sizing: border-box;">.</span><span class="nx" style="box-sizing: border-box;">Save</span><span class="p" style="box-sizing: border-box;">({</span>
  <span class="nx" style="box-sizing: border-box;">path</span><span class="o" style="box-sizing: border-box; color: rgb(102, 102, 102);">:</span> <span class="s2" style="box-sizing: border-box; color: rgb(186, 33, 33);">"/sd/mydata/telemetry.json"</span><span class="p" style="box-sizing: border-box;">,</span>
  <span class="nx" style="box-sizing: border-box;">data</span><span class="o" style="box-sizing: border-box; color: rgb(102, 102, 102);">:</span> <span class="nx" style="box-sizing: border-box;">Duktape</span><span class="p" style="box-sizing: border-box;">.</span><span class="nx" style="box-sizing: border-box;">enc</span><span class="p" style="box-sizing: border-box;">(</span><span class="s1" style="box-sizing: border-box; color: rgb(186, 33, 33);">'jx'</span><span class="p" style="box-sizing: border-box;">,</span> <span class="nx" style="box-sizing: border-box;">telemetry</span><span class="p" style="box-sizing: border-box;">),</span>
  <span class="nx" style="box-sizing: border-box;">fail</span><span class="o" style="box-sizing: border-box; color: rgb(102, 102, 102);">:</span> <span class="kd" style="box-sizing: border-box; color: rgb(0, 128, 0); font-weight: bold;">function</span><span class="p" style="box-sizing: border-box;">(</span><span class="nx" style="box-sizing: border-box;">error</span><span class="p" style="box-sizing: border-box;">)</span> <span class="p" style="box-sizing: border-box;">{</span>
    <span class="nx" style="box-sizing: border-box;">print</span><span class="p" style="box-sizing: border-box;">(</span><span class="s2" style="box-sizing: border-box; color: rgb(186, 33, 33);">"Error saving telemetry: "</span> <span class="o" style="box-sizing: border-box; color: rgb(102, 102, 102);">+</span> <span class="nx" style="box-sizing: border-box;">error</span><span class="p" style="box-sizing: border-box;">);</span>
  <span class="p" style="box-sizing: border-box;">}</span>
<span class="p" style="box-sizing: border-box;">});</span>
</pre>
    I.e. you simply pass the operation arguments including the done/fail
    callbacks to an API method and don't need to care about storing a
    reference to some handle. In JS that normally means the object used
    won't have any reference left after the call, so would be deleted by
    the garbage collector on the next run.<br class="">
    <br class="">
    To avoid garbage collection and lock the JS object in memory, we
    need to store a reference to it in a "public" place. Duktape
    provides a special public place for this, hidden from scripts,
    called the global stash. DuktapeObject maintains a dedicated global
    object registry in that stash.<br class="">
    <br class="">
    Adding and removing the coupled object reference to/from that
    registry is done by the Register() and Deregister() methods.<br class="">
    <br class="">
    So for asynchronous system operations, or system integrations that
    shall be persistent, you normally do a Register() call together with
    the coupling, unless some ressource isn't available. Deregistration
    is then normally done when all pending JS callbacks have been
    executed, or when the persistent system integration has been
    unbound.<br class="">
    <br class="">
    Other API designs are possible here: if you'd rather like the script
    needing to store a reference to your operation handle, you don't
    need to do a registration. The object will then be deleted
    (finalized) by the garbage collector automatically after the script
    deletes the reference.<br class="">
    <br class="">
    <br class="">
    <b class=""><u class="">Concept #4: Callback invocation</u></b><br class="">
    <br class="">
    Triggers on the system side, for example a finished or failed
    network operation, shall normally trigger a JS method execution.<br class="">
    <br class="">
    JS callback methods are simply passed as part of the arguments
    object in modern JS APIs. This allows to pass simple function
    definitions inline, as well as to reference a separately defined
    general handler function. JS allows functions to be excuted in the
    context of any object, and callbacks normally are executed in the
    context of the API object. This adds even more convenience, as the
    callbacks can easily access the other API arguments still stored in
    the object, as well as additional data added by the call.<br class="">
    <br class="">
    JS callbacks cannot be executed directly from any system context,
    they need to run in the Duktape context. So the DuktapeObject
    callback invocation mechanism includes a general method to request a
    callback execution by Duktape: RequestCallback()<br class="">
    <br class="">
    Note: RequestCallback() is an asynchronous operation. A synchronous
    variant can be added if necessary (and probably will be for command
    execution from a console).<br class="">
    <br class="">
    A pending callback automatically increments the reference count, so
    the object is locked in memory until the callback has been executed
    (or aborted) by the Duktape task.<br class="">
    <br class="">
    The callback invocation API provides a void* for simple data (e.g. a
    fixed string) to be passed to the callback method, but for more
    complex data, you will normally fill some DuktapeObject member
    variables before invoking the callback.<br class="">
    <br class="">
    In Duktape context, the callback invocation translates the data
    returned or provided by the system side into the Duktape callback
    arguments and then runs the callback (if the object actually has the
    requested callback set). The default implementation for this is
    DuktapeObject::CallMethod(), which can be used directly for simple
    callbacks without arguments. For more complex handling, override
    this with your custom implementation.<br class="">
    <br class="">
    The callbacks are by default executed on the coupled JS object, so
    data can also be transported by setting properties on that object.
    The callback can then simply access them via "this".<br class="">
    <br class="">
    To simplify callback invocation from code parts that may run outside
    or inside Duktape, it's convenient to allow calling CallMethod()
    without a Duktape context, and let CallMethod() translate that into
    a RequestCallback() call as necessary. Pattern:<br class="">
    <br class="">
    <tt class="">duk_ret_t DuktapeHTTPRequest::CallMethod(duk_context *ctx, const
      char* method, void* data /*=NULL*/)</tt><tt class=""><br class="">
    </tt><tt class="">  {</tt><tt class=""><br class="">
    </tt><tt class="">  if (!ctx)</tt><tt class=""><br class="">
    </tt><tt class="">    {</tt><tt class=""><br class="">
    </tt><tt class="">    RequestCallback(method, data);</tt><tt class=""><br class="">
    </tt><tt class="">    return 0;</tt><tt class=""><br class="">
    </tt><tt class="">    }</tt><tt class=""><br class="">
        …<br class="">
    </tt><br class="">
    A CallMethod() implementation isn't limited to executing a single
    callback. A common example is an API defining "done" & "fail"
    callbacks, as well as a general final "always" callback. <tt class="">DuktapeHTTPRequest::CallMethod()</tt>
    also serves as an example implementation for this.<br class="">
    <br class="">
    <br class="">
    <br class="">
    Wow… that's become more to write & read than I expected. Please
    provide some feedback: is that explanation sufficient & clear?
    I'll refine it for the developer docs then.<br class="">
    <br class="">
    Regards,<br class="">
    Michael<br class="">
    <br class="">
    <br class="">
    <div class="moz-cite-prefix">Am 01.09.20 um 19:52 schrieb Michael
      Balzer:<br class="">
    </div>
    <blockquote type="cite" cite="mid:c19950a1-cf6e-928f-9ddd-90c444bb3d15@expeedo.de" class="">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" class="">
      Mark,<br class="">
      <br class="">
      I'll have a look.<br class="">
      <br class="">
      Regards,<br class="">
      Michael<br class="">
      <br class="">
      <br class="">
      <div class="moz-cite-prefix">Am 01.09.20 um 07:30 schrieb Mark
        Webb-Johnson:<br class="">
      </div>
      <blockquote type="cite" cite="mid:9393E6BF-E1C9-495C-88CE-16082D7678A0@webb-johnson.net" class="">
        <meta http-equiv="Content-Type" content="text/html;
          charset=UTF-8" class="">
        Michael,
        <div class=""><br class="">
        </div>
        <div class="">Still struggling with this. It seems like your
          DuktapeObject will do this, but I can’t work out how it works.</div>
        <div class=""><br class="">
        </div>
        <div class="">Here are some notes one what I have done so far:</div>
        <div class=""><br class="">
        </div>
        <div class="">
          <ol class="MailOutline">
            <li class="">Created a stub DuktapeConsoleCommand (derived
              from DuktapeObject) in ovms_duktape.{h,cpp}. This should
              hold enough to be able to call the javascript callback
              method for that object. It also stores the module filename
              (so the registration can be removed when the module is
              unloaded).<br class="">
              <br class="">
            </li>
            <li class="">Provide a DuktapeCommandMap m_cmdmap in
              ovms_duktape.{h,cpp} OvmsDuktape class that stores a
              mapping from OvmsCommand to DuktapeConsoleCommand.<br class="">
              <br class="">
            </li>
            <li class="">Created
              a OvmsDuktape::RegisterDuktapeConsoleCommand in
              ovms_duktape.{h,cpp) that (a) creates the OvmsCommand()
              object, (b) registers it, (c) creates
              the DuktapeConsoleCommand() object, and (d) updates a map
              from OvmsCommand->DuktapeConsoleCommand. There Is also
              a single callback DukOvmsCommandRegisterRun designed to be
              run by all.<br class="">
              <br class="">
            </li>
            <li class="">Created
              hooks NotifyDuktapeModuleLoad, NotifyDuktapeModuleUnload,
              and NotifyDuktapeModuleUnloadAll in OvmsDuktape. The
              javascript module is identified by filename (path to
              module or script on vfs, usually, but may also be an
              internal module). The Unload functions look through the
              m_cmdmap and unregister commands for javascript modules
              being unloaded.<br class="">
              <br class="">
            </li>
            <li class="">Provide an implementation for
              ovms_command DukOvmsCommandRegister to support registering
              commands from Javascript modules. This should extract the
              details, and then call
              OvmsDuktape::RegisterDuktapeConsoleCommand to do the
              actual registration. This has been implemented, except for
              the callback method (and somehow passing that method from
              Javascript in the OvmsCommand.Register javascript call).<br class="">
              <br class="">
            </li>
            <li class="">Provide a stub implementation for <span style="caret-color: rgb(0, 0, 0);" class="">DukOvmsCommandRegisterRun. This uses m_cmdmap
                to lookup the </span><font class="">DuktapeConsoleCommand
                object for the command to be run. It should execute the
                callback method (but that part is not yet implemented).</font></li>
          </ol>
        </div>
        <div class=""><br class="">
        </div>
        <div class=""><br class="">
        </div>
        <div class="">I still need help with #5 and #6. What needs to be
          implemented in DuktapeConsoleCommand, and how is the parameter
          in <span style="caret-color: rgb(0, 0, 0);" class="">OvmsCommand.Register used to store the
            callback (#5)? Then how to callback the command method from</span> <span style="caret-color: rgb(0, 0, 0);" class="">DukOvmsCommandRegisterRun</span><span style="caret-color: rgb(0, 0, 0);" class=""> (#6)? If you have time, it is probably much
            quicker for you to simply make those changes.</span></div>
        <div class=""><span style="caret-color: rgb(0, 0, 0);" class=""><br class="">
          </span></div>
        <div class=""><font class="">An alternative
            implementation would be to do something like the pubsub
            framework, where the mapping command->callback is done
            from within a javascript module. That I could do, but it
            seems your </font><span style="caret-color: rgb(0, 0, 0);" class="">DuktapeObject can do it
            better.</span><font class=""> </font></div>
        <div class=""><br class="">
        </div>
        <div class="">Thanks, Mark.<br class="">
          <div class=""><br class="">
            <blockquote type="cite" class="">
              <div class="">On 15 Jul 2020, at 3:34 PM, Michael Balzer
                <<a href="mailto:dexter@expeedo.de" class="" moz-do-not-send="true">dexter@expeedo.de</a>>
                wrote:</div>
              <br class="Apple-interchange-newline">
              <div class="">
                <meta http-equiv="Content-Type" content="text/html;
                  charset=UTF-8" class="">
                <div class=""> Mark,<br class="">
                  <br class="">
                  yes, I needed that persistence for the HTTP and VFS
                  classes, but I also needed to be able to couple a
                  dynamic C++ instance with a JS object and have a
                  mechanism to prevent garbage collection while the C++
                  side is still in use. If the C++ side is no longer
                  needed, the JS finalizer also needs to imply the C++
                  instance can be deleted.<br class="">
                  <br class="">
                  That is all implemented by DuktapeObject.
                  DuktapeObject also provides JS method invocation on
                  the coupled JS object and a mutex for concurrency
                  protection.<br class="">
                  <br class="">
                  We probably need some more framework documentation
                  than the header comments (applies to all of our
                  framework classes…):<br class="">
                  <br class="">
                  <tt class="">/***************************************************************************************************</tt><tt class=""><br class="">
                  </tt><tt class=""> * DuktapeObject: coupled C++ / JS
                    object</tt><tt class=""><br class="">
                  </tt><tt class=""> * </tt><tt class=""><br class="">
                  </tt><tt class=""> *  Intended for API methods to
                    attach internal API state to a JS object and provide</tt><tt class=""><br class="">
                  </tt><tt class=""> *    a standard callback invocation
                    interface for JS objects in local scopes.</tt><tt class=""><br class="">
                  </tt><tt class=""> *  </tt><tt class=""><br class="">
                  </tt><tt class=""> *  - Override CallMethod() to
                    implement specific method calls</tt><tt class=""><br class="">
                  </tt><tt class=""> *  - Override Finalize() for
                    specific destruction in JS context (garbage
                    collection)</tt><tt class=""><br class="">
                  </tt><tt class=""> *  - call Register() to prevent
                    normal garbage collection (but not heap destruction)</tt><tt class=""><br class="">
                  </tt><tt class=""> *  - call Ref() to protect against
                    deletion (reference count)</tt><tt class=""><br class="">
                  </tt><tt class=""> *  - call Lock() to protect
                    concurrent access (recursive mutex)</tt><tt class=""><br class="">
                  </tt><tt class=""> *  </tt><tt class=""><br class="">
                  </tt><tt class=""> *  - GetInstance() retrieves the
                    DuktapeObject associated with a JS object if any</tt><tt class=""><br class="">
                  </tt><tt class=""> *  - Push() pushes the JS object
                    onto the Duktape stack</tt><tt class=""><br class="">
                  </tt><tt class=""> *  </tt><tt class=""><br class="">
                  </tt><tt class=""> *  Note: the DuktapeObject may
                    persist after the JS object has been finalized, e.g.</tt><tt class=""><br class="">
                  </tt><tt class=""> *    if some callbacks are pending
                    after the Duktape heap has been destroyed.</tt><tt class=""><br class="">
                  </tt><tt class=""> *    Use IsCoupled() to check if
                    the JS object is still available.</tt><tt class=""><br class="">
                  </tt><tt class=""> *  </tt><tt class=""><br class="">
                  </tt><tt class=""> *  Ref/Unref:</tt><tt class=""><br class="">
                  </tt><tt class=""> *    Normal life cycle is from
                    construction to finalization. Pending callbacks
                    extend</tt><tt class=""><br class="">
                  </tt><tt class=""> *    the life until the last
                    callback has been processed. A subclass may extend
                    the life</tt><tt class=""><br class="">
                  </tt><tt class=""> *    by calling Ref(), which
                    increases the reference count. Unref() deletes the
                    instance</tt><tt class=""><br class="">
                  </tt><tt class=""> *    if no references are left.</tt><tt class=""><br class="">
                  </tt><tt class=""> */</tt><tt class=""><br class="">
                  </tt><br class="">
                  You normally just need to use Register/Deregister
                  & Ref/Unref, and to implement the constructor and
                  CallMethod. Coupling of the instances normally is done
                  on construction, as a JS object is normally already
                  needed for the parameters and can simply be attached
                  to.<br class="">
                  <br class="">
                  Have a look at DuktapeHTTPRequest, DuktapeVFSLoad and
                  DuktapeVFSSave, these are the current subclasses using
                  this.<br class="">
                  <br class="">
                  For the command registration I would probably couple
                  the OvmsCommand instance with a JS command object
                  providing an execution method.<br class="">
                  <br class="">
                  Tell me if you need more info.<br class="">
                  <br class="">
                  Regards,<br class="">
                  Michael<br class="">
                  <br class="">
                  <br class="">
                  <div class="moz-cite-prefix">Am 15.07.20 um 08:12
                    schrieb Mark Webb-Johnson:<br class="">
                  </div>
                  <blockquote type="cite" cite="mid:B291C8AF-8382-4F45-87E3-3DA555E068BE@webb-johnson.net" class="">
                    <meta http-equiv="Content-Type" content="text/html;
                      charset=UTF-8" class="">
                    <div class=""><br class="">
                    </div>
                    <div class="">@Michael this is probably for you.</div>
                    <div class=""><br class="">
                    </div>
                    <div class="">I am trying to implement javascript
                      command registration. The idea is that a
                      javascript module can call something like:</div>
                    <div class=""><br class="">
                    </div>
                    <div class="">
                      <blockquote style="caret-color: rgb(0, 0, 0);
                        margin: 0px 0px 0px 40px; border: none; padding:
                        0px;" class="">OvmsCommand.Register(basecommand,
                        name, title, callbackfn, usage, min, max)</blockquote>
                      <div style="caret-color: rgb(0, 0, 0);" class=""><br class="">
                      </div>
                    </div>
                    <div style="caret-color: rgb(0, 0, 0);" class="">Then
                      we reflect that into MyCommandApp.RegisterCommand,
                      and keep a track of which command is for which
                      javascript callbackfn. When the command is
                      executed, we pass it into duktape.</div>
                    <div style="caret-color: rgb(0, 0, 0);" class=""><br class="">
                    </div>
                    <div style="caret-color: rgb(0, 0, 0);" class="">I
                      also have tracking for javascript module loading
                      and unloading, so I can DeregisterCommand() if
                      duktape is reloaded (and also protected against
                      commands being registered in short-lived scripts
                      run from the command line).</div>
                    <div style="caret-color: rgb(0, 0, 0);" class=""><br class="">
                    </div>
                    <div style="caret-color: rgb(0, 0, 0);" class="">To
                      implement this, I need to store the callbackfn as
                      a persistent reference to a duktape javascript
                      function.</div>
                    <div class=""><br class="">
                    </div>
                    <div class="">The issue with callback function
                      references in duktape is summarised here:</div>
                    <div class=""><br class="">
                    </div>
                    <blockquote style="margin: 0 0 0 40px; border: none;
                      padding: 0px;" class="">
                      <div class=""><a href="https://wiki.duktape.org/howtonativepersistentreferences" class="" moz-do-not-send="true">https://wiki.duktape.org/howtonativepersistentreferences</a></div>
                      <div class=""><br class="">
                      </div>
                      <div class=""><i class="">When a Duktape/C
                          function is called, Duktape places the call
                          arguments on the value stack. While the
                          arguments are on the value stack,
                          they're guaranteed to be reachable and the
                          Duktape/C function can safely work with the
                          arguments.<br class="">
                          <br class="">
                          However, when the Duktape/C function returns,
                          the value stack is unwound and references in
                          the function's value stack frame are lost. If
                          the last reference to a particular value was
                          in the function's value stack frame, the value
                          will be garbage collected when the function
                          return is processed.</i></div>
                    </blockquote>
                    <div class=""><br class="">
                    </div>
                    <div class="">The standard approach is to store the
                      reference back in the
                      duktape duk_push_global_stash so it won’t get
                      garbage-collected. But, that seems messy.</div>
                    <div class=""><br class="">
                    </div>
                    <div class="">I see that Michael has already
                      implemented something that seems similar in
                      ovms_script.{h, cpp}, for the async http
                      callbacks. Presumably to avoid this issue. But,
                      the approach seems very different, and I am not
                      sure if it is stopping _all_ garbage collection
                      for the duration of the async query, or just that
                      particular object being garbage collected. The
                      work seems extensive (quite a few objects
                      involved).</div>
                    <div class=""><br class="">
                    </div>
                    <div class="">So @Michael, any suggestions for this?
                      I don’t want to reinvent the wheel...</div>
                    <div class=""><br class="">
                    </div>
                    <div class="">Regards, Mark.</div>
                    <br class="">
                    <fieldset class="mimeAttachmentHeader"></fieldset>
                    <pre class="moz-quote-pre" wrap="">_______________________________________________
OvmsDev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:OvmsDev@lists.openvehicles.com" moz-do-not-send="true">OvmsDev@lists.openvehicles.com</a>
<a class="moz-txt-link-freetext" href="http://lists.openvehicles.com/mailman/listinfo/ovmsdev" moz-do-not-send="true">http://lists.openvehicles.com/mailman/listinfo/ovmsdev</a>
</pre>
                  </blockquote>
                  <br class="">
                  <pre class="moz-signature" cols="72">-- 
Michael Balzer * Helkenberger Weg 9 * D-58256 Ennepetal
Fon 02333 / 833 5735 * Handy 0176 / 206 989 26
</pre>
                </div>
                _______________________________________________<br class="">
                OvmsDev mailing list<br class="">
                <a href="mailto:OvmsDev@lists.openvehicles.com" class="" moz-do-not-send="true">OvmsDev@lists.openvehicles.com</a><br class="">
                <a class="moz-txt-link-freetext" href="http://lists.openvehicles.com/mailman/listinfo/ovmsdev" moz-do-not-send="true">http://lists.openvehicles.com/mailman/listinfo/ovmsdev</a><br class="">
              </div>
            </blockquote>
          </div>
          <br class="">
        </div>
        <br class="">
        <fieldset class="mimeAttachmentHeader"></fieldset>
        <pre class="moz-quote-pre" wrap="">_______________________________________________
OvmsDev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:OvmsDev@lists.openvehicles.com" moz-do-not-send="true">OvmsDev@lists.openvehicles.com</a>
<a class="moz-txt-link-freetext" href="http://lists.openvehicles.com/mailman/listinfo/ovmsdev" moz-do-not-send="true">http://lists.openvehicles.com/mailman/listinfo/ovmsdev</a>
</pre>
      </blockquote>
      <br class="">
      <pre class="moz-signature" cols="72">-- 
Michael Balzer * Helkenberger Weg 9 * D-58256 Ennepetal
Fon 02333 / 833 5735 * Handy 0176 / 206 989 26</pre>
      <br class="">
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <pre class="moz-quote-pre" wrap="">_______________________________________________
OvmsDev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:OvmsDev@lists.openvehicles.com">OvmsDev@lists.openvehicles.com</a>
<a class="moz-txt-link-freetext" href="http://lists.openvehicles.com/mailman/listinfo/ovmsdev">http://lists.openvehicles.com/mailman/listinfo/ovmsdev</a>
</pre>
    </blockquote>
    <br class="">
    <pre class="moz-signature" cols="72">-- 
Michael Balzer * Helkenberger Weg 9 * D-58256 Ennepetal
Fon 02333 / 833 5735 * Handy 0176 / 206 989 26</pre>
  </div>

_______________________________________________<br class="">OvmsDev mailing list<br class=""><a href="mailto:OvmsDev@lists.openvehicles.com" class="">OvmsDev@lists.openvehicles.com</a><br class="">http://lists.openvehicles.com/mailman/listinfo/ovmsdev<br class=""></div></blockquote></div><br class=""></div></body></html>