@eastgold15/vscode-webview
Version:
优化 webview 页面与 vscode 扩展之间的 postMessage 通信
206 lines (205 loc) • 5.95 kB
JavaScript
//#region \0@oxc-project+runtime@0.144.0/helpers/esm/typeof.js
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
return typeof o;
} : function(o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
//#endregion
//#region \0@oxc-project+runtime@0.144.0/helpers/esm/toPrimitive.js
function toPrimitive(t, r) {
if ("object" != _typeof(t) || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != _typeof(i)) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
//#endregion
//#region \0@oxc-project+runtime@0.144.0/helpers/esm/toPropertyKey.js
function toPropertyKey(t) {
var i = toPrimitive(t, "string");
return "symbol" == _typeof(i) ? i : i + "";
}
//#endregion
//#region \0@oxc-project+runtime@0.144.0/helpers/esm/defineProperty.js
function _defineProperty(e, r, t) {
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: !0,
configurable: !0,
writable: !0
}) : e[r] = t, e;
}
//#endregion
//#region src/index.ts
const INTERVAL = 200;
const TIMEOUT = 1e4;
const TYPE_KEY = "type";
const DATA_KEY = "data";
const globalPostMessageOptions = {
dataKey: DATA_KEY,
interval: INTERVAL,
timeout: TIMEOUT,
typeKey: TYPE_KEY
};
function isNil(v) {
return typeof v === "undefined" || v === null;
}
/**
* A utility wrapper around the acquireVsCodeApi() function, which enables
* message passing and state management between the webview and extension
* contexts.
*/
var WebviewApi = class {
constructor(options) {
_defineProperty(this, "webviewApi", void 0);
_defineProperty(this, "_options", {
interval: INTERVAL,
timeout: TIMEOUT
});
_defineProperty(this, "listeners", /* @__PURE__ */ new Map());
if (typeof acquireVsCodeApi !== "function") {
console.error("acquireVsCodeApi is not a function");
return;
}
this.setOptions(options || {});
this.webviewApi = acquireVsCodeApi();
window.addEventListener("message", (event) => {
const message = event.data || {};
const { typeKey, dataKey } = this._options;
this._runListener(message[typeKey ?? TYPE_KEY], message[dataKey ?? DATA_KEY]);
});
}
/**
* set the post message options
* @param options
*/
setOptions(options) {
this._options = {
...globalPostMessageOptions,
...this._options,
...options
};
}
_postMessage(type, data, options) {
if (!this.webviewApi) return;
this.webviewApi.postMessage({
[options.typeKey ?? TYPE_KEY]: type,
[options.dataKey ?? DATA_KEY]: data
});
}
_runListener(type, result, error) {
if (isNil(type) || this.listeners.size === 0) return;
const listeners = this.listeners.get(type);
if (listeners) {
if (!isNil(result)) {
var _listeners$;
(_listeners$ = listeners[0]) === null || _listeners$ === void 0 || _listeners$.call(listeners, result);
}
if (!isNil(error)) {
var _listeners$2;
(_listeners$2 = listeners[1]) === null || _listeners$2 === void 0 || _listeners$2.call(listeners, error);
}
}
}
/**
* Post a message to the owner of the webview
* @param type the message type
* @param data the message content
* @param options
*/
post(type, data) {
this._postMessage(type, data, this._options);
}
/**
* Post a message to the owner of the webview, and return the response. The type of the message to be sent and received must be the same.
* @param type the message type
* @param data the message content
* @param options
*/
postAndReceive(type, data, options) {
return new Promise((resolve, reject) => {
if (!this.webviewApi) {
reject(/* @__PURE__ */ new Error("acquireVsCodeApi is not available"));
return;
}
const opts = {
...this._options,
...options
};
const post = () => {
this._postMessage(type, data, opts);
};
const intervalId = setInterval(post, opts.interval ?? INTERVAL);
const _runListener = this._runListener;
const timeoutId = setTimeout(() => {
window.removeEventListener("message", receive);
clearInterval(intervalId);
_runListener(type, void 0, /* @__PURE__ */ new Error("Timeout"));
reject(/* @__PURE__ */ new Error("Timeout"));
}, opts.timeout ?? TIMEOUT);
function receive(e) {
if (!(e.origin.startsWith("vscode-webview://") && e.data) || e.data[opts.typeKey ?? TYPE_KEY] !== type) return;
window.removeEventListener("message", receive);
clearTimeout(timeoutId);
clearInterval(intervalId);
const res = e.data[opts.dataKey ?? DATA_KEY];
_runListener(type, res);
resolve(res);
}
window.addEventListener("message", receive);
post();
});
}
/**
* Register a listener for a message type
* @param type the message type
* @param success the success listener
* @param fail the fail listener
*/
on(type, success, fail) {
this.listeners.set(type, fail ? [success, fail] : [success]);
}
/**
* Remove a listener for a message type
* @param type the message type
*/
off(type) {
this.listeners.delete(type);
}
/**
* Post a message to the owner of the webview
* @param message the message content
*/
postMessage(message) {
this.webviewApi.postMessage(message);
}
/**
* Get the persistent state stored for this webview.
*
* @return The current state or `undefined` if no state has been set.
*/
getState() {
return this.webviewApi.getState();
}
/**
* Set the persistent state stored for this webview.
*
* @param newState New persisted state. This must be a JSON serializable object. Can be retrieved
* using {@link getState}.
*
* @return The new state.
*/
setState(newState) {
this.webviewApi.setState(newState);
return newState;
}
};
//#endregion
export { WebviewApi };
//# sourceMappingURL=index.mjs.map