Migrating from xinjs to tosijs
In a nutshell:
- Update to
xinjs(andxinjs-ui) 1.0.6 - Fix any issues
- Replace all references to "xinjs" with "tosijs"
xinjs and tosijs 1.0.6 should be identical (likewise xinjs-ui and tosijs-ui), so the only thing you need to change
should be the module names.
Please let me know if there are any issues.
Upgrading to 1.8.0
Removed. Only one deprecation named 1.8.0 in its 1.7 warning, and it is the only thing actually removed:
| was | now |
|---|---|
data-ref="thing" |
part="thing" (bare CSS-selector refs still work) |
<xin-blueprint>, <xin-loader> markup |
<tosi-blueprint>, <tosi-loader>. The old tags are tombstones: still registered, render nothing, and log exactly what to rename |
<xin-slot> element |
<tosi-slot> (the rewrite produces it automatically) |
Deprecated but still working (their 1.7 warnings named no version, so they survive 1.x and now warn naming 2.0):
| still works | prefer |
|---|---|
xinSlot() |
tosiSlot() |
blueprint() |
tosiBlueprint() |
blueprintLoader() |
tosiLoader() |
Behaviour changes worth checking even if you use no removed names — neither had a prior deprecation warning:
- A component member named
on<Event>now wins over the event sugar. If your component holds a function under, say,onClose, thencreator({ onClose: fn })now assigns the member instead of attaching acloselistener; previously the sugar won and your member was shadowed. Rename tohandle<Event>if you want the event channel. (A member leftundefined/nullstill gets event sugar.) - A type-contradicting attribute write is applied and reported, not
silently discarded. Writing
falseto an attribute declared'on' | 'off'used to remove the attribute — so the default read back and a feature you turned off stayed on. It now lands as written, with oneconsole.errornaming both types.
New, and opt-in: the agent surface (enableAgentInterface()) defaults
to read-only introspection — write() and call() refuse until you
declare expose: { roots, actions } (production) or expose: 'all'
(development). A manifest scopes what may be seen; add write: true to
let an agent change it. Nothing changes for apps that never call it.
License: tosijs is Apache-2.0 as of 1.8.0 (BSD-3-Clause through 1.7.x) — adding an explicit patent grant and a patent-retaliation clause. Apache-2.0 cannot be combined with GPLv2-only code; GPLv3+ is fine.
One new obligation, easy to miss because semver cannot express it.
Apache-2.0 §4(d) requires that redistributors carry the NOTICE text. If you
ship a build containing tosijs to anyone else, include the contents of our
NOTICE file (it also credits the vendored schematic renderer) in your
attribution notices — a THIRD-PARTY-NOTICES file, an about screen, or
alongside your own licence text. BSD-3-Clause imposed no equivalent duty, so
this is genuinely new for existing users, and it applies to redistribution
— using tosijs to build something you host yourself is unaffected.
Upgrading to 1.7.0
1.7.0 is the correctness release — a large batch of bug fixes. Most are pure fixes (things that were broken now work), but a few are observable behavior changes. If your code depended on the old (buggy) behavior, these are the ones to check. No API was removed or renamed.
Observer/touch matching is now segment-exact
Before 1.7, path matching used a raw prefix test, so an observer or binding on
foo also heard foobar, and touch('foo') swallowed a later touch('foobar').
Now matching respects path segment boundaries.
// before 1.7: this observer fired for BOTH 'app.user' and 'app.username'
observe('app.user', cb)
// 1.7+: fires only for 'app.user' and its children ('app.user.name', …),
// NOT the sibling 'app.username'
Hierarchical matching is unchanged (a parent still hears its children and vice
versa). If you relied on the sloppy prefix match — e.g. an observer on item
that you expected to also fire for items — give it the exact path, a RegExp, or
a filter function.
getValue() returns typed values for typed inputs
getValue(element) (and therefore bindings.value's fromDOM) now returns the
control's native type instead of a string:
type="number"/type="range"→ a number (was a string). Empty input still returns'', never a fabricated0.type="date"/datetime-local/month/week→ aDate(was an ISO string fortype=date).type="time"→ milliseconds since midnight.
Bound numeric state now stays numeric across edits. If you read getValue()
directly and expected a string, coerce explicitly (String(getValue(el))), or
read el.value. If you bound a type=date input and stored the ISO string, note
the stored value is now a Date — bind to string state and it keeps the control's
ISO string (the H-6 two-layer coercion, in src/dom.ts — getValue
reads typed controls natively, and handleChange coerces on the way back).
Component change events now bubble (and compose)
A component's change event (fired when its value changes) now bubbles and
crosses shadow boundaries — matching how native <input> change events behave.
This makes a shadow-DOM component bindable like an <input> (bind its
value; see the Building Apps shadow-DOM section).
If you have a change listener on an ancestor of a tosijs component, it will
now fire for the component's changes where before it did not. If that causes
double-handling, scope the listener (check event.target) or use capture-phase
delegation.
Other fixes worth a glance (not breaks, but visible)
- Reactive
classbindings now replace instead of accumulating. on()handlers now fire inside open shadow roots.- Named CSS colors (
Color.fromCss('red')) now parse without a DOM. - Component data-binding sugar placed inside shadow DOM now warns (it
never operated there — bind the component by its
valueinstead).
See CHANGELOG.md for the complete list.