feat: add support for Blob's going over the ctx bridge (#29247)
This commit is contained in:
parent
d0b9a931cc
commit
f01e35f4ea
3 changed files with 41 additions and 2 deletions
|
@ -107,6 +107,7 @@ has been included below for completeness:
|
||||||
| `Function` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending classes or constructors will not work. |
|
| `Function` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending classes or constructors will not work. |
|
||||||
| [Cloneable Types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) | Simple | ✅ | ✅ | See the linked document on cloneable types |
|
| [Cloneable Types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) | Simple | ✅ | ✅ | See the linked document on cloneable types |
|
||||||
| `Element` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending custom elements will not work. |
|
| `Element` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending custom elements will not work. |
|
||||||
|
| `Blob` | Complex | ✅ | ✅ | N/A |
|
||||||
| `Symbol` | N/A | ❌ | ❌ | Symbols cannot be copied across contexts so they are dropped |
|
| `Symbol` | N/A | ❌ | ❌ | Symbols cannot be copied across contexts so they are dropped |
|
||||||
|
|
||||||
If the type you care about is not in the above table, it is probably not supported.
|
If the type you care about is not in the above table, it is probably not supported.
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "shell/common/gin_helper/promise.h"
|
#include "shell/common/gin_helper/promise.h"
|
||||||
#include "shell/common/node_includes.h"
|
#include "shell/common/node_includes.h"
|
||||||
#include "shell/common/world_ids.h"
|
#include "shell/common/world_ids.h"
|
||||||
|
#include "third_party/blink/public/web/web_blob.h"
|
||||||
#include "third_party/blink/public/web/web_element.h"
|
#include "third_party/blink/public/web/web_element.h"
|
||||||
#include "third_party/blink/public/web/web_local_frame.h"
|
#include "third_party/blink/public/web/web_local_frame.h"
|
||||||
|
|
||||||
|
@ -346,6 +347,14 @@ v8::MaybeLocal<v8::Value> PassValueToOtherContext(
|
||||||
destination_context->Global(), destination_context->GetIsolate()));
|
destination_context->Global(), destination_context->GetIsolate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom logic to "clone" Blob references
|
||||||
|
blink::WebBlob blob = blink::WebBlob::FromV8Value(value);
|
||||||
|
if (!blob.IsNull()) {
|
||||||
|
v8::Context::Scope destination_context_scope(destination_context);
|
||||||
|
return v8::MaybeLocal<v8::Value>(blob.ToV8Value(
|
||||||
|
destination_context->Global(), destination_context->GetIsolate()));
|
||||||
|
}
|
||||||
|
|
||||||
// Proxy all objects
|
// Proxy all objects
|
||||||
if (IsPlainObject(value)) {
|
if (IsPlainObject(value)) {
|
||||||
auto object_value = value.As<v8::Object>();
|
auto object_value = value.As<v8::Object>();
|
||||||
|
|
|
@ -584,6 +584,33 @@ describe('contextBridge', () => {
|
||||||
expect(result).to.deep.equal(['BODY', 'HTMLBodyElement', 'function']);
|
expect(result).to.deep.equal(['BODY', 'HTMLBodyElement', 'function']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle Blobs', async () => {
|
||||||
|
await makeBindingWindow(() => {
|
||||||
|
contextBridge.exposeInMainWorld('example', {
|
||||||
|
getBlob: () => new Blob(['ab', 'cd'])
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const result = await callWithBindings(async (root: any) => {
|
||||||
|
return [await root.example.getBlob().text()];
|
||||||
|
});
|
||||||
|
expect(result).to.deep.equal(['abcd']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle Blobs going backwards over the bridge', async () => {
|
||||||
|
await makeBindingWindow(() => {
|
||||||
|
contextBridge.exposeInMainWorld('example', {
|
||||||
|
getBlobText: async (fn: Function) => {
|
||||||
|
const blob = fn();
|
||||||
|
return [await blob.text()];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const result = await callWithBindings((root: any) => {
|
||||||
|
return root.example.getBlobText(() => new Blob(['12', '45']));
|
||||||
|
});
|
||||||
|
expect(result).to.deep.equal(['1245']);
|
||||||
|
});
|
||||||
|
|
||||||
// Can only run tests which use the GCRunner in non-sandboxed environments
|
// Can only run tests which use the GCRunner in non-sandboxed environments
|
||||||
if (!useSandbox) {
|
if (!useSandbox) {
|
||||||
it('should release the global hold on methods sent across contexts', async () => {
|
it('should release the global hold on methods sent across contexts', async () => {
|
||||||
|
@ -789,7 +816,8 @@ describe('contextBridge', () => {
|
||||||
symbolKeyed: {
|
symbolKeyed: {
|
||||||
[Symbol('foo')]: 123
|
[Symbol('foo')]: 123
|
||||||
},
|
},
|
||||||
getBody: () => document.body
|
getBody: () => document.body,
|
||||||
|
getBlob: () => new Blob(['ab', 'cd'])
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const result = await callWithBindings(async (root: any) => {
|
const result = await callWithBindings(async (root: any) => {
|
||||||
|
@ -862,7 +890,8 @@ describe('contextBridge', () => {
|
||||||
[(await example.object.getPromise()).arr[3][0], String],
|
[(await example.object.getPromise()).arr[3][0], String],
|
||||||
[arg, Object],
|
[arg, Object],
|
||||||
[arg.key, String],
|
[arg.key, String],
|
||||||
[example.getBody(), HTMLBodyElement]
|
[example.getBody(), HTMLBodyElement],
|
||||||
|
[example.getBlob(), Blob]
|
||||||
];
|
];
|
||||||
return {
|
return {
|
||||||
protoMatches: protoChecks.map(([a, Constructor]) => Object.getPrototypeOf(a) === Constructor.prototype)
|
protoMatches: protoChecks.map(([a, Constructor]) => Object.getPrototypeOf(a) === Constructor.prototype)
|
||||||
|
|
Loading…
Reference in a new issue