| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 780e65c commit 8759db9
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -256,6 +256,8 @@ In particular, this makes sense for objects that can be cloned, rather than | |||
| 256 | 256 | transferred, and which are used by other objects on the sending side. | |
| 257 | 257 | For example, Node.js marks the `ArrayBuffer`s it uses for its | |
| 258 | 258 | [`Buffer` pool][`Buffer.allocUnsafe()`] with this. | |
| 259 | + `ArrayBuffer.prototype.transfer()` is disallowed on such array buffer | ||
| 260 | + instances. | ||
| 259 | 261 | ||
| 260 | 262 | This operation cannot be undone. | |
| 261 | 263 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -143,6 +143,13 @@ const { | |||
| 143 | 143 | utf8Write, | |
| 144 | 144 | } = require('internal/buffer'); | |
| 145 | 145 | ||
| 146 | + const { | ||
| 147 | + namespace: { | ||
| 148 | + addDeserializeCallback, | ||
| 149 | + isBuildingSnapshot, | ||
| 150 | + }, | ||
| 151 | + } = require('internal/v8/startup_snapshot'); | ||
| 152 | + | ||
| 146 | 153 | FastBuffer.prototype.constructor = Buffer; | |
| 147 | 154 | Buffer.prototype = FastBuffer.prototype; | |
| 148 | 155 | addBufferPrototypeMethods(Buffer.prototype); | |
@@ -173,6 +180,13 @@ function createPool() { | |||
| 173 | 180 | poolOffset = 0; | |
| 174 | 181 | } | |
| 175 | 182 | createPool(); | |
| 183 | + if (isBuildingSnapshot()) { | ||
| 184 | + addDeserializeCallback(() => { | ||
| 185 | + // TODO(legendecas): ArrayBuffer.[[ArrayBufferDetachKey]] is not been serialized. | ||
| 186 | + // Remove this callback when snapshot serialization supports it. | ||
| 187 | + createPool(); | ||
| 188 | + }); | ||
| 189 | + } | ||
| 176 | 190 | ||
| 177 | 191 | function alignPool() { | |
| 178 | 192 | // Ensure aligned slices | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,6 +6,7 @@ const { | |||
| 6 | 6 | Float64Array, | |
| 7 | 7 | MathFloor, | |
| 8 | 8 | Number, | |
| 9 | + Symbol, | ||
| 9 | 10 | Uint8Array, | |
| 10 | 11 | } = primordials; | |
| 11 | 12 | ||
@@ -15,6 +16,8 @@ const { | |||
| 15 | 16 | ERR_OUT_OF_RANGE, | |
| 16 | 17 | } = require('internal/errors').codes; | |
| 17 | 18 | const { validateNumber } = require('internal/validators'); | |
| 19 | + const { isArrayBuffer } = require('util/types'); | ||
| 20 | + | ||
| 18 | 21 | const { | |
| 19 | 22 | asciiSlice, | |
| 20 | 23 | base64Slice, | |
@@ -31,6 +34,7 @@ const { | |||
| 31 | 34 | ucs2Write, | |
| 32 | 35 | utf8WriteStatic, | |
| 33 | 36 | createUnsafeArrayBuffer, | |
| 37 | + setDetachKey, | ||
| 34 | 38 | } = internalBinding('buffer'); | |
| 35 | 39 | ||
| 36 | 40 | const { | |
@@ -1068,12 +1072,17 @@ function addBufferPrototypeMethods(proto) { | |||
| 1068 | 1072 | proto.utf8Write = function(string, offset, length) { return utf8Write(this, string, offset, length); }; | |
| 1069 | 1073 | } | |
| 1070 | 1074 | ||
| 1075 | + const kDetachKey = Symbol('detach_key_for_untransferable_arraybuffer'); | ||
| 1071 | 1076 | // This would better be placed in internal/worker/io.js, but that doesn't work | |
| 1072 | 1077 | // because Buffer needs this and that would introduce a cyclic dependency. | |
| 1073 | 1078 | function markAsUntransferable(obj) { | |
| 1074 | 1079 | if ((typeof obj !== 'object' && typeof obj !== 'function') || obj === null) | |
| 1075 | 1080 | return; // This object is a primitive and therefore already untransferable. | |
| 1076 | 1081 | obj[untransferable_object_private_symbol] = true; | |
| 1082 | + | ||
| 1083 | + if (isArrayBuffer(obj)) { | ||
| 1084 | + setDetachKey(obj, kDetachKey); | ||
| 1085 | + } | ||
| 1077 | 1086 | } | |
| 1078 | 1087 | ||
| 1079 | 1088 | // This simply checks if the object is marked as untransferable and doesn't | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1377,6 +1377,15 @@ static void Atob(const FunctionCallbackInfo<Value>& args) { | |||
| 1377 | 1377 | args.GetReturnValue().Set(error_code); | |
| 1378 | 1378 | } | |
| 1379 | 1379 | ||
| 1380 | + static void SetDetachKey(const FunctionCallbackInfo<Value>& args) { | ||
| 1381 | + CHECK_EQ(args.Length(), 2); | ||
| 1382 | + CHECK(args[0]->IsArrayBuffer()); | ||
| 1383 | + | ||
| 1384 | + Local<ArrayBuffer> ab = args[0].As<ArrayBuffer>(); | ||
| 1385 | + Local<Value> key = args[1]; | ||
| 1386 | + ab->SetDetachKey(key); | ||
| 1387 | + } | ||
| 1388 | + | ||
| 1380 | 1389 | namespace { | |
| 1381 | 1390 | ||
| 1382 | 1391 | std::pair<void*, size_t> DecomposeBufferToParts(Local<Value> buffer) { | |
@@ -1661,6 +1670,8 @@ void Initialize(Local<Object> target, | |||
| 1661 | 1670 | "utf8WriteStatic", | |
| 1662 | 1671 | SlowWriteString<UTF8>, | |
| 1663 | 1672 | &fast_write_string_utf8); | |
| 1673 | + | ||
| 1674 | + SetMethod(context, target, "setDetachKey", SetDetachKey); | ||
| 1664 | 1675 | } | |
| 1665 | 1676 | ||
| 1666 | 1677 | } // anonymous namespace | |
@@ -1715,6 +1726,8 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | |||
| 1715 | 1726 | ||
| 1716 | 1727 | registry->Register(Atob); | |
| 1717 | 1728 | registry->Register(Btoa); | |
| 1729 | + | ||
| 1730 | + registry->Register(SetDetachKey); | ||
| 1718 | 1731 | } | |
| 1719 | 1732 | ||
| 1720 | 1733 | } // namespace Buffer | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -51,6 +51,7 @@ expected.beforePreExec = new Set([ | |||
| 51 | 51 | 'NativeModule events', | |
| 52 | 52 | 'Internal Binding buffer', | |
| 53 | 53 | 'Internal Binding string_decoder', | |
| 54 | + 'NativeModule util/types', | ||
| 54 | 55 | 'NativeModule internal/buffer', | |
| 55 | 56 | 'NativeModule buffer', | |
| 56 | 57 | 'Internal Binding messaging', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -21,3 +21,9 @@ assert.throws(() => port1.postMessage(a, [ a.buffer ]), { | |||
| 21 | 21 | // Verify that the pool ArrayBuffer has not actually been transferred: | |
| 22 | 22 | assert.strictEqual(a.buffer, b.buffer); | |
| 23 | 23 | assert.strictEqual(a.length, length); | |
| 24 | + | ||
| 25 | + // Verify that ArrayBuffer.prototype.transfer() also throws. | ||
| 26 | + assert.throws(() => a.buffer.transfer(), { | ||
| 27 | + name: 'TypeError', | ||
| 28 | + }); | ||
| 29 | + assert.strictEqual(a.buffer, b.buffer); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments