| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 3b5f1b5 commit 24b7831
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -863,6 +863,18 @@ async function* createAsyncPipeline(source, transforms, signal) { | |||
| 863 | 863 | } | |
| 864 | 864 | } | |
| 865 | 865 | ||
| 866 | + /** | ||
| 867 | + * Check if a false sync write result means accepted backpressure. | ||
| 868 | + * @param {object} writer - The writer whose sync method returned. | ||
| 869 | + * @param {*} result - The return value from writeSync() or writevSync(). | ||
| 870 | + * @returns {boolean} | ||
| 871 | + */ | ||
| 872 | + function isAcceptedSyncWriteBackpressure(writer, result) { | ||
| 873 | + return result === false && | ||
| 874 | + writer[kSyncWriteAcceptedOnFalse] === true && | ||
| 875 | + writer.desiredSize === 0; | ||
| 876 | + } | ||
| 877 | + | ||
| 866 | 878 | // ============================================================================= | |
| 867 | 879 | // Public API: pull() and pullSync() | |
| 868 | 880 | // ============================================================================= | |
@@ -950,16 +962,29 @@ function pipeToSync(source, ...args) { | |||
| 950 | 962 | const hasEndSync = typeof writer.endSync === 'function'; | |
| 951 | 963 | ||
| 952 | 964 | try { | |
| 965 | + let canContinue = true; | ||
| 953 | 966 | for (const batch of pipeline) { | |
| 967 | + if (!canContinue) { | ||
| 968 | + break; | ||
| 969 | + } | ||
| 954 | 970 | if (hasWritevSync && batch.length > 1) { | |
| 955 | - writer.writevSync(batch); | ||
| 971 | + const result = writer.writevSync(batch); | ||
| 972 | + if (result === false && | ||
| 973 | + !isAcceptedSyncWriteBackpressure(writer, result)) { | ||
| 974 | + break; | ||
| 975 | + } | ||
| 956 | 976 | for (let i = 0; i < batch.length; i++) { | |
| 957 | 977 | totalBytes += TypedArrayPrototypeGetByteLength(batch[i]); | |
| 958 | 978 | } | |
| 959 | 979 | } else { | |
| 960 | 980 | for (let i = 0; i < batch.length; i++) { | |
| 961 | 981 | const chunk = batch[i]; | |
| 962 | - writer.writeSync(chunk); | ||
| 982 | + const result = writer.writeSync(chunk); | ||
| 983 | + if (result === false && | ||
| 984 | + !isAcceptedSyncWriteBackpressure(writer, result)) { | ||
| 985 | + canContinue = false; | ||
| 986 | + break; | ||
| 987 | + } | ||
| 963 | 988 | totalBytes += TypedArrayPrototypeGetByteLength(chunk); | |
| 964 | 989 | } | |
| 965 | 990 | } | |
@@ -1011,11 +1036,6 @@ async function pipeTo(source, ...args) { | |||
| 1011 | 1036 | const hasWritev = typeof writer.writev === 'function'; | |
| 1012 | 1037 | const hasWritevSync = typeof writer.writevSync === 'function'; | |
| 1013 | 1038 | const hasEndSync = typeof writer.endSync === 'function'; | |
| 1014 | - const syncFalseCanBeAccepted = writer[kSyncWriteAcceptedOnFalse] === true; | ||
| 1015 | - | ||
| 1016 | - function syncFalseWasAccepted() { | ||
| 1017 | - return syncFalseCanBeAccepted && writer.desiredSize === 0; | ||
| 1018 | - } | ||
| 1019 | 1039 | ||
| 1020 | 1040 | function waitForSyncBackpressure() { | |
| 1021 | 1041 | const ondrain = writer[drainableProtocol]; | |
@@ -1032,9 +1052,10 @@ async function pipeTo(source, ...args) { | |||
| 1032 | 1052 | async function writeBatchAsyncFallback(batch, startIndex) { | |
| 1033 | 1053 | for (let i = startIndex; i < batch.length; i++) { | |
| 1034 | 1054 | const chunk = batch[i]; | |
| 1035 | - if (hasWriteSync && writer.writeSync(chunk)) { | ||
| 1055 | + const result = hasWriteSync && writer.writeSync(chunk); | ||
| 1056 | + if (result) { | ||
| 1036 | 1057 | // Sync retry succeeded | |
| 1037 | - } else if (syncFalseWasAccepted()) { | ||
| 1058 | + } else if (isAcceptedSyncWriteBackpressure(writer, result)) { | ||
| 1038 | 1059 | totalBytes += TypedArrayPrototypeGetByteLength(chunk); | |
| 1039 | 1060 | await waitForSyncBackpressure(); | |
| 1040 | 1061 | continue; | |
@@ -1054,22 +1075,23 @@ async function pipeTo(source, ...args) { | |||
| 1054 | 1075 | // is required. Callers must check: const p = writeBatch(b); if (p) await p; | |
| 1055 | 1076 | function writeBatch(batch) { | |
| 1056 | 1077 | if (hasWritev && batch.length > 1) { | |
| 1057 | - if (!hasWritevSync || !writer.writevSync(batch)) { | ||
| 1058 | - if (hasWritevSync && syncFalseWasAccepted()) { | ||
| 1078 | + const result = hasWritevSync && writer.writevSync(batch); | ||
| 1079 | + if (!result) { | ||
| 1080 | + if (isAcceptedSyncWriteBackpressure(writer, result)) { | ||
| 1059 | 1081 | for (let i = 0; i < batch.length; i++) { | |
| 1060 | 1082 | totalBytes += TypedArrayPrototypeGetByteLength(batch[i]); | |
| 1061 | 1083 | } | |
| 1062 | 1084 | return waitForSyncBackpressure(); | |
| 1063 | 1085 | } | |
| 1064 | 1086 | const opts = signal ? { __proto__: null, signal } : undefined; | |
| 1065 | - const result = writer.writev(batch, opts); | ||
| 1066 | - if (result === undefined) { | ||
| 1087 | + const writevResult = writer.writev(batch, opts); | ||
| 1088 | + if (writevResult === undefined) { | ||
| 1067 | 1089 | for (let i = 0; i < batch.length; i++) { | |
| 1068 | 1090 | totalBytes += TypedArrayPrototypeGetByteLength(batch[i]); | |
| 1069 | 1091 | } | |
| 1070 | 1092 | return; | |
| 1071 | 1093 | } | |
| 1072 | - return PromisePrototypeThen(PromiseResolve(result), () => { | ||
| 1094 | + return PromisePrototypeThen(PromiseResolve(writevResult), () => { | ||
| 1073 | 1095 | for (let i = 0; i < batch.length; i++) { | |
| 1074 | 1096 | totalBytes += TypedArrayPrototypeGetByteLength(batch[i]); | |
| 1075 | 1097 | } | |
@@ -1082,8 +1104,9 @@ async function pipeTo(source, ...args) { | |||
| 1082 | 1104 | } | |
| 1083 | 1105 | for (let i = 0; i < batch.length; i++) { | |
| 1084 | 1106 | const chunk = batch[i]; | |
| 1085 | - if (!hasWriteSync || !writer.writeSync(chunk)) { | ||
| 1086 | - if (hasWriteSync && syncFalseWasAccepted()) { | ||
| 1107 | + const result = hasWriteSync && writer.writeSync(chunk); | ||
| 1108 | + if (!result) { | ||
| 1109 | + if (isAcceptedSyncWriteBackpressure(writer, result)) { | ||
| 1087 | 1110 | totalBytes += TypedArrayPrototypeGetByteLength(chunk); | |
| 1088 | 1111 | return writeBatchAfterAcceptedBackpressure(batch, i + 1); | |
| 1089 | 1112 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -154,6 +154,43 @@ async function testPushWriterBlockSyncFalseAccepted() { | |||
| 154 | 154 | })(), 'abcd', 4); | |
| 155 | 155 | } | |
| 156 | 156 | ||
| 157 | + async function testPipeToSyncPushWriterStrictFalseRejected() { | ||
| 158 | + const decoder = new TextDecoder(); | ||
| 159 | + const { writer, readable } = push({ highWaterMark: 1 }); | ||
| 160 | + | ||
| 161 | + const total = pipeToSync(['a', 'b'], writer, { preventClose: true }); | ||
| 162 | + assert.strictEqual(total, 1); | ||
| 163 | + | ||
| 164 | + const iter = readable[Symbol.asyncIterator](); | ||
| 165 | + const first = await iter.next(); | ||
| 166 | + assert.strictEqual(first.done, false); | ||
| 167 | + assert.strictEqual(decoder.decode(first.value[0]), 'a'); | ||
| 168 | + | ||
| 169 | + const second = await Promise.race([ | ||
| 170 | + iter.next().then((result) => { | ||
| 171 | + return result.done ? '<done>' : decoder.decode(result.value[0]); | ||
| 172 | + }), | ||
| 173 | + setImmediatePromise().then(() => '<no second chunk>'), | ||
| 174 | + ]); | ||
| 175 | + assert.strictEqual(second, '<no second chunk>'); | ||
| 176 | + | ||
| 177 | + await iter.return?.(); | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + async function testPipeToSyncWritevFalseNotCounted() { | ||
| 181 | + const writer = { | ||
| 182 | + writevSync() { return false; }, | ||
| 183 | + writeSync: common.mustNotCall(), | ||
| 184 | + endSync() { return 0; }, | ||
| 185 | + }; | ||
| 186 | + function* source() { | ||
| 187 | + yield [new Uint8Array([1]), new Uint8Array([2])]; | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + const total = pipeToSync(source(), writer); | ||
| 191 | + assert.strictEqual(total, 0); | ||
| 192 | + } | ||
| 193 | + | ||
| 157 | 194 | // pipeToSync with writevSync | |
| 158 | 195 | async function testPipeToSyncWritev() { | |
| 159 | 196 | const batches = []; | |
@@ -215,6 +252,8 @@ Promise.all([ | |||
| 215 | 252 | testWriteSyncFailsMidBatch(), | |
| 216 | 253 | testWriteSyncAlwaysFails(), | |
| 217 | 254 | testPushWriterBlockSyncFalseAccepted(), | |
| 255 | + testPipeToSyncPushWriterStrictFalseRejected(), | ||
| 256 | + testPipeToSyncWritevFalseNotCounted(), | ||
| 218 | 257 | testPipeToSyncWritev(), | |
| 219 | 258 | testPipeToSyncPlainChunksWritev(), | |
| 220 | 259 | testPipeToSyncWriteFallback(), | |
| Back | FazBrowse Home | New Git URL |
0 commit comments