Javascript chrome.runtime是否支持使用可转移对象发布消息?

Javascript chrome.runtime是否支持使用可转移对象发布消息?,javascript,google-chrome-extension,transferable,Javascript,Google Chrome Extension,Transferable,我正在学习可转让物品: 它们看起来非常棒,我想在扩展中使用它们来加速从iframe内部到iframe外部的数据传递 我已经有了这个示例代码,但它使用了一个Web Worker: var s = document.createElement("script"); s.type = "text/js-worker"; s.innerHTML = 'console.log("i ran!");'; document.body.appendChild(s); var blob = new Blob(A

我正在学习可转让物品:

它们看起来非常棒,我想在扩展中使用它们来加速从iframe内部到iframe外部的数据传递

我已经有了这个示例代码,但它使用了一个Web Worker:

var s = document.createElement("script");
s.type = "text/js-worker";
s.innerHTML = 'console.log("i ran!");';
document.body.appendChild(s);

var blob = new Blob(Array.prototype.map.call(document.querySelectorAll("script[type=\"text\/js-worker\"]"), function (oScript) {
    return oScript.textContent;
}), { type: "text/javascript" });

var worker = new Worker(window.URL.createObjectURL(blob));

var arrayBuffer = new ArrayBuffer(1);

worker.onmessage = function (oEvent) {
    console.log("Called back by the worker!\n");
};

console.log("worker:", worker);
worker.postMessage(arrayBuffer, [arrayBuffer]);

if (arrayBuffer.byteLength) {
    console.error("nope");
} else {
    console.log("it worked");
}
是否有任何人有任何关于支持的信息,或使用以下端口支持/a crbug的时间表:

var port = chrome.runtime.connect({
    name: 'youTubeIFrameConnectRequest'
});

//port.postMessage -- transferrable object.

我看不到有人支持它,也没有人支持它,但这似乎真的很奇怪

通过的消息始终是JSON序列化的。此格式不仅用于在后台页面和内容脚本之间传递消息,而且还用于。因此,我想消息传递API不太可能支持更多的项

2012年,已经有人请求使用结构化克隆算法(比JSON序列化更强大,比可转移性更小)。问题仍然悬而未决;有人建议用蹦床作为“蹦床”

SharedWorker
受同一来源策略的影响,因此呼叫者需要驻留在同一来源。要实现这一点,您可以向添加页面,并将此页面嵌入到框架中

在这个答案的最后,我附加了一个蹦床的简单实现。使用这些文件创建扩展名。然后,打开一个选项卡。此选项卡将包含嵌入的框架,演示程序将向共享工作程序发送消息。此消息将被传输到后台页面,以便查看这些消息。
演示非常简单,您需要自己实施端口管理(销毁)。
该演示还没有使用可转移消息传递,因为它是一个允许多个端口的通用实现。如果您确保最多同时存在两个端口,那么您可以将代码更改为使用可转移(只有当有一个接收端口和一个发送方时,可转移端口才有意义,因为对象的所有权也被转移)

特殊情况:相同流程 如果您的所有代码都在同一个过程中运行,那么您可以使用更简单的方法,而不必使用
SharedWorker
s

同源策略禁止从/到框架和扩展的直接访问,因此您将使用来跨越此网桥。然后,在页面的onmessage事件中,您可以使用获取对扩展页面之一的
窗口
对象的直接引用(例如,弹出页面、选项页面等)。
从其他页面中,提供对背景页面的
窗口
对象的引用(对于,使用)

如果要连接两个帧,请使用通道消息传递API(请参阅和)。使用此方法,您将在帧之间建立直接连接,即使它们位于不同的原点

例如:蹦床
worker.js
var端口=[];
onconnect=功能(事件){
var port=event.port[0];
端口。推送(端口);
port.start();
port.onmessage=函数(事件){
对于(变量i=0;i
trampoline.js
var-worker=new-SharedWorker(chrome.runtime.getURL('worker.js');
worker.port.start();
//演示:将消息打印到控制台,并记住最后的结果
worker.port.onmessage=函数(事件){
console.log('收到的消息',事件.data);
window.lastMessage=event.data;
};
//演示:发送消息
worker.port.postMessage('Hello');
trampoline.html

contentscript.js
var f=document.createElement('iframe');
f、 src=chrome.runtime.getURL('trampoline.html');
f、 隐藏=真实;
(document.body | | document.documentElement).appendChild(f);
manifest.json
注意:我把
trampoline.js
作为背景脚本,以节省这个答案中的空间。从Web工作者的角度来看,谁发起了消息并不重要,因此我重新使用了发送和接收消息的代码(毕竟这是一个简单的演示!)

{
“名称”:“蹦床演示”,
“版本”:“1”,
“清单版本”:2,
“背景”:{
“脚本”:[“trampoline.js”],
“持久”:正确
},  
“内容脚本”:[{
“js”:[“contentscript.js”],
“匹配项”:[“”]
}],
“网络可访问资源”:[
“trampoline.html”
]   
}

+1还有一个很好的答案!我有一个问题(与此答案无关):我注意到您总是使用
document.head/body | | document.documentElement
。为什么使用
documentElement
部分?@ExpertSystem在
document\u start
运行内容脚本时,
document.head/body
通常为
null
<代码>文档。在某些文档(例如SVG)中,头/体始终为
null
。但是所有文档都有根,所以我添加了
document.documentElement
作为后备方法。@RobW感谢您一如既往地给出了非常有见解的答案。很高兴您能参观chrome扩展开发区。谢谢,Rob。(我认为我们应该正式宣布Rob“Jon Skeet of Chrome Extensions”:P)
f.style=“display:none!important;”“
可能是隐藏帧的更可靠的方法,而不是
f.hidden=true
。如果页面具有类似于
iframe{display:block;}
的CSS,那么
hidden
属性将不起作用。