Skip to content

Commit

Permalink
src: add a fast call for URL.revokeObjectURL
Browse files Browse the repository at this point in the history
Refs: #47728
  • Loading branch information
debadree25 committed Apr 30, 2023
1 parent 6827dbb commit 869ff2a
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 28 deletions.
20 changes: 20 additions & 0 deletions benchmark/url/url-create-revoke-objecturl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';
const common = require('../common.js');
const assert = require('node:assert');
const { Blob } = require('buffer');

const bench = common.createBenchmark(main, {
n: [1e6],
});

function main({ n }) {
const blob = new Blob(['hello']);
let id = '';
bench.start();
for (let i = 0; i < n; i += 1) {
id = URL.createObjectURL(blob);
URL.revokeObjectURL(id);
}
assert.ok(id);
bench.end(n);
}
79 changes: 51 additions & 28 deletions src/node_blob.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "node_external_reference.h"
#include "node_file.h"
#include "util.h"
#include "v8-fast-api-calls.h"
#include "v8.h"

#include <algorithm>
Expand All @@ -19,7 +20,9 @@ using v8::Array;
using v8::ArrayBuffer;
using v8::ArrayBufferView;
using v8::BackingStore;
using v8::CFunction;
using v8::Context;
using v8::FastOneByteString;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
Expand Down Expand Up @@ -107,25 +110,6 @@ void BlobFromFilePath(const FunctionCallbackInfo<Value>& args) {
}
} // namespace

void Blob::Initialize(
Local<Object> target,
Local<Value> unused,
Local<Context> context,
void* priv) {
Realm* realm = Realm::GetCurrent(context);

BlobBindingData* const binding_data =
realm->AddBindingData<BlobBindingData>(context, target);
if (binding_data == nullptr) return;

SetMethod(context, target, "createBlob", New);
SetMethod(context, target, "storeDataObject", StoreDataObject);
SetMethod(context, target, "getDataObject", GetDataObject);
SetMethod(context, target, "revokeObjectURL", RevokeObjectURL);
SetMethod(context, target, "concat", Concat);
SetMethod(context, target, "createBlobFromFilePath", BlobFromFilePath);
}

Local<FunctionTemplate> Blob::GetConstructorTemplate(Environment* env) {
Local<FunctionTemplate> tmpl = env->blob_constructor_template();
if (tmpl.IsEmpty()) {
Expand Down Expand Up @@ -416,14 +400,9 @@ void Blob::StoreDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
std::string(*type, type.length())));
}

