Last active
October 6, 2024 12:35
-
-
Save WebReflection/2d64f34cf58daa812ec876242c91a97c to your computer and use it in GitHub Desktop.
Revisions
-
WebReflection revised this gist
Dec 12, 2022 . 1 changed file with 3 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -65,6 +65,7 @@ interface ESXStatic { // always the same reference when this is used as outer template interface ESXNode extends ESXToken { id: object? children: (ESXStatic | ESXInterpolation | ESXNode)[]; } @@ -76,13 +77,15 @@ class ESXFragment extends ESXNode { // <any-element /> class ESXElement extends ESXNode { type = ESXToken.ELEMENT; name: string; value: string; attributes: (ESXAttribute | ESXInterpolation)[]; } // <AnyComponent /> class ESXComponent extends ESXNode { type = ESXToken.COMPONENT; name: string; value: function; attributes: (ESXAttribute | ESXInterpolation)[]; get properties(): object?; -
WebReflection revised this gist
Dec 5, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -63,8 +63,8 @@ interface ESXStatic { value: string; } // always the same reference when this is used as outer template interface ESXNode extends ESXToken { children: (ESXStatic | ESXInterpolation | ESXNode)[]; } -
WebReflection revised this gist
Dec 2, 2022 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -10,6 +10,8 @@ Feel free to keep an eye on [udomsay](https://github.com/WebReflection/udomsay) This is a [TC39 proposal](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511) and [there is a Babel transformer](https://github.com/ungap/babel-plugin-transform-esx) for it too. There is also a *zero-tooling* solution based on *template litearl tags* [in this repository](https://github.com/ungap/esx#readme), which solves almost all pain-points around having *ESX* as syntax. - - - In a quest to explore improvements over common JSX transformers I have managed to [find great performance](https://twitter.com/WebReflection/status/1589741329378324480?s=20&t=DnTQ1z7G-77ufAMAIeXjrQ) able to compete with template literal based libraries. -
WebReflection revised this gist
Nov 29, 2022 . 1 changed file with 4 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -86,3 +86,7 @@ class ESXComponent extends ESXNode { get properties(): object?; } ``` ## Code samples To better understand what the transformer currently produce, please see [this innput](https://github.com/ungap/babel-plugin-transform-esx/blob/main/test/transform/input.js) and compare it with [this output](https://github.com/ungap/babel-plugin-transform-esx/blob/main/test/transform/output.js). -
WebReflection revised this gist
Nov 29, 2022 . 1 changed file with 39 additions and 295 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -30,315 +30,59 @@ This document describes all the moving parts of ESX in a way that: ## ESX ```ts // base class for instanceof operations class ESXToken { static ATTRIBUTE: number; static INTERPOLATION: number; static STATIC: number; static FRAGMENT: number; static ELEMENT: number; static COMPONENT: number; } // possible `attributes` entry interface ESXAttribute { type = ESXToken.ATTRIBUTE; dynamic: boolean; name: string; value: unknown; } // possible `attributes` or `children` entry interface ESXInterpolation { type = ESXToken.INTERPOLATION; value: unknown; } // possible `children` entry interface ESXStatic { type = ESXToken.STATIC; value: string; } interface ESXNode extends ESXToken { id: object?; children: (ESXStatic | ESXInterpolation | ESXNode)[]; } // <></> class ESXFragment extends ESXNode { type = ESXToken.FRAGMENT; } // <any-element /> class ESXElement extends ESXNode { type = ESXToken.ELEMENT; value: string; attributes: (ESXAttribute | ESXInterpolation)[]; } // <AnyComponent /> class ESXComponent extends ESXNode { type = ESXToken.COMPONENT; value: function; attributes: (ESXAttribute | ESXInterpolation)[]; get properties(): object?; } ``` -
WebReflection revised this gist
Nov 24, 2022 . 1 changed file with 8 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,13 @@ ### About ## Highly Experimental If you are using this already, consider changes soon due [the discussion around current ESX proposal](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/43). Feel free to keep an eye on [udomsay](https://github.com/WebReflection/udomsay) as that will be the implementation reference for consumers. - - - This is a [TC39 proposal](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511) and [there is a Babel transformer](https://github.com/ungap/babel-plugin-transform-esx) for it too. - - - -
WebReflection revised this gist
Nov 21, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ ### About This is a [TC39 proposal](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511) and [there is a Babel transformer](https://github.com/ungap/babel-plugin-transform-esx) for it too. - - - -
WebReflection revised this gist
Nov 21, 2022 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -282,7 +282,7 @@ const component = new ESXTemplate( // properties value [ new ESXProperty(ESXToken.STATIC_TYPE, 'a', 'a'), new ESXProperty(ESXToken.RUNTIME_TYPE, '', props) ] ) ) @@ -321,7 +321,7 @@ const component = { type: 4, value: [ {type: 1, name: 'a', value: 'a'}, {type: 4, name: '', value: props} ] }, children: [] -
WebReflection revised this gist
Nov 16, 2022 . 1 changed file with 4 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,9 @@ ### About This is a [TC39 proposal](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511) - - - In a quest to explore improvements over common JSX transformers I have managed to [find great performance](https://twitter.com/WebReflection/status/1589741329378324480?s=20&t=DnTQ1z7G-77ufAMAIeXjrQ) able to compete with template literal based libraries. In this document I would like to describe, via JS itself, and as PoC, how JSX could be both rebranded as ESX and improved. -
WebReflection revised this gist
Nov 9, 2022 . 1 changed file with 16 additions and 18 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -49,31 +49,16 @@ class ESXToken { // represented as {type: 1 | 2 | 4, name: string, value} class ESXProperty extends ESXToken { /** * @param {number} type ESXToken.STATIC_TYPE | ESXToken.MIXED_TYPE | ESXToken.RUNTIME_TYPE * @param {string} name the property name * @param {any} value the property value */ constructor(type, name, value) { super(type, value); this.name = name; } } // <any /> <>angle</> <Brackets /> class ESXChevrons extends ESXToken { /** @@ -130,6 +115,19 @@ class ESXComponent extends ESXChevrons { super(ESXToken.COMPONENT_TYPE, value, properties, children); } } // Outer JSX template elements // represented as {type: 8, id, value} class ESXTemplate extends ESXToken { /** * @param {object} id unique template reference * @param {ESXChevrons} value the entry value this template carries */ constructor(id, value) { super(ESXToken.TEMPLATE_TYPE, value); this.id = id; } } ``` #### Basic expectations -
WebReflection revised this gist
Nov 9, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -10,7 +10,7 @@ Differently from E4X, but also differently from JSX, this proposal leaves develo This document describes all the moving parts of ESX in a way that: * there is no DOM at all involved, only new primitives introduced by ESX * all relevant details around each part of the transformation are described through simple objects, here represented as classes instances, but these easily work just as object literals (easy polyfills via transformers) * no extra scope pollution is needed, hence no `jsxPragma` or `jsxFragment` around is required at all (no `React.createElement` or `React.Fragment` needed, nor `udomsay.interpolation`) * all classes can be used just as types to infer, as oppsite of being really classes ... no clashing in the logic can happen neither. The only global class needed out there is `ESXToken` which carries types and the prototypal inheritance for brand check. -
WebReflection revised this gist
Nov 9, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,7 +6,7 @@ In this document I would like to describe, via JS itself, and as PoC, how JSX co ### Goal Differently from E4X, but also differently from JSX, this proposal leaves developers provide their own "*render*" implementation, freeing ESX usage from any previous attempt to confine JSX or E4X into the DOM world, where it's been proven, in the JSX case, it's not really where it belongs, as it can be used as neutral, general purpose, DSL. This document describes all the moving parts of ESX in a way that: -
WebReflection revised this gist
Nov 9, 2022 . 1 changed file with 6 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,6 +22,7 @@ This document describes all the moving parts of ESX in a way that: // base class: the only class needed in userland to: // * check if a child value is an instanceof ESXToken // * retrieve all XXX_TYPE values to properly parse // represented as {type: number, value} class ESXToken { // property/ies + interpolations + templates static STATIC_TYPE = 1 << 0; // 1 @@ -45,6 +46,7 @@ class ESXToken { } // any property // represented as {type: 1 | 2 | 4, name: string, value} class ESXProperty extends ESXToken { /** * @param {Object} property @@ -59,6 +61,7 @@ class ESXProperty extends ESXToken { } // Outer JSX template elements // represented as {type: 8, id, value} class ESXTemplate extends ESXToken { /** * @param {Object} template @@ -88,6 +91,7 @@ class ESXChevrons extends ESXToken { } // any <tag-name /> // represented as {type: 64, value: string, properties, children: []} class ESXElement extends ESXChevrons { /** * @@ -101,6 +105,7 @@ class ESXElement extends ESXChevrons { } // any <>fragment</> // represented as {type: 128, value: null, properties: null, children: []} class ESXFragment extends ESXChevrons { /** * @@ -114,6 +119,7 @@ class ESXFragment extends ESXChevrons { } // any <Component /> // represented as {type: 256, value: Function, properties, children: []} class ESXComponent extends ESXChevrons { /** * @param {Function} value the component callback -
WebReflection revised this gist
Nov 9, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -13,7 +13,7 @@ This document describes all the moving parts of ESX in a way that: * there is no DOM at all involved, only new primitives introduced by JSX * all relevant details around each part of the transformation are described through simple objects, here represented as classes instances, but these easily work just as object literals (easy polyfills via transformers) * no extra scope pollution is needed, hence no `jsxPragma` or `jsxFragment` around is required at all (no `React.createElement` or `React.Fragment` needed, nor `udomsay.interpolation`) * all classes can be used just as types to infer, as oppsite of being really classes ... no clashing in the logic can happen neither. The only global class needed out there is `ESXToken` which carries types and the prototypal inheritance for brand check. * hints to "*parse-once*" through templates and/or Components are all over the place, making *usignal* like alternative implementations possible, but also any *SSR* related project can benefit from these ## ESX -
WebReflection revised this gist
Nov 9, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,7 +12,7 @@ This document describes all the moving parts of ESX in a way that: * there is no DOM at all involved, only new primitives introduced by JSX * all relevant details around each part of the transformation are described through simple objects, here represented as classes instances, but these easily work just as object literals (easy polyfills via transformers) * no extra scope pollution is needed, hence no `jsxPragma` or `jsxFragment` around is required at all (no `React.createElement` or `React.Fragment` needed, nor `udomsay.interpolation`) * all classes can be used just as types to infer, as oppsite of being really classes ... no clashing in the logic can happen neither * hints to "*parse-once*" through templates and/or Components are all over the place, making *usignal* like alternative implementations possible, but also any *SSR* related project can benefit from these -
WebReflection revised this gist
Nov 9, 2022 . 1 changed file with 146 additions and 152 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -19,82 +19,109 @@ This document describes all the moving parts of ESX in a way that: ## ESX ```js // base class: the only class needed in userland to: // * check if a child value is an instanceof ESXToken // * retrieve all XXX_TYPE values to properly parse class ESXToken { // property/ies + interpolations + templates static STATIC_TYPE = 1 << 0; // 1 static MIXED_TYPE = 1 << 1; // 2 static RUNTIME_TYPE = 1 << 2; // 4 static TEMPLATE_TYPE = 1 << 3; // 8 // angle-brackets kind static ELEMENT_TYPE = 1 << 6; // 64 static FRAGMENT_TYPE = 1 << 7; // 128 static COMPONENT_TYPE = 1 << 8; // 256 /** * @param {number} type any ESXToken.XXX_TYPE * @param {any} value the value carried by this token */ constructor(type, value) { this.type = type; this.value = value; } } // any property class ESXProperty extends ESXToken { /** * @param {Object} property * @param {number} property.type ESXToken.STATIC_TYPE | ESXToken.MIXED_TYPE | ESXToken.RUNTIME_TYPE * @param {string} property.name the property name * @param {any} property.value the property value */ constructor(type, name, value) { super(type, value); this.name = name; } } // Outer JSX template elements class ESXTemplate extends ESXToken { /** * @param {Object} template * @param {object} template.id unique template reference * @param {ESXEntry} template.value the entry value this template carries */ constructor(id, value) { super(ESXToken.TEMPLATE_TYPE, value); this.id = id; } } // <any /> <>angle</> <Brackets /> class ESXChevrons extends ESXToken { /** * * @param {number} type ESXToken.ELEMENT_TYPE | ESXToken.FRAGMENT_TYPE | ESXToken.COMPONENT_TYPE * @param {string | null | Function} value * @param {ESXToken | null} properties * @param {ESXToken[]} children */ constructor(type, value, properties, children) { super(type, value); this.properties = properties; this.children = children; } } // any <tag-name /> class ESXElement extends ESXChevrons { /** * * @param {string} value the tag name * @param {ESXToken | null} properties the properties, if any * @param {ESXToken[]} children zero, one, or more element child */ constructor(value, properties, ...children) { super(ESXToken.ELEMENT_TYPE, value, properties, children); } } // any <>fragment</> class ESXFragment extends ESXChevrons { /** * * @param {null} value fragments have no representation * @param {ESXToken | null} properties the properties, if any * @param {ESXToken[]} children zero, one, or more element child */ constructor(...children) { super(ESXToken.FRAGMENT_TYPE, null, null, children); } } // any <Component /> class ESXComponent extends ESXChevrons { /** * @param {Function} value the component callback * @param {ESXToken | null} properties the properties, if any * @param {ESXToken[]} children zero, one, or more element child */ constructor(value, properties, ...children) { super(ESXToken.COMPONENT_TYPE, value, properties, children); } } ``` @@ -107,26 +134,21 @@ const div = <div />; ```js // internal representation const templateReference1 = {}; const div = new ESXTemplate( templateReference1, new ESXElement('div', null) ); ``` ```js // concrete JS representation const templateReference1 = {}; const div = { id: templateReference1, type: 8, value: { type: 64, value: 'div', properties: null, children: [] } }; @@ -140,61 +162,51 @@ const div = <div a="a" b={"b"}><p>c</p></div>; ```js // internal representation const templateReference2 = {}; const div = new ESXTemplate( templateReference2, new ESXElement( 'div', // properties token new ESXToken( // STATIC_TYPE: // all properties are static // MIXED_TYPE: // properties can also be static // RUNTIME_TYPE: // all properties are runtime, such as // <div even="though" {...spread} /> // case that can overwrite also static props ESXToken.MIXED_TYPE, // properties value [ new ESXProperty(ESXToken.STATIC_TYPE, 'a', 'a'), new ESXProperty(ESXToken.RUNTIME_TYPE, 'b', 'b') ] ), // a static child new ESXToken( ESXToken.STATIC_TYPE, new ESXElement( 'p', null, new ESXToken(ESXToken.STATIC_TYPE, 'c') ) ) ) ); ``` ```js // concrete JS representation const templateReference2 = {}; const div = { id: templateReference2, type: 8, value: { type: 64, value: 'div', properties: { type: 2, value: [ {type: 1, name: 'a', value: 'a'}, {type: 4, name: 'b', value: 'b'} ] @@ -203,7 +215,7 @@ const div = { { type: 1, value: { type: 64, value: 'p', properties: null, children: [ @@ -236,70 +248,50 @@ const component = <MyComponent a="a" {...props} />; const templateReference3 = {}; const templateReference4 = {}; function MyComponent(...args) { return new ESXTemplate( templateReference3, new ESXFragment( // child as interpolation new ESXToken(ESXToken.RUNTIME_TYPE, 'A'), // the static comma interpolations separator new ESXToken(ESXToken.STATIC_TYPE, ', '), // last child as interpolation new ESXToken(ESXToken.RUNTIME_TYPE, 'B'), ) ); } const props = {a: '', b: 'b'}; const component = new ESXTemplate( templateReference4, new ESXComponent( MyComponent, new ESXToken( // there is a {...spread} involved which could // overwrite even known static props ESXToken.RUNTIME_TYPE, // properties value [ new ESXProperty(ESXToken.STATIC_TYPE, 'a', 'a'), new ESXProperty(ESXToken.RUNTIME_TYPE, 'props', props) ] ) ) ); ``` ```js // concrete JS representation const templateReference3 = {}; const templateReference4 = {}; function MyComponent(...args) { return { id: templateReference3, type: 8, value: { type: 128, value: null, properties: null, children: [ {type: 4, value: 'A'}, @@ -313,16 +305,18 @@ function MyComponent() { const props = {a: '', b: 'b'}; const component = { id: templateReference4, type: 8, value: { type: 256, value: MyComponent, properties: { type: 4, value: [ {type: 1, name: 'a', value: 'a'}, {type: 4, name: 'props', value: props} ] }, children: [] } }; ``` -
WebReflection revised this gist
Nov 8, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -90,7 +90,7 @@ class ESXTemplate { /** * @param {Object} template * @param {object} template.id unique template reference * @param {ESXEntry} template.value the entry value this template refer to */ constructor({id, value}) { this.id = id; -
WebReflection revised this gist
Nov 8, 2022 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,7 +8,7 @@ In this document I would like to describe, via JS itself, and as PoC, how JSX co Differently from E4X, but also differently from JSX, this proposal leaves developers provide their own "*render*" implementation, freeing ESX usage from any previous attempt to confine JSX or E4X into the DOM world, where it's been proven, in the JSX case, it's not really where it belongs, as it can be used as neutral DSL. This document describes all the moving parts of ESX in a way that: * there is no DOM at all involved, only new primitives introduced by JSX * all relevant details around each part of the transformation are described through simple objects, here represented as classes instances, but these easily work just as object literals (easy polyfills via transformers) -
WebReflection revised this gist
Nov 8, 2022 . 1 changed file with 8 additions and 36 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -195,16 +195,8 @@ const div = { properties: { type: 2, values: [ {type: 1, name: 'a', value: 'a'}, {type: 4, name: 'b', value: 'b'} ] }, children: [ @@ -215,10 +207,7 @@ const div = { value: 'p', properties: null, children: [ {type: 1, value: 'c'} ] } } @@ -313,18 +302,9 @@ function MyComponent() { value: ESXFragment, properties: null, children: [ {type: 4, value: 'A'}, {type: 1, value: ', '}, {type: 4, value: 'B'} ] } }; @@ -339,16 +319,8 @@ const component = { properties: { type: 4, values: [ {type: 1, name: 'a', value: 'a'}, {type: 4, name: 'props', value: props} ] } } -
WebReflection revised this gist
Nov 8, 2022 . 1 changed file with 109 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -118,6 +118,19 @@ const div = new ESXTemplate({ ) }); ``` ```js // concrete JS representation const templateReference1 = {}; const div = { id: templateReference1, value: { type: 1, value: 'div', propertis: null, children: [] } }; ``` #### Nested elements + props ```jsx @@ -171,6 +184,48 @@ const div = new ESXTemplate({ ) }); ``` ```js // concrete JS representation const templateReference2 = {}; const div = { id: templateReference2, value: { type: 1, value: 'div', properties: { type: 2, values: [ { type: 1, name: 'a', value: 'a' }, { type: 4, name: 'b', value: 'b' } ] }, children: [ { type: 1, value: { type: 1, value: 'p', properties: null, children: [ { type: 1, value: 'c' } ] } } ] } }; ``` #### All together ```jsx @@ -245,6 +300,60 @@ const component = new ESXTemplate({ ) }); ``` ```js // concrete JS representation const templateReference3 = {}; const templateReference4 = {}; function MyComponent() { return { id: templateReference3, value: { type: 2, value: ESXFragment, properties: null, children: [ { type: 4, value: 'A' }, { type: 1, value: ', ' }, { type: 4, value: 'B' } ] } }; } const props = {a: '', b: 'b'}; const component = { id: templateReference4, value: { type: 4, value: MyComponent, properties: { type: 4, values: [ { type: 1, name: 'a', value: 'a' }, { type: 4, name: 'props', value: props } ] } } }; ``` ### Please help me out! -
WebReflection created this gist
Nov 8, 2022 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,253 @@ ### About In a quest to explore improvements over common JSX transformers I have managed to [find great performance](https://twitter.com/WebReflection/status/1589741329378324480?s=20&t=DnTQ1z7G-77ufAMAIeXjrQ) able to compete with template literal based libraries. In this document I would like to describe, via JS itself, and as PoC, how JSX could be both rebranded as ESX and improved. ### Goal Differently from E4X, but also differently from JSX, this proposal leaves developers provide their own "*render*" implementation, freeing ESX usage from any previous attempt to confine JSX or E4X into the DOM world, where it's been proven, in the JSX case, it's not really where it belongs, as it can be used as neutral DSL. This document describes all the moving part of ESX in a way that: * there is no DOM at all involved, only new primitives introduced by JSX * all relevant details around each part of the transformation are described through simple objects, here represented as classes instances, but these easily work just as object literals (easy polyfills via transformers) * no extra scope pollution is needed, hence no `jsxPragma` or `jsxFragment` around is required at all * all classes can be used just as types to infer, as oppsite of being really classes ... no clashing in the logic can happen neither * hints to "*parse-once*" through templates and/or Components are all over the place, making *usignal* like alternative implementations possible, but also any *SSR* related project can benefit from these ## ESX ```js // unique identifier for the fragment const ESXFragment = Symbol('ESX.Fragment'); // basic ESX value wrapper class ESXValue { static Static = 1 << 0; static Mixed = 1 << 1; static Runtime = 1 << 2; /** * @param {Object} details * @param {number} details.type ESXValue.Static | ESXValue.Mixed | ESXValue.Runtime * @param {any} details.value the reference carried through this instance */ constructor({type, value}) { this.type = type; this.value = value; } } // specialized ESX property value class ESXProperty extends ESXValue { /** * @param {Object} details * @param {number} details.type ESXValue.Static | ESXValue.Mixed | ESXValue.Runtime * @param {string} details.name the entry carried through this reference * @param {any} details.value the entry carried through this reference */ constructor({type, name, value}) { super({type, value}); this.name = name; } } // Static, Mixed,or Runtime properties wrapper class ESXProperties { /** * @param {Object} details * @param {number} details.type ESXValue.Static | ESXValue.Mixed | ESXValue.Runtime * @param {ESXProperty[]} details.values */ constructor({type, values}) { this.type = type; this.values = values; } } // Element, Fragment, or Component wrapper class ESXEntry { static Element = 1 << 0; static Fragment = 1 << 1; static Component = 1 << 2; /** * @param {Object} entry * @param {numer} entry.type ESXEntry.Element | ESXEntry.Fragment | ESXEntry.Component * @param {string | symbol | Function} entry.value tag name | ESXFragment | Component * @param {ESXProperties | null} properties * @param {...ESXValue[]} children */ constructor({type, value}, properties, ...children) { this.type = type; this.value = value; this.properties = properties; this.children = children; } } // Outer JSX template elements class ESXTemplate { /** * @param {Object} template * @param {object} template.id unique template reference * @param {ESXEntry} template.value unique template reference */ constructor({id, value}) { this.id = id; this.value = value; } } ``` #### Basic expectations ```jsx // ESX const div = <div />; ``` ```js // internal representation const templateReference1 = {}; const div = new ESXTemplate({ id: templateReference1, value: new ESXEntry( { type: ESXEntry.Element, value: 'div' }, null ) }); ``` #### Nested elements + props ```jsx // ESX const div = <div a="a" b={"b"}><p>c</p></div>; ``` ```js // internal representation const templateReference2 = {}; const div = new ESXTemplate({ id: templateReference2, value: new ESXEntry( { type: ESXEntry.Element, value: 'div' }, new ESXProperties({ // Static: all properties are static // Mixed: properties can also be Static // Runtime: all properties are runtime, such as // <div even="though" {...spread} /> // case that can overwrite also static props type: ESXProperty.Mixed, values: [ new ESXProperty({ type: ESXProperty.Static, name: 'a', value: 'a' }), new ESXProperty({ type: ESXProperty.Runtime, name: 'b', value: 'b' }) ] }), new ESXValue({ type: ESXValue.Static, value: new ESXEntry( { type: ESXEntry.Element, value: 'p' }, null, new ESXValue({ type: ESXValue.Static, value: 'c' }) ) }) ) }); ``` #### All together ```jsx // ESX function MyComponent(...args) { return ( <> {'A'}, {'B'} </> ); } const props = {a: '', b: 'b'}; const component = <MyComponent a="a" {...props} />; ``` ```js // internal representation const templateReference3 = {}; const templateReference4 = {}; function MyComponent() { return new ESXTemplate({ id: templateReference3, value: new ESXEntry( { type: ESXEntry.Fragment, value: ESXFragment }, null, // children as interpolations new ESXValue({ type: ESXValue.Runtime, value: 'A' }), //the static comma interpolations separator new ESXValue({ type: ESXValue.Static, value: ', ' }), new ESXValue({ type: ESXValue.Runtime, value: 'B' }) ) }); } const props = {a: '', b: 'b'}; const component = new ESXTemplate({ id: templateReference4, value: new ESXEntry( { type: ESXEntry.Component, value: MyComponent }, new ESXProperties({ type: ESXProperty.Runtime, values: [ new ESXProperty({ type: ESXProperty.Static, name: 'a', value: 'a' }), new ESXProperty({ type: ESXProperty.Runtime, name: 'props', value: props }) ] }) ) }); ``` ### Please help me out! If you have ideas around possible improvements, if you want to bring this to the TC39 attention as champion, if have any question related to this proposal, or if you'd like to know more about how *udomsay* became the fastest and smallest runtime using 90% of this proposal through a dedicated transformer, I will be more than happy if you could reach out, either here, in twitter, or in mastodon. Thank you very much for your patience reading through this gist 🙏