react/scripts/flow/environment.js

178 lines
4.5 KiB
JavaScript
Raw Normal View History

/**
* 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.
*
* @flow
*/
/* eslint-disable */
declare var __PROFILE__: boolean;
declare var __UMD__: boolean;
Set up experimental builds (#17071) * Don't bother including `unstable_` in error The method names don't get stripped out of the production bundles because they are passed as arguments to the error decoder. Let's just always use the unprefixed APIs in the messages. * Set up experimental builds The experimental builds are packaged exactly like builds in the stable release channel: same file structure, entry points, and npm package names. The goal is to match what will eventually be released in stable as closely as possible, but with additional features turned on. Versioning and Releasing ------------------------ The experimental builds will be published to the same registry and package names as the stable ones. However, they will be versioned using a separate scheme. Instead of semver versions, experimental releases will receive arbitrary version strings based on their content hashes. The motivation is to thwart attempts to use a version range to match against future experimental releases. The only way to install or depend on an experimental release is to refer to the specific version number. Building -------- I did not use the existing feature flag infra to configure the experimental builds. The reason is because feature flags are designed to configure a single package. They're not designed to generate multiple forks of the same package; for each set of feature flags, you must create a separate package configuration. Instead, I've added a new build dimension called the **release channel**. By default, builds use the **stable** channel. There's also an **experimental** release channel. We have the option to add more in the future. There are now two dimensions per artifact: build type (production, development, or profiling), and release channel (stable or experimental). These are separate dimensions because they are combinatorial: there are stable and experimental production builds, stable and experimental developmenet builds, and so on. You can add something to an experimental build by gating on `__EXPERIMENTAL__`, similar to how we use `__DEV__`. Anything inside these branches will be excluded from the stable builds. This gives us a low effort way to add experimental behavior in any package without setting up feature flags or configuring a new package.
2019-10-15 01:46:42 +08:00
declare var __EXPERIMENTAL__: boolean;
Add test run that uses www feature flags (#18234) In CI, we run our test suite against multiple build configurations. For example, we run our tests in both dev and prod, and in both the experimental and stable release channels. This is to prevent accidental deviations in behavior between the different builds. If there's an intentional deviation in behavior, the test author must account for them. However, we currently don't run tests against the www builds. That's a problem, because it's common for features to land in www before they land anywhere else, including the experimental release channel. Typically we do this so we can gradually roll out the feature behind a flag before deciding to enable it. The way we test those features today is by mutating the `shared/ReactFeatureFlags` module. There are a few downsides to this approach, though. The flag is only overridden for the specific tests or test suites where you apply the override. But usually what you want is to run *all* tests with the flag enabled, to protect against unexpected regressions. Also, mutating the feature flags module only works when running the tests against source, not against the final build artifacts, because the ReactFeatureFlags module is inlined by the build script. Instead, we should run the test suite against the www configuration, just like we do for prod, experimental, and so on. I've added a new command, `yarn test-www`. It automatically runs in CI. Some of the www feature flags are dynamic; that is, they depend on a runtime condition (i.e. a GK). These flags are imported from an external module that lives in www. Those flags will be enabled for some clients and disabled for others, so we should run the tests against *both* modes. So I've added a new global `__VARIANT__`, and a new test command `yarn test-www-variant`. `__VARIANT__` is set to false by default; when running `test-www-variant`, it's set to true. If we were going for *really* comprehensive coverage, we would run the tests against every possible configuration of feature flags: 2 ^ numberOfFlags total combinations. That's not practical, though, so instead we only run against two combinations: once with `__VARIANT__` set to `true`, and once with it set to `false`. We generally assume that flags can be toggled independently, so in practice this should be enough. You can also refer to `__VARIANT__` in tests to detect which mode you're running in. Or, you can import `shared/ReactFeatureFlags` and read the specific flag you can about. However, we should stop mutating that module going forward. Treat it as read-only. In this commit, I have only setup the www tests to run against source. I'll leave running against build for a follow up. Many of our tests currently assume they run only in the default configuration, and break when certain flags are toggled. Rather than fix these all up front, I've hard-coded the relevant flags to the default values. We can incrementally migrate those tests later.
2020-03-07 01:29:05 +08:00
declare var __VARIANT__: boolean;
declare var __REACT_DEVTOOLS_GLOBAL_HOOK__: any; /*?{
inject: ?((stuff: Object) => void)
};*/
declare var globalThis: Object;
declare var queueMicrotask: (fn: Function) => void;
Add onRecoverableError option to hydrateRoot, createRoot (#23207) * [RFC] Add onHydrationError option to hydrateRoot This is not the final API but I'm pushing it for discussion purposes. When an error is thrown during hydration, we fallback to client rendering, without triggering an error boundary. This is good because, in many cases, the UI will recover and the user won't even notice that something has gone wrong behind the scenes. However, we shouldn't recover from these errors silently, because the underlying cause might be pretty serious. Server-client mismatches are not supposed to happen, even if UI doesn't break from the users perspective. Ignoring them could lead to worse problems later. De-opting from server to client rendering could also be a significant performance regression, depending on the scope of the UI it affects. So we need a way to log when hydration errors occur. This adds a new option for `hydrateRoot` called `onHydrationError`. It's symmetrical to the server renderer's `onError` option, and serves the same purpose. When no option is provided, the default behavior is to schedule a browser task and rethrow the error. This will trigger the normal browser behavior for errors, including dispatching an error event. If the app already has error monitoring, this likely will just work as expected without additional configuration. However, we can also expose additional metadata about these errors, like which Suspense boundaries were affected by the de-opt to client rendering. (I have not exposed any metadata in this commit; API needs more design work.) There are other situations besides hydration where we recover from an error without surfacing it to the user, or notifying an error boundary. For example, if an error occurs during a concurrent render, it could be due to a data race, so we try again synchronously in case that fixes it. We should probably expose a way to log these types of errors, too. (Also not implemented in this commit.) * Log all recoverable errors This expands the scope of onHydrationError to include all errors that are not surfaced to the UI (an error boundary). In addition to errors that occur during hydration, this also includes errors that recoverable by de-opting to synchronous rendering. Typically (or really, by definition) these errors are the result of a concurrent data race; blocking the main thread fixes them by prevents subsequent races. The logic for de-opting to synchronous rendering already existed. The only thing that has changed is that we now log the errors instead of silently proceeding. The logging API has been renamed from onHydrationError to onRecoverableError. * Don't log recoverable errors until commit phase If the render is interrupted and restarts, we don't want to log the errors multiple times. This change only affects errors that are recovered by de-opting to synchronous rendering; we'll have to do something else for errors during hydration, since they use a different recovery path. * Only log hydration error if client render succeeds Similar to previous step. When an error occurs during hydration, we only want to log it if falling back to client rendering _succeeds_. If client rendering fails, the error will get reported to the nearest error boundary, so there's no need for a duplicate log. To implement this, I added a list of errors to the hydration context. If the Suspense boundary successfully completes, they are added to the main recoverable errors queue (the one I added in the previous step.) * Log error with queueMicrotask instead of Scheduler If onRecoverableError is not provided, we default to rethrowing the error in a separate task. Originally, I scheduled the task with idle priority, but @sebmarkbage made the good point that if there are multiple errors logs, we want to preserve the original order. So I've switched it to a microtask. The priority can be lowered in userspace by scheduling an additional task inside onRecoverableError. * Only use host config method for default behavior Redefines the contract of the host config's logRecoverableError method to be a default implementation for onRecoverableError if a user-provided one is not provided when the root is created. * Log with reportError instead of rethrowing In modern browsers, reportError will dispatch an error event, emulating an uncaught JavaScript error. We can do this instead of rethrowing recoverable errors in a microtask, which is nice because it avoids any subtle ordering issues. In older browsers and test environments, we'll fall back to console.error. * Naming nits queueRecoverableHydrationErrors -> upgradeHydrationErrorsToRecoverable
2022-02-04 23:57:33 +08:00
declare var reportError: (error: mixed) => void;
2020-01-23 02:02:30 +08:00
declare module 'create-react-class' {
declare var exports: React$CreateClass;
}
declare var trustedTypes: {
isHTML: (value: any) => boolean,
isScript: (value: any) => boolean,
isScriptURL: (value: any) => boolean,
// TrustedURLs are deprecated and will be removed soon: https://github.com/WICG/trusted-types/pull/204
isURL?: (value: any) => boolean,
};
// ReactFeatureFlags www fork
declare module 'ReactFeatureFlags' {
declare module.exports: any;
}
// ReactFiberErrorDialog www fork
declare module 'ReactFiberErrorDialog' {
declare module.exports: {showErrorDialog: (error: mixed) => boolean, ...};
}
// EventListener www fork
declare module 'EventListener' {
declare module.exports: {
listen: (
target: EventTarget,
type: string,
callback: Function,
priority?: number,
options?: {passive: boolean, ...},
) => mixed,
capture: (target: EventTarget, type: string, callback: Function) => mixed,
captureWithPassiveFlag: (
target: EventTarget,
type: string,
callback: Function,
passive: boolean,
) => mixed,
bubbleWithPassiveFlag: (
target: EventTarget,
type: string,
callback: Function,
passive: boolean,
) => mixed,
...
};
}
declare function __webpack_chunk_load__(id: string): Promise<mixed>;
Support named exports from client references (#20312) * Rename "name"->"filepath" field on Webpack module references This field name will get confused with the imported name or the module id. * Switch back to transformSource instead of getSource getSource would be more efficient in the cases where we don't need to read the original file but we'll need to most of the time. Even then, we can't return a JS file if we're trying to support non-JS loader because it'll end up being transformed. Similarly, we'll need to parse the file and we can't parse it before it's transformed. So we need to chain with other loaders that know how. * Add acorn dependency This should be the version used by Webpack since we have a dependency on Webpack anyway. * Parse exported names of ESM modules We need to statically resolve the names that a client component will export so that we can export a module reference for each of the names. For export * from, this gets tricky because we need to also load the source of the next file to parse that. We don't know exactly how the client is built so we guess it's somewhat default. * Handle imported names one level deep in CommonJS using a Proxy We use a proxy to see what property the server access and that will tell us which property we'll want to import on the client. * Add export name to module reference and Webpack map To support named exports each name needs to be encoded as a separate reference. It's possible with module splitting that different exports end up in different chunks. It's also possible that the export is renamed as part of minification. So the map also includes a map from the original to the bundled name. * Special case plain CJS requires and conditional imports using __esModule This models if the server tries to import .default or a plain require. We should replicate the same thing on the client when we load that module reference. * Dedupe acorn-related deps Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
2020-12-01 06:37:27 +08:00
declare function __webpack_require__(id: string): any;
declare module 'fs/promises' {
declare var access: (path: string, mode?: number) => Promise<void>;
declare var lstat: (
path: string,
options?: ?{bigint?: boolean},
) => Promise<mixed>;
declare var readdir: (
path: string,
options?:
| ?string
| {
encoding?: ?string,
withFileTypes?: ?boolean,
},
) => Promise<Buffer>;
declare var readFile: (
path: string,
options?:
| ?string
| {
encoding?: ?string,
},
) => Promise<Buffer>;
declare var readlink: (
path: string,
options?:
| ?string
| {
encoding?: ?string,
},
) => Promise<mixed>;
declare var realpath: (
path: string,
options?:
| ?string
| {
encoding?: ?string,
},
) => Promise<mixed>;
declare var stat: (
path: string,
options?: ?{bigint?: boolean},
) => Promise<mixed>;
}
declare module 'pg' {
declare var Pool: (
options: mixed,
) => {
query: (query: string, values?: Array<mixed>) => void,
};
}
declare module 'util' {
declare function debuglog(section: string): (data: any, ...args: any) => void;
declare function format(format: string, ...placeholders: any): string;
declare function log(string: string): void;
declare function inspect(object: any, options?: util$InspectOptions): string;
declare function isArray(object: any): boolean;
declare function isRegExp(object: any): boolean;
declare function isDate(object: any): boolean;
declare function isError(object: any): boolean;
declare function inherits(
constructor: Function,
superConstructor: Function,
): void;
declare function deprecate(f: Function, string: string): Function;
declare function promisify(f: Function): Function;
declare function callbackify(f: Function): Function;
declare class TextEncoder {
constructor(encoding?: string): TextEncoder;
encode(buffer: string): Uint8Array;
encodeInto(
buffer: string,
dest: Uint8Array,
): {read: number, written: number};
encoding: string;
}
}
declare module 'pg/lib/utils' {
declare module.exports: {
prepareValue(val: any): mixed,
};
}
declare class AsyncLocalStorage<T> {
disable(): void;
getStore(): T | void;
run(store: T, callback: (...args: any[]) => void, ...args: any[]): void;
enterWith(store: T): void;
}
declare module 'async_hooks' {
declare class AsyncLocalStorage<T> {
disable(): void;
getStore(): T | void;
run(store: T, callback: (...args: any[]) => void, ...args: any[]): void;
enterWith(store: T): void;
}
}