feat(wasm)!: native JS arrays via emscripten::val (replaces VectorDouble)#2977
Conversation
…ble) (CoolProp-71a partial)
The JS binding surface previously required JS code to interact with an
embind ``register_vector<double>("VectorDouble")`` wrapper class — push_back
on the way in, .get(i).value() / size() on the way out, with manual .delete()
for memory. The .get(i) path also depended on a workaround
(CoolProp-71a.8) to register std::optional<double> against an emcc
template-elision quirk under -O3.
This PR replaces every vector-shaped binding with native JS arrays via
emscripten::val:
- Setters take a JS array directly:
AS.set_mole_fractions([0.4, 0.6])
- Getters return a JS Array:
var z = AS.get_mole_fractions();
console.log(z[0], z.length);
- get_phase_envelope_data() returns a plain object whose fields are
native arrays:
var d = AS.get_phase_envelope_data();
console.log(d.T[i], d.p[i]);
Cleaner API, no VectorDouble/VectorString classes on the JS side, no
optional<double> registration needed (CoolProp-71a.8's workaround is
fully removed), no #include <optional> needed in the binding TU.
Two thin C++ helpers in src/emscripten_interface.cxx do the conversion:
template <class T>
val vec_to_js_array(const std::vector<T>& v);
std::vector<double> js_array_to_vec(const val& arr);
# Why this PR doesn't bump emsdk
The original motivation was to also unblock the emcc 5.x migration
(CoolProp-71a.2) by removing the optional<double> dependency that breaks
emcc's EMBIND_AOT path. Investigation showed AOT still fails against
our binding shape at the link-time '<<< EMBIND_AOT_INVOKERS >>>'
substitution step (tsgen.js itself succeeds; the sentinel is missing
from the final JS template). The Dockerfile + CI workflow stay pinned
to emsdk 4.0.12. CoolProp-71a.2 stays open with this finding documented.
# Breaking change
JS callers using the previous VectorDouble pattern will need to update:
Before: var v = new coolprop.VectorDouble();
v.push_back(0.4); v.push_back(0.6);
AS.set_mole_fractions(v);
v.delete();
After: AS.set_mole_fractions([0.4, 0.6]);
Before: var z = AS.get_mole_fractions();
console.log(z.get(0).value(), z.get(1).value());
z.delete();
After: var z = AS.get_mole_fractions();
console.log(z[0], z[1]);
# Test verification
Local docker build + node test_wasm.mjs against pinned emsdk 4.0.12:
all 5 sections pass (AbstractState, mixture set+get round-trip, enum
coverage, phase envelope value reads, derivative bindings).
test_wasm.mjs no longer constructs/manipulates VectorDouble; uses
[0.4, 0.6] and z[i] / d.T[i] directly.
Changelog entry added under 'Behavior changes (potentially breaking)'.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
💤 Files with no reviewable changes (1)
📝 WalkthroughWalkthroughThis PR migrates the CoolProp JavaScript/WASM interface from embind-managed vector wrapper types (VectorDouble, VectorString) to native JavaScript arrays. The change includes conversion utilities, updated bindings for composition fractions and phase envelopes, header cleanup, and test validation of the new array-based API surface. ChangesWASM Vector to Native Array Binding Migration
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Summary
Replaces the embind
VectorDouble/VectorStringwrapper classes on the JS binding surface with native JavaScript arrays viaemscripten::val.Before
After
Same shape for
get_phase_envelope_data()— returns a plain JS object whose fields (T,p, …) are native arrays. No.delete()calls needed for vector returns; standard JS GC handles them.Two thin helpers in
src/emscripten_interface.cxxdo the conversion:Drops the
register_vector/register_optional/value_objectregistrations, the#include <optional>, and theset_mole_fractions_double/_mass_fractions_double/_volu_fractions_doubleEMSCRIPTEN-only wrappers frominclude/AbstractState.h(no longer needed — the val→vector conversion happens in the lambda). The directinternal::_embind_register_optionalcall from PR #2974 (CoolProp-71a.8) is also gone with this refactor — no moreoptional<double>registration dependency.Why this doesn't bump emsdk
The original motivation was to also unblock the emcc 5.x migration (CoolProp-71a.2) by removing the
optional<double>dependency that breaks emcc'sEMBIND_AOTpath. Investigation showed AOT still fails against our binding shape at the link-time<<< EMBIND_AOT_INVOKERS >>>substitution (tsgen.jsitself succeeds; the sentinel is missing from the final JS template). The Dockerfile + CI workflow stay pinned to emsdk 4.0.12. CoolProp-71a.2 stays open with this finding documented in the bead.Breaking change
JS callers using the prior
VectorDoublepattern will need to update (see Summary above). Changelog entry added under "Behavior changes (potentially breaking)".Test plan
cd wrappers/Javascript && docker compose run --rm runneragainst pinned emsdk 4.0.12 links cleanlynode test_wasm.mjsexits 0 with all 5 sections passing — including:get_mole_fractions()returns[0.4, 0.6](real JS Array)env.T[107]andenv.p[107]read directlyJavascript libraryworkflow green🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation