123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- /** @license React v16.12.0
- * react-dom-unstable-flight-server.browser.development.js
- *
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
- 'use strict';
-
- (function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react-dom/server')) :
- typeof define === 'function' && define.amd ? define(['react-dom/server'], factory) :
- (global.ReactFlightDOMServer = factory(global.ReactDOMServer));
- }(this, (function (ReactDOMServer) { 'use strict';
-
- function scheduleWork(callback) {
- callback();
- }
-
-
- function writeChunk(destination, buffer) {
- destination.enqueue(buffer);
- return destination.desiredSize > 0;
- }
-
- function close(destination) {
- destination.close();
- }
- var textEncoder = new TextEncoder();
- function convertStringToBuffer(content) {
- return textEncoder.encode(content);
- }
-
- function renderHostChildrenToString(children) {
- // TODO: This file is used to actually implement a server renderer
- // so we can't actually reference the renderer here. Instead, we
- // should replace this method with a reference to Fizz which
- // then uses this file to implement the server renderer.
- return ReactDOMServer.renderToStaticMarkup(children);
- }
-
- // The Symbol used to tag the ReactElement-like types. If there is no native Symbol
- // nor polyfill, then a plain number is used for performance.
- var hasSymbol = typeof Symbol === 'function' && Symbol.for;
- var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
-
-
-
-
-
- // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary
- // (unstable) APIs that have been removed. Can we remove the symbols?
-
- /*
-
- FLIGHT PROTOCOL GRAMMAR
-
- Response
- - JSONData RowSequence
- - JSONData
-
- RowSequence
- - Row RowSequence
- - Row
-
- Row
- - "J" RowID JSONData
- - "H" RowID HTMLData
- - "B" RowID BlobData
- - "U" RowID URLData
- - "E" RowID ErrorData
-
- RowID
- - HexDigits ":"
-
- HexDigits
- - HexDigit HexDigits
- - HexDigit
-
- HexDigit
- - 0-F
-
- URLData
- - (UTF8 encoded URL) "\n"
-
- ErrorData
- - (UTF8 encoded JSON: {message: "...", stack: "..."}) "\n"
-
- JSONData
- - (UTF8 encoded JSON) "\n"
- - String values that begin with $ are escaped with a "$" prefix.
- - References to other rows are encoding as JSONReference strings.
-
- JSONReference
- - "$" HexDigits
-
- HTMLData
- - ByteSize (UTF8 encoded HTML)
-
- BlobData
- - ByteSize (Binary Data)
-
- ByteSize
- - (unsigned 32-bit integer)
- */
- // TODO: Implement HTMLData, BlobData and URLData.
-
- var stringify = JSON.stringify;
- function createRequest(model, destination) {
- var pingedSegments = [];
- var request = {
- destination: destination,
- nextChunkId: 0,
- pendingChunks: 0,
- pingedSegments: pingedSegments,
- completedJSONChunks: [],
- completedErrorChunks: [],
- flowing: false,
- toJSON: function (key, value) {
- return resolveModelToJSON(request, value);
- }
- };
- request.pendingChunks++;
- var rootSegment = createSegment(request, model);
- pingedSegments.push(rootSegment);
- return request;
- }
-
- function attemptResolveModelComponent(element) {
- var type = element.type;
- var props = element.props;
-
- if (typeof type === 'function') {
- // This is a nested view model.
- return type(props);
- } else if (typeof type === 'string') {
- // This is a host element. E.g. HTML.
- return renderHostChildrenToString(element);
- } else {
- throw new Error('Unsupported type.');
- }
- }
-
- function pingSegment(request, segment) {
- var pingedSegments = request.pingedSegments;
- pingedSegments.push(segment);
-
- if (pingedSegments.length === 1) {
- scheduleWork(function () {
- return performWork(request);
- });
- }
- }
-
- function createSegment(request, model) {
- var id = request.nextChunkId++;
- var segment = {
- id: id,
- model: model,
- ping: function () {
- return pingSegment(request, segment);
- }
- };
- return segment;
- }
-
- function serializeIDRef(id) {
- return '$' + id.toString(16);
- }
-
- function serializeRowHeader(tag, id) {
- return tag + id.toString(16) + ':';
- }
-
- function escapeStringValue(value) {
- if (value[0] === '$') {
- // We need to escape $ prefixed strings since we use that to encode
- // references to IDs.
- return '$' + value;
- } else {
- return value;
- }
- }
-
- function resolveModelToJSON(request, value) {
- if (typeof value === 'string') {
- return escapeStringValue(value);
- }
-
- while (typeof value === 'object' && value !== null && value.$$typeof === REACT_ELEMENT_TYPE) {
- var element = value;
-
- try {
- value = attemptResolveModelComponent(element);
- } catch (x) {
- if (typeof x === 'object' && x !== null && typeof x.then === 'function') {
- // Something suspended, we'll need to create a new segment and resolve it later.
- request.pendingChunks++;
- var newSegment = createSegment(request, element);
- var ping = newSegment.ping;
- x.then(ping, ping);
- return serializeIDRef(newSegment.id);
- } else {
- request.pendingChunks++;
- var errorId = request.nextChunkId++;
- emitErrorChunk(request, errorId, x);
- return serializeIDRef(errorId);
- }
- }
- }
-
- return value;
- }
-
- function emitErrorChunk(request, id, error) {
- // TODO: We should not leak error messages to the client in prod.
- // Give this an error code instead and log on the server.
- // We can serialize the error in DEV as a convenience.
- var message;
- var stack = '';
-
- try {
- if (error instanceof Error) {
- message = '' + error.message;
- stack = '' + error.stack;
- } else {
- message = 'Error: ' + error;
- }
- } catch (x) {
- message = 'An error occurred but serializing the error message failed.';
- }
-
- var errorInfo = {
- message: message,
- stack: stack
- };
- var row = serializeRowHeader('E', id) + stringify(errorInfo) + '\n';
- request.completedErrorChunks.push(convertStringToBuffer(row));
- }
-
- function retrySegment(request, segment) {
- var value = segment.model;
-
- try {
- while (typeof value === 'object' && value !== null && value.$$typeof === REACT_ELEMENT_TYPE) {
- // If this is a nested model, there's no need to create another chunk,
- // we can reuse the existing one and try again.
- var element = value;
- segment.model = element;
- value = attemptResolveModelComponent(element);
- }
-
- var json = stringify(value, request.toJSON);
- var row;
- var id = segment.id;
-
- if (id === 0) {
- row = json + '\n';
- } else {
- row = serializeRowHeader('J', id) + json + '\n';
- }
-
- request.completedJSONChunks.push(convertStringToBuffer(row));
- } catch (x) {
- if (typeof x === 'object' && x !== null && typeof x.then === 'function') {
- // Something suspended again, let's pick it back up later.
- var ping = segment.ping;
- x.then(ping, ping);
- return;
- } else {
- // This errored, we need to serialize this error to the
- emitErrorChunk(request, segment.id, x);
- }
- }
- }
-
- function performWork(request) {
- var pingedSegments = request.pingedSegments;
- request.pingedSegments = [];
-
- for (var i = 0; i < pingedSegments.length; i++) {
- var segment = pingedSegments[i];
- retrySegment(request, segment);
- }
-
- if (request.flowing) {
- flushCompletedChunks(request);
- }
- }
-
- var reentrant = false;
-
- function flushCompletedChunks(request) {
- if (reentrant) {
- return;
- }
-
- reentrant = true;
- var destination = request.destination;
- try {
- var jsonChunks = request.completedJSONChunks;
- var i = 0;
-
- for (; i < jsonChunks.length; i++) {
- request.pendingChunks--;
- var chunk = jsonChunks[i];
-
- if (!writeChunk(destination, chunk)) {
- request.flowing = false;
- i++;
- break;
- }
- }
-
- jsonChunks.splice(0, i);
- var errorChunks = request.completedErrorChunks;
- i = 0;
-
- for (; i < errorChunks.length; i++) {
- request.pendingChunks--;
- var _chunk = errorChunks[i];
-
- if (!writeChunk(destination, _chunk)) {
- request.flowing = false;
- i++;
- break;
- }
- }
-
- errorChunks.splice(0, i);
- } finally {
- reentrant = false;
-
- }
-
- if (request.pendingChunks === 0) {
- // We're done.
- close(destination);
- }
- }
-
- function startWork(request) {
- request.flowing = true;
- scheduleWork(function () {
- return performWork(request);
- });
- }
- function startFlowing(request) {
- request.flowing = true;
- flushCompletedChunks(request);
- }
-
- // This file intentionally does *not* have the Flow annotation.
- // Don't add it. See `./inline-typed.js` for an explanation.
-
- function renderToReadableStream(model) {
- var request;
- return new ReadableStream({
- start: function (controller) {
- request = createRequest(model, controller);
- startWork(request);
- },
- pull: function (controller) {
- startFlowing(request);
- },
- cancel: function (reason) {}
- });
- }
-
- var ReactFlightDOMServerBrowser = {
- renderToReadableStream: renderToReadableStream
- };
-
- var ReactFlightDOMServerBrowser$1 = Object.freeze({
- default: ReactFlightDOMServerBrowser
- });
-
- var ReactFlightDOMServerBrowser$2 = ( ReactFlightDOMServerBrowser$1 && ReactFlightDOMServerBrowser ) || ReactFlightDOMServerBrowser$1;
-
- // TODO: decide on the top-level export form.
- // This is hacky but makes it work with both Rollup and Jest
-
-
- var unstableFlightServer_browser = ReactFlightDOMServerBrowser$2.default || ReactFlightDOMServerBrowser$2;
-
- return unstableFlightServer_browser;
-
- })));
|