Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
557022396b |
@@ -792,20 +792,18 @@ export class Environment {
|
||||
* NOTE: Zod doesn't work when specifying a function as a default, so we have to
|
||||
* fallback to the default value here
|
||||
*/
|
||||
const moduleTypeProvider = this.config.moduleTypeProvider;
|
||||
if (
|
||||
moduleTypeProvider != null &&
|
||||
typeof moduleTypeProvider !== 'function'
|
||||
) {
|
||||
const moduleTypeProvider =
|
||||
this.config.moduleTypeProvider ?? defaultModuleTypeProvider;
|
||||
if (moduleTypeProvider == null) {
|
||||
return null;
|
||||
}
|
||||
if (typeof moduleTypeProvider !== 'function') {
|
||||
CompilerError.throwInvalidConfig({
|
||||
reason: `Expected a function for \`moduleTypeProvider\``,
|
||||
loc,
|
||||
});
|
||||
}
|
||||
const unparsedModuleConfig =
|
||||
(typeof moduleTypeProvider === 'function'
|
||||
? moduleTypeProvider(moduleName)
|
||||
: null) ?? defaultModuleTypeProvider(moduleName);
|
||||
const unparsedModuleConfig = moduleTypeProvider(moduleName);
|
||||
if (unparsedModuleConfig != null) {
|
||||
const parsedModuleConfig = TypeSchema.safeParse(unparsedModuleConfig);
|
||||
if (!parsedModuleConfig.success) {
|
||||
|
||||
@@ -28,14 +28,6 @@ import {
|
||||
BuiltInWeakMapId,
|
||||
BuiltInWeakSetId,
|
||||
BuiltInEffectEventId,
|
||||
BuiltInIntlDateTimeFormatId,
|
||||
BuiltInIntlNumberFormatId,
|
||||
BuiltInIntlCollatorId,
|
||||
BuiltInIntlPluralRulesId,
|
||||
BuiltInIntlListFormatId,
|
||||
BuiltInIntlRelativeTimeFormatId,
|
||||
BuiltInIntlSegmenterId,
|
||||
BuiltInIntlDisplayNamesId,
|
||||
ReanimatedSharedValueId,
|
||||
ShapeRegistry,
|
||||
addFunction,
|
||||
@@ -628,145 +620,6 @@ const TYPED_GLOBALS: Array<[string, BuiltInType]> = [
|
||||
true,
|
||||
),
|
||||
],
|
||||
[
|
||||
'Intl',
|
||||
addObject(DEFAULT_SHAPES, 'Intl', [
|
||||
[
|
||||
'DateTimeFormat',
|
||||
addFunction(
|
||||
DEFAULT_SHAPES,
|
||||
[],
|
||||
{
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {
|
||||
kind: 'Object',
|
||||
shapeId: BuiltInIntlDateTimeFormatId,
|
||||
},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Frozen,
|
||||
},
|
||||
null,
|
||||
true,
|
||||
),
|
||||
],
|
||||
[
|
||||
'NumberFormat',
|
||||
addFunction(
|
||||
DEFAULT_SHAPES,
|
||||
[],
|
||||
{
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInIntlNumberFormatId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Frozen,
|
||||
},
|
||||
null,
|
||||
true,
|
||||
),
|
||||
],
|
||||
[
|
||||
'Collator',
|
||||
addFunction(
|
||||
DEFAULT_SHAPES,
|
||||
[],
|
||||
{
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInIntlCollatorId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Frozen,
|
||||
},
|
||||
null,
|
||||
true,
|
||||
),
|
||||
],
|
||||
[
|
||||
'PluralRules',
|
||||
addFunction(
|
||||
DEFAULT_SHAPES,
|
||||
[],
|
||||
{
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInIntlPluralRulesId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Frozen,
|
||||
},
|
||||
null,
|
||||
true,
|
||||
),
|
||||
],
|
||||
[
|
||||
'ListFormat',
|
||||
addFunction(
|
||||
DEFAULT_SHAPES,
|
||||
[],
|
||||
{
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInIntlListFormatId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Frozen,
|
||||
},
|
||||
null,
|
||||
true,
|
||||
),
|
||||
],
|
||||
[
|
||||
'RelativeTimeFormat',
|
||||
addFunction(
|
||||
DEFAULT_SHAPES,
|
||||
[],
|
||||
{
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {
|
||||
kind: 'Object',
|
||||
shapeId: BuiltInIntlRelativeTimeFormatId,
|
||||
},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Frozen,
|
||||
},
|
||||
null,
|
||||
true,
|
||||
),
|
||||
],
|
||||
[
|
||||
'Segmenter',
|
||||
addFunction(
|
||||
DEFAULT_SHAPES,
|
||||
[],
|
||||
{
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInIntlSegmenterId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Frozen,
|
||||
},
|
||||
null,
|
||||
true,
|
||||
),
|
||||
],
|
||||
[
|
||||
'DisplayNames',
|
||||
addFunction(
|
||||
DEFAULT_SHAPES,
|
||||
[],
|
||||
{
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInIntlDisplayNamesId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Frozen,
|
||||
},
|
||||
null,
|
||||
true,
|
||||
),
|
||||
],
|
||||
]),
|
||||
],
|
||||
// TODO: rest of Global objects
|
||||
];
|
||||
|
||||
|
||||
@@ -389,16 +389,6 @@ export const BuiltInEffectEventId = 'BuiltInEffectEventFunction';
|
||||
// See getReanimatedModuleType() in Globals.ts — this is part of supporting Reanimated's ref-like types
|
||||
export const ReanimatedSharedValueId = 'ReanimatedSharedValueId';
|
||||
|
||||
// Intl formatter instance shapes
|
||||
export const BuiltInIntlDateTimeFormatId = 'BuiltInIntlDateTimeFormat';
|
||||
export const BuiltInIntlNumberFormatId = 'BuiltInIntlNumberFormat';
|
||||
export const BuiltInIntlCollatorId = 'BuiltInIntlCollator';
|
||||
export const BuiltInIntlPluralRulesId = 'BuiltInIntlPluralRules';
|
||||
export const BuiltInIntlListFormatId = 'BuiltInIntlListFormat';
|
||||
export const BuiltInIntlRelativeTimeFormatId = 'BuiltInIntlRelativeTimeFormat';
|
||||
export const BuiltInIntlSegmenterId = 'BuiltInIntlSegmenter';
|
||||
export const BuiltInIntlDisplayNamesId = 'BuiltInIntlDisplayNames';
|
||||
|
||||
// ShapeRegistry with default definitions for built-ins.
|
||||
export const BUILTIN_SHAPES: ShapeRegistry = new Map();
|
||||
|
||||
@@ -1242,297 +1232,6 @@ addObject(BUILTIN_SHAPES, BuiltInRefValueId, [
|
||||
|
||||
addObject(BUILTIN_SHAPES, ReanimatedSharedValueId, []);
|
||||
|
||||
/**
|
||||
* Intl formatter instance shapes.
|
||||
*
|
||||
* All Intl formatter objects are immutable after construction — calling their
|
||||
* methods does not modify the formatter. Methods like `format()` return
|
||||
* primitives (strings/numbers), `formatToParts()` returns a new array, and
|
||||
* `resolvedOptions()` returns a new object.
|
||||
*/
|
||||
|
||||
/* Intl.DateTimeFormat instance */
|
||||
addObject(BUILTIN_SHAPES, BuiltInIntlDateTimeFormatId, [
|
||||
[
|
||||
'format',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Primitive'},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Primitive,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'formatToParts',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'formatRange',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Primitive'},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Primitive,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'formatRangeToParts',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'resolvedOptions',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInObjectId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
]);
|
||||
|
||||
/* Intl.NumberFormat instance */
|
||||
addObject(BUILTIN_SHAPES, BuiltInIntlNumberFormatId, [
|
||||
[
|
||||
'format',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Primitive'},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Primitive,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'formatToParts',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'formatRange',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Primitive'},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Primitive,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'formatRangeToParts',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'resolvedOptions',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInObjectId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
]);
|
||||
|
||||
/* Intl.Collator instance */
|
||||
addObject(BUILTIN_SHAPES, BuiltInIntlCollatorId, [
|
||||
[
|
||||
'compare',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Primitive'},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Primitive,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'resolvedOptions',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInObjectId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
]);
|
||||
|
||||
/* Intl.PluralRules instance */
|
||||
addObject(BUILTIN_SHAPES, BuiltInIntlPluralRulesId, [
|
||||
[
|
||||
'select',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Primitive'},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Primitive,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'selectRange',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Primitive'},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Primitive,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'resolvedOptions',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInObjectId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
]);
|
||||
|
||||
/* Intl.ListFormat instance */
|
||||
addObject(BUILTIN_SHAPES, BuiltInIntlListFormatId, [
|
||||
[
|
||||
'format',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Primitive'},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Primitive,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'formatToParts',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'resolvedOptions',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInObjectId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
]);
|
||||
|
||||
/* Intl.RelativeTimeFormat instance */
|
||||
addObject(BUILTIN_SHAPES, BuiltInIntlRelativeTimeFormatId, [
|
||||
[
|
||||
'format',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Primitive'},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Primitive,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'formatToParts',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read, Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'resolvedOptions',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInObjectId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
]);
|
||||
|
||||
/* Intl.Segmenter instance */
|
||||
addObject(BUILTIN_SHAPES, BuiltInIntlSegmenterId, [
|
||||
[
|
||||
'segment',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Poly'},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'resolvedOptions',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInObjectId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
]);
|
||||
|
||||
/* Intl.DisplayNames instance */
|
||||
addObject(BUILTIN_SHAPES, BuiltInIntlDisplayNamesId, [
|
||||
[
|
||||
'of',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [Effect.Read],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Primitive'},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Primitive,
|
||||
}),
|
||||
],
|
||||
[
|
||||
'resolvedOptions',
|
||||
addFunction(BUILTIN_SHAPES, [], {
|
||||
positionalParams: [],
|
||||
restParam: null,
|
||||
returnType: {kind: 'Object', shapeId: BuiltInObjectId},
|
||||
calleeEffect: Effect.Read,
|
||||
returnValueKind: ValueKind.Mutable,
|
||||
}),
|
||||
],
|
||||
]);
|
||||
|
||||
addFunction(
|
||||
BUILTIN_SHAPES,
|
||||
[],
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function DateComponent({date}) {
|
||||
const formatter = new Intl.DateTimeFormat('en-US');
|
||||
|
||||
return <time dateTime={date.toISOString()}>{formatter.format(date)}</time>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: DateComponent,
|
||||
params: [{date: new Date('2024-01-01')}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
function DateComponent(t0) {
|
||||
const $ = _c(6);
|
||||
const { date } = t0;
|
||||
let t1;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = new Intl.DateTimeFormat("en-US");
|
||||
$[0] = t1;
|
||||
} else {
|
||||
t1 = $[0];
|
||||
}
|
||||
const formatter = t1;
|
||||
let t2;
|
||||
if ($[1] !== date) {
|
||||
t2 = date.toISOString();
|
||||
$[1] = date;
|
||||
$[2] = t2;
|
||||
} else {
|
||||
t2 = $[2];
|
||||
}
|
||||
const t3 = formatter.format(date);
|
||||
let t4;
|
||||
if ($[3] !== t2 || $[4] !== t3) {
|
||||
t4 = <time dateTime={t2}>{t3}</time>;
|
||||
$[3] = t2;
|
||||
$[4] = t3;
|
||||
$[5] = t4;
|
||||
} else {
|
||||
t4 = $[5];
|
||||
}
|
||||
return t4;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: DateComponent,
|
||||
params: [{ date: new Date("2024-01-01") }],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) <time datetime="2024-01-01T00:00:00.000Z">12/31/2023</time>
|
||||
@@ -1,10 +0,0 @@
|
||||
function DateComponent({date}) {
|
||||
const formatter = new Intl.DateTimeFormat('en-US');
|
||||
|
||||
return <time dateTime={date.toISOString()}>{formatter.format(date)}</time>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: DateComponent,
|
||||
params: [{date: new Date('2024-01-01')}],
|
||||
};
|
||||
@@ -54,7 +54,6 @@ Each filter object must include `type` and `isEnabled`. Some filters also requir
|
||||
|------------------------|---------------|---------------------------------------------------------------------------------------------------------------------------|
|
||||
| `host` | `"localhost"` | Socket connection to frontend should use this host. |
|
||||
| `isAppActive` | | (Optional) function that returns true/false, telling DevTools when it's ready to connect to React. |
|
||||
| `path` | `""` | Path appended to the WebSocket URI (e.g. `"/__react_devtools__/"`). Useful when proxying through a reverse proxy on a subpath. A leading `/` is added automatically if missing. |
|
||||
| `port` | `8097` | Socket connection to frontend should use this port. |
|
||||
| `resolveRNStyle` | | (Optional) function that accepts a key (number) and returns a style (object); used by React Native. |
|
||||
| `retryConnectionDelay` | `200` | Delay (ms) to wait between retrying a failed Websocket connection |
|
||||
@@ -142,51 +141,16 @@ function onStatus(
|
||||
}
|
||||
```
|
||||
|
||||
#### `startServer(port?, host?, httpsOptions?, loggerOptions?, path?, clientOptions?)`
|
||||
#### `startServer(port?: number, host?: string, httpsOptions?: Object, loggerOptions?: Object)`
|
||||
Start a socket server (used to communicate between backend and frontend) and renders the DevTools UI.
|
||||
|
||||
This method accepts the following parameters:
|
||||
| Name | Default | Description |
|
||||
|---|---|---|
|
||||
| `port` | `8097` | Port the local server listens on. |
|
||||
| `host` | `"localhost"` | Host the local server binds to. |
|
||||
| `port` | `8097` | Socket connection to backend should use this port. |
|
||||
| `host` | `"localhost"` | Socket connection to backend should use this host. |
|
||||
| `httpsOptions` | | _Optional_ object defining `key` and `cert` strings. |
|
||||
| `loggerOptions` | | _Optional_ object defining a `surface` string (to be included with DevTools logging events). |
|
||||
| `path` | | _Optional_ path to append to the WebSocket URI served to connecting clients (e.g. `"/__react_devtools__/"`). Also set via the `REACT_DEVTOOLS_PATH` env var in the Electron app. |
|
||||
| `clientOptions` | | _Optional_ object with client-facing overrides (see below). |
|
||||
|
||||
##### `clientOptions`
|
||||
|
||||
When connecting through a reverse proxy, the client may need to connect to a different host, port, or protocol than the local server. Use `clientOptions` to override what appears in the `connectToDevTools()` script served to clients. Any field not set falls back to the corresponding server value.
|
||||
|
||||
| Field | Default | Description |
|
||||
|---|---|---|
|
||||
| `host` | server `host` | Host the client connects to. |
|
||||
| `port` | server `port` | Port the client connects to. |
|
||||
| `useHttps` | server `useHttps` | Whether the client should use `wss://`. |
|
||||
|
||||
These can also be set via environment variables in the Electron app:
|
||||
|
||||
| Env Var | Description |
|
||||
|---|---|
|
||||
| `REACT_DEVTOOLS_CLIENT_HOST` | Overrides the host in the served client script. |
|
||||
| `REACT_DEVTOOLS_CLIENT_PORT` | Overrides the port in the served client script. |
|
||||
| `REACT_DEVTOOLS_CLIENT_USE_HTTPS` | Set to `"true"` to make the served client script use `wss://`. |
|
||||
|
||||
##### Reverse proxy example
|
||||
|
||||
Run DevTools locally on the default port, but tell clients to connect through a remote proxy:
|
||||
```sh
|
||||
REACT_DEVTOOLS_CLIENT_HOST=remote.example.com \
|
||||
REACT_DEVTOOLS_CLIENT_PORT=443 \
|
||||
REACT_DEVTOOLS_CLIENT_USE_HTTPS=true \
|
||||
REACT_DEVTOOLS_PATH=/__react_devtools__/ \
|
||||
react-devtools
|
||||
```
|
||||
The server listens on `localhost:8097`. The served script tells clients:
|
||||
```js
|
||||
connectToDevTools({host: 'remote.example.com', port: 443, useHttps: true, path: '/__react_devtools__/'})
|
||||
```
|
||||
|
||||
# Development
|
||||
|
||||
|
||||
5
packages/react-devtools-core/src/backend.js
vendored
5
packages/react-devtools-core/src/backend.js
vendored
@@ -33,7 +33,6 @@ import type {ResolveNativeStyle} from 'react-devtools-shared/src/backend/NativeS
|
||||
type ConnectOptions = {
|
||||
host?: string,
|
||||
nativeStyleEditorValidAttributes?: $ReadOnlyArray<string>,
|
||||
path?: string,
|
||||
port?: number,
|
||||
useHttps?: boolean,
|
||||
resolveRNStyle?: ResolveNativeStyle,
|
||||
@@ -94,7 +93,6 @@ export function connectToDevTools(options: ?ConnectOptions) {
|
||||
const {
|
||||
host = 'localhost',
|
||||
nativeStyleEditorValidAttributes,
|
||||
path = '',
|
||||
useHttps = false,
|
||||
port = 8097,
|
||||
websocket,
|
||||
@@ -109,7 +107,6 @@ export function connectToDevTools(options: ?ConnectOptions) {
|
||||
} = options || {};
|
||||
|
||||
const protocol = useHttps ? 'wss' : 'ws';
|
||||
const prefixedPath = path !== '' && !path.startsWith('/') ? '/' + path : path;
|
||||
let retryTimeoutID: TimeoutID | null = null;
|
||||
|
||||
function scheduleRetry() {
|
||||
@@ -132,7 +129,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
|
||||
let bridge: BackendBridge | null = null;
|
||||
|
||||
const messageListeners = [];
|
||||
const uri = protocol + '://' + host + ':' + port + prefixedPath;
|
||||
const uri = protocol + '://' + host + ':' + port;
|
||||
|
||||
// If existing websocket is passed, use it.
|
||||
// This is necessary to support our custom integrations.
|
||||
|
||||
47
packages/react-devtools-core/src/standalone.js
vendored
47
packages/react-devtools-core/src/standalone.js
vendored
@@ -306,19 +306,11 @@ type LoggerOptions = {
|
||||
surface?: ?string,
|
||||
};
|
||||
|
||||
type ClientOptions = {
|
||||
host?: string,
|
||||
port?: number,
|
||||
useHttps?: boolean,
|
||||
};
|
||||
|
||||
function startServer(
|
||||
port: number = 8097,
|
||||
host: string = 'localhost',
|
||||
httpsOptions?: ServerOptions,
|
||||
loggerOptions?: LoggerOptions,
|
||||
path?: string,
|
||||
clientOptions?: ClientOptions,
|
||||
): {close(): void} {
|
||||
registerDevToolsEventLogger(loggerOptions?.surface ?? 'standalone');
|
||||
|
||||
@@ -353,18 +345,7 @@ function startServer(
|
||||
server.on('error', (event: $FlowFixMe) => {
|
||||
onError(event);
|
||||
log.error('Failed to start the DevTools server', event);
|
||||
startServerTimeoutID = setTimeout(
|
||||
() =>
|
||||
startServer(
|
||||
port,
|
||||
host,
|
||||
httpsOptions,
|
||||
loggerOptions,
|
||||
path,
|
||||
clientOptions,
|
||||
),
|
||||
1000,
|
||||
);
|
||||
startServerTimeoutID = setTimeout(() => startServer(port), 1000);
|
||||
});
|
||||
|
||||
httpServer.on('request', (request: $FlowFixMe, response: $FlowFixMe) => {
|
||||
@@ -377,21 +358,14 @@ function startServer(
|
||||
// This will ensure that saved filters are shared across different web pages.
|
||||
const componentFiltersString = JSON.stringify(getSavedComponentFilters());
|
||||
|
||||
// Client overrides: when connecting through a reverse proxy, the client
|
||||
// may need to connect to a different host/port/protocol than the server.
|
||||
const clientHost = clientOptions?.host ?? host;
|
||||
const clientPort = clientOptions?.port ?? port;
|
||||
const clientUseHttps = clientOptions?.useHttps ?? useHttps;
|
||||
|
||||
response.end(
|
||||
backendFile.toString() +
|
||||
'\n;' +
|
||||
`var ReactDevToolsBackend = typeof ReactDevToolsBackend !== "undefined" ? ReactDevToolsBackend : require("ReactDevToolsBackend");\n` +
|
||||
`ReactDevToolsBackend.initialize(undefined, undefined, undefined, ${componentFiltersString});` +
|
||||
'\n' +
|
||||
`ReactDevToolsBackend.connectToDevTools({port: ${clientPort}, host: '${clientHost}', useHttps: ${
|
||||
clientUseHttps ? 'true' : 'false'
|
||||
}${path != null ? `, path: '${path}'` : ''}});
|
||||
`ReactDevToolsBackend.connectToDevTools({port: ${port}, host: '${host}', useHttps: ${
|
||||
useHttps ? 'true' : 'false'
|
||||
}});
|
||||
`,
|
||||
);
|
||||
});
|
||||
@@ -399,18 +373,7 @@ function startServer(
|
||||
httpServer.on('error', (event: $FlowFixMe) => {
|
||||
onError(event);
|
||||
statusListener('Failed to start the server.', 'error');
|
||||
startServerTimeoutID = setTimeout(
|
||||
() =>
|
||||
startServer(
|
||||
port,
|
||||
host,
|
||||
httpsOptions,
|
||||
loggerOptions,
|
||||
path,
|
||||
clientOptions,
|
||||
),
|
||||
1000,
|
||||
);
|
||||
startServerTimeoutID = setTimeout(() => startServer(port), 1000);
|
||||
});
|
||||
|
||||
httpServer.listen(port, () => {
|
||||
|
||||
@@ -44,7 +44,6 @@ module.exports = {
|
||||
// This name is important; standalone references it in order to connect.
|
||||
library: 'ReactDevToolsBackend',
|
||||
libraryTarget: 'umd',
|
||||
umdNamedDefine: true,
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
|
||||
@@ -87,31 +87,7 @@ This will ensure the developer tools are connected. **Don’t forget to remove i
|
||||
|
||||
## Advanced
|
||||
|
||||
By default DevTools listen to port `8097` on `localhost`. If you need to customize the server or client connection settings, the following environment variables are available:
|
||||
|
||||
| Env Var | Default | Description |
|
||||
|---|---|---|
|
||||
| `HOST` | `"localhost"` | Host the local server binds to. |
|
||||
| `PORT` | `8097` | Port the local server listens on. |
|
||||
| `REACT_DEVTOOLS_PORT` | | Alias for `PORT`. Takes precedence if both are set. |
|
||||
| `KEY` | | Path to an SSL key file. Enables HTTPS when set alongside `CERT`. |
|
||||
| `CERT` | | Path to an SSL certificate file. Enables HTTPS when set alongside `KEY`. |
|
||||
| `REACT_DEVTOOLS_PATH` | | Path appended to the WebSocket URI served to clients (e.g. `/__react_devtools__/`). |
|
||||
| `REACT_DEVTOOLS_CLIENT_HOST` | `HOST` | Overrides the host in the script served to connecting clients. |
|
||||
| `REACT_DEVTOOLS_CLIENT_PORT` | `PORT` | Overrides the port in the script served to connecting clients. |
|
||||
| `REACT_DEVTOOLS_CLIENT_USE_HTTPS` | | Set to `"true"` to make the served client script use `wss://`. |
|
||||
|
||||
When connecting through a reverse proxy, use the `REACT_DEVTOOLS_CLIENT_*` variables to tell clients to connect to a different host/port/protocol than the local server:
|
||||
|
||||
```sh
|
||||
REACT_DEVTOOLS_CLIENT_HOST=remote.example.com \
|
||||
REACT_DEVTOOLS_CLIENT_PORT=443 \
|
||||
REACT_DEVTOOLS_CLIENT_USE_HTTPS=true \
|
||||
REACT_DEVTOOLS_PATH=/__react_devtools__/ \
|
||||
react-devtools
|
||||
```
|
||||
|
||||
For more details, see the [`react-devtools-core` documentation](https://github.com/facebook/react/tree/main/packages/react-devtools-core).
|
||||
By default DevTools listen to port `8097` on `localhost`. The port can be modified by setting the `REACT_DEVTOOLS_PORT` environment variable. If you need to further customize host, port, or other settings, see the `react-devtools-core` package instead.
|
||||
|
||||
## FAQ
|
||||
|
||||
|
||||
@@ -158,19 +158,12 @@
|
||||
<script>
|
||||
// window.api is defined in preload.js
|
||||
const {electron, readEnv, ip, getDevTools} = window.api;
|
||||
const {options, useHttps, host, protocol, port, path, clientHost, clientPort, clientUseHttps} = readEnv();
|
||||
const {options, useHttps, host, protocol, port} = readEnv();
|
||||
|
||||
const localIp = ip.address();
|
||||
|
||||
// Effective values for display URLs: client overrides take precedence over server values.
|
||||
const effectiveHost = clientHost != null ? clientHost : host;
|
||||
const effectivePort = clientPort != null ? clientPort : port;
|
||||
const effectiveUseHttps = clientUseHttps != null ? clientUseHttps : useHttps;
|
||||
const effectiveProtocol = effectiveUseHttps ? 'https' : 'http';
|
||||
const defaultPort = (effectivePort === 443 && effectiveUseHttps) || (effectivePort === 80 && !effectiveUseHttps);
|
||||
const pathStr = path != null ? path : '';
|
||||
const server = defaultPort ? `${effectiveProtocol}://${effectiveHost}${pathStr}` : `${effectiveProtocol}://${effectiveHost}:${effectivePort}${pathStr}`;
|
||||
const serverIp = defaultPort ? `${effectiveProtocol}://${localIp}${pathStr}` : `${effectiveProtocol}://${localIp}:${effectivePort}${pathStr}`;
|
||||
const defaultPort = (port === 443 && useHttps) || (port === 80 && !useHttps);
|
||||
const server = defaultPort ? `${protocol}://${host}` : `${protocol}://${host}:${port}`;
|
||||
const serverIp = defaultPort ? `${protocol}://${localIp}` : `${protocol}://${localIp}:${port}`;
|
||||
const $ = document.querySelector.bind(document);
|
||||
|
||||
let timeoutID;
|
||||
@@ -241,7 +234,7 @@
|
||||
element.innerText = status;
|
||||
}
|
||||
})
|
||||
.startServer(port, host, options, undefined, path, {host: clientHost, port: clientPort, useHttps: clientUseHttps});
|
||||
.startServer(port, host, options);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
19
packages/react-devtools/preload.js
vendored
19
packages/react-devtools/preload.js
vendored
@@ -36,23 +36,6 @@ contextBridge.exposeInMainWorld('api', {
|
||||
const host = process.env.HOST || 'localhost';
|
||||
const protocol = useHttps ? 'https' : 'http';
|
||||
const port = +process.env.REACT_DEVTOOLS_PORT || +process.env.PORT || 8097;
|
||||
const path = process.env.REACT_DEVTOOLS_PATH || undefined;
|
||||
const clientHost = process.env.REACT_DEVTOOLS_CLIENT_HOST || undefined;
|
||||
const clientPort = process.env.REACT_DEVTOOLS_CLIENT_PORT
|
||||
? +process.env.REACT_DEVTOOLS_CLIENT_PORT
|
||||
: undefined;
|
||||
const clientUseHttps =
|
||||
process.env.REACT_DEVTOOLS_CLIENT_USE_HTTPS === 'true' ? true : undefined;
|
||||
return {
|
||||
options,
|
||||
useHttps,
|
||||
host,
|
||||
protocol,
|
||||
port,
|
||||
path,
|
||||
clientHost,
|
||||
clientPort,
|
||||
clientUseHttps,
|
||||
};
|
||||
return {options, useHttps, host, protocol, port};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -208,7 +208,7 @@ export const disableLegacyMode: boolean = true;
|
||||
// in open source, but www codebase still relies on it. Need to remove.
|
||||
export const disableCommentsAsDOMContainers: boolean = true;
|
||||
|
||||
export const enableTrustedTypesIntegration: boolean = true;
|
||||
export const enableTrustedTypesIntegration: boolean = false;
|
||||
|
||||
// Prevent the value and checked attributes from syncing with their related
|
||||
// DOM properties
|
||||
|
||||
@@ -62,7 +62,7 @@ export const enableSuspenseAvoidThisFallback: boolean = false;
|
||||
export const enableSuspenseCallback: boolean = true;
|
||||
export const enableTaint: boolean = true;
|
||||
export const enableTransitionTracing: boolean = false;
|
||||
export const enableTrustedTypesIntegration: boolean = true;
|
||||
export const enableTrustedTypesIntegration: boolean = false;
|
||||
export const enableUpdaterTracking: boolean = __PROFILE__;
|
||||
export const retryLaneExpirationMs = 5000;
|
||||
export const syncLaneExpirationMs = 250;
|
||||
|
||||
@@ -50,7 +50,7 @@ export const enableSuspenseAvoidThisFallback: boolean = false;
|
||||
export const enableSuspenseCallback: boolean = false;
|
||||
export const enableTaint: boolean = true;
|
||||
export const enableTransitionTracing: boolean = false;
|
||||
export const enableTrustedTypesIntegration: boolean = true;
|
||||
export const enableTrustedTypesIntegration: boolean = false;
|
||||
export const passChildrenWhenCloningPersistedNodes: boolean = false;
|
||||
export const retryLaneExpirationMs = 5000;
|
||||
export const syncLaneExpirationMs = 250;
|
||||
|
||||
@@ -26,7 +26,7 @@ export const disableInputAttributeSyncing: boolean = false;
|
||||
export const enableScopeAPI: boolean = false;
|
||||
export const enableCreateEventHandleAPI: boolean = false;
|
||||
export const enableSuspenseCallback: boolean = false;
|
||||
export const enableTrustedTypesIntegration: boolean = true;
|
||||
export const enableTrustedTypesIntegration: boolean = false;
|
||||
export const disableTextareaChildren: boolean = false;
|
||||
export const enableSuspenseAvoidThisFallback: boolean = false;
|
||||
export const enableCPUSuspense: boolean = false;
|
||||
|
||||
@@ -47,7 +47,7 @@ export const enableSuspenseAvoidThisFallback = false;
|
||||
export const enableSuspenseCallback = false;
|
||||
export const enableTaint = true;
|
||||
export const enableTransitionTracing = false;
|
||||
export const enableTrustedTypesIntegration = true;
|
||||
export const enableTrustedTypesIntegration = false;
|
||||
export const enableUpdaterTracking = false;
|
||||
export const passChildrenWhenCloningPersistedNodes = false;
|
||||
export const retryLaneExpirationMs = 5000;
|
||||
|
||||
@@ -28,7 +28,7 @@ export const enableCreateEventHandleAPI: boolean = false;
|
||||
export const enableSuspenseCallback: boolean = true;
|
||||
export const disableLegacyContext: boolean = false;
|
||||
export const disableLegacyContextForFunctionComponents: boolean = false;
|
||||
export const enableTrustedTypesIntegration: boolean = true;
|
||||
export const enableTrustedTypesIntegration: boolean = false;
|
||||
export const disableTextareaChildren: boolean = false;
|
||||
export const enableSuspenseAvoidThisFallback: boolean = true;
|
||||
export const enableCPUSuspense: boolean = false;
|
||||
|
||||
@@ -36,6 +36,7 @@ export const enableFragmentRefs: boolean = __VARIANT__;
|
||||
export const enableFragmentRefsScrollIntoView: boolean = __VARIANT__;
|
||||
export const enableFragmentRefsTextNodes: boolean = __VARIANT__;
|
||||
export const enableInternalInstanceMap: boolean = __VARIANT__;
|
||||
export const enableTrustedTypesIntegration: boolean = __VARIANT__;
|
||||
export const enableParallelTransitions: boolean = __VARIANT__;
|
||||
|
||||
export const enableEffectEventMutationPhase: boolean = __VARIANT__;
|
||||
|
||||
@@ -25,6 +25,7 @@ export const {
|
||||
enableObjectFiber,
|
||||
enableRetryLaneExpiration,
|
||||
enableTransitionTracing,
|
||||
enableTrustedTypesIntegration,
|
||||
retryLaneExpirationMs,
|
||||
syncLaneExpirationMs,
|
||||
transitionLaneExpirationMs,
|
||||
@@ -44,7 +45,7 @@ export const enableProfilerTimer = __PROFILE__;
|
||||
export const enableProfilerCommitHooks = __PROFILE__;
|
||||
export const enableProfilerNestedUpdatePhase = __PROFILE__;
|
||||
export const enableUpdaterTracking = __PROFILE__;
|
||||
export const enableTrustedTypesIntegration: boolean = true;
|
||||
|
||||
export const enableSuspenseAvoidThisFallback: boolean = true;
|
||||
|
||||
export const enableAsyncDebugInfo: boolean = true;
|
||||
|
||||
Reference in New Issue
Block a user