You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`lang.mjs`:
Added the function `reset` which is a counterpart of `deref`.
Intended mainly for observable references from the `obs` module.
`isRec` and associated assertion functions now consider instances of
`Promise` to be non-records. This may help detecting some cases of
forgetting to use `await`.
`isCls` now returns `false` for all functions defined with the keyword
`function`, and `true` for anything defined with the keyword `class`,
as well as built-ins. Not all built-ins have been tested. It produces
false positives for some built-ins, such as `Symbol` and `BigInt`.
`show` now shows own enumerable properties, if any, when describing
functions and classes.
`obs.mjs`:
Dereferencing any observable via `l.deref` or `l.derefAll` is now a
reactive operation.
Added the function `getTar` for non-reactively dereferencing proxies.
This is supported by all types of observables provided by this
package. For inputs which do not specially implement this feature,
this simply returns the input, similarly to `l.deref`.
The new function `l.reset` works on all observables. The support
for `reset` in proxy-based observables is tentative: it requires
the input to be either nil or a record, and patches the target by
copying the own properties of the input, similar to `Object.assign`,
without deleting any pre-existing properties. This may be changed
to a full reset in the future. This is virtually identical to using
`Object.assign`, with the difference that the proxy trap `set` is
invoked only once, and in case of changes, the observable queue is
flushed only once. This may minimize the need for pausing the
synchronous scheduler when reassigning multiple fields.
Added a precaution against some cases of accidental infinite
recurrence. When a callback which runs in an implicitly reactive
context, such in a `recur`, modifies one of the observables which
it also observes, it will not recur from this modification.
`prax.mjs`:
Breaking changes across the board. A redesign of the system.
The renderer no longer has any methods with variadic parameters, and
no longer provides any methods with separate parameters for props and
children. Children have been rolled into props, under the keys `.chi`
or `.children`, which are treated the same. The chi-only methods such
as `.replaceChi` take children as a non-variadic parameter.
Props reactivity can be more fine-grained than before. Individual
props can be functions or observable references. When reactivity is
enabled, which is the default, each such prop will be automatically
updated on changes to any observables it uses, separately from other
props. Replacing a prop deinits the previous recurrent for that prop,
if any.
As a special case, props whose values are functions and keys begin
with `on` are treated non-reactively, assigning event callbacks as
usual.
Like before, the renderer still supports providing a function or an
observable reference as the entire props, or as an individual child
node.
Reverted a recent change where calls to `Ren..mutProps`, or calls to
`Ren..mut` with non-nil props, would entirely replace the previous
props. With children being part of the props, and individual props
having the option to be reactive, the replacement behavior is no
longer ergonomic, and can be a hurdle.
The renderer methods `E` and `S` now allow functions and classes as
the "target", the first argument. They immediately invoke the given
function or class with the props argument in an empty reactive
context, isolated from the reactive context of the caller. Code which
heavily uses observables and reactivity is encouraged to prefer the
calling convention `E(View, props)` over `View(props)` because this
automatically isolates reactive contexts from each other, preventing
accidental over-subscription, which in degenerate cases can lead to
infinite rendering loops without this precaution.
Small breaking change in `PropBui`: removed `.with` and renamed
`.mut`. The previous behavior of `.with` was to adopt the given
object, if any, for subsequent mutations. But remembering where
it was safe to adopt objects, vs where it wasn't and a copy was
needed, was too error prone, and the micro-optimization enabled
by this wasn't measurable anyway. Now it never mutates inputs.
Added `PropBui..chi` which stores `.children`, for compatibility
with the changes above.
`PropBui` no longer converts boolean props to booleans, for
compatibility with passing functions and observable references
in their place.
`dom_reg.mjs`:
Fixed how `.localName` set on superclasses is treated for subclasses.
An inherited "custom" `.localName` is ignored, while an inherited
non-"custom" `.localName` is respected.
`coll.mjs`:
Small breaking change: removed `CompatMap`.
`test.mjs`:
Small breaking change: renamed `optInst` to `instOpt`.
`http_deno.mjs`:
Added the `.txt` content type.
When guessing content types from file extensions, the latter are
treated case-insensitively.
True if the value is a non-iterable object. Excludes both {{link lang isIter sync_iterables}} and {{link lang isIterAsync async_iterables}}. Note that {{link lang isDict dicts}} are automatically records, but not all records are dicts.
4
+
5
+
Technically, promises would qualify as records under this definition. But as a
6
+
special case, instances of `Promise` are excluded to help detect the common
7
+
case of forgetting `await`. The overhead on that check should be virtually
Defines a "reference" interface which is consistently across all modules in this library. A "reference" is something that can be {{link lang deref}} into an underlying value. Any object can implement this interface by providing a symbolic property `Symbol.for("val")`.
2
+
3
+
References are used via the functions {{link lang deref}} and {{link lang reset}}.
4
+
5
+
The most notable reference types are observables provided by the module {{featLink obs}}.
6
+
7
+
The names `deref` and `reset` for this interface are lifted from Clojure.
These modifications automatically notify all observers monitoring the
@@ -84,7 +86,7 @@ setTimeout(() => {
84
86
Remove all nodes. When the engine runs garbage collection, all observers will
85
87
be automatically deinitialized and removed from observable queues.
86
88
*/
87
-
E(document.body, {},undefined)
89
+
E(document.body, {chi:undefined})
88
90
```
89
91
90
92
For operations with side effects, you can use lower-level procedural tools such as `recur`. Takes a function and an argument (in any order), and invokes it in a reactive context; future modifications of any observables accessed during the call will rerun the function.
@@ -248,6 +250,22 @@ finally {
248
250
}
249
251
```
250
252
253
+
### Classes
254
+
255
+
Any class can become observable by wrapping the instance in `obs` straight in the constructor. Make sure to actually return the resulting object from the constructor.
256
+
257
+
```js
258
+
import*asobfrom'{{featUrl obs}}'
259
+
260
+
classMyCls {constructor() {returnob.obs(this)}}
261
+
262
+
constval=newMyCls()
263
+
264
+
val instanceof MyCls // true
265
+
266
+
ob.isObsRef(val) // true
267
+
```
268
+
251
269
## Errors
252
270
253
271
In non-browser environments, exceptions in async scheduler callbacks crash the process. In browsers, they may lead to silent failures. In all environments, you should define your own error handling callbacks, with the logic appropriate for your app, and provide them to async schedulers.
Copy file name to clipboardExpand all lines: doc/prax_readme.md
+71-60Lines changed: 71 additions & 60 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,25 +8,25 @@ Supports observables and reactivity via the module {{featLink obs}}.
8
8
9
9
Short overview of features:
10
10
11
-
* Directly create DOM nodes.
12
-
* No string templates.
13
-
* No VDOM.
14
-
* Can instantiate with `new`.
15
-
* Convenient syntax. Nice-to-use in plain JS.
16
-
* No templates.
17
-
* No string parsing.
18
-
* No need for JSX.
19
-
* No need for a build system.
20
-
* Can use native [custom elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) for state.
21
-
* Use {{featLink dom_reg}} for more convenient element registration.
22
-
*Built-in reactivity with {{featLink obs}}.
23
-
* Good for SSR/SPA hybrids.
11
+
* Directly create DOM nodes.
12
+
* No string templates.
13
+
* No VDOM.
14
+
* Can instantiate with `new`.
15
+
* Convenient syntax. Nice-to-use in plain JS.
16
+
* No templates.
17
+
* No string parsing.
18
+
* No need for JSX.
19
+
* No need for a build system.
20
+
* Built-in reactivity with {{featLink obs}}.
21
+
* Can use native [custom elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements)for state.
22
+
*Use {{featLink dom_reg}} for more convenient element registration.
23
+
* Good for SSR/SPA hybrids.
24
24
25
25
Complemented by:
26
26
27
-
* {{featLink dom_shim}} for SSR.
28
-
* {{featLink dom_reg}} for registering custom elements in SSR.
29
-
* {{featLink obs}} for observables and implicit reactivity for elements.
27
+
* {{featLink dom_shim}} for SSR.
28
+
* {{featLink dom_reg}} for registering custom elements in SSR.
29
+
* {{featLink obs}} for observables and implicit reactivity for elements.
30
30
31
31
## TOC
32
32
@@ -40,19 +40,23 @@ Complemented by:
40
40
41
41
Rendering is done via `Ren`. You must create an instance, which should be a singleton. You can also subclass `Ren` and override individual methods to customize its behavior.
42
42
43
+
For server-side rendering, see the section [SSR](#ssr) below.
44
+
43
45
Browser example:
44
46
45
47
```js
46
48
import*aspfrom'{{featUrl prax}}'
47
49
48
50
const {E} =p.Ren.main
49
51
50
-
constelem=E(`div`, {id:`main`, class:`outer`},
51
-
E(`p`, {class:`inner`},
52
-
`hello `,
53
-
`world!`,
54
-
),
55
-
)
52
+
constelem=E(`div`, {
53
+
id:`main`,
54
+
class:`outer`,
55
+
chi:E(`p`, {
56
+
class:`inner`
57
+
chi: [`hello `, `world!`],
58
+
}),
59
+
})
56
60
57
61
document.body.append(elem)
58
62
@@ -63,16 +67,6 @@ The following elements (not strings) have been appended:
0 commit comments