UNPKG

dinou

Version:

Dinou is a modern React 19 framework with React Server Components, Server Functions, and streaming SSR.

1,316 lines (1,285 loc) 213 kB
/** * @license React * react-server-dom-esm-client.browser.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import * as React from 'react'; import * as ReactDOM from 'react-dom'; var ReactVersion = '19.2.0-experimental-594fb5e9-20250811'; function createStringDecoder() { return new TextDecoder(); } var decoderOptions = { stream: true }; function readPartialStringChunk(decoder, buffer) { return decoder.decode(buffer, decoderOptions); } function readFinalStringChunk(decoder, buffer) { return decoder.decode(buffer); } // Keep in sync with ReactServerConsoleConfig var badgeFormat = '%c%s%c'; // Same badge styling as DevTools. var badgeStyle = // We use a fixed background if light-dark is not supported, otherwise // we use a transparent background. 'background: #e6e6e6;' + 'background: light-dark(rgba(0,0,0,0.1), rgba(255,255,255,0.25));' + 'color: #000000;' + 'color: light-dark(#000000, #ffffff);' + 'border-radius: 2px'; var resetStyle = ''; var pad = ' '; var bind = Function.prototype.bind; function bindToConsole(methodName, args, badgeName) { var offset = 0; switch (methodName) { case 'dir': case 'dirxml': case 'groupEnd': case 'table': { // These methods cannot be colorized because they don't take a formatting string. // $FlowFixMe return bind.apply(console[methodName], [console].concat(args)); // eslint-disable-line react-internal/no-production-logging } case 'assert': { // assert takes formatting options as the second argument. offset = 1; } } var newArgs = args.slice(0); if (typeof newArgs[offset] === 'string') { newArgs.splice(offset, 1, badgeFormat + ' ' + newArgs[offset], badgeStyle, pad + badgeName + pad, resetStyle); } else { newArgs.splice(offset, 0, badgeFormat, badgeStyle, pad + badgeName + pad, resetStyle); } // The "this" binding in the "bind"; newArgs.unshift(console); // $FlowFixMe return bind.apply(console[methodName], newArgs); // eslint-disable-line react-internal/no-production-logging } // Module root path function resolveClientReference(bundlerConfig, metadata) { var baseURL = bundlerConfig; return { specifier: baseURL + metadata[0], name: metadata[1] }; } function resolveServerReference(config, id) { var baseURL = config; var idx = id.lastIndexOf('#'); var exportName = id.slice(idx + 1); var fullURL = id.slice(0, idx); if (!fullURL.startsWith(baseURL)) { throw new Error('Attempted to load a Server Reference outside the hosted root.'); } return { specifier: fullURL, name: exportName }; } var asyncModuleCache = new Map(); function preloadModule(metadata) { var existingPromise = asyncModuleCache.get(metadata.specifier); if (existingPromise) { if (existingPromise.status === 'fulfilled') { return null; } return existingPromise; } else { // $FlowFixMe[unsupported-syntax] var modulePromise = import(metadata.specifier); modulePromise.then(function (value) { var fulfilledThenable = modulePromise; fulfilledThenable.status = 'fulfilled'; fulfilledThenable.value = value; }, function (reason) { var rejectedThenable = modulePromise; rejectedThenable.status = 'rejected'; rejectedThenable.reason = reason; }); asyncModuleCache.set(metadata.specifier, modulePromise); return modulePromise; } } function requireModule(metadata) { var moduleExports; // We assume that preloadModule has been called before, which // should have added something to the module cache. var promise = asyncModuleCache.get(metadata.specifier); if (promise.status === 'fulfilled') { moduleExports = promise.value; } else { throw promise.reason; } return moduleExports[metadata.name]; } var ReactDOMSharedInternals = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE; // This client file is in the shared folder because it applies to both SSR and browser contexts. // It is the configuration of the FlightClient behavior which can run in either environment. function dispatchHint(code, model) { var dispatcher = ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */ switch (code) { case 'D': { var refined = refineModel(code, model); var href = refined; dispatcher.D( /* prefetchDNS */href); return; } case 'C': { var _refined = refineModel(code, model); if (typeof _refined === 'string') { var _href = _refined; dispatcher.C( /* preconnect */_href); } else { var _href2 = _refined[0]; var crossOrigin = _refined[1]; dispatcher.C( /* preconnect */_href2, crossOrigin); } return; } case 'L': { var _refined2 = refineModel(code, model); var _href3 = _refined2[0]; var as = _refined2[1]; if (_refined2.length === 3) { var options = _refined2[2]; dispatcher.L( /* preload */_href3, as, options); } else { dispatcher.L( /* preload */_href3, as); } return; } case 'm': { var _refined3 = refineModel(code, model); if (typeof _refined3 === 'string') { var _href4 = _refined3; dispatcher.m( /* preloadModule */_href4); } else { var _href5 = _refined3[0]; var _options = _refined3[1]; dispatcher.m( /* preloadModule */_href5, _options); } return; } case 'X': { var _refined4 = refineModel(code, model); if (typeof _refined4 === 'string') { var _href6 = _refined4; dispatcher.X( /* preinitScript */_href6); } else { var _href7 = _refined4[0]; var _options2 = _refined4[1]; dispatcher.X( /* preinitScript */_href7, _options2); } return; } case 'S': { var _refined5 = refineModel(code, model); if (typeof _refined5 === 'string') { var _href8 = _refined5; dispatcher.S( /* preinitStyle */_href8); } else { var _href9 = _refined5[0]; var precedence = _refined5[1] === 0 ? undefined : _refined5[1]; var _options3 = _refined5.length === 3 ? _refined5[2] : undefined; dispatcher.S( /* preinitStyle */_href9, precedence, _options3); } return; } case 'M': { var _refined6 = refineModel(code, model); if (typeof _refined6 === 'string') { var _href10 = _refined6; dispatcher.M( /* preinitModuleScript */_href10); } else { var _href11 = _refined6[0]; var _options4 = _refined6[1]; dispatcher.M( /* preinitModuleScript */_href11, _options4); } return; } } } // Flow is having trouble refining the HintModels so we help it a bit. // This should be compiled out in the production build. function refineModel(code, model) { return model; } var rendererPackageName = 'react-server-dom-esm'; var REACT_ELEMENT_TYPE = Symbol.for('react.transitional.element') ; var REACT_PORTAL_TYPE = Symbol.for('react.portal'); var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment'); var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode'); var REACT_PROFILER_TYPE = Symbol.for('react.profiler'); var REACT_CONSUMER_TYPE = Symbol.for('react.consumer'); var REACT_CONTEXT_TYPE = Symbol.for('react.context'); var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref'); var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense'); var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list'); var REACT_MEMO_TYPE = Symbol.for('react.memo'); var REACT_LAZY_TYPE = Symbol.for('react.lazy'); var REACT_ACTIVITY_TYPE = Symbol.for('react.activity'); var REACT_POSTPONE_TYPE = Symbol.for('react.postpone'); var REACT_VIEW_TRANSITION_TYPE = Symbol.for('react.view_transition'); var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; var FAUX_ITERATOR_SYMBOL = '@@iterator'; function getIteratorFn(maybeIterable) { if (maybeIterable === null || typeof maybeIterable !== 'object') { return null; } var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]; if (typeof maybeIterator === 'function') { return maybeIterator; } return null; } var ASYNC_ITERATOR = Symbol.asyncIterator; var isArrayImpl = Array.isArray; function isArray(a) { return isArrayImpl(a); } var getPrototypeOf = Object.getPrototypeOf; // Used for DEV messages to keep track of which parent rendered some props, // in case they error. var jsxPropsParents = new WeakMap(); var jsxChildrenParents = new WeakMap(); function isObjectPrototype(object) { if (!object) { return false; } var ObjectPrototype = Object.prototype; if (object === ObjectPrototype) { return true; } // It might be an object from a different Realm which is // still just a plain simple object. if (getPrototypeOf(object)) { return false; } var names = Object.getOwnPropertyNames(object); for (var i = 0; i < names.length; i++) { if (!(names[i] in ObjectPrototype)) { return false; } } return true; } function isSimpleObject(object) { if (!isObjectPrototype(getPrototypeOf(object))) { return false; } var names = Object.getOwnPropertyNames(object); for (var i = 0; i < names.length; i++) { var descriptor = Object.getOwnPropertyDescriptor(object, names[i]); if (!descriptor) { return false; } if (!descriptor.enumerable) { if ((names[i] === 'key' || names[i] === 'ref') && typeof descriptor.get === 'function') { // React adds key and ref getters to props objects to issue warnings. // Those getters will not be transferred to the client, but that's ok, // so we'll special case them. continue; } return false; } } return true; } function objectName(object) { // $FlowFixMe[method-unbinding] var name = Object.prototype.toString.call(object); // Extract 'Object' from '[object Object]': return name.slice(8, name.length - 1); } function describeKeyForErrorMessage(key) { var encodedKey = JSON.stringify(key); return '"' + key + '"' === encodedKey ? key : encodedKey; } function describeValueForErrorMessage(value) { switch (typeof value) { case 'string': { return JSON.stringify(value.length <= 10 ? value : value.slice(0, 10) + '...'); } case 'object': { if (isArray(value)) { return '[...]'; } if (value !== null && value.$$typeof === CLIENT_REFERENCE_TAG) { return describeClientReference(); } var name = objectName(value); if (name === 'Object') { return '{...}'; } return name; } case 'function': { if (value.$$typeof === CLIENT_REFERENCE_TAG) { return describeClientReference(); } var _name = value.displayName || value.name; return _name ? 'function ' + _name : 'function'; } default: // eslint-disable-next-line react-internal/safe-string-coercion return String(value); } } function describeElementType(type) { if (typeof type === 'string') { return type; } switch (type) { case REACT_SUSPENSE_TYPE: return 'Suspense'; case REACT_SUSPENSE_LIST_TYPE: return 'SuspenseList'; case REACT_VIEW_TRANSITION_TYPE: { return 'ViewTransition'; } } if (typeof type === 'object') { switch (type.$$typeof) { case REACT_FORWARD_REF_TYPE: return describeElementType(type.render); case REACT_MEMO_TYPE: return describeElementType(type.type); case REACT_LAZY_TYPE: { var lazyComponent = type; var payload = lazyComponent._payload; var init = lazyComponent._init; try { // Lazy may contain any component type so we recursively resolve it. return describeElementType(init(payload)); } catch (x) {} } } } return ''; } var CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference'); function describeClientReference(ref) { return 'client'; } function describeObjectForErrorMessage(objectOrArray, expandedName) { var objKind = objectName(objectOrArray); if (objKind !== 'Object' && objKind !== 'Array') { return objKind; } var str = ''; var start = -1; var length = 0; if (isArray(objectOrArray)) { if (jsxChildrenParents.has(objectOrArray)) { // Print JSX Children var type = jsxChildrenParents.get(objectOrArray); str = '<' + describeElementType(type) + '>'; var array = objectOrArray; for (var i = 0; i < array.length; i++) { var value = array[i]; var substr = void 0; if (typeof value === 'string') { substr = value; } else if (typeof value === 'object' && value !== null) { substr = '{' + describeObjectForErrorMessage(value) + '}'; } else { substr = '{' + describeValueForErrorMessage(value) + '}'; } if ('' + i === expandedName) { start = str.length; length = substr.length; str += substr; } else if (substr.length < 15 && str.length + substr.length < 40) { str += substr; } else { str += '{...}'; } } str += '</' + describeElementType(type) + '>'; } else { // Print Array str = '['; var _array = objectOrArray; for (var _i = 0; _i < _array.length; _i++) { if (_i > 0) { str += ', '; } var _value = _array[_i]; var _substr = void 0; if (typeof _value === 'object' && _value !== null) { _substr = describeObjectForErrorMessage(_value); } else { _substr = describeValueForErrorMessage(_value); } if ('' + _i === expandedName) { start = str.length; length = _substr.length; str += _substr; } else if (_substr.length < 10 && str.length + _substr.length < 40) { str += _substr; } else { str += '...'; } } str += ']'; } } else { if (objectOrArray.$$typeof === REACT_ELEMENT_TYPE) { str = '<' + describeElementType(objectOrArray.type) + '/>'; } else if (objectOrArray.$$typeof === CLIENT_REFERENCE_TAG) { return describeClientReference(); } else if (jsxPropsParents.has(objectOrArray)) { // Print JSX var _type = jsxPropsParents.get(objectOrArray); str = '<' + (describeElementType(_type) || '...'); var object = objectOrArray; var names = Object.keys(object); for (var _i2 = 0; _i2 < names.length; _i2++) { str += ' '; var name = names[_i2]; str += describeKeyForErrorMessage(name) + '='; var _value2 = object[name]; var _substr2 = void 0; if (name === expandedName && typeof _value2 === 'object' && _value2 !== null) { _substr2 = describeObjectForErrorMessage(_value2); } else { _substr2 = describeValueForErrorMessage(_value2); } if (typeof _value2 !== 'string') { _substr2 = '{' + _substr2 + '}'; } if (name === expandedName) { start = str.length; length = _substr2.length; str += _substr2; } else if (_substr2.length < 10 && str.length + _substr2.length < 40) { str += _substr2; } else { str += '...'; } } str += '>'; } else { // Print Object str = '{'; var _object = objectOrArray; var _names = Object.keys(_object); for (var _i3 = 0; _i3 < _names.length; _i3++) { if (_i3 > 0) { str += ', '; } var _name2 = _names[_i3]; str += describeKeyForErrorMessage(_name2) + ': '; var _value3 = _object[_name2]; var _substr3 = void 0; if (typeof _value3 === 'object' && _value3 !== null) { _substr3 = describeObjectForErrorMessage(_value3); } else { _substr3 = describeValueForErrorMessage(_value3); } if (_name2 === expandedName) { start = str.length; length = _substr3.length; str += _substr3; } else if (_substr3.length < 10 && str.length + _substr3.length < 40) { str += _substr3; } else { str += '...'; } } str += '}'; } } if (expandedName === undefined) { return str; } if (start > -1 && length > 0) { var highlight = ' '.repeat(start) + '^'.repeat(length); return '\n ' + str + '\n ' + highlight; } return '\n ' + str; } function createTemporaryReferenceSet() { return new Map(); } function writeTemporaryReference(set, reference, object) { set.set(reference, object); } function readTemporaryReference(set, reference) { return set.get(reference); } var ObjectPrototype = Object.prototype; var knownServerReferences = new WeakMap(); // Serializable values // Thenable<ReactServerValue> function serializeByValueID(id) { return '$' + id.toString(16); } function serializePromiseID(id) { return '$@' + id.toString(16); } function serializeServerReferenceID(id) { return '$F' + id.toString(16); } function serializeTemporaryReferenceMarker() { return '$T'; } function serializeFormDataReference(id) { // Why K? F is "Function". D is "Date". What else? return '$K' + id.toString(16); } function serializeNumber(number) { if (Number.isFinite(number)) { if (number === 0 && 1 / number === -Infinity) { return '$-0'; } else { return number; } } else { if (number === Infinity) { return '$Infinity'; } else if (number === -Infinity) { return '$-Infinity'; } else { return '$NaN'; } } } function serializeUndefined() { return '$undefined'; } function serializeDateFromDateJSON(dateJSON) { // JSON.stringify automatically calls Date.prototype.toJSON which calls toISOString. // We need only tack on a $D prefix. return '$D' + dateJSON; } function serializeBigInt(n) { return '$n' + n.toString(10); } function serializeMapID(id) { return '$Q' + id.toString(16); } function serializeSetID(id) { return '$W' + id.toString(16); } function serializeBlobID(id) { return '$B' + id.toString(16); } function serializeIteratorID(id) { return '$i' + id.toString(16); } function escapeStringValue(value) { if (value[0] === '$') { // We need to escape $ prefixed strings since we use those to encode // references to IDs and as special symbol values. return '$' + value; } else { return value; } } function processReply(root, formFieldPrefix, temporaryReferences, resolve, reject) { var nextPartId = 1; var pendingParts = 0; var formData = null; var writtenObjects = new WeakMap(); var modelRoot = root; function serializeTypedArray(tag, typedArray) { var blob = new Blob([ // We should be able to pass the buffer straight through but Node < 18 treat // multi-byte array blobs differently so we first convert it to single-byte. new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength)]); var blobId = nextPartId++; if (formData === null) { formData = new FormData(); } formData.append(formFieldPrefix + blobId, blob); return '$' + tag + blobId.toString(16); } function serializeBinaryReader(reader) { if (formData === null) { // Upgrade to use FormData to allow us to stream this value. formData = new FormData(); } var data = formData; pendingParts++; var streamId = nextPartId++; var buffer = []; function progress(entry) { if (entry.done) { var blobId = nextPartId++; data.append(formFieldPrefix + blobId, new Blob(buffer)); data.append(formFieldPrefix + streamId, '"$o' + blobId.toString(16) + '"'); data.append(formFieldPrefix + streamId, 'C'); // Close signal pendingParts--; if (pendingParts === 0) { resolve(data); } } else { buffer.push(entry.value); reader.read(new Uint8Array(1024)).then(progress, reject); } } reader.read(new Uint8Array(1024)).then(progress, reject); return '$r' + streamId.toString(16); } function serializeReader(reader) { if (formData === null) { // Upgrade to use FormData to allow us to stream this value. formData = new FormData(); } var data = formData; pendingParts++; var streamId = nextPartId++; function progress(entry) { if (entry.done) { data.append(formFieldPrefix + streamId, 'C'); // Close signal pendingParts--; if (pendingParts === 0) { resolve(data); } } else { try { // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here. var partJSON = JSON.stringify(entry.value, resolveToJSON); data.append(formFieldPrefix + streamId, partJSON); reader.read().then(progress, reject); } catch (x) { reject(x); } } } reader.read().then(progress, reject); return '$R' + streamId.toString(16); } function serializeReadableStream(stream) { // Detect if this is a BYOB stream. BYOB streams should be able to be read as bytes on the // receiving side. For binary streams, we serialize them as plain Blobs. var binaryReader; try { // $FlowFixMe[extra-arg]: This argument is accepted. binaryReader = stream.getReader({ mode: 'byob' }); } catch (x) { return serializeReader(stream.getReader()); } return serializeBinaryReader(binaryReader); } function serializeAsyncIterable(iterable, iterator) { if (formData === null) { // Upgrade to use FormData to allow us to stream this value. formData = new FormData(); } var data = formData; pendingParts++; var streamId = nextPartId++; // Generators/Iterators are Iterables but they're also their own iterator // functions. If that's the case, we treat them as single-shot. Otherwise, // we assume that this iterable might be a multi-shot and allow it to be // iterated more than once on the receiving server. var isIterator = iterable === iterator; // There's a race condition between when the stream is aborted and when the promise // resolves so we track whether we already aborted it to avoid writing twice. function progress(entry) { if (entry.done) { if (entry.value === undefined) { data.append(formFieldPrefix + streamId, 'C'); // Close signal } else { // Unlike streams, the last value may not be undefined. If it's not // we outline it and encode a reference to it in the closing instruction. try { // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here. var partJSON = JSON.stringify(entry.value, resolveToJSON); data.append(formFieldPrefix + streamId, 'C' + partJSON); // Close signal } catch (x) { reject(x); return; } } pendingParts--; if (pendingParts === 0) { resolve(data); } } else { try { // $FlowFixMe[incompatible-type]: While plain JSON can return undefined we never do here. var _partJSON = JSON.stringify(entry.value, resolveToJSON); data.append(formFieldPrefix + streamId, _partJSON); iterator.next().then(progress, reject); } catch (x) { reject(x); return; } } } iterator.next().then(progress, reject); return '$' + (isIterator ? 'x' : 'X') + streamId.toString(16); } function resolveToJSON(key, value) { var parent = this; // Make sure that `parent[key]` wasn't JSONified before `value` was passed to us { // $FlowFixMe[incompatible-use] var originalValue = parent[key]; if (typeof originalValue === 'object' && originalValue !== value && !(originalValue instanceof Date)) { if (objectName(originalValue) !== 'Object') { console.error('Only plain objects can be passed to Server Functions from the Client. ' + '%s objects are not supported.%s', objectName(originalValue), describeObjectForErrorMessage(parent, key)); } else { console.error('Only plain objects can be passed to Server Functions from the Client. ' + 'Objects with toJSON methods are not supported. Convert it manually ' + 'to a simple value before passing it to props.%s', describeObjectForErrorMessage(parent, key)); } } } if (value === null) { return null; } if (typeof value === 'object') { switch (value.$$typeof) { case REACT_ELEMENT_TYPE: { if (temporaryReferences !== undefined && key.indexOf(':') === -1) { // TODO: If the property name contains a colon, we don't dedupe. Escape instead. var parentReference = writtenObjects.get(parent); if (parentReference !== undefined) { // If the parent has a reference, we can refer to this object indirectly // through the property name inside that parent. var reference = parentReference + ':' + key; // Store this object so that the server can refer to it later in responses. writeTemporaryReference(temporaryReferences, reference, value); return serializeTemporaryReferenceMarker(); } } throw new Error('React Element cannot be passed to Server Functions from the Client without a ' + 'temporary reference set. Pass a TemporaryReferenceSet to the options.' + (describeObjectForErrorMessage(parent, key) )); } case REACT_LAZY_TYPE: { // Resolve lazy as if it wasn't here. In the future this will be encoded as a Promise. var lazy = value; var payload = lazy._payload; var init = lazy._init; if (formData === null) { // Upgrade to use FormData to allow us to stream this value. formData = new FormData(); } pendingParts++; try { var resolvedModel = init(payload); // We always outline this as a separate part even though we could inline it // because it ensures a more deterministic encoding. var lazyId = nextPartId++; var partJSON = serializeModel(resolvedModel, lazyId); // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above. var data = formData; data.append(formFieldPrefix + lazyId, partJSON); return serializeByValueID(lazyId); } catch (x) { if (typeof x === 'object' && x !== null && typeof x.then === 'function') { // Suspended pendingParts++; var _lazyId = nextPartId++; var thenable = x; var retry = function () { // While the first promise resolved, its value isn't necessarily what we'll // resolve into because we might suspend again. try { var _partJSON2 = serializeModel(value, _lazyId); // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above. var _data = formData; _data.append(formFieldPrefix + _lazyId, _partJSON2); pendingParts--; if (pendingParts === 0) { resolve(_data); } } catch (reason) { reject(reason); } }; thenable.then(retry, retry); return serializeByValueID(_lazyId); } else { // In the future we could consider serializing this as an error // that throws on the server instead. reject(x); return null; } } finally { pendingParts--; } } } // $FlowFixMe[method-unbinding] if (typeof value.then === 'function') { // We assume that any object with a .then property is a "Thenable" type, // or a Promise type. Either of which can be represented by a Promise. if (formData === null) { // Upgrade to use FormData to allow us to stream this value. formData = new FormData(); } pendingParts++; var promiseId = nextPartId++; var _thenable = value; _thenable.then(function (partValue) { try { var _partJSON3 = serializeModel(partValue, promiseId); // $FlowFixMe[incompatible-type] We know it's not null because we assigned it above. var _data2 = formData; _data2.append(formFieldPrefix + promiseId, _partJSON3); pendingParts--; if (pendingParts === 0) { resolve(_data2); } } catch (reason) { reject(reason); } }, // In the future we could consider serializing this as an error // that throws on the server instead. reject); return serializePromiseID(promiseId); } var existingReference = writtenObjects.get(value); if (existingReference !== undefined) { if (modelRoot === value) { // This is the ID we're currently emitting so we need to write it // once but if we discover it again, we refer to it by id. modelRoot = null; } else { // We've already emitted this as an outlined object, so we can // just refer to that by its existing ID. return existingReference; } } else if (key.indexOf(':') === -1) { // TODO: If the property name contains a colon, we don't dedupe. Escape instead. var _parentReference = writtenObjects.get(parent); if (_parentReference !== undefined) { // If the parent has a reference, we can refer to this object indirectly // through the property name inside that parent. var _reference = _parentReference + ':' + key; writtenObjects.set(value, _reference); if (temporaryReferences !== undefined) { // Store this object so that the server can refer to it later in responses. writeTemporaryReference(temporaryReferences, _reference, value); } } } if (isArray(value)) { // $FlowFixMe[incompatible-return] return value; } // TODO: Should we the Object.prototype.toString.call() to test for cross-realm objects? if (value instanceof FormData) { if (formData === null) { // Upgrade to use FormData to allow us to use rich objects as its values. formData = new FormData(); } var _data3 = formData; var refId = nextPartId++; // Copy all the form fields with a prefix for this reference. // These must come first in the form order because we assume that all the // fields are available before this is referenced. var prefix = formFieldPrefix + refId + '_'; // $FlowFixMe[prop-missing]: FormData has forEach. value.forEach(function (originalValue, originalKey) { // $FlowFixMe[incompatible-call] _data3.append(prefix + originalKey, originalValue); }); return serializeFormDataReference(refId); } if (value instanceof Map) { var mapId = nextPartId++; var _partJSON4 = serializeModel(Array.from(value), mapId); if (formData === null) { formData = new FormData(); } formData.append(formFieldPrefix + mapId, _partJSON4); return serializeMapID(mapId); } if (value instanceof Set) { var setId = nextPartId++; var _partJSON5 = serializeModel(Array.from(value), setId); if (formData === null) { formData = new FormData(); } formData.append(formFieldPrefix + setId, _partJSON5); return serializeSetID(setId); } if (value instanceof ArrayBuffer) { var blob = new Blob([value]); var blobId = nextPartId++; if (formData === null) { formData = new FormData(); } formData.append(formFieldPrefix + blobId, blob); return '$' + 'A' + blobId.toString(16); } if (value instanceof Int8Array) { // char return serializeTypedArray('O', value); } if (value instanceof Uint8Array) { // unsigned char return serializeTypedArray('o', value); } if (value instanceof Uint8ClampedArray) { // unsigned clamped char return serializeTypedArray('U', value); } if (value instanceof Int16Array) { // sort return serializeTypedArray('S', value); } if (value instanceof Uint16Array) { // unsigned short return serializeTypedArray('s', value); } if (value instanceof Int32Array) { // long return serializeTypedArray('L', value); } if (value instanceof Uint32Array) { // unsigned long return serializeTypedArray('l', value); } if (value instanceof Float32Array) { // float return serializeTypedArray('G', value); } if (value instanceof Float64Array) { // double return serializeTypedArray('g', value); } if (value instanceof BigInt64Array) { // number return serializeTypedArray('M', value); } if (value instanceof BigUint64Array) { // unsigned number // We use "m" instead of "n" since JSON can start with "null" return serializeTypedArray('m', value); } if (value instanceof DataView) { return serializeTypedArray('V', value); } // TODO: Blob is not available in old Node/browsers. Remove the typeof check later. if (typeof Blob === 'function' && value instanceof Blob) { if (formData === null) { formData = new FormData(); } var _blobId = nextPartId++; formData.append(formFieldPrefix + _blobId, value); return serializeBlobID(_blobId); } var iteratorFn = getIteratorFn(value); if (iteratorFn) { var iterator = iteratorFn.call(value); if (iterator === value) { // Iterator, not Iterable var iteratorId = nextPartId++; var _partJSON6 = serializeModel(Array.from(iterator), iteratorId); if (formData === null) { formData = new FormData(); } formData.append(formFieldPrefix + iteratorId, _partJSON6); return serializeIteratorID(iteratorId); } return Array.from(iterator); } // TODO: ReadableStream is not available in old Node. Remove the typeof check later. if (typeof ReadableStream === 'function' && value instanceof ReadableStream) { return serializeReadableStream(value); } var getAsyncIterator = value[ASYNC_ITERATOR]; if (typeof getAsyncIterator === 'function') { // We treat AsyncIterables as a Fragment and as such we might need to key them. return serializeAsyncIterable(value, getAsyncIterator.call(value)); } // Verify that this is a simple plain object. var proto = getPrototypeOf(value); if (proto !== ObjectPrototype && (proto === null || getPrototypeOf(proto) !== null)) { if (temporaryReferences === undefined) { throw new Error('Only plain objects, and a few built-ins, can be passed to Server Functions. ' + 'Classes or null prototypes are not supported.' + (describeObjectForErrorMessage(parent, key) )); } // We will have written this object to the temporary reference set above // so we can replace it with a marker to refer to this slot later. return serializeTemporaryReferenceMarker(); } { if (value.$$typeof === REACT_CONTEXT_TYPE) { console.error('React Context Providers cannot be passed to Server Functions from the Client.%s', describeObjectForErrorMessage(parent, key)); } else if (objectName(value) !== 'Object') { console.error('Only plain objects can be passed to Server Functions from the Client. ' + '%s objects are not supported.%s', objectName(value), describeObjectForErrorMessage(parent, key)); } else if (!isSimpleObject(value)) { console.error('Only plain objects can be passed to Server Functions from the Client. ' + 'Classes or other objects with methods are not supported.%s', describeObjectForErrorMessage(parent, key)); } else if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(value); if (symbols.length > 0) { console.error('Only plain objects can be passed to Server Functions from the Client. ' + 'Objects with symbol properties like %s are not supported.%s', symbols[0].description, describeObjectForErrorMessage(parent, key)); } } } // $FlowFixMe[incompatible-return] return value; } if (typeof value === 'string') { // TODO: Maybe too clever. If we support URL there's no similar trick. if (value[value.length - 1] === 'Z') { // Possibly a Date, whose toJSON automatically calls toISOString // $FlowFixMe[incompatible-use] var _originalValue = parent[key]; if (_originalValue instanceof Date) { return serializeDateFromDateJSON(value); } } return escapeStringValue(value); } if (typeof value === 'boolean') { return value; } if (typeof value === 'number') { return serializeNumber(value); } if (typeof value === 'undefined') { return serializeUndefined(); } if (typeof value === 'function') { var referenceClosure = knownServerReferences.get(value); if (referenceClosure !== undefined) { var id = referenceClosure.id, bound = referenceClosure.bound; var referenceClosureJSON = JSON.stringify({ id: id, bound: bound }, resolveToJSON); if (formData === null) { // Upgrade to use FormData to allow us to stream this value. formData = new FormData(); } // The reference to this function came from the same client so we can pass it back. var _refId = nextPartId++; formData.set(formFieldPrefix + _refId, referenceClosureJSON); return serializeServerReferenceID(_refId); } if (temporaryReferences !== undefined && key.indexOf(':') === -1) { // TODO: If the property name contains a colon, we don't dedupe. Escape instead. var _parentReference2 = writtenObjects.get(parent); if (_parentReference2 !== undefined) { // If the parent has a reference, we can refer to this object indirectly // through the property name inside that parent. var _reference2 = _parentReference2 + ':' + key; // Store this object so that the server can refer to it later in responses. writeTemporaryReference(temporaryReferences, _reference2, value); return serializeTemporaryReferenceMarker(); } } throw new Error('Client Functions cannot be passed directly to Server Functions. ' + 'Only Functions passed from the Server can be passed back again.'); } if (typeof value === 'symbol') { if (temporaryReferences !== undefined && key.indexOf(':') === -1) { // TODO: If the property name contains a colon, we don't dedupe. Escape instead. var _parentReference3 = writtenObjects.get(parent); if (_parentReference3 !== undefined) { // If the parent has a reference, we can refer to this object indirectly // through the property name inside that parent. var _reference3 = _parentReference3 + ':' + key; // Store this object so that the server can refer to it later in responses. writeTemporaryReference(temporaryReferences, _reference3, value); return serializeTemporaryReferenceMarker(); } } throw new Error('Symbols cannot be passed to a Server Function without a ' + 'temporary reference set. Pass a TemporaryReferenceSet to the options.' + (describeObjectForErrorMessage(parent, key) )); } if (typeof value === 'bigint') { return serializeBigInt(value); } throw new Error("Type " + typeof value + " is not supported as an argument to a Server Function."); } function serializeModel(model, id) { if (typeof model === 'object' && model !== null) { var reference = serializeByValueID(id); writtenObjects.set(model, reference); if (temporaryReferences !== undefined) { // Store this object so that the server can refer to it later in responses. writeTemporaryReference(temporaryReferences, reference, model); } } modelRoot = model; // $FlowFixMe[incompatible-return] it's not going to be undefined because we'll encode it. return JSON.stringify(model, resolveToJSON); } function abort(reason) { if (pendingParts > 0) { pendingParts = 0; // Don't resolve again later. // Resolve with what we have so far, which may have holes at this point. // They'll error when the stream completes on the server. if (formData === null) { resolve(json); } else { resolve(formData); } } } var json = serializeModel(root, 0); if (formData === null) { // If it's a simple data structure, we just use plain JSON. resolve(json); } else { // Otherwise, we use FormData to let us stream in the result. formData.set(formFieldPrefix + '0', json); if (pendingParts === 0) { // $FlowFixMe[incompatible-call] this has already been refined. resolve(formData); } } return abort; } var fakeServerFunctionIdx = 0; function createFakeServerFunction(name, filename, sourceMap, line, col, environmentName, innerFunction) { // This creates a fake copy of a Server Module. It represents the Server Action on the server. // We use an eval so we can source map it to the original location. var comment = '/* This module is a proxy to a Server Action. Turn on Source Maps to see the server source. */'; if (!name) { // An eval:ed function with no name gets the name "eval". We give it something more descriptive. name = '<anonymous>'; } var encodedName = JSON.stringify(name); // We generate code where both the beginning of the function and its parenthesis is at the line // and column of the server executed code. We use a method form since that lets us name it // anything we want and because the beginning of the function and its parenthesis is the same // column. Because Chrome inspects the location of the parenthesis and Firefox inspects the // location of the beginning of the function. By not using a function expression we avoid the // ambiguity. var code; if (line <= 1) { var minSize = encodedName.length + 7; code = 's=>({' + encodedName + ' '.repeat(col < minSize ? 0 : col - minSize) + ':' + '(...args) => s(...args)' + '})\n' + comment; } else { code = comment + '\n'.repeat(line - 2) + 'server=>({' + encodedName + ':\n' + ' '.repeat(col < 1 ? 0 : col - 1) + // The function body can get printed so we make it look nice. // This "calls the server with the arguments". '(...args) => server(...args)' + '})'; } if (filename.startsWith('/')) { // If the filename starts with `/` we assume that it is a file system file // rather than relative to the current host. Since on the server fully qualified // stack traces use the file path. // TODO: What does this look like on Windows? filename = 'file://' + filename; } if (sourceMap) { // We use the prefix about://React/ to separate these from other files listed in // the Chrome DevTools. We need a "host name" and not just a protocol because // otherwise the group name becomes the root folder. Ideally we don't want to // show these at all but there's two reasons to assign a fake URL. // 1) A printed stack trace string needs a unique URL to be able to source map it. // 2) If source maps are disabled or fails, you should at least be able to tell // which file it was. code += '\n//# sourceURL=about://React/' + encodeURIComponent(environmentName) + '/' + encodeURI(filename) + '?s' + // We add an extra s here to distinguish from the fake stack frames fakeServerFunctionIdx++; code += '\n//# sourceMappingURL=' + sourceMap; } else if (filename) { code += '\n//# sourceURL=' + filename; } try { // Eval a factory and then call it to create a closure over the inner function. // eslint-disable-next-line no-eval return (0, eval)(code)(innerFunction)[name]; } catch (x) { // If eval fails, such as if in an environment that doesn't support it, // we fallback to just returning the inner function. return innerFunction; } } function registerBoundServerReference(reference, id, bound, encodeFormAction) { if (knownServerReferences.has(reference)) { return; } knownServerReferences.set(reference, { id: id, originalBind: reference.bind, bound: bound }); } function registerServerReference(reference, id, encodeFormAction) { registerBoundServerReference(reference, id, null); return reference; } function createBoundServerReference(metaData, callServer, encodeFormAction, findSourceMapURL // DEV-only ) { var id = metaData.id; var bound = metaData.bound; var action = function () { // $FlowFixMe[method-unbinding] var args = Array.prototype.slice.call(arguments); var p = bound; if (!p) { return callServer(id, args); } if (p.status === 'fulfilled') { var boundArgs = p.value; return callServer(id, boundArgs.concat(args)); } // Since this is a fake Promise whose .then doesn't chain, we have to wrap it. // TODO: Remove the wrapper once that's fixed. return Promise.resolve(p).then(function (boundArgs) { return callServer(id, boundArgs.concat(args)); }); }; { var location = metaData.location; if (location) { var functionName = metaData.name || ''; var filename = location[1], line = location[2], col = location[3]; var env = metaData.env || 'Server'; var sourceMap = findSourceMapURL == null ? null : findSourceMapURL(filename, env); action = createFakeServerFunction(functionName, filename, sourceMap, line, col, env, action); } } registerBoundServerReference(action, id, bound); return action; } // This matches either of these V8 formats. // at name (filename:0:0) // at filename:0:0 // at async filename:0:0 var v8FrameRegExp = /^ {3} at (?:(.+) \((.+):(\d+):(\d+)\)|(?:async )?(.+):(\d+):(\d+))$/; // This matches either of these JSC/SpiderMonkey formats. // name@filename:0:0 // filename:0:0 var jscSpiderMonkeyFrameRegExp = /(?:(.*)@)?(.*):(\d+):(\d+)/; function parseStackLocation(error) { // This parsing is special in that we know that the calling function will always // be a module that initializes the server action. We also need this part to work // cross-browser so not worth a Config. It's DEV only so not super code size // sensitive but also a non-essential feature. var stack = error.stack; if (stack.startsWith('Error: react-stack-top-frame\n')) { // V8's default formatting prefixes with the error message which we // don't want/need. stack = stack.slice(29); } var endOfFirst = stack.indexOf('\n'); var secondFrame; if (endOfFirst !== -1) { // Skip the first frame. var endOfSecond = stack.indexOf('\n', endOfFirst + 1); if (endOfSecond === -1) {