cloneInto()
This function provides a safe way to take an object defined in a privileged scope and create astructured clone of it in a less-privileged scope. It returns a reference to the clone:
const clonedObject = cloneInto(myObject, targetWindow);You can then assign the clone to an object in the target scope as an expando property, and scripts running in that scope can access it:
targetWindow.foo = clonedObject;This enables privileged code, such as an extension, to share an object with less-privileged code, such as a web page script.
In this article
Syntax
let clonedObject = cloneInto( obj, // object targetScope, // object options // optional object);Parameters
objobject. The object to clone.targetScopeobject. The object to attach the object to.optionsOptionalobject. Options for the function.cloneFunctionsOptionalboolean. Whether the object's functions should be cloned. Default tofalse. Cloned functions have the same semantics as functions exported usingexportFunction. SeeCloning objects that have functions.OptionalwrapReflectorsOptionalboolean. Whether DOM objects should be passed by reference instead of cloned. DOM objects are usually not clonable. Defaults tofalse. SeeCloning objects that contain DOM elements.
Return value
A reference to the cloned object.
Examples
This content script creates an object, clones it into the content window and makes it a property of the content window global:
// content scriptconst addonScriptObject = { greeting: "hello from your extension" };window.addonScriptObject = cloneInto(addonScriptObject, window);Scripts running in the page can access the object:
// page scriptbutton.addEventListener("click", () => { console.log(window.addonScriptObject.greeting); // "hello from your extension"});Of course, you don't have to assign the clone to the window itself; you can assign it to some other object in the target scope:
// Content scriptwindow.foo.addonScriptObject = cloneInto(addonScriptObject, window);You can also pass it into a function defined in the page script. Suppose the page script defines a function like this:
// page scriptfunction foo(greeting) { console.log(`they said: ${greeting.message}`);}The content script can define an object, clone it, and pass it into this function:
// content scriptconst addonScriptObject = { message: "hello from your extension" };window.foo(cloneInto(addonScriptObject, window)); // "they said: hello from your extension"Cloning objects that have functions
If the object to clone contains functions, you must pass the{ cloneFunctions: true } flag, or you get an error. If you do pass this flag, then functions in the object are cloned using the same mechanism used inexportFunction:
// content scriptconst addonScriptObject = { greetMe() { alert("hello from your extension"); },};window.addonScriptObject = cloneInto(addonScriptObject, window, { cloneFunctions: true,});// page scriptconst test = document.getElementById("test");test.addEventListener("click", () => { window.addonScriptObject.greetMe();});Cloning objects that contain DOM elements
By default, if the object you clone contains objects reflected from C++, such as DOM elements, the cloning operation fails with an error. If you pass the{ wrapReflectors: true } flag, then the object you clone contains these objects:
// content scriptconst addonScriptObject = { body: window.document.body,};window.addonScriptObject = cloneInto(addonScriptObject, window, { wrapReflectors: true,});// page scriptconst test = document.getElementById("test");test.addEventListener("click", () => { console.log(window.addonScriptObject.body.innerHTML);});Access to these objects in the target scope is subject to the normalscript security checks.