@yuneta/gobj-js 7.26.25 → 7.26.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -11
- package/dist/gobj-js.cjs.js +277 -77
- package/dist/gobj-js.cjs.js.map +1 -1
- package/dist/gobj-js.cjs.min.js +1685 -1563
- package/dist/gobj-js.cjs.min.js.map +1 -1
- package/dist/gobj-js.es.js +277 -78
- package/dist/gobj-js.es.js.map +1 -1
- package/dist/gobj-js.es.min.js +1716 -1594
- package/dist/gobj-js.es.min.js.map +1 -1
- package/dist/gobj-js.iife.js +277 -77
- package/dist/gobj-js.iife.js.map +1 -1
- package/dist/gobj-js.iife.min.js +1685 -1563
- package/dist/gobj-js.iife.min.js.map +1 -1
- package/dist/gobj-js.umd.js +277 -77
- package/dist/gobj-js.umd.js.map +1 -1
- package/dist/gobj-js.umd.min.js +1685 -1563
- package/dist/gobj-js.umd.min.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -306,15 +306,35 @@ thrown (7.26.24). So is a value that is not json ALL THE WAY DOWN given to a
|
|
|
306
306
|
string, a `DTP_DICT` or a `DTP_LIST` (7.26.25): a cycle anywhere inside, a
|
|
307
307
|
`BigInt` inside (`[1n]`), a `Map`, a `Set`, a `Date`, a typed array, an instance
|
|
308
308
|
of a class. They were written, and burst (or turned into `"{}"`) when the value
|
|
309
|
-
was serialized, far from the write.
|
|
310
|
-
|
|
309
|
+
was serialized, far from the write. And so is a value whose text would say
|
|
310
|
+
another value (7.26.26): an object with a `toJSON()`, `NaN` or `Infinity` inside
|
|
311
|
+
(the text says `null`; jansson holds no such real), a function, `undefined`, a
|
|
312
|
+
symbol or a hole inside an array (`[1, , 3]`: the text says `null`), and a value
|
|
313
|
+
nested deeper than 2048 levels (a scalar is a level too), which C would not read
|
|
314
|
+
back and which bursts `JSON.stringify()` a little further on. Every version
|
|
315
|
+
before 7.26.26 wrote them, so this is a BREAKING change for a caller that wrote
|
|
316
|
+
one. A getter or a `Proxy` trap that
|
|
317
|
+
throws is a refusal too, never an exception (7.26.26). A key whose value is
|
|
318
|
+
`undefined`, a function or a symbol is dropped, as `JSON.stringify()` drops it:
|
|
319
|
+
an absent key. A plain object of another realm (a `vm` context, an iframe) is a
|
|
320
|
+
plain object. A `Proxy` is read through its traps, as `JSON.stringify()` reads
|
|
321
|
+
it: JS cannot tell one from its target.
|
|
311
322
|
|
|
312
323
|
```javascript
|
|
313
324
|
gobj_write_attr(gobj, "settings", {a: 1, b: undefined}); // 0: b goes when serialized
|
|
314
325
|
gobj_write_attr(gobj, "settings", new Map([["a", 1]])); // -1, ERROR "a value with no json text"
|
|
315
326
|
gobj_write_str_attr(gobj, "name", new Map()); // -1: it was the text "{}"
|
|
327
|
+
gobj_write_attr(gobj, "settings", {ratio: NaN}); // -1: it was the text {"ratio":null}
|
|
328
|
+
gobj_write_attr(gobj, "items", [1, undefined]); // -1: it was the text [1,null]
|
|
329
|
+
gobj_write_attr(gobj, "items", [1, , 3]); // -1: a hole, it was the text [1,null,3]
|
|
330
|
+
gobj_write_str_attr(gobj, "name", NaN); // -1: it was the text "null"
|
|
316
331
|
```
|
|
317
332
|
|
|
333
|
+
The check walks the whole value on every write of a string, a dict or a list:
|
|
334
|
+
it costs about what a `JSON.stringify()` of the value costs (some 20-30 ms for a
|
|
335
|
+
dict of 50 000 records), once per write. It is not cached: an object found json
|
|
336
|
+
once can be changed into one that is not before its next write.
|
|
337
|
+
|
|
318
338
|
A `DTP_JSON` attribute is not checked: it takes any value, as before.
|
|
319
339
|
|
|
320
340
|
A json TEXT is read as the C parser reads it: one that C
|
|
@@ -322,11 +342,14 @@ refuses is refused in JS too -- an escaped NUL (`"\u0000"`), a lone surrogate,
|
|
|
322
342
|
an integer out of int64, a real that overflows (`1e309`; to a `DTP_JSON` it is
|
|
323
343
|
the text `"1e309"`, not `Infinity`), a text nested deeper than 2048 levels (a
|
|
324
344
|
scalar is a level too; 7.26.25). A number beyond int64 is "a real" to a dict,
|
|
325
|
-
as in C (`1e20`)
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
345
|
+
as in C (`1e20`). Three differences remain, because a JS number cannot carry
|
|
346
|
+
them: an integer beyond 2^53 is rounded; `2.0` (and `-0.0`) is the integer; and
|
|
347
|
+
the last 512 integers of int64 round up to 2^63, which is OUT of int64, so an
|
|
348
|
+
integer attr refuses them, as text or as a number (`"9223372036854775807"`,
|
|
349
|
+
the int64 maximum C takes, is "a number out of its range" in JS: its JS number
|
|
350
|
+
is 2^63, whose text C refuses as "too big integer"; 7.26.26, 7.26.25 took it).
|
|
351
|
+
See `tests/fixtures/attr_types_parity.json`, which the C test
|
|
352
|
+
`tests/c/attr_types` of yunetas reads too.
|
|
330
353
|
|
|
331
354
|
### Events & Pub-Sub
|
|
332
355
|
|
|
@@ -703,8 +726,20 @@ kw_clone_by_not_keys(gobj, kw, keys, verbose)
|
|
|
703
726
|
|
|
704
727
|
// Local storage helpers (browser localStorage, no "store" parameter)
|
|
705
728
|
kw_get_local_storage_value(key, default_value, create) // create=false
|
|
706
|
-
kw_set_local_storage_value(key, value)
|
|
729
|
+
kw_set_local_storage_value(key, value) // 0, or -1 logged
|
|
707
730
|
kw_remove_local_storage_value(key)
|
|
731
|
+
// BREAKING in 7.26.26: kw_get_local_storage_value() answers default_value
|
|
732
|
+
// where it answered null (an absent entry, a json null) or undefined (no
|
|
733
|
+
// browser), and an entry that is not json is REMOVED, with one WARNING
|
|
734
|
+
// that never shows its text. A store the browser blocks (cookies blocked,
|
|
735
|
+
// a sandboxed iframe: reading window.localStorage throws) answers the
|
|
736
|
+
// default, warned once per key, and a write to it is -1 (7.26.27: before,
|
|
737
|
+
// every helper and node_uuid() threw). A value with no json text is
|
|
738
|
+
// refused by the writer, -1 with an ERROR, as a typed writer refuses it
|
|
739
|
+
// (7.26.27; a function was stored as the text "undefined"):
|
|
740
|
+
// kw_set_local_storage_value("k", () => 1) → -1
|
|
741
|
+
// kw_set_local_storage_value("k", {w: NaN}) → -1 (it was {"w":null})
|
|
742
|
+
// kw_set_local_storage_value("k", [1, , 3]) → -1 (a hole: [1,null,3])
|
|
708
743
|
|
|
709
744
|
// Misc utilities
|
|
710
745
|
current_timestamp() // ISO string
|
|
@@ -1040,7 +1075,9 @@ const event_types = [
|
|
|
1040
1075
|
["EV_MT_COMMAND_ANSWER", event_flag_t.EVF_PUBLIC_EVENT],
|
|
1041
1076
|
["EV_REALTIME_ALARM", event_flag_t.EVF_PUBLIC_EVENT],
|
|
1042
1077
|
];
|
|
1043
|
-
```
|
|
1078
|
+
```
|
|
1079
|
+
|
|
1080
|
+
What the server gets wrong is a WARNING, never an ERROR. Before the session only `EV_IDENTITY_CARD_ACK` is taken; a `dst_role` or `dst_yuno` that is not this yuno's closes the channel too (an empty one is legal: anybody's), as the C transport does; an event that the named service does not take as public is dropped (7.26.24). A channel closed for a fault of the server is closed with **4002**, not 1000 (a browser may send only 1000 or 3000-4999, so 1002 cannot be used), so `EV_ON_CLOSE` says the session was cut (7.26.25).
|
|
1044
1081
|
|
|
1045
1082
|
`EV_ON_CLOSE` carries `code`, `reason` (masked) and `was_clean`, and so does `EV_ON_OPEN_ERROR` (7.26.24). A session that ends cleanly (a stop, a logout, the server closing with 1000 or 1001) is logged by nobody; a session CUT -- not clean, or any other code (1006, 1008, 1011) -- is one WARNING with the code and the reason masked:
|
|
1046
1083
|
|
|
@@ -1066,8 +1103,25 @@ that is just coming back. The backoff resets when a session is actually reached,
|
|
|
1066
1103
|
and on `mt_start` — a deliberate reconnect never inherits a previous run's
|
|
1067
1104
|
penalty. A session the transport closes for a fault of the server (4002) does not
|
|
1068
1105
|
count as reached: the backoff goes on from where it was (7.26.25), so a server
|
|
1069
|
-
that breaks every session is not reconnected at the first delay for ever
|
|
1070
|
-
`
|
|
1106
|
+
that breaks every session is not reconnected at the first delay for ever -- unless
|
|
1107
|
+
the session outlived `timeout_retry_max`: a session that long was served, and its
|
|
1108
|
+
fault starts the backoff over, as a clean end does (7.26.26). For the old fixed-interval behaviour set `timeout_retry_max` equal to
|
|
1109
|
+
`timeout_retry`. The first delay is **at least 1000 ms** (7.26.27): a lower
|
|
1110
|
+
`timeout_retry` is raised to 1000 with one WARNING, because 0 never doubled
|
|
1111
|
+
away from 0 and a server that closes before the ack was reconnected in a loop
|
|
1112
|
+
with no wait, hundreds of times a second.
|
|
1113
|
+
|
|
1114
|
+
**A refused identity card** (`result < 0` in its ack) publishes `EV_ON_ID_NAK`
|
|
1115
|
+
and closes the channel with 1000; no session was reached, so the close is then
|
|
1116
|
+
`EV_ON_OPEN_ERROR` (one WARNING), and the link retries -- as the C transport.
|
|
1117
|
+
A subscriber that shows the refusal on `EV_ON_ID_NAK` should not show a second
|
|
1118
|
+
error on the `EV_ON_OPEN_ERROR` that follows it.
|
|
1119
|
+
|
|
1120
|
+
**Stats and commands the server asks of this client** (`EV_MT_STATS`,
|
|
1121
|
+
`EV_MT_COMMAND`) are not served: the C client runs them on the service named and
|
|
1122
|
+
answers, a browser client does not run what its server asks. Each is one WARNING
|
|
1123
|
+
naming what was asked (masked), and the session goes on (7.26.26; up to 7.26.25
|
|
1124
|
+
they were dropped without a trace).
|
|
1071
1125
|
|
|
1072
1126
|
---
|
|
1073
1127
|
|