Breaking BuckleScript changes, library maintainership, and versioning compiled-output: How are y'all handling this?


#1

So, BuckleScript 5.2 introduced a somewhat-major breaking change (at least, from one perspective) to the runtime structure of compiled output. This is having major implications for some of my libraries. For instance, given a library like the following …

module Sub = struct
   let f x = x * 2
end

Here’s what was produced pre-5.2:

function f(x) {
  return (x << 1);
}

var Sub = /* module */[/* f */f];

exports.Sub = Sub;

… and post-5.2, with the new modules-as-objects:

function f(x) {
  return (x << 1);
}

var Sub = {
  f: f
};

exports.Sub = Sub;

Cool! New features! Nice! Except … that bsb doesn’t compile every single dependency every time someone builds a project: BuckleScript-compiled projects are published to npm as compiled output, like the above, and consumed as-is.

Let’s say I have the above published to npm as bs-thingie, and a consuming client-project with a bsconfig.json that includes something like this:

  "bs-dependencies": [
    "bs-thingie"
  ],

Furthermore, let’s assume they haven’t updated their project to bs-platform@5.2.x yet: they’re still on 5.1.0, say. Well, given a line of code like …

let _ = Thingie.Sub.f 123

… with my library installed, they’re going to see something along these lines:

var Thingie = require("bs-thingie/thingie.bs.js");

Thingie.Sub[/* f */0](123);

Oh-oh. The file bs-thingie.bs.js, compiled by the upstream author under 5.2.1, isn’t going to play well with that — Thingie.Sub is published as an object, not an array.

Okay, forgive me if I moved really slowly with all of — basically, we’re talking about ABI-compatibility, because at this point, a BuckleScript library on npm is effectively a dynamically-linked shared-libaray, right? In terms of versioning, publication, and compatibility?

This is biting me in the real world with bs-uchar; as far as I can tell, there’s absolutely no way for me to publish a version of this that will work with consumers using BuckleScript ≥v5.2, and also continue to work with BuckleScript <5.2. The absolute best thing I can come up with, is to break backwards-compatibility, and require users to know about this, and manually install a particular version of my library, depending on the version of BuckleScript they have installed … but, come on, there’s gotta be a better way.

Those of you also maintaining BuckleScript libraries (I have quite a few, at this point; several of which this change is probably breaking) — how are you handling this?


ANN: bs-platform 5.2.1 and 6.2.1 released
#2

Hi Elliot, see the discussion here ANN: bs-platform 5.2.1 and 6.2.1 released


#3

K, I added a reply over there. Bit of a novel, though.


#4

@yawaramin suggested moving the discussion back here; so I’ll reply to his replies here instead.

This doesn’t seem like it’s a reply to anything I brought up? First, I’m not talking about anything that require()'s the runtime, here; first, runtime-versioning is a separate topic (and one that’s been discussed to death, elsewhere — I’m all for separating bs-lib out from bs-platform, but that particular design issue isn’t the relevant one here :P)

Second, I’m not talking about accessing BuckleScript from JavaScript; note that my examples are all accessing BuckleScript … from BuckleScript. I really don’t think “just write simpler OCaml if you’re going to be sharing the code!” is a good answer in a BuckleScript-to-BuckleScript library situation — that’s basically saying ‘most OCaml features are only accessible if you write monolithic codebases, and share nothing.’ I don’t think that’s the design-goal of this community, right?

(Note my example-code: simple line of ML, no JavaScript interop, no calls into the runtime; and note the compiled output — no requires() of external libraries, no requires() of BS-runtime components.)


#5

Ah, this wasn’t that related too much to my main point, and I don’t want to side-track this thread, too — but that wasn’t my experience, at all. Note, again, my examples! I wrote this out; but if an npm package ships with .bs.js files in the tree, BuckleScript doesn’t recompile them, it simply uses them directly … which contributes to this whole mess, because that’s how pre-v5.2-output files shipped to npm affect users’ post-v5.2 BuckleScript codebases.


#6

From my reading of the thread–seems like this is the main issue? Just to clarify, if you either:

  • Did not ship .bs.js compiled output with your libraries
  • Or ran bsb -clean-world && bsb -make-world to guarantee a clean build

This issue would go away, correct?