# Proposal: ESX as core JS feature

**URL:** <https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [November 9, 2022, 2:42pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511 "2022-11-09T14:42:45Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 24, 2022, 12:13pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/41 "2022-11-24T12:13:04Z")

</div>

**edit** actually never mind as this misses interpolations as child nodes so that the boolean without a specific type INTERPOLATION hence an Interpolation class won't represent all cases ... sorry for the confusion.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 24, 2022, 1:12pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/42 "2022-11-24T13:12:00Z")

</div>

@bergus OK, I think this is the most elegant and easy to reason about representation of ESX:

- it never requires usage of `typeof`
- it defines interpolations as either attributes or children
- it could have unique IDs all over the place in specs, but the Babel transformer for the time being will simply ignore, or better never set, IDs for static nested components or elements / fragments
- it uses type to describe the shape we're dealing with, these can be symbols too, it doesn't matter (JSON can understand these and use numbers instead on serialization)
- it allows interpolations non spec'd ... it doesn't have to be spread, but I am still convinced for attributes spread should be the only non named attribute allowed, while spreading within a named attribute should throw, as well as having just `{123}` in the wild should ... still TBD but this proposal won't stop decisions there
- all details are still available so that any library can decide best strategy to consume each and every token of ESX

```nohighlight
interface Token {
  __proto__ : Token.prototype
  type: Token.ATTRIBUTE |
        Token.COMPONENT |
        Token.ELEMENT |
        Token.FRAGMENT |
        Token.INTERPOLATION |
        Token.STATIC
}

// non constructable
interface Template extends Token {
  id: null | object | symbol
  children: (
    Component | Element | Fragment | Interpolation | Static
  )[]
}

// constrcutables?
interface Attribute extends Token {
  type: Token.ATTRIBUTE
  dynamic: boolean
  name: string
  value: unknown
}

interface Component extends Template {
  type: Token.COMPONENT
  value: function // object or any ref in the scope, really
  attributes: (Attribute | Interpolation)[]
}

interface Element extends Template {
  type: Token.ELEMENT
  name: string
  attributes: (Attribute | Interpolation)[]
}

interface Fragment extends Template {
  type: Token.FRAGMENT
}

interface Interpolation extends Token {
  type: Token.INTERPOLATION
  value: unknown
}

interface Static extends Token {
  type: Token.STATIC
  value: string
}

```

The key-change here is around `Attribute` and its `dynamic` field, which already distinguishes between static, dynamic, and keeps interpolation for spread around, so nothing is missed.

The `Static` interface might seem redundant on the surface, but it makes operations around children `typeof` or `instanceof` free which is not only great for performance, but I believe it improves DX too.

`Static` can never be an attribute, there's an interface for attributes indeed, but it could be part of the children list. All statics means one-off population/render and bye bye ... very desirable.

This version would address all your points but also will address all my points, and it doesn't stagnate this proposal as all IDs are fine, id as symbol are fine, types as symbol are fine, and so are bitwise operations but all of this is left to transformer implementations or the eventual standard definition but it won't block me from updating/rewriting the vurrent ESX transformer, and it shouldn't stop anyone else from defining best type/primitive to use to define 'em all.

I hope this middle-ground compromise works well, and I think it can cover every single case. If that's not the case though, I'd be happy to re-iterate on this one more time ... but I think at this point I might end up out of ideas.

**edit** for transformer / history sake, this is how the class would look with this proposal in related repositories:

```nohighlight
class ESXToken {
  static ATTRIBUTE = 1;
  static COMPONENT = 2;
  static ELEMENT = 3;
  static FRAGMENT = 4;
  static INTERPOLATION = 5;
  static STATIC = 6;

  // internal/transformer implementation details
  static a = (dynamic, name, value) => ({
    __proto__ : ESXToken.prototype,
    type: 1, dynamic, name, value
  });
  static c = (id, value, attributes, children) => ({
    __proto__ : ESXToken.prototype,
    type: 2, id, value, attributes, children
  });
  static e = (id, name, attributes, children) => ({
    __proto__ : ESXToken.prototype,
    type: 3, id, name, attributes, children
  });
  static f = (id, children) => ({
    __proto__ : ESXToken.prototype,
    type: 4, id, children
  });
  static i = value => ({
    __proto__ : ESXToken.prototype,
    type: 5, value
  });
  static s = value => ({
    __proto__ : ESXToken.prototype,
    type: 6, value
  });
}

```

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 24, 2022, 1:17pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/43 "2022-11-24T13:17:39Z")

