You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #9600 (closed) and its fix #9607. The UnpackerLoader guard shipped in #9607 does not fully close the crash: a debug native build (Expo dev client) loading a release-transformed bundle (EAS Update / expo export) can still abort at startup with
Error: Exception in HostFunction: Error parsing source map:1:1: JSON object or array expected
at evalWithSourceMap (native)
We hit this in production tooling (Dorsia member app, preview dev-client channel) on react-native-worklets 0.10.0 — a version that already contains the #9607 guard (UnpackerLoader.h → useSourceMaps = !valueUnpacker_.sourceMap.empty()), so #9607 alone demonstrably does not cover all paths. Verified the situation is unchanged in 0.10.2 and on current main.
Two call paths can still hand an empty string to the evalWithSourceMap host function, which passes it to HermesRuntime::evaluateJavaScriptWithSourceMap, where Hermes rejects '' as invalid source-map JSON:
UnpackerLoader.h guard only samples one unpacker.useSourceMaps is derived from valueUnpacker_.sourceMap alone. If valueUnpacker_ has a non-empty map while any other unpacker (synchronizable / customSerializable / shareableHost / shareableGuest / remoteFunction) carries an empty one — e.g. mixed debug/release metadata after the flavor-detection issue fixed in fix(Worklets): Babel plugin not detecting production environment #9609, or partially transformed bundles — evalWithSourceMap is still called with '' for those.
valueUnpacker.native.js per-worklet eval is unguarded. It calls globalThis.evalWithSourceMap('(' + initData.code + '\n)', initData.location, initData.sourceMap) whenever the global exists, without checking initData.sourceMap. undefined happens to be safe (fails the isString() check in the host function), but an empty string crashes. Unchanged on main today.
Suggested fix
Guard at the single native boundary all call paths share — the evalWithSourceMap host function in WorkletHermesRuntime.cpp — by treating an empty string the same as an absent source map:
std::shared_ptr<const jsi::Buffer> sourceMap;
if (count > 2 && args[2].isString()) {
auto sourceMapString = args[2].asString(rt).utf8(rt);
// Hermes treats an empty string as invalid source-map JSON. Release// worklet transforms may omit source maps, so treat empty strings the// same as absent source maps.if (!sourceMapString.empty()) {
sourceMap = std::make_shared<const jsi::StringBuffer>(std::move(sourceMapString));
}
}
We have been shipping exactly this as a local patch on 0.10.0–0.10.2 and it resolves the startup crash for every caller (unpackers, per-worklet evals, custom serializables) without affecting the debugger's source-map behaviour when a real map is present. Happy to open a PR if this direction is acceptable.
Description
Follow-up to #9600 (closed) and its fix #9607. The
UnpackerLoaderguard shipped in #9607 does not fully close the crash: a debug native build (Expo dev client) loading a release-transformed bundle (EAS Update /expo export) can still abort at startup withWe hit this in production tooling (Dorsia member app, preview dev-client channel) on react-native-worklets 0.10.0 — a version that already contains the #9607 guard (
UnpackerLoader.h→useSourceMaps = !valueUnpacker_.sourceMap.empty()), so #9607 alone demonstrably does not cover all paths. Verified the situation is unchanged in 0.10.2 and on currentmain.Why #9607 is incomplete
Two call paths can still hand an empty string to the
evalWithSourceMaphost function, which passes it toHermesRuntime::evaluateJavaScriptWithSourceMap, where Hermes rejects''as invalid source-map JSON:UnpackerLoader.hguard only samples one unpacker.useSourceMapsis derived fromvalueUnpacker_.sourceMapalone. IfvalueUnpacker_has a non-empty map while any other unpacker (synchronizable / customSerializable / shareableHost / shareableGuest / remoteFunction) carries an empty one — e.g. mixed debug/release metadata after the flavor-detection issue fixed in fix(Worklets): Babel plugin not detecting production environment #9609, or partially transformed bundles —evalWithSourceMapis still called with''for those.valueUnpacker.native.jsper-worklet eval is unguarded. It callsglobalThis.evalWithSourceMap('(' + initData.code + '\n)', initData.location, initData.sourceMap)whenever the global exists, without checkinginitData.sourceMap.undefinedhappens to be safe (fails theisString()check in the host function), but an empty string crashes. Unchanged onmaintoday.Suggested fix
Guard at the single native boundary all call paths share — the
evalWithSourceMaphost function inWorkletHermesRuntime.cpp— by treating an empty string the same as an absent source map:We have been shipping exactly this as a local patch on 0.10.0–0.10.2 and it resolves the startup crash for every caller (unpackers, per-worklet evals, custom serializables) without affecting the debugger's source-map behaviour when a real map is present. Happy to open a PR if this direction is acceptable.
Steps to reproduce
Same shape as #9600 (its repro https://github.com/bj97301/worklets-ota-sourcemap-repro applies):
expo-dev-clienteas updateorexpo export) where at least one worklet__initData.sourceMapis an empty stringevalWithSourceMapVersions
main(code paths verified still unguarded)