Repository navigation
Releases: compuzz-eventus/backbone
Releases · compuzz-eventus/backbone
Release list
1.7.1
Evergreen: the modernization release (ES2022, native fetch, Vitest, Yarn 4)
Drops the dead IE6/IE7 code paths, modernizes prototype method syntax to
ES6 shorthand, ships a native fetch() fallback for Backbone.ajax,
and moves the project off npm onto Yarn 4.
Added
Backbone.ajaxfalls back to nativefetch()whenBackbone.$
is absent. Previously the library was unusable without jQuery (or a
hand-rolledBackbone.ajaxoverride). The fallback maps the subset
of jQuery options thatBackbone.syncemits —type,url,data,
contentType,dataType,headers,beforeSend,success,
error— ontofetch()+AbortController, and returns a thenable
carrying.abort()so thevar xhr = model.fetch(); xhr.abort();
consumer pattern keeps working. The jQuery path is preserved verbatim
wheneverBackbone.$is present.
Removed (breaking for IE6/IE7)
- The hidden iframe trick that simulated
hashchangefor IE7, plus
the four call sites inHistorythat special-casedthis.iframe. - The
setIntervalpolling fallback for browsers without
onhashchange, and the orphanHistory#intervalknob that only
existed to feed it. - The
attachEvent/detachEventshims around
addEventListener/removeEventListener. - The
document.documentMode > 7gate that guarded against IE7's
brokenonhashchange. - Zepto and Ender from the browser-global
$resolution chain in the
UMD factory; only jQuery (or$) remains. - The IE6 hash/search and Firefox
location.hash-decoding workaround
comments.History#getHashalso loses its unusedwindowargument. - The
attachEvent/detachEventESLint globals.
Changed
- Every prototype method literal on
Model,Collection,View,
Router, andHistorynow uses ES6 method shorthand:
methodName(args) { ... }instead of
methodName: function(args) { ... }. Pure syntactic, no behavior
change. The function-style constructor wrappers
(var Model = Backbone.Model = function(...) {...}) are preserved
on purpose: converting them toclasswould break the documented
Backbone.Model.apply(this, arguments)pattern in user-provided
constructor:overrides (exercised by test jashkenas#2612), sincesuper()
must come first in a derived class constructor. Backbone.VERSION, the source header, andpackage.jsonare all
aligned at1.7.0.
Tooling
- Package manager: npm → Yarn 4.14, pinned via Corepack and the
packageManagerfield.node-moduleslinker for full compatibility
with Karma/Rollup/Docco; no Zero-Install (cache stays out of git).
package-lock.jsonis replaced byyarn.lock. - CI Node 14 → 20, required by Yarn 4 (≥ 18.12).
npm cibecomes
yarn install --immutable. dependenciesMeta.puppeteer.builtis set explicitly so Yarn 4's
default postinstall block doesn't strand the Chromium download that
karma.conf.jsdepends on.
Bug fixes, modern toolchain, 0 vulnerabilities
A maintenance pass that closes a backlog of bugs, modernizes the test/build
toolchain, and clears every known vulnerability without breaking drop-in
compatibility with upstream Backbone.
Fixed
- Memory leak when a non-Backbone listenee's
onthrows.Events.listenTo
used to insert the newListeningbookkeeping before callingobj.on(...),
so a throw left an orphaned reference in_listeningTo. The bookkeeping is
now rolled back whenobj.onthrows. - Memory leak when a callback re-enters
stopListeningduring a global
stop.Events.stopListening()(with no argument) snapshots all listenee
ids; if anoffhandler removed a later id from the snapshot, the outer
loop hitbreakand abandoned every remaining listenee. Changed to
continue. Backbone.syncwas mutating the caller's options. Repeated calls with
the same options compounded theerror/beforeSendwrappers, firing
callbacks and triggers multiple times.syncnow operates on a shallow
clone of the caller's options while still publishingxhrand the
jQuerytextStatus/errorThrownfields on the caller object so the
public contract is preserved.Collection.set/addsilently corrupted state whenoptions.atcoerced
toNaN. The model was registered in_byIdbut never spliced into
this.models. A non-numericatis now treated as if it were omitted
(append at the end).Router.executethrewTypeErrorwhenthis[name]resolved to a
non-function (e.g. a string handler). It now silently no-ops and the
route:(empty name) trigger is skipped so listeners no longer see a
spurious event.View.undelegatethrew if$elhad been nulled out by a subclass
_removeElement. Now mirrorsundelegateEvents'sif (this.$el)guard.History.start()produced a crypticReferenceErroroutside the
browser despite the constructor specifically guarding for non-browser
use. It now throws a clearBackbone.history.start() requires a browser windowerror instead.Backbone.syncwas emitting therequestevent with the cloned options
object (the internal clone introduced to stoperror/beforeSendfrom
compounding). Listeners that mutateoptsfor instrumentation
(e.g. tagging a start timestamp onrequest, reading it onsync) saw
their mutations land on the discarded clone.requestnow fires with the
caller's own options, matching upstream behavior.Backbone.history.stop()threwReferenceErroroutside a browser
when called before any successfulstart()(typical in test cleanup).
Now early-returns whenHistory.startedis false, mirroring the guard
instart()andnavigate().require('jquery')swallowed every error, not justMODULE_NOT_FOUND.
ESM/CJS mismatches and corrupt installs now propagate instead of leaving
Backbone half-initialized. jQuery 4'sjQuery requires a window with a documentis also tolerated (Node-only Backbone use without DOM is
unaffected when jQuery 4 is present as a transitive dependency).debugInfomis-identified bundled browser builds as Node when bundlers
(Webpack, etc.) injected a polyfilledprocess. Detection now requires
process.versions.node.Backbone.VERSIONwas out of sync withpackage.jsonafter the 1.6.1
/ 1.6.2 fork bumps. All three (source header,Backbone.VERSION, and
package.json) are aligned again.
Changed
changeIdguard expression simplified to
!_.isEqual(prevId, this.id) && !(prevId == null && this.id == null).
Behavior unchanged, readability improved.Collection.set(null)returns the collection instead ofundefined,
matchingModel.set(null)and keepingadd(null)chainable.extend()static-merge priority is nowstaticProps > child's own preexisting > parent. Previously parent statics could silently clobber
statics the caller had already attached to a user-supplied constructor.
The common cases (no preexisting constructor statics) are unchanged —
parent statics still flow into the child to fill gaps.
Tooling
- Test runner: PhantomJS → puppeteer-bundled Chrome Headless.
karma-phantomjs-launcher+phantomjs-prebuilt(archived since 2018,
unreliable install on modern systems) replaced withkarma-chrome-launcherpuppeteer, which ships its own Chromium binary.npm testno longer
requires a system Chrome.
.gitattributesadded with* text=auto eol=lfto keep line endings
consistent across OSes regardless of each developer'score.autocrlf
setting. Fixes the cascade oflinebreak-styleerrors on Windows
checkouts.- ESLint 8 → 10, including the migration from three nested
.eslintrc
files to one flateslint.config.js. Stylistic rules (indent, quotes,
semi, linebreak-style, …) moved to@stylistic/eslint-plugin. Deprecated
rules (no-catch-shadow,no-native-reassign,no-negated-in-lhs,
no-new-object,no-spaced-func) replaced or removed. - All other devDependencies bumped: rollup 3→4, puppeteer 22→24
(Chromium 127→148), cpy-cli 3→7, replace-in-file 7→8, plus every
in-range patch/minor. .idea/and.claude/added to.gitignore.
Security
underscore1.13.2 → 1.13.8 patches the only CVE that reached
consumers of this package
(GHSA-qpx9-hpmf-5gmw:
unbounded recursion DoS in_.flatten/_.isEqual).- The dependency range is now
^1.8.3instead of>=1.8.3, so a future
underscore 2.x won't be pulled in untested. npm auditis clean: 0 vulnerabilities. Down from 29 (2 low, 10
moderate, 16 high, 1 critical) at the start of this release cycle.
Compatibility
- Verified against jQuery 4.0 (stable since January 2026) in addition
to the existing 1.8.x → 3.x range. Swapping jQuery 4 into the test
vendor directory: 450 karma tests green, 4 Node CoffeeScript tests
green. The only Backbone-side adjustment was widening the Node loader
guard (see Fixed) to absorb jQuery 4'sjQuery requires a window with a documenterror when loaded server-side without a DOM. None
of the 8 jQuery APIs Backbone consumes ($(),$.ajax,.on/.off
with namespaces,.find,.remove,.attr,[0]) was affected by
the 4.0 upgrade.
Added (tests)
Regression coverage was added for every behavioral fix above:
changeIdonly fires on real id changes (no spurious null/undefined
transitions)listenTocleans up_listeningTowhenobj.onthrowsstopListeningkeeps cleaning remaining listenees after re-entrancyBackbone.syncdoes not mutate the caller-supplied optionsBackbone.syncemitsrequestwith the caller options (mutations from a
requestlistener persist on the same object)Collection.add(model, {at: 'invalid'})appends instead of corrupting
the indexCollection.set(null)andCollection.add(null)return the collectionRouter.executeignores non-function callbacks instead of throwingextend()static merge priority is what the docstring claims
448 → 450 karma tests, all green.
1.6.2 - trigger changeId
Full Changelog: 1.6.1...1.6.2