Skip to content

Commit b6efadf

Browse files
src: add V8 Fast API for URL.revokeObjectURL
co-authored-by: Nicholas Paun <npaun@cloudflare.com>
1 parent b981253 commit b6efadf

File tree

4 files changed

+76
-3
lines changed

4 files changed

+76
-3
lines changed

src/node_blob.cc

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
#include "env-inl.h"
66
#include "memory_tracker-inl.h"
77
#include "node_bob-inl.h"
8+
#include "node_debug.h"
89
#include "node_errors.h"
910
#include "node_external_reference.h"
1011
#include "node_file.h"
1112
#include "path.h"
1213
#include "permission/permission.h"
1314
#include "util.h"
15+
#include "v8-value.h"
1416
#include "v8.h"
17+
#include "v8-fast-api-calls.h"
1518

1619
#include <algorithm>
1720

@@ -39,6 +42,8 @@ using v8::String;
3942
using v8::Uint32;
4043
using v8::Undefined;
4144
using v8::Value;
45+
using v8::CFunction;
46+
using v8::FastApiCallbackOptions;
4247

4348
namespace {
4449

@@ -130,7 +135,7 @@ void Blob::CreatePerIsolateProperties(IsolateData* isolate_data,
130135
SetMethod(isolate, target, "createBlob", New);
131136
SetMethod(isolate, target, "storeDataObject", StoreDataObject);
132137
SetMethod(isolate, target, "getDataObject", GetDataObject);
133-
SetMethod(isolate, target, "revokeObjectURL", RevokeObjectURL);
138+
SetFastMethod(isolate, target, "revokeObjectURL", RevokeObjectURL, &fast_revoke_object_url_method);
134139
SetMethod(isolate, target, "concat", Concat);
135140
SetMethod(isolate, target, "createBlobFromFilePath", BlobFromFilePath);
136141
}
@@ -450,7 +455,6 @@ void Blob::StoreDataObject(const FunctionCallbackInfo<Value>& args) {
450455
std::string(*type, type.length())));
451456
}
452457

453-
// TODO(@anonrig): Add V8 Fast API to the following function
454458
void Blob::RevokeObjectURL(const FunctionCallbackInfo<Value>& args) {
455459
CHECK_GE(args.Length(), 1);
456460
CHECK(args[0]->IsString());
@@ -477,6 +481,38 @@ void Blob::RevokeObjectURL(const FunctionCallbackInfo<Value>& args) {
477481
}
478482
}
479483

484+
void Blob::FastRevokeObjectURL(
485+
Local<Value> receiver,
486+
Local<Value> raw_input, FastApiCallbackOptions& options) {
487+
TRACK_V8_FAST_API_CALL("blob.revokeObjectURL");
488+
CHECK(raw_input->IsString());
489+
490+
auto isolate = options.isolate;
491+
HandleScope handleScope(isolate);
492+
Realm* realm = Realm::GetCurrent(isolate->GetCurrentContext());
493+
BlobBindingData* binding_data = realm->GetBindingData<BlobBindingData>();
494+
495+
Utf8Value input(isolate, raw_input.As<String>());
496+
auto out = ada::parse<ada::url_aggregator>(input.ToStringView());
497+
498+
if (!out) {
499+
return;
500+
}
501+
502+
auto pathname = out->get_pathname();
503+
auto start_index = pathname.find(':');
504+
505+
if (start_index != std::string_view::npos && start_index != pathname.size()) {
506+
auto end_index = pathname.find(':', start_index + 1);
507+
if (end_index == std::string_view::npos) {
508+
auto id = std::string(pathname.substr(start_index + 1));
509+
binding_data->revoke_data_object(id);
510+
}
511+
}
512+
}
513+
514+
CFunction Blob::fast_revoke_object_url_method = CFunction::Make(Blob::FastRevokeObjectURL);
515+
480516
void Blob::GetDataObject(const FunctionCallbackInfo<Value>& args) {
481517
CHECK(args[0]->IsString());
482518
Realm* realm = Realm::GetCurrent(args);
@@ -584,9 +620,11 @@ void Blob::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
584620
registry->Register(Blob::StoreDataObject);
585621
registry->Register(Blob::GetDataObject);
586622
registry->Register(Blob::RevokeObjectURL);
623+
registry->Register(Blob::FastRevokeObjectURL);
587624
registry->Register(Blob::Reader::Pull);
588625
registry->Register(Concat);
589626
registry->Register(BlobFromFilePath);
627+
registry->Register(fast_revoke_object_url_method.GetTypeInfo());
590628
}
591629

592630
} // namespace node

src/node_blob.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include "node_snapshotable.h"
1515
#include "node_worker.h"
1616
#include "v8.h"
17-
17+
#include "v8-fast-api-calls.h"
1818
#include <string>
1919
#include <unordered_map>
2020
#include <vector>
@@ -39,6 +39,9 @@ class Blob : public BaseObject {
3939
static void StoreDataObject(const v8::FunctionCallbackInfo<v8::Value>& args);
4040
static void GetDataObject(const v8::FunctionCallbackInfo<v8::Value>& args);
4141
static void RevokeObjectURL(const v8::FunctionCallbackInfo<v8::Value>& args);
42+
static void FastRevokeObjectURL(v8::Local<v8::Value> receiver, v8::Local<v8::Value> raw_input, v8::FastApiCallbackOptions& options);
43+
44+
static v8::CFunction fast_revoke_object_url_method;
4245

4346
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
4447
Environment* env);

src/node_external_reference.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ using CFunctionCallbackWithInt64 = void (*)(v8::Local<v8::Object> unused,
4646
using CFunctionCallbackWithBool = void (*)(v8::Local<v8::Object> unused,
4747
v8::Local<v8::Object> receiver,
4848
bool);
49+
50+
using CFunctionCallbackWithValue = void (*)(v8::Local<v8::Value>,
51+
v8::Local<v8::Value>,
52+
v8::FastApiCallbackOptions&);
53+
4954
using CFunctionCallbackWithString =
5055
bool (*)(v8::Local<v8::Value>, const v8::FastOneByteString& input);
5156
using CFunctionCallbackWithStrings =
@@ -116,6 +121,7 @@ class ExternalReferenceRegistry {
116121
V(CFunctionCallbackWithBool) \
117122
V(CFunctionCallbackWithString) \
118123
V(CFunctionCallbackWithStrings) \
124+
V(CFunctionCallbackWithValue) \
119125
V(CFunctionCallbackWithTwoUint8Arrays) \
120126
V(CFunctionCallbackWithUint8ArrayUint32Int64Bool) \
121127
V(CFunctionWithUint32) \
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Flags: --expose-internals --allow-natives-syntax
2+
'use strict';
3+
const common = require('../common');
4+
const assert = require('node:assert');
5+
6+
const { internalBinding } = require('internal/test/binding');
7+
8+
const blob = new Blob([JSON.stringify({ hello: "world" }, null, 2)], {
9+
type: "application/json",
10+
});
11+
12+
function testFastPath() {
13+
const objURL = URL.createObjectURL(blob);
14+
URL.revokeObjectURL(objURL);
15+
}
16+
17+
eval('%PrepareFunctionForOptimization(URL.revokeObjectURL)');
18+
testFastPath();
19+
20+
eval('%OptimizeFunctionOnNextCall(URL.revokeObjectURL)');
21+
testFastPath();
22+
23+
if (common.isDebug) {
24+
const { getV8FastApiCallCount } = internalBinding('debug');
25+
assert.strictEqual(getV8FastApiCallCount('blob.revokeObjectURL'), 1);
26+
}

0 commit comments

Comments
 (0)