vike 0.4.149-commit-19b2220 → 0.4.149-commit-aa0ab7b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -200,7 +200,9 @@ exports.pipeToStreamWritableNode = pipeToStreamWritableNode;
200
200
  async function processStream(streamOriginal, { injectStringAtBegin, injectStringAtEnd, onErrorWhileStreaming, enableEagerStreaming }) {
201
201
  const buffer = [];
202
202
  let streamOriginalHasStartedEmitting = false;
203
- let streamEnded = false;
203
+ let streamOriginalEnded = false;
204
+ let streamClosed = false;
205
+ let onEndWasCalled = false;
204
206
  let isReadyToWrite = false;
205
207
  let wrapperCreated = false;
206
208
  let shouldFlushStream = false;
@@ -224,6 +226,14 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
224
226
  writeStream(injectionBegin); // Adds injectionBegin to buffer
225
227
  flushStream(); // Sets shouldFlushStream to true
226
228
  }
229
+ // We call onStreamEvent() also when the stream ends in order to properly handle the situation when the stream didn't emit any data
230
+ const onStreamDataOrEnd = (cb) => {
231
+ (0, utils_js_1.assert)(streamOriginalEnded === false);
232
+ streamOriginalHasStartedEmitting = true;
233
+ cb();
234
+ if (wrapperCreated)
235
+ resolvePromise();
236
+ };
227
237
  const { streamWrapper, streamWrapperOperations } = await createStreamWrapper({
228
238
  streamOriginal,
229
239
  onReadyToWrite() {
@@ -241,19 +251,21 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
241
251
  }
242
252
  },
243
253
  onData(chunk) {
244
- (0, utils_js_1.assert)(streamEnded === false);
245
- streamOriginalHasStartedEmitting = true;
246
- writeStream(chunk);
247
- if (wrapperCreated)
248
- resolvePromise();
254
+ onStreamDataOrEnd(() => {
255
+ writeStream(chunk);
256
+ });
249
257
  },
250
- async onEnd() {
258
+ async onEnd(
259
+ // Should we use this `isCancel`? Maybe we can skip `injectStringAtEnd()`?
260
+ isCancel) {
251
261
  try {
262
+ (0, utils_js_1.assert)(!onEndWasCalled);
263
+ onEndWasCalled = true;
252
264
  debug('stream end');
253
- streamEnded = true;
254
- streamOriginalHasStartedEmitting = true; // In case original stream (stream provided by user) emits no data
255
- if (wrapperCreated)
256
- resolvePromise(); // In case original stream (stream provided by user) emits no data
265
+ // We call onStreamEvent() also here in case the stream didn't emit any data
266
+ onStreamDataOrEnd(() => {
267
+ streamOriginalEnded = true;
268
+ });
257
269
  if (injectStringAtEnd) {
258
270
  const injectEnd = await injectStringAtEnd();
259
271
  writeStream(injectEnd);
@@ -261,10 +273,12 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
261
273
  await promiseReadyToWrite; // E.g. if the user calls the pipe wrapper after the original writable has ended
262
274
  (0, utils_js_1.assert)(isReady());
263
275
  flushBuffer();
276
+ streamClosed = true;
264
277
  debug('stream ended');
265
278
  }
266
279
  catch (err) {
267
- // We should catch and gracefully handle user land errors, as any error thrown here kills the server
280
+ // Ideally, we should catch and gracefully handle user land errors, as any error thrown here kills the server. (I assume that the fact it kills the server is a Node.js bug?)
281
+ // Show "[vike][Bug] You stumbled upon a bug in Vike's source code" to user while printing original error
268
282
  if (!(0, utils_js_1.isBug)(err)) {
269
283
  console.error(err);
270
284
  (0, utils_js_1.assert)(false);
@@ -288,6 +302,7 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
288
302
  function flushBuffer() {
289
303
  if (!isReady())
290
304
  return;
305
+ (0, utils_js_1.assert)(!streamClosed);
291
306
  buffer.forEach((chunk) => {
292
307
  streamWrapperOperations.writeChunk(chunk);
293
308
  });
@@ -485,6 +500,17 @@ async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onF
485
500
  if (isStreamReadableWeb(streamOriginal)) {
486
501
  debug('onRenderHtml() hook returned Web Readable');
487
502
  const readableOriginal = streamOriginal;
503
+ let controllerProxyIsClosed = false;
504
+ let isClosed = false;
505
+ let isCancel = false;
506
+ const closeStream = async () => {
507
+ if (isClosed)
508
+ return;
509
+ isClosed = true;
510
+ await onEnd(isCancel);
511
+ controllerProxy.close();
512
+ controllerProxyIsClosed = true;
513
+ };
488
514
  let controllerProxy;
489
515
  assertReadableStreamConstructor();
490
516
  const readableProxy = new ReadableStream({
@@ -498,16 +524,30 @@ async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onF
498
524
  controllerProxy.close();
499
525
  },
500
526
  async onEnd() {
501
- await onEnd();
502
- controllerProxy.close();
527
+ await closeStream();
503
528
  }
504
529
  });
530
+ },
531
+ async cancel(...args) {
532
+ isCancel = true;
533
+ await readableOriginal.cancel(...args);
534
+ // If readableOriginal has implemented readableOriginal.cancel() then the onEnd() callback and therfore closeStream() may already have been called at this point
535
+ await closeStream();
505
536
  }
506
537
  });
507
538
  const writeChunk = (chunk) => {
508
- controllerProxy.enqueue(encodeForWebStream(chunk));
509
- if (debug.isEnabled) {
510
- debug('data written (Web Readable)', String(chunk));
539
+ if (
540
+ // If readableOriginal doesn't implement readableOriginal.cancel() then it may still emit data after we close the stream. We therefore need to check whether we closed `controllerProxy`.
541
+ !controllerProxyIsClosed) {
542
+ controllerProxy.enqueue(encodeForWebStream(chunk));
543
+ if (debug.isEnabled) {
544
+ debug('data written (Web Readable)', String(chunk));
545
+ }
546
+ }
547
+ else {
548
+ if (debug.isEnabled) {
549
+ debug('data emitted but not written (Web Readable)', String(chunk));
550
+ }
511
551
  }
512
552
  };
513
553
  // Readables don't have the notion of flushing
@@ -76,7 +76,7 @@ function getHttpResponseBodyStreamHandlers(htmlRender, renderHook) {
76
76
  return;
77
77
  }
78
78
  else {
79
- (0, utils_js_1.assert)((0, stream_js_1.isStreamReadableWeb)(htmlRender) || (0, stream_js_1.isStreamPipeWeb)(htmlRender));
79
+ (0, utils_js_1.assert)((0, stream_js_1.isStreamReadableNode)(htmlRender) || (0, stream_js_1.isStreamPipeNode)(htmlRender));
80
80
  (0, utils_js_1.assertUsage)(false, getErrMsgMixingStreamTypes('Web Writable'));
81
81
  }
82
82
  }
@@ -86,7 +86,7 @@ function getHttpResponseBodyStreamHandlers(htmlRender, renderHook) {
86
86
  return;
87
87
  }
88
88
  else {
89
- (0, utils_js_1.assert)((0, stream_js_1.isStreamReadableNode)(htmlRender) || (0, stream_js_1.isStreamPipeNode)(htmlRender));
89
+ (0, utils_js_1.assert)((0, stream_js_1.isStreamReadableWeb)(htmlRender) || (0, stream_js_1.isStreamPipeWeb)(htmlRender));
90
90
  (0, utils_js_1.assertUsage)(false, getErrMsgMixingStreamTypes('Node.js Writable'));
91
91
  }
92
92
  }
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PROJECT_VERSION = exports.projectInfo = void 0;
4
4
  const assertSingleInstance_js_1 = require("./assertSingleInstance.js");
5
- const PROJECT_VERSION = '0.4.149-commit-19b2220';
5
+ const PROJECT_VERSION = '0.4.149-commit-aa0ab7b';
6
6
  exports.PROJECT_VERSION = PROJECT_VERSION;
7
7
  const projectInfo = {
8
8
  projectName: 'Vike',
@@ -205,7 +205,9 @@ function pipeToStreamWritableNode(htmlRender, writable) {
205
205
  async function processStream(streamOriginal, { injectStringAtBegin, injectStringAtEnd, onErrorWhileStreaming, enableEagerStreaming }) {
206
206
  const buffer = [];
207
207
  let streamOriginalHasStartedEmitting = false;
208
- let streamEnded = false;
208
+ let streamOriginalEnded = false;
209
+ let streamClosed = false;
210
+ let onEndWasCalled = false;
209
211
  let isReadyToWrite = false;
210
212
  let wrapperCreated = false;
211
213
  let shouldFlushStream = false;
@@ -229,6 +231,14 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
229
231
  writeStream(injectionBegin); // Adds injectionBegin to buffer
230
232
  flushStream(); // Sets shouldFlushStream to true
231
233
  }
234
+ // We call onStreamEvent() also when the stream ends in order to properly handle the situation when the stream didn't emit any data
235
+ const onStreamDataOrEnd = (cb) => {
236
+ assert(streamOriginalEnded === false);
237
+ streamOriginalHasStartedEmitting = true;
238
+ cb();
239
+ if (wrapperCreated)
240
+ resolvePromise();
241
+ };
232
242
  const { streamWrapper, streamWrapperOperations } = await createStreamWrapper({
233
243
  streamOriginal,
234
244
  onReadyToWrite() {
@@ -246,19 +256,21 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
246
256
  }
247
257
  },
248
258
  onData(chunk) {
249
- assert(streamEnded === false);
250
- streamOriginalHasStartedEmitting = true;
251
- writeStream(chunk);
252
- if (wrapperCreated)
253
- resolvePromise();
259
+ onStreamDataOrEnd(() => {
260
+ writeStream(chunk);
261
+ });
254
262
  },
255
- async onEnd() {
263
+ async onEnd(
264
+ // Should we use this `isCancel`? Maybe we can skip `injectStringAtEnd()`?
265
+ isCancel) {
256
266
  try {
267
+ assert(!onEndWasCalled);
268
+ onEndWasCalled = true;
257
269
  debug('stream end');
258
- streamEnded = true;
259
- streamOriginalHasStartedEmitting = true; // In case original stream (stream provided by user) emits no data
260
- if (wrapperCreated)
261
- resolvePromise(); // In case original stream (stream provided by user) emits no data
270
+ // We call onStreamEvent() also here in case the stream didn't emit any data
271
+ onStreamDataOrEnd(() => {
272
+ streamOriginalEnded = true;
273
+ });
262
274
  if (injectStringAtEnd) {
263
275
  const injectEnd = await injectStringAtEnd();
264
276
  writeStream(injectEnd);
@@ -266,10 +278,12 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
266
278
  await promiseReadyToWrite; // E.g. if the user calls the pipe wrapper after the original writable has ended
267
279
  assert(isReady());
268
280
  flushBuffer();
281
+ streamClosed = true;
269
282
  debug('stream ended');
270
283
  }
271
284
  catch (err) {
272
- // We should catch and gracefully handle user land errors, as any error thrown here kills the server
285
+ // Ideally, we should catch and gracefully handle user land errors, as any error thrown here kills the server. (I assume that the fact it kills the server is a Node.js bug?)
286
+ // Show "[vike][Bug] You stumbled upon a bug in Vike's source code" to user while printing original error
273
287
  if (!isBug(err)) {
274
288
  console.error(err);
275
289
  assert(false);
@@ -293,6 +307,7 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
293
307
  function flushBuffer() {
294
308
  if (!isReady())
295
309
  return;
310
+ assert(!streamClosed);
296
311
  buffer.forEach((chunk) => {
297
312
  streamWrapperOperations.writeChunk(chunk);
298
313
  });
@@ -489,6 +504,17 @@ async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onF
489
504
  if (isStreamReadableWeb(streamOriginal)) {
490
505
  debug('onRenderHtml() hook returned Web Readable');
491
506
  const readableOriginal = streamOriginal;
507
+ let controllerProxyIsClosed = false;
508
+ let isClosed = false;
509
+ let isCancel = false;
510
+ const closeStream = async () => {
511
+ if (isClosed)
512
+ return;
513
+ isClosed = true;
514
+ await onEnd(isCancel);
515
+ controllerProxy.close();
516
+ controllerProxyIsClosed = true;
517
+ };
492
518
  let controllerProxy;
493
519
  assertReadableStreamConstructor();
494
520
  const readableProxy = new ReadableStream({
@@ -502,16 +528,30 @@ async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onF
502
528
  controllerProxy.close();
503
529
  },
504
530
  async onEnd() {
505
- await onEnd();
506
- controllerProxy.close();
531
+ await closeStream();
507
532
  }
508
533
  });
534
+ },
535
+ async cancel(...args) {
536
+ isCancel = true;
537
+ await readableOriginal.cancel(...args);
538
+ // If readableOriginal has implemented readableOriginal.cancel() then the onEnd() callback and therfore closeStream() may already have been called at this point
539
+ await closeStream();
509
540
  }
510
541
  });
511
542
  const writeChunk = (chunk) => {
512
- controllerProxy.enqueue(encodeForWebStream(chunk));
513
- if (debug.isEnabled) {
514
- debug('data written (Web Readable)', String(chunk));
543
+ if (
544
+ // If readableOriginal doesn't implement readableOriginal.cancel() then it may still emit data after we close the stream. We therefore need to check whether we closed `controllerProxy`.
545
+ !controllerProxyIsClosed) {
546
+ controllerProxy.enqueue(encodeForWebStream(chunk));
547
+ if (debug.isEnabled) {
548
+ debug('data written (Web Readable)', String(chunk));
549
+ }
550
+ }
551
+ else {
552
+ if (debug.isEnabled) {
553
+ debug('data emitted but not written (Web Readable)', String(chunk));
554
+ }
515
555
  }
516
556
  };
517
557
  // Readables don't have the notion of flushing
@@ -71,7 +71,7 @@ function getHttpResponseBodyStreamHandlers(htmlRender, renderHook) {
71
71
  return;
72
72
  }
73
73
  else {
74
- assert(isStreamReadableWeb(htmlRender) || isStreamPipeWeb(htmlRender));
74
+ assert(isStreamReadableNode(htmlRender) || isStreamPipeNode(htmlRender));
75
75
  assertUsage(false, getErrMsgMixingStreamTypes('Web Writable'));
76
76
  }
77
77
  }
@@ -81,7 +81,7 @@ function getHttpResponseBodyStreamHandlers(htmlRender, renderHook) {
81
81
  return;
82
82
  }
83
83
  else {
84
- assert(isStreamReadableNode(htmlRender) || isStreamPipeNode(htmlRender));
84
+ assert(isStreamReadableWeb(htmlRender) || isStreamPipeWeb(htmlRender));
85
85
  assertUsage(false, getErrMsgMixingStreamTypes('Node.js Writable'));
86
86
  }
87
87
  }
@@ -1,13 +1,13 @@
1
1
  export { projectInfo };
2
2
  export type { ProjectTag };
3
3
  export { PROJECT_VERSION };
4
- declare const PROJECT_VERSION: "0.4.149-commit-19b2220";
4
+ declare const PROJECT_VERSION: "0.4.149-commit-aa0ab7b";
5
5
  type PackageName = typeof projectInfo.npmPackageName;
6
6
  type ProjectVersion = typeof projectInfo.projectVersion;
7
7
  type ProjectTag = `[${PackageName}]` | `[${PackageName}@${ProjectVersion}]`;
8
8
  declare const projectInfo: {
9
9
  projectName: "Vike";
10
- projectVersion: "0.4.149-commit-19b2220";
10
+ projectVersion: "0.4.149-commit-aa0ab7b";
11
11
  npmPackageName: "vike";
12
12
  githubRepository: "https://github.com/vikejs/vike";
13
13
  };
@@ -1,7 +1,7 @@
1
1
  export { projectInfo };
2
2
  export { PROJECT_VERSION };
3
3
  import { onProjectInfo } from './assertSingleInstance.js';
4
- const PROJECT_VERSION = '0.4.149-commit-19b2220';
4
+ const PROJECT_VERSION = '0.4.149-commit-aa0ab7b';
5
5
  const projectInfo = {
6
6
  projectName: 'Vike',
7
7
  projectVersion: PROJECT_VERSION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.149-commit-19b2220",
3
+ "version": "0.4.149-commit-aa0ab7b",
4
4
  "scripts": {
5
5
  "dev": "tsc --watch",
6
6
  "build": "rimraf dist/ && pnpm run build:esm && pnpm run build:cjs",