v2.0.0-rc.7
Several new bug fixes, including the dreaded Uncaught TypeError: Cannot read property 'onbeforeupdate' of undefined
on Chrome, TypeError: vnode.state is undefined
on Firefox, but there are also a few breaking changes since v2.0.0-rc.6:
- Paths no longer accept
#a=b&c=d
as equivalent to?a=b&c=d
. This aligns with the URL spec better, where#
is itself illegal in URL fragments. #2448 - Fragments must either all contain keys or none contain keys. This is not only recommended by the docs, but also enforced by the framework itself. #2452
null
/undefined
are no longer valid in keyed fragments. #2452true
,false
, andundefined
are all normalized tonull
at the vnode level. Unlikely to break people, as the past behavior was so counterintuitive and inconsistent people actively avoided using it as it had a knack for creating subtle bugs. #2452
Breaking changes
- API: Component vnode
children
are not normalized into vnodes on ingestion; normalization only happens if and when they are ingested by the view (#2155 (thanks to @magikstm for related optimization #2064)) - API:
m.redraw()
is always asynchronous (#1592) - API:
m.mount()
will only render its own root when called, it will not trigger aredraw()
(#1592) - API: Assigning to
vnode.state
(as invnode.state = ...
) is no longer supported. Instead, an error is thrown ifvnode.state
changes upon the invocation of a lifecycle hook. - API:
m.request
will no longer reject the Promise on server errors (eg. status >= 400) if the caller supplies anextract
callback. This gives applications more control over handling server responses. - hyperscript: when attributes have a
null
orundefined
value, they are treated as if they were absent. #1773 (#2174) - API:
m.request
errors no longer copy response fields to the error, but instead assign the parsed JSON response toerror.response
and the HTTP status codeerror.code
. - hyperscript: when an attribute is defined on both the first and second argument (as a CSS selector and an
attrs
field, respectively), the latter takes precedence, except forclass
attributes that are still added together. #2172 (#2174) - render: Align custom elements to work like normal elements, minus all the HTML-specific magic. (#2221)
- cast className using toString (#2309)
- render: call attrs' hooks first, with express exception of
onbeforeupdate
to allow attrs to block components from even diffing (#2297) - API:
m.withAttr
removed. (#2317) - request:
data
has now been split toparams
andbody
anduseBody
has been removed in favor of just usingbody
. (#2361) - route, request: Interpolated arguments are URL-escaped (and for declared routes, URL-unescaped) automatically. If you want to use a raw route parameter, use a variadic parameter like in
/asset/:path.../view
. This was previously only available inm.route
route definitions, but it's now usable in both that and where paths are accepted. (#2361) - route, request: Interpolated arguments are not appended to the query string. This means
m.request({url: "/api/user/:id/get", params: {id: user.id}})
would result in a request likeGET /api/user/1/get
, not one likeGET /api/user/1/get?id=1
. If you really need it in both places, pass the same value via two separate parameters with the non-query-string parameter renamed, like inm.request({url: "/api/user/:urlID/get", params: {id: user.id, urlID: user.id}})
. (#2361) - route, request:
m.route.set
,m.request
, andm.jsonp
all use the same path template syntax now, and vary only in how they receive their parameters. Furthermore, declared routes inm.route
shares the same syntax and semantics, but acts in reverse as if via pattern matching. (#2361) - request:
options.responseType
now defaults to"json"
ifextract
is absent, anddeserialize
receives the parsed response, not the raw string. If you want the old behavior, useresponseType: "text"
. (#2335) - request: set
Content-Type: application/json; charset=utf-8
for all XHR methods by default, provided they have a body that's!= null
(#2361, #2421)- This can cause CORS issues when issuing
GET
with bodies, but you can address them through configuring CORS appropriately. - Previously, it was only set for all non-
GET
methods and only whenuseBody: true
was passed (the default), and it was always set for them. Now it's automatically omitted when no body is present, so the hole is slightly broadened.
- This can cause CORS issues when issuing
- route: query parameters in hash strings are no longer supported (#2448 @isiahmeadows)
- It's technically invalid in hashes, so I'd rather push people to keep in line with spec.
- render: validate all elements are either keyed or unkeyed, and treat
null
/undefined
/booleans as strictly unkeyed (#2452 @isiahmeadows)- Gives a nice little perf boost with keyed fragments.
- Minor, but imperceptible impact (within the margin of error) with unkeyed fragments.
- Also makes the model a lot more consistent - all values are either keyed or unkeyed.
- vnodes: normalize boolean children to
null
/undefined
at the vnode level, always stringify non-object children that aren't holes (#2452 @isiahmeadows)- Previously,
true
was equivalent to"true"
andfalse
was equivalent to""
. - Previously, numeric children weren't coerced. Now, they are.
- Unlikely to break most components, but it could break some users.
- This increases consistency with how booleans are handled with children, so it should be more intuitive.
- Previously,
News
- Mithril now only officially supports IE11, Firefox ESR, and the last two versions of Chrome/FF/Edge/Safari. (#2296)
- API: Introduction of
m.redraw.sync()
(#1592) - API: Event handlers may also be objects with
handleEvent
methods (#1949, #2222). - API:
m.route.link
accepts an optionaloptions
object (#1930) - API:
m.request
better error message on JSON parse error - (#2195, @codeclown) - API:
m.request
supportstimeout
as attr - (#1966) - API:
m.request
supportsresponseType
as attr - (#2193) - Mocks: add limited support for the DOMParser API (#2097)
- API: add support for raw SVG in
m.trust()
string (#2097) - render/core: remove the DOM nodes recycling pool (#2122)
- render/core: revamp the core diff engine, and introduce a longest-increasing-subsequence-based logic to minimize DOM operations when re-ordering keyed nodes.
- docs: Emphasize Closure Components for stateful components, use them for all stateful component examples.
- API: ES module bundles are now available for
mithril
andmithril/stream
(#2194 @porsager).- All of the
m.*
properties frommithril
are re-exported as named exports in addition to being attached tom
. m()
itself frommithril
is exported as the default export.mithril/stream
's primary export is exported as the default export.
- All of the
- fragments: allow same attrs/children overloading logic as hyperscript (#2328)
- route: Declared routes may check against path names with query strings. (#2361)
- route: Declared routes in
m.route
now support-
and.
as delimiters for path segments. This means you can have a route like"/edit/:file.:ext"
. (#2361)- Previously, this was possible to do in
m.route.set
,m.request
, andm.jsonp
, but it was wholly untested for and also undocumented.
- Previously, this was possible to do in
- API:
m.buildPathname
andm.parsePathname
added. (#2361) - route: Use
m.mount(root, null)
to unsubscribe and clean up after am.route(root, ...)
call. (#2453) - version:
m.version
returns the previous version string for what's innext
. (#2453)- If you're using
next
, you should hopefully know what you're doing. If you need stability, don't usenext
. (This is also why I'm not labelling it as a breaking change.)
- If you're using
Bug fixes
- API:
m.route.set()
causes all mount points to be redrawn (#1592) - render/attrs: Using style objects in hyperscript calls will now properly diff style properties from one render to another as opposed to re-writing all element style properties every render.
- render/attrs All vnodes attributes are properly removed when absent or set to
null
orundefined
#1804 #2082 (#1865, #2130) - render/core: Render state correctly on select change event #1916 (#1918 @robinchew, #2052)
- render/core: fix various updateNodes/removeNodes issues when the pool and fragments are involved #1990, #1991, #2003, #2021
- render/core: fix crashes when the keyed vnodes with the same
key
had differenttag
values #2128 @JacksonJN (#2130) - render/core: fix cached nodes behavior in some keyed diff scenarios #2132 (#2130)
- render/events:
addEventListener
andremoveEventListener
are always used to manage event subscriptions, preventing external interference. - render/events: Event listeners allocate less memory, swap at low cost, and are properly diffed now when rendered via
m.mount()
/m.redraw()
. - render/events:
Object.prototype
properties can no longer interfere with event listener calls. - render/events: Event handlers, when set to literally
undefined
(or any non-function), are now correctly removed. - render/hooks: fixed an ommission that caused
oninit
to be called unnecessarily in some cases #1992 - docs: tweaks: (#2104 @mikeyb, #2205, @cavemansspa, #2250 @isiahmeadows, #2265, @isiahmeadows)
- render/core: avoid touching
Object.prototype.__proto__
setter withkey: "__proto__"
in certain situations (#2251) - render/core: Vnodes stored in the dom node supplied to
m.render()
are now normalized #2266 - render/core: CSS vars can now be specified in
{style}
attributes (#2192 @barneycarroll), (#2311 @porsager), (#2312 @isiahmeadows) - request: don't modify params, call
extract
/serialize
/deserialize
with correctthis
value (#2288) - render: simplify component removal (#2214)
- render: remove some redundancy within the component initialization code (#2213)
- API:
mithril
loadsmithril/index.js
, not the bundle, so users ofmithril/hyperscript
,mithril/render
, and similar see the same Mithril instance as those just usingmithril
itself.https://unpkg.com/mithril
is configured to receive the minified bundle, not the development bundle.- The raw bundle itself remains accessible at
mithril.js
, and is not browser-wrapped. - Note: this will increase overhead with bundlers like Webpack, Rollup, and Browserify.
- request: autoredraw support fixed for
async
/await
in Chrome (#2428 @isiahmeadows) - render: fix when attrs change with
onbeforeupdate
returning false, then remaining the same on next redraw (#2447 @isiahmeadows) - render: fix internal error when
onbeforeupdate
returns false and then true with new child tree (#2447 @isiahmeadows) - route: arbitrary prefixes are properly supported now, including odd prefixes like
?#
and invalid prefixes like#foo#bar
(#2448 @isiahmeadows) - request: correct IE workaround for response type non-support (#2449 @isiahmeadows)
- render: correct
contenteditable
check to also check forcontentEditable
property name (#2450 @isiahmeadows) - docs: clarify valid key usage (#2452 @isiahmeadows)
- route: don't pollute globals (#2453 @isiahmeadows)
- request: track xhr replacements correctly (#2455 @isiahmeadows)