Dashboard sipadu mbip
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

react-dom-unstable-flight-server.browser.development.js 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /** @license React v16.12.0
  2. * react-dom-unstable-flight-server.browser.development.js
  3. *
  4. * Copyright (c) Facebook, Inc. and its affiliates.
  5. *
  6. * This source code is licensed under the MIT license found in the
  7. * LICENSE file in the root directory of this source tree.
  8. */
  9. 'use strict';
  10. if (process.env.NODE_ENV !== "production") {
  11. (function() {
  12. 'use strict';
  13. var ReactDOMServer = require('react-dom/server');
  14. function scheduleWork(callback) {
  15. callback();
  16. }
  17. function writeChunk(destination, buffer) {
  18. destination.enqueue(buffer);
  19. return destination.desiredSize > 0;
  20. }
  21. function close(destination) {
  22. destination.close();
  23. }
  24. var textEncoder = new TextEncoder();
  25. function convertStringToBuffer(content) {
  26. return textEncoder.encode(content);
  27. }
  28. function renderHostChildrenToString(children) {
  29. // TODO: This file is used to actually implement a server renderer
  30. // so we can't actually reference the renderer here. Instead, we
  31. // should replace this method with a reference to Fizz which
  32. // then uses this file to implement the server renderer.
  33. return ReactDOMServer.renderToStaticMarkup(children);
  34. }
  35. // The Symbol used to tag the ReactElement-like types. If there is no native Symbol
  36. // nor polyfill, then a plain number is used for performance.
  37. var hasSymbol = typeof Symbol === 'function' && Symbol.for;
  38. var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
  39. // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary
  40. // (unstable) APIs that have been removed. Can we remove the symbols?
  41. /*
  42. FLIGHT PROTOCOL GRAMMAR
  43. Response
  44. - JSONData RowSequence
  45. - JSONData
  46. RowSequence
  47. - Row RowSequence
  48. - Row
  49. Row
  50. - "J" RowID JSONData
  51. - "H" RowID HTMLData
  52. - "B" RowID BlobData
  53. - "U" RowID URLData
  54. - "E" RowID ErrorData
  55. RowID
  56. - HexDigits ":"
  57. HexDigits
  58. - HexDigit HexDigits
  59. - HexDigit
  60. HexDigit
  61. - 0-F
  62. URLData
  63. - (UTF8 encoded URL) "\n"
  64. ErrorData
  65. - (UTF8 encoded JSON: {message: "...", stack: "..."}) "\n"
  66. JSONData
  67. - (UTF8 encoded JSON) "\n"
  68. - String values that begin with $ are escaped with a "$" prefix.
  69. - References to other rows are encoding as JSONReference strings.
  70. JSONReference
  71. - "$" HexDigits
  72. HTMLData
  73. - ByteSize (UTF8 encoded HTML)
  74. BlobData
  75. - ByteSize (Binary Data)
  76. ByteSize
  77. - (unsigned 32-bit integer)
  78. */
  79. // TODO: Implement HTMLData, BlobData and URLData.
  80. var stringify = JSON.stringify;
  81. function createRequest(model, destination) {
  82. var pingedSegments = [];
  83. var request = {
  84. destination: destination,
  85. nextChunkId: 0,
  86. pendingChunks: 0,
  87. pingedSegments: pingedSegments,
  88. completedJSONChunks: [],
  89. completedErrorChunks: [],
  90. flowing: false,
  91. toJSON: function (key, value) {
  92. return resolveModelToJSON(request, value);
  93. }
  94. };
  95. request.pendingChunks++;
  96. var rootSegment = createSegment(request, model);
  97. pingedSegments.push(rootSegment);
  98. return request;
  99. }
  100. function attemptResolveModelComponent(element) {
  101. var type = element.type;
  102. var props = element.props;
  103. if (typeof type === 'function') {
  104. // This is a nested view model.
  105. return type(props);
  106. } else if (typeof type === 'string') {
  107. // This is a host element. E.g. HTML.
  108. return renderHostChildrenToString(element);
  109. } else {
  110. throw new Error('Unsupported type.');
  111. }
  112. }
  113. function pingSegment(request, segment) {
  114. var pingedSegments = request.pingedSegments;
  115. pingedSegments.push(segment);
  116. if (pingedSegments.length === 1) {
  117. scheduleWork(function () {
  118. return performWork(request);
  119. });
  120. }
  121. }
  122. function createSegment(request, model) {
  123. var id = request.nextChunkId++;
  124. var segment = {
  125. id: id,
  126. model: model,
  127. ping: function () {
  128. return pingSegment(request, segment);
  129. }
  130. };
  131. return segment;
  132. }
  133. function serializeIDRef(id) {
  134. return '$' + id.toString(16);
  135. }
  136. function serializeRowHeader(tag, id) {
  137. return tag + id.toString(16) + ':';
  138. }
  139. function escapeStringValue(value) {
  140. if (value[0] === '$') {
  141. // We need to escape $ prefixed strings since we use that to encode
  142. // references to IDs.
  143. return '$' + value;
  144. } else {
  145. return value;
  146. }
  147. }
  148. function resolveModelToJSON(request, value) {
  149. if (typeof value === 'string') {
  150. return escapeStringValue(value);
  151. }
  152. while (typeof value === 'object' && value !== null && value.$$typeof === REACT_ELEMENT_TYPE) {
  153. var element = value;
  154. try {
  155. value = attemptResolveModelComponent(element);
  156. } catch (x) {
  157. if (typeof x === 'object' && x !== null && typeof x.then === 'function') {
  158. // Something suspended, we'll need to create a new segment and resolve it later.
  159. request.pendingChunks++;
  160. var newSegment = createSegment(request, element);
  161. var ping = newSegment.ping;
  162. x.then(ping, ping);
  163. return serializeIDRef(newSegment.id);
  164. } else {
  165. request.pendingChunks++;
  166. var errorId = request.nextChunkId++;
  167. emitErrorChunk(request, errorId, x);
  168. return serializeIDRef(errorId);
  169. }
  170. }
  171. }
  172. return value;
  173. }
  174. function emitErrorChunk(request, id, error) {
  175. // TODO: We should not leak error messages to the client in prod.
  176. // Give this an error code instead and log on the server.
  177. // We can serialize the error in DEV as a convenience.
  178. var message;
  179. var stack = '';
  180. try {
  181. if (error instanceof Error) {
  182. message = '' + error.message;
  183. stack = '' + error.stack;
  184. } else {
  185. message = 'Error: ' + error;
  186. }
  187. } catch (x) {
  188. message = 'An error occurred but serializing the error message failed.';
  189. }
  190. var errorInfo = {
  191. message: message,
  192. stack: stack
  193. };
  194. var row = serializeRowHeader('E', id) + stringify(errorInfo) + '\n';
  195. request.completedErrorChunks.push(convertStringToBuffer(row));
  196. }
  197. function retrySegment(request, segment) {
  198. var value = segment.model;
  199. try {
  200. while (typeof value === 'object' && value !== null && value.$$typeof === REACT_ELEMENT_TYPE) {
  201. // If this is a nested model, there's no need to create another chunk,
  202. // we can reuse the existing one and try again.
  203. var element = value;
  204. segment.model = element;
  205. value = attemptResolveModelComponent(element);
  206. }
  207. var json = stringify(value, request.toJSON);
  208. var row;
  209. var id = segment.id;
  210. if (id === 0) {
  211. row = json + '\n';
  212. } else {
  213. row = serializeRowHeader('J', id) + json + '\n';
  214. }
  215. request.completedJSONChunks.push(convertStringToBuffer(row));
  216. } catch (x) {
  217. if (typeof x === 'object' && x !== null && typeof x.then === 'function') {
  218. // Something suspended again, let's pick it back up later.
  219. var ping = segment.ping;
  220. x.then(ping, ping);
  221. return;
  222. } else {
  223. // This errored, we need to serialize this error to the
  224. emitErrorChunk(request, segment.id, x);
  225. }
  226. }
  227. }
  228. function performWork(request) {
  229. var pingedSegments = request.pingedSegments;
  230. request.pingedSegments = [];
  231. for (var i = 0; i < pingedSegments.length; i++) {
  232. var segment = pingedSegments[i];
  233. retrySegment(request, segment);
  234. }
  235. if (request.flowing) {
  236. flushCompletedChunks(request);
  237. }
  238. }
  239. var reentrant = false;
  240. function flushCompletedChunks(request) {
  241. if (reentrant) {
  242. return;
  243. }
  244. reentrant = true;
  245. var destination = request.destination;
  246. try {
  247. var jsonChunks = request.completedJSONChunks;
  248. var i = 0;
  249. for (; i < jsonChunks.length; i++) {
  250. request.pendingChunks--;
  251. var chunk = jsonChunks[i];
  252. if (!writeChunk(destination, chunk)) {
  253. request.flowing = false;
  254. i++;
  255. break;
  256. }
  257. }
  258. jsonChunks.splice(0, i);
  259. var errorChunks = request.completedErrorChunks;
  260. i = 0;
  261. for (; i < errorChunks.length; i++) {
  262. request.pendingChunks--;
  263. var _chunk = errorChunks[i];
  264. if (!writeChunk(destination, _chunk)) {
  265. request.flowing = false;
  266. i++;
  267. break;
  268. }
  269. }
  270. errorChunks.splice(0, i);
  271. } finally {
  272. reentrant = false;
  273. }
  274. if (request.pendingChunks === 0) {
  275. // We're done.
  276. close(destination);
  277. }
  278. }
  279. function startWork(request) {
  280. request.flowing = true;
  281. scheduleWork(function () {
  282. return performWork(request);
  283. });
  284. }
  285. function startFlowing(request) {
  286. request.flowing = true;
  287. flushCompletedChunks(request);
  288. }
  289. // This file intentionally does *not* have the Flow annotation.
  290. // Don't add it. See `./inline-typed.js` for an explanation.
  291. function renderToReadableStream(model) {
  292. var request;
  293. return new ReadableStream({
  294. start: function (controller) {
  295. request = createRequest(model, controller);
  296. startWork(request);
  297. },
  298. pull: function (controller) {
  299. startFlowing(request);
  300. },
  301. cancel: function (reason) {}
  302. });
  303. }
  304. var ReactFlightDOMServerBrowser = {
  305. renderToReadableStream: renderToReadableStream
  306. };
  307. var ReactFlightDOMServerBrowser$1 = Object.freeze({
  308. default: ReactFlightDOMServerBrowser
  309. });
  310. var ReactFlightDOMServerBrowser$2 = ( ReactFlightDOMServerBrowser$1 && ReactFlightDOMServerBrowser ) || ReactFlightDOMServerBrowser$1;
  311. // TODO: decide on the top-level export form.
  312. // This is hacky but makes it work with both Rollup and Jest
  313. var unstableFlightServer_browser = ReactFlightDOMServerBrowser$2.default || ReactFlightDOMServerBrowser$2;
  314. module.exports = unstableFlightServer_browser;
  315. })();
  316. }