// TODO(@anonrig): Add V8 Fast API to the following function
void Blob::RevokeObjectURL(const FunctionCallbackInfo<Value>& args) {
CHECK_GE(args.Length(), 1);
CHECK(args[0]->IsString());
BlobBindingData* binding_data = Realm::GetBindingData<BlobBindingData>(args);
Environment* env = Environment::GetCurrent(args);
Utf8Value input(env->isolate(), args[0].As<String>());
auto out = ada::parse<ada::url_aggregator>(input.ToStringView());
void RevokeObjectURLImpl(std::string_view input,
BlobBindingData* binding_data) {
auto out = ada::parse<ada::url_aggregator>(input);

if (!out) {
return;
Expand All @@ -441,6 +420,26 @@ void Blob::RevokeObjectURL(const FunctionCallbackInfo<Value>& args) {
}
}

void Blob::RevokeObjectURL(const FunctionCallbackInfo<Value>& args) {
CHECK_GE(args.Length(), 1);
CHECK(args[0]->IsString());
BlobBindingData* binding_data = Realm::GetBindingData<BlobBindingData>(args);
Environment* env = Environment::GetCurrent(args);
Utf8Value input(env->isolate(), args[0].As<String>());
RevokeObjectURLImpl(input.ToStringView(), binding_data);
}

void Blob::FastRevokeObjectURL(Local<Value> receiver,
const FastOneByteString& input) {
printf("FastRevokeObjectURL\n");
BlobBindingData* binding_data = FromJSObject<BlobBindingData>(receiver);
std::string_view input_view(input.data, input.length);
RevokeObjectURLImpl(input_view, binding_data);
}

CFunction Blob::fast_revoke_object_url(
CFunction::Make(Blob::FastRevokeObjectURL));

void Blob::GetDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
BlobBindingData* binding_data = Realm::GetBindingData<BlobBindingData>(args);

Expand Down Expand Up @@ -548,16 +547,40 @@ InternalFieldInfoBase* BlobBindingData::Serialize(int index) {
return info;
}

void Blob::Initialize(Local<Object> target,
Local<Value> unused,
Local<Context> context,
void* priv) {
Realm* realm = Realm::GetCurrent(context);

BlobBindingData* const binding_data =
realm->AddBindingData<BlobBindingData>(context, target);
if (binding_data == nullptr) return;

SetMethod(context, target, "createBlob", New);
SetMethod(context, target, "storeDataObject", StoreDataObject);
SetMethod(context, target, "getDataObject", GetDataObject);
SetFastMethod(context,
target,
"revokeObjectURL",
RevokeObjectURL,
&fast_revoke_object_url);
SetMethod(context, target, "concat", Concat);
SetMethod(context, target, "createBlobFromFilePath", BlobFromFilePath);
}

void Blob::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
registry->Register(Blob::New);
registry->Register(Blob::GetReader);
registry->Register(Blob::ToSlice);
registry->Register(Blob::StoreDataObject);
registry->Register(Blob::GetDataObject);
registry->Register(Blob::RevokeObjectURL);
registry->Register(Blob::Reader::Pull);
registry->Register(Concat);
registry->Register(BlobFromFilePath);
registry->Register(Blob::RevokeObjectURL);
registry->Register(Blob::FastRevokeObjectURL);
registry->Register(fast_revoke_object_url.GetTypeInfo());
}

} // namespace node
Expand Down
4 changes: 4 additions & 0 deletions src/node_blob.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "node_internals.h"
#include "node_snapshotable.h"
#include "node_worker.h"
#include "v8-fast-api-calls.h"
#include "v8.h"

#include <string>
Expand All @@ -38,6 +39,8 @@ class Blob : public BaseObject {
static void StoreDataObject(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetDataObject(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RevokeObjectURL(const v8::FunctionCallbackInfo<v8::Value>& args);
static void FastRevokeObjectURL(v8::Local<v8::Value> receiver,
const v8::FastOneByteString& input);

static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
Environment* env);
Expand Down Expand Up @@ -107,6 +110,7 @@ class Blob : public BaseObject {

private:
std::shared_ptr<DataQueue> data_queue_;
static v8::CFunction fast_revoke_object_url;
};

class BlobBindingData : public SnapshotableObject {
Expand Down
4 changes: 4 additions & 0 deletions src/node_external_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ using CFunctionCallbackWithBool = void (*)(v8::Local<v8::Object> receiver,
using CFunctionCallbackWithStrings =
bool (*)(v8::Local<v8::Value>, const v8::FastOneByteString& input);

using CFunctionCallbackWithStringsReturnVoid =
void (*)(v8::Local<v8::Value>, const v8::FastOneByteString& input);

// This class manages the external references from the V8 heap
// to the C++ addresses in Node.js.
class ExternalReferenceRegistry {
Expand All @@ -35,6 +38,7 @@ class ExternalReferenceRegistry {
V(CFunctionCallbackWithInt64) \
V(CFunctionCallbackWithBool) \
V(CFunctionCallbackWithStrings) \
V(CFunctionCallbackWithStringsReturnVoid) \
V(const v8::CFunctionInfo*) \
V(v8::FunctionCallback) \
V(v8::AccessorGetterCallback) \
Expand Down

0 comments on commit 869ff2a

Please sign in to comment.