See https://github.com/Birch-san/box2d-wasm/releases
Closes Birch-san/box2d-wasm#38
Closes Birch-san/box2d-wasm#36
Closes Birch-san/box2d-wasm#35
Exposed new Box2D functionality:
b2BodyDef#enabled
attribute (resolves Birch-san/box2d-wasm#38)b2Body#ApplyLinearImpulseToCenter
method (resolves Birch-san/box2d-wasm#36)
Added LeakMitigator
for freeing retained references from Emscripten's JS object caches.
See documentation.
Breaking changes:
- Deleted (unreachable) type
JSContactListenerWithoutSolveCallbacks
(resolves Birch-san/box2d-wasm#35); the performance problem it was designed to solve (eliminating WASM->JS calls) is not a problem nowadays. PreferJSContactListener
.
Added .d.ts
declarations accompanying entry.js
, Box2D.js
and Box2D.simd.js
(in case anybody wants to bypass the Node module specifier or the entrypoint and import an asset directly).
Updated UMD entrypoint to be better statically-analysable by Parcel.
Fixed substantial performance & size regression introduced in v5.0.0
. We now correctly set optimization level.
Box2D.js is still 319kB. Box2D.simd.js is still 319kB. Box2D.wasm is 161kB (down from 226kB). Box2D.simd.wasm is 162kB (down from 226kB).
Performance is back to normal now, so it's now possible to try out SIMD properly.
Do not use: suffers from performance/size regression introduced in v5.0.0
. Prefer v6.0.2
Added a mechanism to the 'browser global' loader in the UMD entrypoint that enables you to specify the directory from which you serve Box2D.js, via the data-box2d-dir
attribute on its <script>
tag:
<script data-box2d-dir="Box2D" src='Box2D/entry.js'></script>
This tells entry.js
that Box2D.js
can be found at Box2D/Box2D.js
.
Do not use: suffers from performance/size regression introduced in v5.0.0
. Prefer v6.0.2
Simplified (i.e. flattened) directory structure introduced in v5.0.0, to make it easier to import the library and serve deferred assets.
Inlined SIMD feature detection, eliminating dependency on wasm-feature-detect
. This simplifies the entrypoints (fewer files to locate and load in).
Eliminated "ES explicit" entrypoint (now that we are zero-dependency again, we no longer need to cater for differences in ES module resolution).
Simplified UMD entrypoint by writing bespoke loaders for each of CommonJS, AMD and Browser globals.
Tested AMD entrypoint and confirmed working. Can be used by serving a folder with the following assets:
entry.js
Box2D.js
Box2D.wasm
Box2D.simd.js
Box2D.simd.wasm
index.html
main.js
require.js
<!-- load RequireJS library, import main.js -->
<script data-main="main" src="require.js"></script>
// main.js
// import Box2D's umd/entry.js
requirejs(['./entry.js'], function (Box2DFactory) {
(async () => {
const box2D = await Box2DFactory();
console.log(box2D);
})();
});
Do not use: suffers from performance/size regression introduced in v5.0.0
. Prefer v6.0.2
Additionally: UMD release appears to be broken (was built using a text-replace trick which doesn't work in newer Emscripten)
Updated from Emscripten 2.0.17
->2.0.26
.
Box2D.js is still 319kB. Box2D.wasm is 226kB (up from 162kB).
Hopefully the extra code means more performance (more inlining?).
The most dramatic change in the changelog is the LLVM library/runtime updates in Emscripten 2.0.23.
Emscripten 2.0.21 introduces some hints that will help your bundler locate the .wasm
asset (and obviate the need to implement locateFile
). Will try to determine whether there's any instructions that can be simplified as a result of this.
Do not use: suffers from performance/size regression introduced in v5.0.0
. Prefer v6.0.2
The ES module entrypoint es/entry.js
introduced in v5.0.0 relied on NodeJS-style import resolution of the library wasm-feature-detect
. This worked in environments where a bundler is available, but not on the Web. An additional entrypoint, es-explicit/entry.js
is provided to support ES imports on the Web.
The "modern" demo demonstrates a working configuration of SIMD, and a simpler configuration without SIMD.
Do not use: suffers from performance/size regression introduced in v5.0.0
. Prefer v6.0.2
The UMD module distribution in v5.0.0 was a misnomer — it was actually only ever a CJS module.
5.0.1 introduces a real UMD module, which has been confirmed working in NodeJS and on the Web. It includes an attempt at AMD support, but this is untested.
On the Web, entry.js
expects the wasm-feature-detect
UMD module to be already-loaded into your webpage, inserted as a <script>
tag prior to Box2D's. Additionally it expects
node_modules/box2d-wasm/build/flavour/simd/umd/Box2D.simd.{js,wasm}
to be served from /build/flavour/simd/umd
, and node_modules/box2d-wasm/build/flavour/standard/umd/Box2D.{js,wasm}
to be served from /build/flavour/standard/umd
.
The "classic" demo demonstrates a working configuration of SIMD, and a simpler configuration without SIMD.
Do not use: introduces performance/size regression. Prefer v6.0.2
Added support for WebAssembly SIMD acceleration (in supported browsers). This can make specific parts of the code 4x faster (but performance overall is unlikely to be dramatically different).
package.json now specifies the entrypoint to the library as entry.js
(rather than pointing directly to Box2D.js
). entry.js
uses wasm-feature-detect
to determine whether SIMD is available on your platform. It will then load in either Box2D.js
or Box2D.simd.js
as appropriate (after which, said .js file will load in Box2D.wasm
or Box2D.simd.wasm
respectively).
If you import the ES module distribution of box2d-wasm
: entry.js
will use ES2020 dynamic import()
and ES2017 await
to load in Box2D.js
or Box2D.simd.js
.
The browsers which support dynamic import and async/await
are very similar to the ones which support WebAssembly.
You may find that you need to reconfigure your bundler. The Svelte/Rollup demo demonstrates a working configuration (format: 'esm'
is the important part).
If you import the UMD module distribution of box2d-wasm
: entry.js
will use CommonJS require()
to load in Box2D.js
or Box2D.simd.js
.
Updated Emscripten 2.0.16->2.0.17. This uses LLVM's new pass manager:
Use LLVM's new pass manager by default, as LLVM does. This changes a bunch of things about how LLVM optimizes and inlines, so it may cause noticeable changes in compile times, code size, and speed, either for better or for worse.
In practice, code size seems comparable:
Box2D.js is still 319kB.
Box2D.wasm is 162kB (down from 163kB).
If you encounter any performance regressions, please say so (in case we need to tune --one-caller-inline-max-function-size
emscripten-core/emscripten#13899, or revert to legacy pass manager).
Exposed new helpers b2LinearStiffness
and b2AngularStiffness
:
const { _malloc, _free, b2LinearStiffness, HEAPF32 } = box2D;
// allocate two 4-byte floats on emscripten heap
const output_p = _malloc(Float32Array.BYTES_PER_ELEMENT * 2);
// give Box2D pointers to our floats on the heap, so it can mutate them
b2LinearStiffness(output_p, output_p + Float32Array.BYTES_PER_ELEMENT, 0.9, 0.3, bodyA, bodyB)
// create a Float32Array view over our heap offset, destructure two floats out of it
const [stiffness, damping] = HEAPF32.subarray(output_p >> 2)
// free the memory we allocated
_free(output_p);
const { _malloc, _free, b2AngularStiffness, HEAPF32 } = box2D;
// allocate two 4-byte floats on emscripten heap
const output_p = _malloc(Float32Array.BYTES_PER_ELEMENT * 2);
// give Box2D pointers to our floats on the heap, so it can mutate them
b2AngularStiffness(output_p, output_p + Float32Array.BYTES_PER_ELEMENT, 0.9, 0.3, bodyA, bodyB)
// create a Float32Array view over our heap offset, destructure two floats out of it
const [stiffness, damping] = HEAPF32.subarray(output_p >> 2)
// free the memory we allocated
_free(output_p);
The Box2DModule
type alias has been removed (again), because (in VSCode) neither .js
files using CommonJS imports (const Box2DFactory = require('box2d-wasm')
) nor .js
files using JSDoc hints (@type {import('box2d-wasm')}
or @type {import('box2d-wasm').default}
) were able to detect the type exported as export default Box2DFactory
in Box2DModule.d.ts
.
Box2DModule.d.ts
now exports Box2DFactory
via export assignment, like it did in v2.0.0:
export = Box2DFactory;
This is a CommonJS style which seems to be more compatible when imported via legacy mechanisms (CommonJS import or from global namespace).
Making the TypeScript typings more correct.
We once again export a type Box2DModule
(same as the Box2DEmscriptenModule
which existed pre-v2.0.0). You can use it as a shorthand to refer to the value returned from Box2DFactory
:
import type { Box2DModule } from 'box2d-wasm'
import Box2DFactory from 'box2d-wasm';
const box2D: Box2DModule = await Box2DFactory();
You can shorten this further if your tsconfig's compilerOptions
specifies "importsNotUsedAsValues": "remove"
(i.e. the default):
import Box2DFactory, { Box2DModule } from 'box2d-wasm';
const box2D: Box2DModule = await Box2DFactory();
The longhand still works:
import Box2DFactory from 'box2d-wasm';
const box2D: typeof Box2D & EmscriptenModule = await Box2DFactory();
Box2D.WrapperObject
and it subclasses used to have public properties __cache__
, __class__
, and ptr
. These do exist at runtime, but with different names (due to mangling in the build process).
These properties are now private.
Prefer getPointer()
to lookup the value of ptr
.
Prefer getCache()
to lookup the value of __cache__
.
Prefer getClass()
to lookup the value of __class__
. In TypeScript the subclass will not be inferred, so you will need to cast the result.
Classes such as Box2D.b2Vec2
have (in addition to their 2-arg constructor) a no-args constructor. This was not originally exposed (since it's not useful; it just throws an error).
These no-args constructor are now declared, in order to make such classes structurally compatible with their superclass, Box2D.WrapperObject
. It has been annotated with @deprecated
to discourage accidental usage.
The HasPointer
interface has been removed, since it was used to indicate the presence of a property ptr
(whose name would be mangled at runtime).
Helper functions such as wrapPointer
, getPointer
, castObject
, compare
getCache
, destroy
, getClass
and the helper constant NULL
are now simplified to not rely on the presence of now-private properties such as __cache__
, __class__
and ptr
, or removed interfaces such as HasPointer
.
getPointer
is now more permissive; you do not need to assert truthiness of an instance's ptr
to use it. Optional ptr
was only ever used to model edge-cases (casting of a manually-created WrapperObject
to a more specific class) — in usual use we can expect ptr
to be set.
Inference of specific subclasses is less powerful as a result (e.g. on getClass
).
Fixes final compile error in TypeScript type declarations.
Fix errors in TypeScript type declarations.
Breaking change: we no longer export a type Box2DEmscriptenModule
. Instead, use typeof Box2D & EmscriptenModule
. These two types are made available as ambient declarations in all your TypeScript source files, provided you import Box2DFactory from 'box2d-wasm';
in at least once place in your project.
Added support for NodeJS (tested on v14.13.0).
Exposed collision helpers and array helpers.
Compile WebAssembly with -O3 optimizations (previously -O2).