react-native-webview-comlink
Version:
Add JavaScript interface for react-native-webview, based on Comlink
119 lines (118 loc) • 3.52 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { generateID } from './utils';
export function toWireValue(value, channel) {
// proxy function
if (typeof value === 'function') {
let id = channel.tryGetLocalFuntionID(value);
if (!id) {
id = generateID();
}
const vid = generateID();
channel.registerLocalFunction(id, vid, value);
return {
type: "P" /* PROXY */,
id,
vid,
};
}
if (value instanceof Error) {
const { message, name, stack } = value, rest = __rest(value, ["message", "name", "stack"]);
return {
type: "R" /* RAW */,
val: Object.assign({ message }, rest),
};
}
// raw value
return {
type: "R" /* RAW */,
val: value,
};
}
export function fromWireValue(value, channel) {
switch (value.type) {
case "R" /* RAW */:
return value.val;
case "P" /* PROXY */:
const { id, vid } = value;
let remoteFunction = channel.tryGetRemoteFunction(id);
if (remoteFunction) {
remoteFunction.addRef(vid);
}
else {
remoteFunction = createRemoteFunction(id, vid, channel);
channel.registerRemoteFunction(id, remoteFunction);
}
return remoteFunction;
case "T" /* THROW */:
const _a = value.val, { message } = _a, rest = __rest(_a, ["message"]);
return Object.assign(new Error(message), rest);
default:
return undefined;
}
}
export function createRemoteFunction(id, vid, channel) {
let refCount = 1;
let latestVid = vid;
const cleanup = () => {
if (refCount <= 0) {
return;
}
refCount = 0;
channel.unregisterRemoteFunction(id);
channel.notifyRelease({
type: "RLS" /* RELEASE */,
id,
vid: latestVid,
});
};
return Object.assign((...args) => {
return channel
.requestResponse({
type: "REQ" /* REQUEST */,
id,
rid: generateID(),
args: args.map((arg) => toWireValue(arg, channel)),
})
.then((response) => {
if (!response) {
return;
}
const value = fromWireValue(response, channel);
if (value instanceof Error) {
throw value;
}
return value;
});
}, {
addRef: (vid) => {
if (refCount <= 0) {
return 0;
}
latestVid = vid;
refCount += 1;
return refCount;
},
release: () => {
if (refCount <= 0) {
return 0;
}
if (refCount === 1) {
cleanup();
return refCount;
}
refCount -= 1;
return refCount;
},
cleanup,
});
}