| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1304,6 +1304,45 @@ setTimeout(() => { | |||
| 1304 | 1304 | }, 1000); | |
| 1305 | 1305 | ``` | |
| 1306 | 1306 | ||
| 1307 | + ## `v8.isStringOneByteRepresentation(content)` | ||
| 1308 | + | ||
| 1309 | + <!-- YAML | ||
| 1310 | + added: REPLACEME | ||
| 1311 | + --> | ||
| 1312 | + | ||
| 1313 | + * `content` {string} | ||
| 1314 | + * Returns: {boolean} | ||
| 1315 | + | ||
| 1316 | + V8 only supports `Latin-1/ISO-8859-1` and `UTF16` as the underlying representation of a string. | ||
| 1317 | + If the `content` uses `Latin-1/ISO-8859-1` as the underlying representation, this function will return true; | ||
| 1318 | + otherwise, it returns false. | ||
| 1319 | + | ||
| 1320 | + If this method returns false, that does not mean that the string contains some characters not in `Latin-1/ISO-8859-1`. | ||
| 1321 | + Sometimes a `Latin-1` string may also be represented as `UTF16`. | ||
| 1322 | + | ||
| 1323 | + ```js | ||
| 1324 | + const { isStringOneByteRepresentation } = require('node:v8'); | ||
| 1325 | + | ||
| 1326 | + const Encoding = { | ||
| 1327 | + latin1: 1, | ||
| 1328 | + utf16le: 2, | ||
| 1329 | + }; | ||
| 1330 | + const buffer = Buffer.alloc(100); | ||
| 1331 | + function writeString(input) { | ||
| 1332 | + if (isStringOneByteRepresentation(input)) { | ||
| 1333 | + buffer.writeUint8(Encoding.latin1); | ||
| 1334 | + buffer.writeUint32LE(input.length, 1); | ||
| 1335 | + buffer.write(input, 5, 'latin1'); | ||
| 1336 | + } else { | ||
| 1337 | + buffer.writeUint8(Encoding.utf16le); | ||
| 1338 | + buffer.writeUint32LE(input.length * 2, 1); | ||
| 1339 | + buffer.write(input, 5, 'utf16le'); | ||
| 1340 | + } | ||
| 1341 | + } | ||
| 1342 | + writeString('hello'); | ||
| 1343 | + writeString('你好'); | ||
| 1344 | + ``` | ||
| 1345 | + | ||
| 1307 | 1346 | [HTML structured clone algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm | |
| 1308 | 1347 | [Hook Callbacks]: #hook-callbacks | |
| 1309 | 1348 | [V8]: https://developers.google.com/v8/ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -108,6 +108,7 @@ const binding = internalBinding('v8'); | |||
| 108 | 108 | const { | |
| 109 | 109 | cachedDataVersionTag, | |
| 110 | 110 | setFlagsFromString: _setFlagsFromString, | |
| 111 | + isStringOneByteRepresentation: _isStringOneByteRepresentation, | ||
| 111 | 112 | updateHeapStatisticsBuffer, | |
| 112 | 113 | updateHeapSpaceStatisticsBuffer, | |
| 113 | 114 | updateHeapCodeStatisticsBuffer, | |
@@ -159,6 +160,17 @@ function setFlagsFromString(flags) { | |||
| 159 | 160 | _setFlagsFromString(flags); | |
| 160 | 161 | } | |
| 161 | 162 | ||
| 163 | + /** | ||
| 164 | + * Return whether this string uses one byte as underlying representation or not. | ||
| 165 | + * @param {string} content | ||
| 166 | + * @returns {boolean} | ||
| 167 | + */ | ||
| 168 | + function isStringOneByteRepresentation(content) { | ||
| 169 | + validateString(content, 'content'); | ||
| 170 | + return _isStringOneByteRepresentation(content); | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + | ||
| 162 | 174 | /** | |
| 163 | 175 | * Gets the current V8 heap statistics. | |
| 164 | 176 | * @returns {{ | |
@@ -445,4 +457,5 @@ module.exports = { | |||
| 445 | 457 | startupSnapshot, | |
| 446 | 458 | setHeapSnapshotNearHeapLimit, | |
| 447 | 459 | GCProfiler, | |
| 460 | + isStringOneByteRepresentation, | ||
| 448 | 461 | }; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,6 +12,9 @@ namespace node { | |||
| 12 | 12 | ||
| 13 | 13 | using CFunctionCallbackWithOneByteString = | |
| 14 | 14 | uint32_t (*)(v8::Local<v8::Value>, const v8::FastOneByteString&); | |
| 15 | + | ||
| 16 | + using CFunctionCallbackReturnBool = bool (*)(v8::Local<v8::Value> unused, | ||
| 17 | + v8::Local<v8::Value> receiver); | ||
| 15 | 18 | using CFunctionCallback = void (*)(v8::Local<v8::Value> unused, | |
| 16 | 19 | v8::Local<v8::Value> receiver); | |
| 17 | 20 | using CFunctionCallbackReturnDouble = | |
@@ -90,6 +93,7 @@ class ExternalReferenceRegistry { | |||
| 90 | 93 | #define ALLOWED_EXTERNAL_REFERENCE_TYPES(V) \ | |
| 91 | 94 | V(CFunctionCallback) \ | |
| 92 | 95 | V(CFunctionCallbackWithOneByteString) \ | |
| 96 | + V(CFunctionCallbackReturnBool) \ | ||
| 93 | 97 | V(CFunctionCallbackReturnDouble) \ | |
| 94 | 98 | V(CFunctionCallbackReturnInt32) \ | |
| 95 | 99 | V(CFunctionCallbackValueReturnDouble) \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -32,6 +32,7 @@ | |||
| 32 | 32 | namespace node { | |
| 33 | 33 | namespace v8_utils { | |
| 34 | 34 | using v8::Array; | |
| 35 | + using v8::CFunction; | ||
| 35 | 36 | using v8::Context; | |
| 36 | 37 | using v8::FunctionCallbackInfo; | |
| 37 | 38 | using v8::FunctionTemplate; | |
@@ -238,6 +239,23 @@ void SetFlagsFromString(const FunctionCallbackInfo<Value>& args) { | |||
| 238 | 239 | V8::SetFlagsFromString(*flags, static_cast<size_t>(flags.length())); | |
| 239 | 240 | } | |
| 240 | 241 | ||
| 242 | + static void IsStringOneByteRepresentation( | ||
| 243 | + const FunctionCallbackInfo<Value>& args) { | ||
| 244 | + CHECK_EQ(args.Length(), 1); | ||
| 245 | + CHECK(args[0]->IsString()); | ||
| 246 | + bool is_one_byte = args[0].As<String>()->IsOneByte(); | ||
| 247 | + args.GetReturnValue().Set(is_one_byte); | ||
| 248 | + } | ||
| 249 | + | ||
| 250 | + static bool FastIsStringOneByteRepresentation(Local<Value> receiver, | ||
| 251 | + const Local<Value> target) { | ||
| 252 | + CHECK(target->IsString()); | ||
| 253 | + return target.As<String>()->IsOneByte(); | ||
| 254 | + } | ||
| 255 | + | ||
| 256 | + CFunction fast_is_string_one_byte_representation_( | ||
| 257 | + CFunction::Make(FastIsStringOneByteRepresentation)); | ||
| 258 | + | ||
| 241 | 259 | static const char* GetGCTypeName(v8::GCType gc_type) { | |
| 242 | 260 | switch (gc_type) { | |
| 243 | 261 | case v8::GCType::kGCTypeScavenge: | |
@@ -478,6 +496,13 @@ void Initialize(Local<Object> target, | |||
| 478 | 496 | // Export symbols used by v8.setFlagsFromString() | |
| 479 | 497 | SetMethod(context, target, "setFlagsFromString", SetFlagsFromString); | |
| 480 | 498 | ||
| 499 | + // Export symbols used by v8.isStringOneByteRepresentation() | ||
| 500 | + SetFastMethodNoSideEffect(context, | ||
| 501 | + target, | ||
| 502 | + "isStringOneByteRepresentation", | ||
| 503 | + IsStringOneByteRepresentation, | ||
| 504 | + &fast_is_string_one_byte_representation_); | ||
| 505 | + | ||
| 481 | 506 | // GCProfiler | |
| 482 | 507 | Local<FunctionTemplate> t = | |
| 483 | 508 | NewFunctionTemplate(env->isolate(), GCProfiler::New); | |
@@ -497,6 +522,9 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | |||
| 497 | 522 | registry->Register(GCProfiler::New); | |
| 498 | 523 | registry->Register(GCProfiler::Start); | |
| 499 | 524 | registry->Register(GCProfiler::Stop); | |
| 525 | + registry->Register(IsStringOneByteRepresentation); | ||
| 526 | + registry->Register(FastIsStringOneByteRepresentation); | ||
| 527 | + registry->Register(fast_is_string_one_byte_representation_.GetTypeInfo()); | ||
| 500 | 528 | } | |
| 501 | 529 | ||
| 502 | 530 | } // namespace v8_utils | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,36 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + require('../common'); | ||
| 3 | + const assert = require('assert'); | ||
| 4 | + const { isStringOneByteRepresentation } = require('v8'); | ||
| 5 | + | ||
| 6 | + [ | ||
| 7 | + undefined, | ||
| 8 | + null, | ||
| 9 | + false, | ||
| 10 | + 5n, | ||
| 11 | + 5, | ||
| 12 | + Symbol(), | ||
| 13 | + () => {}, | ||
| 14 | + {}, | ||
| 15 | + ].forEach((value) => { | ||
| 16 | + assert.throws( | ||
| 17 | + () => { isStringOneByteRepresentation(value); }, | ||
| 18 | + /The "content" argument must be of type string/ | ||
| 19 | + ); | ||
| 20 | + }); | ||
| 21 | + | ||
| 22 | + { | ||
| 23 | + const latin1String = 'hello world!'; | ||
| 24 | + // Run this inside a for loop to trigger the fast API | ||
| 25 | + for (let i = 0; i < 10_000; i++) { | ||
| 26 | + assert.strictEqual(isStringOneByteRepresentation(latin1String), true); | ||
| 27 | + } | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + { | ||
| 31 | + const utf16String = '你好😀😃'; | ||
| 32 | + // Run this inside a for loop to trigger the fast API | ||
| 33 | + for (let i = 0; i < 10_000; i++) { | ||
| 34 | + assert.strictEqual(isStringOneByteRepresentation(utf16String), false); | ||
| 35 | + } | ||
| 36 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments