backbone: Multiple backbones inside Node makes instanceof fail

This just consumed the last 4 hours of my life… and boy was it the most crazy difficult thing to debug.

If we have two modules:

  • Module A provides custom backbone.js models
  • Module B provides custom backbone.js collections

Then we have our app which:

  • Requires Module A
  • Requires Module B
  • Creates a model instance using a custom model from Module A
  • Creates a collection instance using a custom collection from Module B
  • Adds the model instance to the collection instance

Then the sky falls down and burns all the horrible plagues at once. Why? I know the answer, but I’ll give you a gold star if you can guess it.

Here’s the answer: because our lovely model instanceof Model inside Backbone.Model.prototype._prepareModel fails, as the models are using one backbone.js and the collections are using another!!! Despite them being the same backbone.js version.

ARGH! That line needs to be better, perhaps check for the presence of a this.isBackboneModel variable defined by the Backbone.Model.prototype.

ARGHHHH. For now, it seems the only solution is to pass the Modules the Backbone.js module that we want them to use, rather than having them use their own local copies. Which is a real PIA. Which imho, the flag idea is a much better one.

Thoughts?

About this issue

  • Original URL
  • State: closed
  • Created 12 years ago
  • Comments: 17 (2 by maintainers)

Commits related to this issue

Most upvoted comments

I stumbled across this discussion while trying to figure out how instance testing gets handled with Node.js dependencies. I know I’m a bit late, but I think @balupton has been misunderstood.

Here’s the issue, stripped down:

  • Package thing v1.0.0 gets submitted to the npm registry. It exports a Thing constructor.
  • Package thingutils v1.0.0 gets submitted to the npm registry. It requires thing v1.0.0, and has utility functions for creating Thing instances.
  • My app, foobar, requires thing v1.0.0 and thingutils v1.0.0. I install them both via npm, and therefore two separate package directories for the exact same version of thing, version 1.0.0, get installed:
    • One in foobar/node_modules/thing
    • One in foobar/node_modules/thingutils/node_modules/thing
  • I create a Thing instance in my foobar app using thingutils.
  • I now have no way of checking that this instance is an instance of Thing, even though my app and thingutils are both requiring the same exact version of the thing package, and thing.Thing is available to me. Node sees the two Thing constructors (and their prototypes) as different because they come from “different” modules with different filesystem paths.

I hope this helps someone else, as I was going a bit crazy trying to figure it out. This is the downside to the Node.js node_modules system: while you avoid versioning hell in resolving dependencies, you can’t reliably test instances across modules the way you can in Python (where I come from) and other languages.

You’re using package.json very incorrectly. A package.json should exist at the root of your application not your module. Each module having a package.json does not make sense, since the definitions therein define the package as an application. Therefore your entire application should have a single node_modules at the root containing a single instance of Backbone.js.

There is nothing Backbone.js can do to solve this problem for you, its entirely a design decision to include two redundant copies of Backbone. There might be a way you can work around the issue, but instead you should try and figure out why you need multiple application configs (package.json) and eliminate those so you can avoid issues like this.