<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style></head><body lang=EN-US link=blue vlink="#954F72"><div class=WordSection1><p class=MsoNormal>You would have to put the proxies in the scenegraph, I am fairly sure.   So you would pass an object (not a route path) into the proxy creator, get an object out, and then replace it in the scenegraph.  You would end up with a lot more proxies, whereas I have a single proxy in this case.  I think you would have to go from lowest tree depth  to highest tree depth, but I could be wrong. I don’t know if I saw a proxy loop or not.  I have a single proxy based on the route path down the hierarchy.  The Proxy is merely an event handler, it doesn’t set object values, you have to do that in the event handler.   Also the proxy proxies the whole object, so you can’t set up an unhandled property.  Thus you get events for properties you don’t even want.  If you have a separate toScenegraph, then you’ll have to check the field to see if it has an event handler, so you don’t set it in the toScenegraph.  If your from and your to objects are the same and your properties are different, which they might be, you might get a stack overflow, which JavaScript may handle.   That was why I set up a single proxy.  I am not ruling out a better design, I am just avoiding recursion.  You can’t return false from the event handler, because then the proxy object will revert.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Please play with my code and prove me, wrong.  I think I’m right.  I am fairly sure that when the proxy was in the scene graph, I was getting recursion, but it didn’t last too long,  I think that JavaScript detected it or something, I am not sure.  I could also stop the event handling setInternalField from setting a proxy in the fromScenegraph now I think.  So it might be possible.  I found it frustrating that the proxy didn’t automatically set the original object, and setting the original object didn’t fire the event, only setting the proxy did.</p><p class=MsoNormal><br>I would love to have another pair of eyes on this, and now we have the infrastructure to do it.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>You could probably create your own proxy from a graphics object, and use setInterfield to push the proxy into a scenegraph.  Then you would have to take out the setInternalField call out of the event handler for the fromScenegraph, but leave it in for the toScenegraph.</p><p class=MsoNormal><br>I’ll probably play with the code some soon, I’ve about given up on XSLT.  I’ll work on making it more SAI compliant, but I really do want the path so I can start wildcarding, etc.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>My paths are from the route to the field.  I stop one level up to set the field, I believe.  I could separate the field from the path, but why?   Imagine how I might use a CSS selector language in this same infrastructure (well, it’s a stretch).</p><p class=MsoNormal><br>I left you with something that works.  That was my goal. Whether it suits your goals is up to you.  I do think that making ROUTE fromNode and toNode a MFString may make it easier to extend.  But then they wouldn’t be SFNodes.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>John</p><p class=MsoNormal>Sent from <a href="https://go.microsoft.com/fwlink/?LinkId=550986">Mail</a> for Windows 10</p><p class=MsoNormal><o:p> </o:p></p><div style='mso-element:para-border-div;border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><p class=MsoNormal style='border:none;padding:0in'><b>From: </b><a href="mailto:andreasplesch@gmail.com">Andreas Plesch</a><br><b>Sent: </b>Saturday, April 15, 2017 4:13 PM<br><b>To: </b><a href="mailto:yottzumm@gmail.com">John Carlson</a><br><b>Cc: </b><a href="mailto:x3d-public@web3d.org">X3D Graphics public mailing list</a><br><b>Subject: </b>Re: Routes with JS Proxy</p></div><p class=MsoNormal><o:p> </o:p></p><div><div><div><div><p class=MsoNormal>Hi John,</p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>thanks, I am trying to follow what this is doing and copied the code here:</p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal><a href="https://gist.github.com/andreasplesch/59da818dbb4b7bc55c4c1aed401faa7c">https://gist.github.com/andreasplesch/59da818dbb4b7bc55c4c1aed401faa7c</a></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>I am imagining that after creating a Route with route(), the proxies would automatically ensure that if a value in the js object derived from the JSON is modified (set) (in any way), the routed to property value is also modified immediately. Is that the idea ?.</p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>But then there are custom, public and private setField, and setInternalField functions ? Would it be possible to avoid those and use direct js object manipulation functionality ? </p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Here is the short line on how addRoute is defined in the SAI (as a function of an executioncontext):</p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal><a href="http://www.web3d.org/documents/specifications/19777-1/V3.3/Part1/functions.html#t-ExecutionContextFunctions">http://www.web3d.org/documents/specifications/19777-1/V3.3/Part1/functions.html#t-ExecutionContextFunctions</a></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Do you think it would be possible to do this directly for DOM (or XML encoded) scenes as well ? I think it could be since the json path translates to .querySelector and setField to .setAttribute and .addChild</p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Generally, I think using Proxy as a mechanism to trap setting values and then forwarding those could be a good idea allowing separation from DOM events.</p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>-Andreas</p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal> </p></div><blockquote style='border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt'><p class=MsoNormal style='margin-left:4.8pt'>Date: Sat, 15 Apr 2017 11:45:57 -0400<br>From: <<a href="mailto:yottzumm@gmail.com">yottzumm@gmail.com</a>><br>To: X3D Graphics public mailing list <<a href="mailto:x3d-public@web3d.org">x3d-public@web3d.org</a>><br>Subject: [x3d-public] (no subject)<br>Message-ID: <<a href="mailto:58f24034.8f2e6b0a.7ce43.ba74@mx.google.com">58f24034.8f2e6b0a.7ce43.ba74@mx.google.com</a>><br>Content-Type: text/plain; charset="utf-8"<br><br>Inclosed is my first attempt at a new style of routes and events with JavaScript.  Routes are MFString path<br>Down the JS object hierarchy.  Once the proxy and routes are set up, you can set values in the proxy, and the scenegraphs will change.  Please see my test cases and add more!  It does not handle script functions yet, but there is a path forward.  Perhaps someone will look at this code and find something of value.<br><br>John<br><br>/****************************************************************************/<br>'use strict';<br>/*<br>Copyright (c) 2017, John Carlson<br>All rights reserved.<br><br>Redistribution and use in source and binary forms, with or without<br>modification, are permitted provided that the following conditions are met:<br><br>* Redistributions of source code must retain the above copyright notice, this<br>  list of conditions and the following disclaimer.<br><br>* Redistributions in binary form must reproduce the above copyright notice,<br>  this list of conditions and the following disclaimer in the documentation<br>  and/or other materials provided with the distribution.<br><br>* Neither the name of content nor the names of its<br>  contributors may be used to endorse or promote products derived from<br>  this software without specific prior written permission.<br><br>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"<br>AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE<br>IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE<br>DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE<br>FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<br>DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR<br>SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER<br>CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,<br>OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE<br>OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE<br>*/<br><br><br>test();<br><br>/**<br> * Override this to get rid of self-test code<br> * proxyAction should be paired with a scenegraph exclusively<br> */<br>function test() {<br>        let fromScenegraph = [ {d: { f: 7 , e: [1, 2, 3]}}, { c : [4]}]<br>        let toScenegraph = fromScenegraph;<br>        info("Scenegraph originally "+stringify(fromScenegraph));<br>        assert(fromScenegraph, toScenegraph);<br>        let proxyAction = {};<br>        let proxy = createProxy(proxyAction, fromScenegraph);<br><br>        // Create actionable fields in the fromScenegraph, that set<br>        // fields in the toScenegraph<br>        //<br>        // path are MFStirngs which follw a path down the scenegraph, one<br>        // element at a time.  The final SFSTring is thei field to modify.<br>        //<br>        // This does not handle script nodes yet (both getting and setting<br>        // values, but could possibly be handled by modifying SetInternalField.<br>        //<br>        route(proxyAction,<br>                fromScenegraph, '"0" "d" "e" "0"',<br>                toScenegraph, '"1" "c"');<br>        route(proxyAction,<br>                fromScenegraph, '"0" "d"',<br>                toScenegraph, '"1"');<br>        route(proxyAction,<br>                fromScenegraph, '"0" "A"',<br>                toScenegraph, '"0" "B"');<br>        // no changes to scenegraph yet<br>        assert(fromScenegraph, [{"d":{"f":7,"e":[1,2,3]}},{"c":[4]}]);<br><br>        setField(proxy, '"0" "d" "e" "0"', 5);<br>        assert(fromScenegraph, [{"d":{"f":7,"e":[5,2,3]}},{"c":5}]);<br>        setField(proxy, '"0" "d" "e" "1"', 8);<br>        assert(fromScenegraph, [{"d":{"f":7,"e":[5,8,3]}},{"c":5}]);<br>        setField(proxy, '"0" "d"', 6);<br>        assert(fromScenegraph, [{"d":6},6]);<br>        setField(proxy, '"0" "d"', 9);<br>        assert(fromScenegraph, [{"d":9},9]);<br>        // add field'<br>        setField(proxy, '"0" "A"',  10);<br>        assert(fromScenegraph, [{"d":9,"B":10,"A":10},9]);<br>        setField(proxy, '"0" "A"', [ "Test!" ]);<br>        assert(fromScenegraph, [{"d":9,"B":["Test!"],"A":["Test!"]},9]);<br>        setField(proxy, '"0" "B"', null);<br>        assert(fromScenegraph, [{"d":9,"B":null,"A":["Test!"]},9]);<br>        setField(proxy, '"0" "A" "0" "0"', ["Cr"]);  // set a part of a string<br>        assert(fromScenegraph, [{"d":9,"B":null,"A":["Crest!"]},9]);<br>        setField(proxy, '"0" "A"', { "/": "/" }); // now A and B point to same<br>        assert(fromScenegraph, [{"d":9,"B":{"/":"/"},"A":{"/":"/"}},9]);<br>        setField(proxy, '"0" "A" "/"', "\\");<br>        assert(fromScenegraph, [{"d":9,"B":{"/":"\\"},"A":{"/":"\\"}},9]);<br>        setField(proxy, '"0" "A"', { "\\": "\\" }); // now A and B point to same<br>        assert(fromScenegraph, [{"d":9,"B":{"\\":"\\"},"A":{"\\":"\\"}},9]);<br>        setField(proxy, '"0" "A" "\\"', "]");<br>        assert(fromScenegraph, [{"d":9,"B":{"\\":"]"},"A":{"\\":"]"}},9]);<br>        setField(proxy, '"0" "A"', { "]" : "]" }); // now A and B point to same<br>        assert(fromScenegraph, [{"d":9,"B":{"]":"]"},"A":{"]":"]"}},9]);<br>        setField(proxy, '"0" "A" "]"', "[");<br>        assert(fromScenegraph, [{"d":9,"B":{"]":"["},"A":{"]":"["}},9]);<br>        setField(proxy, '"0" "A"', { "[" : "[" }); // now A and B point to same<br>        assert(fromScenegraph, [{"d":9,"B":{"[":"["},"A":{"[":"["}},9]);<br>        setField(proxy, '"0" "A" "["', "][");<br>        assert(fromScenegraph, [{"d":9,"B":{"[":"]["},"A":{"[":"]["}},9]);<br>        setField(proxy, '"0" "A"', { "][" : "][" }); // now A and B point to same<br>        assert(fromScenegraph, [{"d":9,"B":{"][":"]["},"A":{"][":"]["}},9]);<br>        setField(proxy, '"0" "A" "]["', "][][" );<br>        assert(fromScenegraph, [{"d":9,"B":{"][":"][]["},"A":{"][":"][]["}},9]);<br>        setField(proxy, '"0" "A"', { "][][" : "][][" }); // now A and B point to same<br>        assert(fromScenegraph, [{"d":9,"B":{"][][":"][]["},"A":{"][][":"][]["}},9]);<br>        setField(proxy, '"0" "A" "][]["',   "[][]");<br>        assert(fromScenegraph, [{"d":9,"B":{"][][":"[][]"},"A":{"][][":"[][]"}},9]);<br>        setField(proxy, '"0" "A"', { "[][]" : "[][]" }); // now A and B point to same<br>        assert(fromScenegraph, [{"d":9,"B":{"[][]":"[][]"},"A":{"[][]":"[][]"}},9]);<br>        setField(proxy, '"0" "A" "[][]"', "C");<br>        assert(fromScenegraph, [{"d":9,"B":{"[][]":"C"},"A":{"[][]":"C"}},9]);<br>        assert(fromScenegraph, toScenegraph);<br>        info("Scenegraph finally "+stringify(fromScenegraph));<br>}<br><br>function setField(proxy, fromPath, value) {<br>        let selector = MFStringToProperty(fromPath);<br>        raw("\n");<br>        info("Storing "+fromPath+" = "+selector+" = "+stringify(value)+" in Proxy");<br>        proxy[selector] = value;<br>}<br><br>/**<br> * Override this if you don't want test warnings about scenegraphs<br> */<br><br>function assert(modifiedScenegraph, goldenScenegraph) {<br>        var mod = stringify(modifiedScenegraph);<br>        var testcase = stringify(goldenScenegraph);<br>        if (mod !== testcase) {<br>                fatal("Scenegraph "+mod)<br>                fatal("        != "+testcase);<br>        } else {<br>                debug("Scenegraph "+mod+" == "+testcase);<br>                info("TEST PASSED");<br>        }<br>}<br><br>/**<br> * Pass in a JSON parseable object be stringified,<br> * or a regular JSON object.  Or a string to be parsed.<br> * selector returned the is the path into the proxy.<br> *<br> * This should normalize the string, but there may be issues<br> * with ordering objects.<br> */<br>function stringify(selectorPath) {<br>        if (typeof selectorPath === 'string') {<br>                debug("selector output "+selectorPath);<br>                return selectorPath;<br>        /*<br>                let indexes = parse(selectorPath);<br>                let selector = JSON.stringify(indexes);<br>                debug("selector output "+selector);<br>                return selector;<br>        */<br>        } else {<br>                let selector = JSON.stringify(selectorPath);<br>                debug("selector output "+selector);<br>                return selector;<br>        }<br>}<br><br>/**<br> * breaks up selectorPath into component pieces and returns them<br> */<br>function parse(selectorPath) {<br>        debug("selector input "+selectorPath);<br>        if (typeof selectorPath === 'string') {<br>                let indexes = JSON.parse(selectorPath);<br>                return indexes;<br>        } else {<br>                return selectorPath;<br>        }<br>}<br><br>function MFStringToProperty(string) {<br>        debug("MFString input "+string+" "+typeof string);<br>        string = string.replace(/" "/g, ',');<br>        string = string.substr(1, string.length-2);<br>        return string;<br>}<br><br>/*<br>function JsonToMFString(json) {<br>        let str = stringify(json).split(/,/).join('" "')<br>        str = "'"+str.substr(1, str.length-2)+'"';<br>        return str;<br>}<br>*/<br><br>function PropertyToJson(string) {<br>        debug("property input "+string+" "+typeof string);<br>        return string.split(/,/);<br>}<br><br>/** override this function if you want a feature other than a raw message<br> */<br>function raw(string) {<br>        console.log(string);<br>}<br><br>/** override this function if you want a feature other than a fatal message<br> */<br>function fatal(string) {<br>        console.error("FATAL: "+string);<br>}<br><br>/** override this function if you want a feature other than a warning message<br> */<br>function warning(string) {<br>        console.error("============ WARNING: "+string);<br>}<br><br>/** override this function if you want a feature other than console.log or to<br> * disable this function<br> */<br>function debug(string) {<br>        // raw(string);<br>}<br><br>/** override this function if you want a feature other than console.log or to<br> * disable this function<br> */<br>function info(string) {<br>        raw("****** "+string);<br>}<br><br>/**<br> * setInternalField() --  set a field in a scenegraph internally.  Use<br> * setField() and set up routes and the proxy object on the scenegraph so<br> * events flow.<br> * Override this if you want a different selector language.<br> * The scenegraph is the javascript object to set the path to value on.<br> * selectorPath is a JSON array path of keys and indexes into the scenegraph.<br> *      You may use quotes to backslashes to escape things<br> * The value is set in the scenegraph at the selectorPath location<br> *<br> * The client may want the select to impact several objects.  That is up<br> * to the implementer of setInternalField().  The selectorPath affects the<br> * scenegraph.<br> * Right now we just have a simple JavaScript implementation.  Something like<br> * JSONPath is realizable in this framework I think.<br> *<br> * You should not use this method to set values on the proxy.<br> *<br> * Calls:<br> *      stringify: to return a string for viewing.<br> *      parse: to return javascript object indexes as a selector.<br> */<br>function setInternalField(scenegraph, selectorPath, value) {<br>        debug("Scenegraph before "+ stringify(scenegraph));<br>        let skipDescendants = 0; // number of descendents to skip<br>        let selectedValue = scenegraph;<br>        let higherValue = selectedValue;<br>        var selector  = PropertyToJson(selectorPath);<br>        let depth = (selector.length - skipDescendants);<br>        debug("Trying to Set "+stringify(scenegraph)+stringify(selector)+" = "+<br>                stringify(value));<br>        for (var index = 0; index < depth - 1; index++) {<br>                debug("Index "+index+" is "+selector[index]);<br>                higherValue = selectedValue;<br>                debug("Previous downselected selectedValue === "+<br>                        stringify(selectedValue));<br>                debug("Index "+index+" is "+selector[index]);<br>                debug("New Selected Value === "+selectedValue[selector[index]]);<br>                selectedValue = selectedValue[selector[index]];<br>                debug("Now downselected selectedValue === "+selectedValue);<br>        }<br>        if (typeof value === 'string') {<br>                value = value.replace(/\\\\/g, '\u005c');<br>        }<br>        debug("Index "+index+" is "+selector[index]);<br>        /**<br>         * This is the code that has to change to call functions in X3D Scripts<br>         * fields.   For toField, I would check to make sure the LHS is a<br>         * function, and pass a value to the function (along with a timestamp),<br>         * for From Field, I would make sure value is a function, and call it<br>         * with a timestamp.<br>         */<br>        if (typeof selectedValue === 'string') {<br>            var str = selectedValue.split('');<br>                    info("Setting "+ stringify(higherValue) +<br>                        "[" + selector[depth-2] + "] = "+<br>                        stringify(value));<br>                    str[selector[depth-1]] = value;<br>                    higherValue[selector[depth-2]] = str.join('');<br>                    // unless there's more than one<br>        } else {<br>                info("Setting "+<br>                        stringify(selectedValue) +<br>                        "[" + selector[depth-1] + "] = "+ stringify(value));<br>                selectedValue[selector[depth-1]] = value;<br>                // unless there's more than one<br>        }<br>        raw("RESULT scenegraph "+stringify(scenegraph));<br>        return true;<br>}<br><br><br>/**<br> * This proxy works on individual values in a scenegraph, because a shadow<br> * scenegraph is keep with fromPaths kept as proxy objects.<br> *<br> * If a route hasn't been set up yet, then the toScenegraph is not affected,<br> * unless it's a part of the fromSceneGraph.<br> */<br><br>function createProxy(proxyAction, fromScenegraph) {<br>        var proxy = new Proxy(proxyAction, {<br>                set : function(target, property, value, receiver) {<br>                        debug("Value set is "+value);<br>                        debug("property is "+ property);<br>                        for (let action in proxyAction) {<br>                                debug(" "+action+" "+typeof proxyAction[property]);<br>                        }<br>                        if (typeof proxyAction[property] === 'function') {<br>                                // set the toScenegraph, act on the route<br>                                proxyAction[property](property, value);<br>                        } else {<br>                                warning("Failed to set value on toScenegraph (no route)");<br>                        }<br>                        return setInternalField(fromScenegraph, property, value);<br>                }<br>        });<br>        return proxy;<br>}<br><br>/**<br> * Proxy action, set on route.   This should only be called when a route<br> * is in place.  It's private an should not be called by others.<br> * Scenegraphs are JavaSCript objects<br> * Paths are selectors into scenegraphs.<br> * property is the property being set and should be equal to fromPath<br> * value is the value being set on the toScenegraph.   To set the<br> * fromScenegraph, use setField() on the proxy or setInternalField, if you don'<br> * want to affect the toScenegraph.<br> */<br>function proxySetAction(fromScenegraph, fromPath, toScenegraph, toPath, property, value) {<br>        let fromProperty = MFStringToProperty(fromPath);<br>        if (fromProperty != property) {<br>                fatal("from"+fromPath+" out of sync with property "+property+".  Did you forget to set a route?");<br>        }<br>        debug("fromPath is "+fromPath);<br>        debug("toPath is "+toPath);<br>        debug("property is "+property);<br>        let toProperty = MFStringToProperty(toPath);<br>        debug("toProperty is "+toProperty);<br>        if (toScenegraph == fromScenegraph && fromPath == toPath) {<br>                warning("We don't need to set the same value twice!");<br>        } else {<br>                setInternalField(toScenegraph, toProperty, value);<br>        }<br><br>        return true;<br>}<br><br>/**<br> * Activate a proxy route from fromPath to toPath<br> * The proxy map is a private object which must be passed around.  I will later<br> * make it unaccessible.<br> * Paths are selectors which can be used with setInternalField()<br> * fromScenegraph and toScenegraph may be separate.  If they are the<br> * same, be sure that fromField and toField are distinct, or else the<br> * results may be undetermined.<br> */<br>function route(proxyAction, fromScenegraph, fromPath, toScenegraph, toPath) {<br>        info("<ROUTE fromPath='"+ fromPath+ "' "+ "toPath='"+ toPath+ "'/>"<br>                );<br>        if (fromScenegraph === toScenegraph &&<br>                fromPath.startsWith(toPath) &&<br>                toPath.startsWith(fromPath) &&<br>                fromPath !== toPath) {<br>                warning("possible undetermined behavior, fromPath "+fromPath+" and toPath "+toPath+" overlap and the scenegraphs are the same");<br>        }<br>        proxyAction[MFStringToProperty(fromPath)] = function(property, value) {<br>                return proxySetAction(fromScenegraph, fromPath,<br>                        toScenegraph, toPath,<br>                        property, value);<br>        };<br>}<br>-------------- next part --------------<br>An HTML attachment was scrubbed...<br>URL: <<a href="http://web3d.org/pipermail/x3d-public_web3d.org/attachments/20170415/50b036e8/attachment.html" target="_blank">http://web3d.org/pipermail/x3d-public_web3d.org/attachments/20170415/50b036e8/attachment.html</a>><br><br>------------------------------<br><br>Subject: Digest Footer<br><br>_______________________________________________<br>x3d-public mailing list<br><a href="mailto:x3d-public@web3d.org">x3d-public@web3d.org</a><br><a href="http://web3d.org/mailman/listinfo/x3d-public_web3d.org" target="_blank">http://web3d.org/mailman/listinfo/x3d-public_web3d.org</a><br><br><br>------------------------------<br><br>End of x3d-public Digest, Vol 97, Issue 38<br>******************************************</p></blockquote></div><p class=MsoNormal><br><br clear=all></p><div><p class=MsoNormal><o:p> </o:p></p></div><p class=MsoNormal>-- </p></div></div><p class=MsoNormal>Andreas Plesch<br>39 Barbara Rd.<br>Waltham, MA 02453</p><p class=MsoNormal><o:p> </o:p></p></div></body></html>