{"id":671,"date":"2018-08-26T01:11:15","date_gmt":"2018-08-26T01:11:15","guid":{"rendered":"http:\/\/www.onux.com\/jspp\/blog\/?p=671"},"modified":"2019-01-26T03:00:47","modified_gmt":"2019-01-26T03:00:47","slug":"tips-tricks-fromexternal-toexternal-design-pattern","status":"publish","type":"post","link":"https:\/\/www.onux.com\/jspp\/blog\/tips-tricks-fromexternal-toexternal-design-pattern\/","title":{"rendered":"Tips &#038; Tricks: fromExternal\/toExternal Design Pattern"},"content":{"rendered":"<p>JS++ provides <a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Standard-Library\/System\/Object\/toString\" rel=\"noopener\" target=\"_blank\">toString<\/a> and fromString (<a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Standard-Library\/System\/Integer32\/fromString\" rel=\"noopener\" target=\"_blank\">one example<\/a>) methods in the Standard Library. However, it can be argued that the <code>external<\/code> type is just as important or even more important in JS++ as <code>string<\/code>.<\/p>\n<p>We introduce a design pattern for converting complex <a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Language\/Reference\/Types\/user-defined-types\" rel=\"noopener\" target=\"_blank\">user-defined JS++ types<\/a> (such as classes) to JavaScript.<\/p>\n<h3>toExternal<\/h3>\n<p>You can define a <code>toExternal<\/code> method that enables you to convert an object of an internal type to external:<\/p>\n<pre class=\"brush:jspp\">\r\nimport System;\r\n\r\nclass Point\r\n{\r\n    int x;\r\n    int y;\r\n\r\n    Point(int x, int y) {\r\n        this.x = x;\r\n        this.y = y;\r\n    }\r\n\r\n    function toExternal() {\r\n        return {\r\n            x: x,\r\n            y: y\r\n        };\r\n    }\r\n}\r\n\r\nPoint p = new Point(2, 3);\r\nvar p2 = p.toExternal(); \/\/ conversion to 'external'\r\nConsole.log(p2.x); \/\/ 2\r\nConsole.log(p2.y); \/\/ 3\r\n<\/pre>\n<h3>fromExternal<\/h3>\n<p>Likewise, you can convert incoming JavaScript data to a complex, user-defined JS++ type:<\/p>\n<pre class=\"brush:jspp\">\r\nimport System;\r\nimport System.Assert;\r\n\r\nclass Point\r\n{\r\n    int x;\r\n    int y;\r\n\r\n    Point(int x, int y) {\r\n        this.x = x;\r\n        this.y = y;\r\n    }\r\n\r\n    static Point fromExternal(obj) {\r\n        assert(typeof obj == \"object\", \"Expected external 'object' type\");\r\n        assert(typeof obj.x == \"number\", \"Expected incoming external to have numeric 'x' property\");\r\n        assert(typeof obj.y == \"number\", \"Expected incoming external to have numeric 'y' property\");\r\n        return new Point(Integer32.fromString(obj.x), Integer32.fromString(obj.y));\r\n    }\r\n}\r\n\r\nPoint p1 = Point.fromExternal({ x: 2, y: 3 });\r\n\/\/ Point p2 = Point.fromExternal({ x: \"x\", y: 3 }); \/\/ this will fail\r\n\/\/ Point p3 = Point.fromExternal({ x: 2, y: \"y\" }); \/\/ this will fail\r\n<\/pre>\n<h3>Protecting References<\/h3>\n<p>For functions, you don&#8217;t want to send out a direct reference to external JavaScript. Otherwise, external JavaScript code can modify the JS++ reference in unsafe ways. Therefore, you should wrap the function using closures:<\/p>\n<pre class=\"brush:jspp\">\r\nclass Foo\r\n{\r\n    void bar() {}\r\n\r\n    function toExternal() {\r\n        Foo self = this;\r\n\r\n        return {\r\n            bar: void() {\r\n                self.bar();\r\n            }\r\n        };\r\n    }\r\n}\r\n<\/pre>\n<p>Furthermore, you can use the Standard Library&#8217;s <a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Standard-Library\/System\/BoxedExternal\" rel=\"noopener\" target=\"_blank\">System.BoxedExternal<\/a> to handle this case without wrapping in a closure:<\/p>\n<pre class=\"brush:jspp\">\r\nimport System;\r\n\r\nclass Foo\r\n{\r\n    BoxedExternal bar;\r\n\r\n    Foo() {\r\n        this.bar = new BoxedExternal(void() {\r\n        \/\/ ...\r\n        });\r\n    }\r\n \r\n    function toExternal() {\r\n        return {\r\n            bar: this.bar\r\n        };\r\n    }\r\n}\r\n<\/pre>\n<p>If the reference to the function accidentally escapes to <code>external<\/code>, you&#8217;ll be alerted by the compiler:<\/p>\n<p style=\"background:#2F3335;color:#D5D5D5;padding:4px;font-family:monospace;\"><span style=\"color:#ff0000;\">[  ERROR  ]<\/span> JSPPE5000: Cannot convert `System.Dictionary<System.BoxedExternal>&#8216; to `external&#8217; at line 14 char 15<\/p>\n<p>However, if you actually intended to allow the function reference to escape to <code>external<\/code>, you can call the <code>unbox<\/code> method on System.BoxedExternal:<\/p>\n<pre class=\"brush:jspp;highlight:14\">\r\nimport System;\r\n\r\nclass Foo\r\n{\r\n    BoxedExternal bar;\r\n\r\n    Foo() {\r\n        this.bar = new BoxedExternal(void() {\r\n            \/\/ ...\r\n        });\r\n    }\r\n \r\n    function toExternal() {\r\n        return {\r\n            bar: this.bar.unbox()\r\n        };\r\n    }\r\n}\r\n<\/pre>\n<p>The above code will now compile and the <code>bar<\/code> function can be passed to external code. However, unlike the code where we wrapped the function in a closure, the external code can now modify the reference to the <code>bar<\/code> function directly so be careful.<\/p>\n<p>For arrays and containers, you can likewise pass a shallow copy or manually clone each element &#8211; depending on the level of trust and safety you desire.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>JS++ provides toString and fromString (one example) methods in the Standard Library. However, it can be argued that the external type is just as important or even more important in JS++ as string. We introduce a design pattern for converting complex user-defined JS++ types (such as classes) to JavaScript. toExternal You can define a toExternal &hellip; <a href=\"https:\/\/www.onux.com\/jspp\/blog\/tips-tricks-fromexternal-toexternal-design-pattern\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Tips &#038; Tricks: fromExternal\/toExternal Design Pattern&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[2,18],"tags":[],"_links":{"self":[{"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/posts\/671"}],"collection":[{"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/comments?post=671"}],"version-history":[{"count":6,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/posts\/671\/revisions"}],"predecessor-version":[{"id":985,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/posts\/671\/revisions\/985"}],"wp:attachment":[{"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/media?parent=671"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/categories?post=671"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/tags?post=671"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}