</div>

P.S. I've sponsored the current ESX transformer and that costed both time and money so I am not updating neither the gist nor the transformer until we reach somehow an agreement that can move this proposal forward. If that won't happen, I might still try to adjust the transformer and update the gist to represent my latest attempt just to prove everything _can_ work and _does_ work as expected already, but FYI please don't take the current gist or transformer for granted, as it's clear things are moving pretty fast (although my latest attempt is close to what we have already as ESX transformer).

I am updating all posts specifying this after posting this comment so that new-comers will also be informed about the current state of both gist proposal and transformer. Thanks for your patience and understanding.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 25, 2022, 2:13pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/44 "2022-11-25T14:13:47Z")

</div>

P.S. a better polyfill suggestion might be this one, in case there is an agreement all issues have been addressed:

```nohighlight
export class ESXToken {
  static ATTRIBUTE = 1;
  static COMPONENT = 2;
  static ELEMENT = 3;
  static FRAGMENT = 4;
  static INTERPOLATION = 5;
  static STATIC = 6;
}

export class ESXAttribute extends ESXToken {
  type = ESXToken.ATTRIBUTE;
  constructor(dynamic, name, value) {
    this.dynamic = dynamic;
    this.name = name;
    this.value = value;
  }
}

class ESXDetail extends ESXToken {
  constructor(value) {
    this.value = value;
  }
}

export class ESXInterpolation extends ESXDetail {
  type = ESXToken.INTERPOLATION;
}

export class ESXStatic extends ESXDetail {
  type = ESXToken.STATIC;
}

class ESXTemplate extends ESXToken {
  constructor(id, children) {
    this.id = id;
    this.children = children;
  }
}

export class ESXFragment extends ESXTemplate {
  type = ESXToken.FRAGMENT;
}

export class ESXComponent extends ESXTemplate {
  type = ESXToken.COMPONENT;
  constructor(id, value, attributes, children) {
    super(id, children);
    this.value = value;
    this.attributes = attributes;
  }
}

export class ESXElement extends ESXFragment {
  type = ESXToken.ELEMENT;
  constructor(id, name, attributes, children) {
    super(id, children);
    this.name = name;
    this.attributes = attributes;
  }
}

```

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 28, 2022, 3:03pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/45 "2022-11-28T15:03:08Z")

</div>

