GeezerVison is showing github.com — test: add permission fast api test · nodejs/node@bf86fab
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: src/permission/permission.cc +32-6Lines changed: 32 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -127,7 +127,6 @@ static void Has(const FunctionCallbackInfo<Value>& args) { | 127 | 127 |
| 128 | 128 | static bool FastHas(Local<Value> receiver, | 129 | 129 | Local<Value> scope_arg, | 130 | | - Local<Value> resource_arg, | 131 | 130 | // NOLINTNEXTLINE(runtime/references) This is V8 api. | 132 | 131 | FastApiCallbackOptions& options) { | 133 | 132 | TRACK_V8_FAST_API_CALL("permission.has"); | @@ -148,8 +147,31 @@ static bool FastHas(Local<Value> receiver, | 148 | 147 | return false; | 149 | 148 | } | 150 | 149 |
| 151 | | - if (resource_arg->IsUndefined()) { | 152 | | - return env->permission()->is_granted(env, scope); | | 150 | + return env->permission()->is_granted(env, scope); | | 151 | +} | | 152 | + | | 153 | +static bool FastHasResource( | | 154 | + Local<Value> receiver, | | 155 | + Local<Value> scope_arg, | | 156 | + Local<Value> resource_arg, | | 157 | + // NOLINTNEXTLINE(runtime/references) This is V8 api. | | 158 | + FastApiCallbackOptions& options) { | | 159 | + TRACK_V8_FAST_API_CALL("permission.has"); | | 160 | + auto isolate = options.isolate; | | 161 | + v8::HandleScope handle_scope(isolate); | | 162 | + auto context = isolate->GetCurrentContext(); | | 163 | + | | 164 | + Environment* env = Environment::GetCurrent(context); | | 165 | + | | 166 | + Local<String> str; | | 167 | + if (!scope_arg->ToString(context).ToLocal(&str)) { | | 168 | + return false; | | 169 | + } | | 170 | + Utf8Value utf8_scope(isolate, str); | | 171 | + PermissionScope scope = | | 172 | + Permission::StringToPermission(utf8_scope.ToStringView()); | | 173 | + if (scope == PermissionScope::kPermissionsRoot) { | | 174 | + return false; | 153 | 175 | } | 154 | 176 |
| 155 | 177 | Local<String> res_str; | @@ -164,7 +186,8 @@ static bool FastHas(Local<Value> receiver, | 164 | 186 | return env->permission()->is_granted(env, scope, utf8_res.ToStringView()); | 165 | 187 | } | 166 | 188 |
| 167 | | -static CFunction fast_has_(CFunction::Make(FastHas)); | | 189 | +static CFunction fast_has_methods_[] = {CFunction::Make(FastHas), | | 190 | + CFunction::Make(FastHasResource)}; | 168 | 191 |
| 169 | 192 | } // namespace | 170 | 193 |
| @@ -370,15 +393,18 @@ void Initialize(Local<Object> target, | 370 | 393 | Local<Value> unused, | 371 | 394 | Local<Context> context, | 372 | 395 | void* priv) { | 373 | | - SetFastMethodNoSideEffect(context, target, "has", Has, &fast_has_); | | 396 | + SetFastMethodNoSideEffect( | | 397 | + context, target, "has", Has, {fast_has_methods_, 2}); | 374 | 398 | SetMethod(context, target, "drop", Drop); | 375 | 399 |
| 376 | 400 | target->SetIntegrityLevel(context, IntegrityLevel::kFrozen).FromJust(); | 377 | 401 | } | 378 | 402 |
| 379 | 403 | void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | 380 | 404 | registry->Register(Has); | 381 | | - registry->Register(fast_has_); | | 405 | + for (const CFunction& method : fast_has_methods_) { | | 406 | + registry->Register(method); | | 407 | + } | 382 | 408 | registry->Register(Drop); | 383 | 409 | } | 384 | 410 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/util.cc +25Lines changed: 25 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -468,6 +468,31 @@ void SetFastMethodNoSideEffect( | 468 | 468 | that->Set(name_string, t); | 469 | 469 | } | 470 | 470 |
| | 471 | +void SetFastMethodNoSideEffect( | | 472 | + Local<v8::Context> context, | | 473 | + Local<v8::Object> that, | | 474 | + const std::string_view name, | | 475 | + v8::FunctionCallback slow_callback, | | 476 | + const v8::MemorySpan<const v8::CFunction>& methods) { | | 477 | + Isolate* isolate = Isolate::GetCurrent(); | | 478 | + Local<v8::Function> function = FunctionTemplate::NewWithCFunctionOverloads( | | 479 | + isolate, | | 480 | + slow_callback, | | 481 | + Local<Value>(), | | 482 | + Local<v8::Signature>(), | | 483 | + 0, | | 484 | + v8::ConstructorBehavior::kThrow, | | 485 | + v8::SideEffectType::kHasNoSideEffect, | | 486 | + methods) | | 487 | + ->GetFunction(context) | | 488 | + .ToLocalChecked(); | | 489 | + const v8::NewStringType type = v8::NewStringType::kInternalized; | | 490 | + Local<v8::String> name_string = | | 491 | + v8::String::NewFromUtf8(isolate, name.data(), type, name.size()) | | 492 | + .ToLocalChecked(); | | 493 | + that->Set(context, name_string, function).Check(); | | 494 | +} | | 495 | + | 471 | 496 | void SetMethodNoSideEffect(Local<v8::Context> context, | 472 | 497 | Local<v8::Object> that, | 473 | 498 | const std::string_view name, | |
Collapse file Copy file name to clipboardExpand all lines: src/util.h +6Lines changed: 6 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -912,6 +912,12 @@ void SetFastMethodNoSideEffect( | 912 | 912 | const std::string_view name, | 913 | 913 | v8::FunctionCallback slow_callback, | 914 | 914 | const v8::MemorySpan<const v8::CFunction>& methods); | | 915 | +void SetFastMethodNoSideEffect( | | 916 | + v8::Local<v8::Context> context, | | 917 | + v8::Local<v8::Object> that, | | 918 | + const std::string_view name, | | 919 | + v8::FunctionCallback slow_callback, | | 920 | + const v8::MemorySpan<const v8::CFunction>& methods); | 915 | 921 | void SetProtoMethod(v8::Isolate* isolate, | 916 | 922 | v8::Local<v8::FunctionTemplate> that, | 917 | 923 | const std::string_view name, | |
Collapse file Copy file name to clipboard +38Lines changed: 38 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +// Flags: --permission --allow-fs-read=* --allow-fs-write=* --allow-natives-syntax --expose-internals --no-warnings | | 2 | +'use strict'; | | 3 | + | | 4 | +const common = require('../common'); | | 5 | +const assert = require('assert'); | | 6 | +const { internalBinding } = require('internal/test/binding'); | | 7 | +const path = require('path'); | | 8 | + | | 9 | +// Test that process.permission.has() uses the V8 fast API path. | | 10 | + | | 11 | +// Test with scope only (no resource argument). | | 12 | +function testHasScope() { | | 13 | + assert.strictEqual(process.permission.has('fs.read', __filename), true); | | 14 | + assert.strictEqual(process.permission.has('fs.write', __dirname), true); | | 15 | + assert.strictEqual( | | 16 | + process.permission.has('fs.read', path.resolve('/nonexistent')), | | 17 | + true | | 18 | + ); | | 19 | + assert.strictEqual(process.permission.has('fs.read'), true); | | 20 | + assert.strictEqual(process.permission.has('fs.write'), true); | | 21 | + assert.strictEqual(process.permission.has('child'), false); | | 22 | + assert.strictEqual(process.permission.has('worker'), false); | | 23 | + assert.strictEqual(process.permission.has('invalid-key'), false); | | 24 | +} | | 25 | + | | 26 | +// Warm up and optimize for the fast API path. | | 27 | +eval('%PrepareFunctionForOptimization(testHasScope)'); | | 28 | +testHasScope(); | | 29 | +testHasScope(); | | 30 | + | | 31 | +eval('%OptimizeFunctionOnNextCall(testHasScope)'); | | 32 | +testHasScope(); | | 33 | + | | 34 | +if (common.isDebug) { | | 35 | + const { getV8FastApiCallCount } = internalBinding('debug'); | | 36 | + // After optimization: testHasScope = 4, testHasResource = 3, testHasInvalid = 1 | | 37 | + assert.strictEqual(getV8FastApiCallCount('permission.has'), 8); | | 38 | +} |
|