FYI I've changed the _ESXToken_ class and also the transformer to satisfy latest discussions.  
The current MR is here: [v0.2 with perf and structural changes by WebReflection · Pull Request #3 · ungap/babel-plugin-transform-esx · GitHub](https://github.com/ungap/babel-plugin-transform-esx/pull/3)

The current TS like description is [the following](https://github.com/ungap/esxtoken#esxtoken):

 ![Screenshot from 2022-11-29 12-44-40](https://global.discourse-cdn.com/free1/uploads/es/original/2X/4/4fc3857e7909ade0b7b2cea9cdffd3479ad8626d.png)

**edit** I now have 100% test covered polyfill for the proposal and the only misaligned part is that statics are numbers instead of Symbols, and the `name` field for the _ESXElement_ case is still `value`. To make relevant classes homogeneous I've used `value` instead, but if there's any will to move this forward as ECMAScript implementation I'll be more than happy to add some extra logic to have the `name` field for elements too and/or improve the polyfill in general.

However, I must admit I am pretty pleased with how the original idea became actually simpler, yet more structured, still satisfying all requirements around discussions and non-blocking possible improvements (e.g. interpolation also as non spread operations).

As summary, the current _ESXToken_ polyfill and transformer look pretty aligned and "_done_" at this point, so thanks so far to all participants.

**edit2**

> Showing **3 changed files** with **50 additions** and **112 deletions**.

the latest transformer makes _SSR_ an absolute no-brainer to deal with 🥳 [this split is amazing](https://github.com/WebReflection/esx/commit/6bf4dc65ddd3e4d346a8a1adfd9cb5e8fe9568e2?diff=split)

---

<div class="post-metadata">

**Author:** ![pygy](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/pygy/32/231_2.png) [@pygy](https://es.discourse.group/u/pygy)\
**Post date:** [November 30, 2022, 12:43pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/46 "2022-11-30T12:43:05Z")

</div>

@WebReflection I have a nit to pick regarding your table, I think that you can spread properties using tagged templates: `h`<x ...${{aha: "oho"}}>``.

* * *

* * *

@mhofman Early errors are always better, the shorter the feedback loop, the more you can stay in the zone and the quicker you can fix your mistakes. The industry moving towards TypeScript is not a coincidence, squiggle-oriented programming rules.

In a world where JSX isn't a thing, `esx`<div>` ` would have had the advantage of tooling backwards compatibility.

But JSX exists, it is widely supported by the ecosystem, and the ESX syntax is backwards compatible with it.

From an implementation stand point, a naive JS parser that generates the inline ESX data structures at load time would increase the initial parse time vs having a template tag. However, AFAIK, JS parsers are tiered with a pre-parser that doesn't create an AST, so the overhead of the inline syntax should be minimal.

So ultimately (and for the host of reasons listed by @WebReflection) I think that inline ESX is superior to a builtin template tag.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 30, 2022, 1:02pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/47 "2022-11-30T13:02:51Z")

</div>

> [@pygy](#):
>
> I think that you can spread properties using tagged templates: `h`\<x ...${{aha: "oho"}}\>``.

That requires a tag that checks last 4 chars of a chunk of the template to see if it's ` ...` and, after that, it crawls all chunks before that to be sure that's actually a spread within an element or component, which is the error prone approach I've mentioned as there is no context or notion of the fact spread is happening as element spread, instead of a content spread like it is in the `<pre> ...${anything}</pre>` case.

**edit** let's keep in mind the `...` just scratches the surface of the amount of issues using strings around would cause ... invalid attributes, or even elements name, are another check: do we really want to have so much slowdown through template literal tags so that we end up representing trees with a tool that was not designed to represent XML like trees?

[this parser](https://github.com/WebReflection/uparser/blob/9783796c2d38b0dd65fa3632ed0d804e45b338f2/esm/index.js) is optimistic and it provides zero feedback on wrong syntax.

[this one is also problematic](https://github.com/WebReflection/domsanitizer/blob/093f07c94cdb96ca7d8403423f03b054a625cb5d/esm/index.js).

A slower but more convoluted solution previously adopted [is still error prone](https://github.com/WebReflection/uparser/commit/bac19e5027e20c31641e34827bfca0591b91be70#diff-da39439bf50b1a9758067fbc3d3309420fca5569f4a03f3649cb27b3de92ac5eR1-R36).

On top of that, let's compare the potential future of JS to define trees, if we go with the template literal proposed alternative:

```js
// template literal tag with scope resolution
esx`<${Component} ...${props}> ...${text}</${Component}>`;
esx`<${Component} ...${props} />`;

// VS this proposal
<Component {...props}> ...{text}</Component>;
<Component {...props} />;

```

There are visual hints in current IDEs that makes reading this proposal 20x easier than dealing with the template literal tag alternative, which is why I still believe _ESX_ as template literal tag is a dead-end.

> [@pygy](#):
>
> I think that inline ESX is superior to a builtin template tag.

Thanks for sharing some love around _ESX_, appreciated!

---

<div class="post-metadata">

**Author:** ![pygy](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/pygy/32/231_2.png) [@pygy](https://es.discourse.group/u/pygy)\
**Post date:** [November 30, 2022, 1:18pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/48 "2022-11-30T13:18:30Z")

</div>

Is spread syntax even needed in children position? `<pre>${yop}<pre>` can dispatch at run time on the type of `yop`, and treat it as a fragment if it is an Array (or even iterable). _Edit: I think I see you point, in children position, you want the triple dots to be interpreted as a static string, and thus you have to parse all string fragments up to that point and pieces to know what to do with them._

Otherwise, I agree that visual clutter is another major drawback with the template tag solution, and the reason why I never adopted or even explored such a solution.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 30, 2022, 1:26pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/49 "2022-11-30T13:26:14Z")

</div>

> [@pygy](#):
>
> Is spread syntax even needed in children position?

That's not a spread ... it was the whole point of comparison: with template literal tags you can't define an explicit spread intent ... it's all the same, with dots before ... in ESX the spread on text breaks as indeed children as spread are not, and should not, be supported, for the static children position as index previously mentioned and, like you said, the ability to understand/accept array as children.

The outcome of my example is that the component receives props and it has **text content** ` ...whatever` ... let me rewrite the example:

```jsx
const text = 'test';
const props = {a: 'ny'};

function Component({a}, ...children) {
  return `<div a="${a}">${children.join('')}</div>`;
}

// both solutions return these two strings:
// <div a="ny"> ...test</div>
// <div a="ny"></div>

// template literal tag with scope resolution
esx`<${Component} ...${props}> ...${text}</${Component}>`;
esx`<${Component} ...${props} />`;

// VS this proposal
<Component {...props}> ...{text}</Component>;
<Component {...props} />;

```

Having `...` **outside** the _ESX_ means it's static string content as children ... having `...` anywhere in _esx_ as template literal tag means, visually, confusion to me.

---

<div class="post-metadata">

**Author:** ![pygy](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/pygy/32/231_2.png) [@pygy](https://es.discourse.group/u/pygy)\
**Post date:** [November 30, 2022, 1:26pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/50 "2022-11-30T13:26:50Z")

</div>

Yes, I edited my message, too late :-)

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 30, 2022, 1:33pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/51 "2022-11-30T13:33:22Z")

</div>

to complete the comparison, let's see what IDEs would show:

![Screenshot from 2022-11-30 14-32-29](https://global.discourse-cdn.com/free1/uploads/es/original/2X/a/a1e326b98e999bdcc8ad8517272261aa76b27321.png)

> [@pygy](#):
>
> Yes, I edited my message, too late :-)

to be fair, the fact you were already confused about spreading children with template literals _esx_ would suggest indeed that template literal tags are _not_ the road to take, imho (and the reason JSX won in terms of DX/adoption compared to "_standard template literal based_" alternatives).

---

<div class="post-metadata">

**Author:** ![pygy](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/pygy/32/231_2.png) [@pygy](https://es.discourse.group/u/pygy)\
**Post date:** [November 30, 2022, 2:26pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/52 "2022-11-30T14:26:43Z")

</div>

I've been out of the game for months, so not everything is pristine in my mind... When I come to think of it. You don't need spread syntax in attribute position either.

`<x staticName={dynValue} {spreadThisPls}>` could work too, by dispatching on the presence of `=` before the splice point if inside an element.

---

<div class="post-metadata">

**Author:** ![pygy](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/pygy/32/231_2.png) [@pygy](https://es.discourse.group/u/pygy)\
**Post date:** [November 30, 2022, 3:11pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/53 "2022-11-30T15:11:21Z")

</div>

Another thing that comes to mind is the fact that, as proposed, a new template tree is allocated every time the ESX expression is evaluated.

We could use our own advice re. static vs dynamic bits, and hoist the template allocation, then only allocate a single ESXInstance object with a

```javascript
{
  template: ESXElement | ESXFragment | ESXComponent,
  values: any[], 
  metadata: any = null
}

```

structure.

It would be best IMO if the template tree was made of immutable values (see [records and tuples](https://github.com/tc39/proposal-record-tuple)) since it derives from the immutable source code, and that would offer strong guarantees to consumers. I wouldn't want this to be blocked on another proposal though, I just think it makes sense conceptually, if records and tuples land before this.

Hoisting the static template would also make it easier to the consuming code to find the dynamic bits without having to reach deep within the ESXNode tree (assuming the ESX tree is compiled by a library into, say, a

```javascript
interface Compiled{  
  DOM, 
  setters: Array<(x:any)=>void>
}

```

and kept in in a `(Template => Compiled)` map the first time it is seen. The immutable template can be used as key, no need for an explicit ID. From then on, subsequent invocations can clone the DOM and iterate through the setters/values). I'd expect this to perform better. It would be gentler on the allocator/GC, and would have fewer property lookups.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 30, 2022, 3:13pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/54 "2022-11-30T15:13:22Z")

</div>

> [@pygy](#):
>
> You don't need spread syntax in attribute position either

that makes the proposal break with current industry de-facto standard but it's true ... although ...

> [@pygy](#):
>
> `<x staticName={dynValue} {spreadThisPls}>` could work too

that still requires look behind to rebuild and understand it's attributes we're after, not just content, so it needs to crawl previous chunks and guestimate what's the intent ... as previously mentioned after editing, `...spread` within _ESX_ is just **one** of the many issues around templates based solutions.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 30, 2022, 3:16pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/55 "2022-11-30T15:16:15Z")

</div>

everything in this comment looks based on older proposal ... the latter one, and its transformer, covers everything except it doesn't output frozen references, but that won't work anyway for repeated updates with different values in those interpolations. The latest proposal fixes all previous points, so please be sure you have looked at it, otherwise we might discuss stuff already discussed and changed.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 30, 2022, 3:18pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/56 "2022-11-30T15:18:08Z")

</div>

> [@pygy](#):
>
> ```javascript
> interface Compiled{  
> DOM, 
> setters: Array<(x:any)=>void>
> }
> 
> ```

also ... anything with _DOM_ in it is a red-flag to me, as _ESX_ has strictly nothing to do with the _DOM_, so pointing at it won't make it portable for SSR or any other environment where _DOM_ doesn't exist.

Current proposal works already even in Espruino devices, and I believe as syntax and nothing else that should be a desirable goal. Make it _DOM_ related and it doesn't belong to TC39 anymore.

---

<div class="post-metadata">

**Author:** ![pygy](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/pygy/32/231_2.png) [@pygy](https://es.discourse.group/u/pygy)\
**Post date:** [November 30, 2022, 3:35pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/57 "2022-11-30T15:35:34Z")

</div>

Yes, let's forget the DOM for a minute.

> [Proposal: ESX as core JS feature - #45 by WebReflection](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/45)

^^^ This is the latest proposal, right?

What I propose is to:

- drop `ESXNode.id` and `ESXInterpolation.value`.
- Hoist the ESXNode tree and use the root node as ID (or even sub nodes, for element passed as children to components)
- Only allocate a `{template: ESXNode, values: unkown[], metadata?}` object when an ESX expression is evaluated.

The client code can then walk the tree, and consume the `values` array in order when it finds `ESXInterpolation` nodes.

As an optimization, user code can compile the template into a different representation (I picked DOM because it is a well known example), with setters that match the interpolations. On a further run, the setters can consume the dynamic values in order.

_Edit: clarification in the last paragraph_

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 30, 2022, 3:46pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/58 "2022-11-30T15:46:57Z")

</div>

> [@pygy](#):
>
> ^^^ This is the latest proposal, right?

correct

> [@pygy](#):
>
> drop `ESXNode.id` and `ESXInterpolation.value`.

the `id` is there because as previously discussed a representation of ESX cannot be frozen. I mean, it could be unique (like the id already is) but its attributes or children values cannot be frozen (or your values as I understand these).

In previous discussions the id should be unique per each static children too, to which I disagree as it has no practical usage, but current proposal doesn't stop that from happening, real-world consumers like _udomsay_ library wouldn't care a single bit about those though.

> [@pygy](#):
>
> Only allocate a `{template: ESXNode, values: unkown[], metadata?}` object when an ESX expression is evaluated.

It wouldn't be enough. Attributes and children must be understood and a static template as component has no meaning in your representation, if I understand correctly. `<Component />` is a valid unique outer template and it means nothing, because `Component(props, ...children)` is what matters, as it can return anything, _if_ anything is even returned. A component can be outer template or sub-tree static children too, having it either ways tells the consumer nothing in practice. Current ESX still provides an ID but it's discarded in real world usage.

The reason I've sponsored and updated the _ESX_ Babel transformer is to stop guessing its usage and actually use it, like I am doing already with the _SSR_ example and planning to do with _udomsay_.

So far the latest proposal made me drop many lines of code and provides every single needed detail.

It'd be great if people would play around it instead of imagining how it works, because there is already an implementation of the current proposal, so we should (hopefully) start from there, not from scratch each time.

Current _udomsay_ library uses a different version of _ESX_ but it already showed the idea works, all details are there, anod literally nothing else is needed.

Can we make it better for GC and perf? I hope so ... but can we also try to use it in practice as there is already an implementation that covers everything already discussed in here? That'd be awesome!

> [@pygy](#):
>
> The client code can then walk the tree, and consume the `values` array in order when it finds `ESXInterpolation` nodes.

That's happening already.

> [@pygy](#):
>
> setters that match the interpolations

That is a consumer implementation detail, not magic behing _ESX_. _ESX_ is meant to land as **syntax** , not as library ... if we go for the latter I am pretty sure it'll never land.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 30, 2022, 4:03pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/59 "2022-11-30T16:03:25Z")

</div>

thinking about my latest reply, maybe we should discuss in a different way: which use case the current proposal wouldn't cover? To me it covers every possible use case _JSX_ covers already, except it has a way to _cache_ unique outer templates, _JSX_ doesn't, it reuse the same empty array for attributes or children, when not available (the GC and heap part), it provides an always crawable list of information either as attributes or children, no `typeof` checks or `instanceof` operations needed, and everything else is up to the consumer, like it is already, and worked, with the current _JSX_ standard, except nobody needs to define callbacks around the code, as the representation doesn't need any callback.

In short, current state is that _ESX_ already covers everything missing in _JSX_, and _JSX_ has been proven to work for any sort of client/server/native/mobile application, so we should kinda start from this fact and improve when, or if, is really necessary, without diverging too much, or I can see already memes floating around the proposal. That's at least my thinking ... we don't need to re-invent the wheel, we have an opportunity to make it "_rounder_" than it is, even if everyone is driving with squared wheels to date and that works regardless of GC or heap constraints we all do care about.

I hope this makes sense.

---

<div class="post-metadata">

**Author:** ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)\
**Post date:** [November 30, 2022, 4:15pm UTC](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511/60 "2022-11-30T16:15:37Z")

</div>

worth mentioning ... my current proposal took inspiration from _MutationObserver_ [records](https://developer.mozilla.org/en-US/docs/Web/API/MutationRecord) based API:

- `addedNodes` and `removedNodes` are always crawable (`attributes` and `children` in here) ... are these always the same unique frozen array when empty to avoid GC pressure? If I was the implementer, my answer would be _yes_ (current transformer indeed does that, it's always the same array, no GC pressure added)
- all other properties represent the actual record state ... these could be `null` or actually point to a value, independently from the kind of record/change these represent (curent proposal has that for `id` or `properties` and it could be extended as long as the `type` makes it possible to understand what kind of record we're dealing with)

The previous proposal had homogeneous, always same, _record_ structure, and accordingly with the `type` other properties/fields made sense to be accessed ... and this is kinda reflected with the current proposal too.

The `type` of a token is what matters, and _tokens_ should be expected in `attributes`, `children`, and can distinguish between all cases around templates (static, interpolation, attribute, element, fragment, component) so if we stick with this approach, I think the current transformer already satisfy all possible consumers, but of course it can be improved _if_ improvements are suggested.

This was just to underline current idea/API is nothing new for standard bodies, it's based on previous work that worked out there, and it's happy to change the `type` field as _symbol_ or _string_, where latter is used to describe operations in the _MutationObserver_ case.

[Previous page](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511.md?page=2)

[Next page](https://es.discourse.group/t/proposal-esx-as-core-js-feature/1511.md?page=4)
