Compare commits

...

5 Commits

Author SHA1 Message Date
Brian Vaughn
12adaffef7 Remove scheduler sampling profiler shared array buffer (#20840)
No one has been using this data so there's no reason to collect it. Event log has been maintained and tests have been updated.
2021-03-22 20:01:35 +00:00
Brian Vaughn
b2bbee7ba3 Disable (unstable) scheduler sampling profiler for OSS builds (#20832)
* Disabled Scheduler sampling profiler for OSS builds
* Added missing conditional feature flag around profiling calls
2021-03-22 19:57:29 +00:00
Toru Kobayashi
8cc6ff2488 fix: use SharedArrayBuffer only when cross-origin isolation is enabled (#20831)
* fix: check cross-origin isolation for SharedArrayBuffer

* chore: remove unused a $FlowFixMe comment

* prettier
2021-03-22 19:50:49 +00:00
Dan Abramov
8e5adfbd7e Remove usage of Array#fill (#20071) 2020-10-22 12:59:20 +01:00
Dan Abramov
89b610969d Bump versions for 17 2020-10-20 21:33:44 +01:00
29 changed files with 69 additions and 161 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "create-subscription",
"description": "utility for subscribing to external data sources inside React components",
"version": "17.0.0-alpha.0",
"version": "17.0.0",
"repository": {
"type": "git",
"url": "https://github.com/facebook/react.git",
@@ -15,7 +15,7 @@
"cjs/"
],
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "^17.0.0"
},
"devDependencies": {
"rxjs": "^5.5.6"

View File

@@ -1,7 +1,7 @@
{
"name": "eslint-plugin-react-hooks",
"description": "ESLint rules for React Hooks",
"version": "4.1.2",
"version": "4.2.0",
"repository": {
"type": "git",
"url": "https://github.com/facebook/react.git",

View File

@@ -20,7 +20,7 @@
"homepage": "https://reactjs.org/",
"peerDependencies": {
"jest": "^23.0.1 || ^24.0.0 || ^25.1.0",
"scheduler": "^0.15.0"
"scheduler": "^0.20.0"
},
"files": [
"LICENSE",

View File

@@ -1,6 +1,6 @@
{
"name": "jest-react",
"version": "0.12.0-alpha.0",
"version": "0.12.0",
"description": "Jest matchers and utilities for testing React components.",
"main": "index.js",
"repository": {
@@ -20,8 +20,8 @@
"homepage": "https://reactjs.org/",
"peerDependencies": {
"jest": "^23.0.1 || ^24.0.0 || ^25.1.0",
"react": "^17.0.0-alpha",
"react-test-renderer": "^17.0.0-alpha"
"react": "^17.0.0",
"react-test-renderer": "^17.0.0"
},
"dependencies": {
"object-assign": "^4.1.1"

View File

@@ -1,7 +1,7 @@
{
"name": "react-art",
"description": "React ART is a JavaScript library for drawing vector graphics using React. It provides declarative and reactive bindings to the ART library. Using the same declarative API you can render the output to either Canvas, SVG or VML (IE8).",
"version": "17.0.0-alpha.0",
"version": "17.0.0",
"main": "index.js",
"repository": {
"type": "git",
@@ -26,10 +26,10 @@
"create-react-class": "^15.6.2",
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"scheduler": "^0.19.0"
"scheduler": "^0.20.0"
},
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "17.0.0"
},
"files": [
"LICENSE",

View File

@@ -17,6 +17,6 @@
"umd/"
],
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "^17.0.0"
}
}

View File

@@ -24,7 +24,7 @@
"node": ">=0.10.0"
},
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "^17.0.0"
},
"dependencies": {
"loose-envify": "^1.1.0",

View File

@@ -26,7 +26,7 @@
"node": ">=0.10.0"
},
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "^17.0.0"
},
"dependencies": {
"error-stack-parser": "^2.0.2",

View File

@@ -1,6 +1,6 @@
{
"name": "react-dom",
"version": "17.0.0-alpha.0",
"version": "17.0.0",
"description": "React package for working with the DOM.",
"main": "index.js",
"repository": {
@@ -19,10 +19,10 @@
"dependencies": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"scheduler": "^0.19.0"
"scheduler": "^0.20.0"
},
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "17.0.0"
},
"files": [
"LICENSE",

View File

@@ -18,7 +18,7 @@
"cjs/"
],
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "^17.0.0"
},
"browser": {
"./index.js": "./index.browser.js"

View File

@@ -38,7 +38,7 @@
"loose-envify": "^1.1.0"
},
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "^17.0.0"
},
"browserify": {
"transform": [

View File

@@ -1,6 +1,6 @@
{
"name": "react-is",
"version": "17.0.0-alpha.0",
"version": "17.0.0",
"description": "Brand checking of React Elements.",
"main": "index.js",
"repository": {

View File

@@ -12,6 +12,6 @@
"scheduler": "^0.11.0"
},
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "^17.0.0"
}
}

View File

@@ -17,7 +17,7 @@
"react-server": "*"
},
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "^17.0.0"
},
"files": [
"LICENSE",

View File

@@ -1,7 +1,7 @@
{
"name": "react-reconciler",
"description": "React package for creating custom renderers.",
"version": "0.25.1",
"version": "0.26.0",
"keywords": [
"react"
],
@@ -26,12 +26,12 @@
"node": ">=0.10.0"
},
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "^17.0.0"
},
"dependencies": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"scheduler": "^0.19.0"
"scheduler": "^0.20.0"
},
"browserify": {
"transform": [

View File

@@ -640,7 +640,13 @@ export function higherLanePriority(
}
export function createLaneMap<T>(initial: T): LaneMap<T> {
return new Array(TotalLanes).fill(initial);
// Intentionally pushing one by one.
// https://v8.dev/blog/elements-kinds#avoid-creating-holes
const laneMap = [];
for (let i = 0; i < TotalLanes; i++) {
laneMap.push(initial);
}
return laneMap;
}
export function markRootUpdated(

View File

@@ -4,7 +4,7 @@
"keywords": [
"react"
],
"version": "0.8.3",
"version": "0.9.0",
"homepage": "https://reactjs.org/",
"bugs": "https://github.com/facebook/react/issues",
"license": "MIT",

View File

@@ -27,7 +27,7 @@
"node": ">=0.10.0"
},
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "^17.0.0"
},
"dependencies": {
"loose-envify": "^1.1.0",

View File

@@ -1,6 +1,6 @@
{
"name": "react-test-renderer",
"version": "17.0.0-alpha.0",
"version": "17.0.0",
"description": "React package for snapshot testing.",
"main": "index.js",
"repository": {
@@ -20,12 +20,12 @@
"homepage": "https://reactjs.org/",
"dependencies": {
"object-assign": "^4.1.1",
"react-is": "^17.0.0-alpha",
"react-is": "^17.0.0",
"react-shallow-renderer": "^16.13.1",
"scheduler": "^0.19.0"
"scheduler": "^0.20.0"
},
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "17.0.0"
},
"files": [
"LICENSE",

View File

@@ -12,7 +12,7 @@
"scheduler": "^0.11.0"
},
"peerDependencies": {
"react": "^17.0.0-alpha",
"react-dom": "^17.0.0-alpha"
"react": "^17.0.0",
"react-dom": "^17.0.0"
}
}

View File

@@ -34,8 +34,8 @@
"node": ">=0.10.0"
},
"peerDependencies": {
"react": "^17.0.0-alpha",
"react-dom": "^17.0.0-alpha",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"webpack": "^4.43.0"
},
"dependencies": {

View File

@@ -4,7 +4,7 @@
"keywords": [
"react"
],
"version": "17.0.0-alpha.0",
"version": "17.0.0",
"homepage": "https://reactjs.org/",
"bugs": "https://github.com/facebook/react/issues",
"license": "MIT",

View File

@@ -1,6 +1,6 @@
{
"name": "scheduler",
"version": "0.19.1",
"version": "0.20.0",
"description": "Cooperative scheduler for the browser environment.",
"main": "index.js",
"repository": {

View File

@@ -32,7 +32,6 @@ import {
IdlePriority,
} from './SchedulerPriorities';
import {
sharedProfilingBuffer,
markTaskRun,
markTaskYield,
markTaskCompleted,
@@ -181,12 +180,16 @@ function workLoop(hasTimeRemaining, initialTime) {
currentTask.callback = null;
currentPriorityLevel = currentTask.priorityLevel;
const didUserCallbackTimeout = currentTask.expirationTime <= currentTime;
markTaskRun(currentTask, currentTime);
if (enableProfiling) {
markTaskRun(currentTask, currentTime);
}
const continuationCallback = callback(didUserCallbackTimeout);
currentTime = getCurrentTime();
if (typeof continuationCallback === 'function') {
currentTask.callback = continuationCallback;
markTaskYield(currentTask, currentTime);
if (enableProfiling) {
markTaskYield(currentTask, currentTime);
}
} else {
if (enableProfiling) {
markTaskCompleted(currentTask, currentTime);
@@ -420,6 +423,5 @@ export const unstable_Profiling = enableProfiling
? {
startLoggingProfilingEvents,
stopLoggingProfilingEvents,
sharedProfilingBuffer,
}
: null;

View File

@@ -8,4 +8,4 @@
export const enableSchedulerDebugging = false;
export const enableIsInputPending = false;
export const enableProfiling = __PROFILE__;
export const enableProfiling = __VARIANT__;

View File

@@ -10,40 +10,9 @@
import type {PriorityLevel} from './SchedulerPriorities';
import {enableProfiling} from './SchedulerFeatureFlags';
import {NoPriority} from './SchedulerPriorities';
let runIdCounter: number = 0;
let mainThreadIdCounter: number = 0;
const profilingStateSize = 4;
export const sharedProfilingBuffer = enableProfiling
? // $FlowFixMe Flow doesn't know about SharedArrayBuffer
typeof SharedArrayBuffer === 'function'
? new SharedArrayBuffer(profilingStateSize * Int32Array.BYTES_PER_ELEMENT)
: // $FlowFixMe Flow doesn't know about ArrayBuffer
typeof ArrayBuffer === 'function'
? new ArrayBuffer(profilingStateSize * Int32Array.BYTES_PER_ELEMENT)
: null // Don't crash the init path on IE9
: null;
const profilingState =
enableProfiling && sharedProfilingBuffer !== null
? new Int32Array(sharedProfilingBuffer)
: []; // We can't read this but it helps save bytes for null checks
const PRIORITY = 0;
const CURRENT_TASK_ID = 1;
const CURRENT_RUN_ID = 2;
const QUEUE_SIZE = 3;
if (enableProfiling) {
profilingState[PRIORITY] = NoPriority;
// This is maintained with a counter, because the size of the priority queue
// array might include canceled tasks.
profilingState[QUEUE_SIZE] = 0;
profilingState[CURRENT_TASK_ID] = 0;
}
// Bytes per element is 4
const INITIAL_EVENT_LOG_SIZE = 131072;
const MAX_EVENT_LOG_SIZE = 524288; // Equivalent to 2 megabytes
@@ -111,8 +80,6 @@ export function markTaskStart(
ms: number,
) {
if (enableProfiling) {
profilingState[QUEUE_SIZE]++;
if (eventLog !== null) {
// performance.now returns a float, representing milliseconds. When the
// event is logged, it's coerced to an int. Convert to microseconds to
@@ -131,10 +98,6 @@ export function markTaskCompleted(
ms: number,
) {
if (enableProfiling) {
profilingState[PRIORITY] = NoPriority;
profilingState[CURRENT_TASK_ID] = 0;
profilingState[QUEUE_SIZE]--;
if (eventLog !== null) {
logEvent([TaskCompleteEvent, ms * 1000, task.id]);
}
@@ -150,8 +113,6 @@ export function markTaskCanceled(
ms: number,
) {
if (enableProfiling) {
profilingState[QUEUE_SIZE]--;
if (eventLog !== null) {
logEvent([TaskCancelEvent, ms * 1000, task.id]);
}
@@ -167,10 +128,6 @@ export function markTaskErrored(
ms: number,
) {
if (enableProfiling) {
profilingState[PRIORITY] = NoPriority;
profilingState[CURRENT_TASK_ID] = 0;
profilingState[QUEUE_SIZE]--;
if (eventLog !== null) {
logEvent([TaskErrorEvent, ms * 1000, task.id]);
}
@@ -188,10 +145,6 @@ export function markTaskRun(
if (enableProfiling) {
runIdCounter++;
profilingState[PRIORITY] = task.priorityLevel;
profilingState[CURRENT_TASK_ID] = task.id;
profilingState[CURRENT_RUN_ID] = runIdCounter;
if (eventLog !== null) {
logEvent([TaskRunEvent, ms * 1000, task.id, runIdCounter]);
}
@@ -200,10 +153,6 @@ export function markTaskRun(
export function markTaskYield(task: {id: number, ...}, ms: number) {
if (enableProfiling) {
profilingState[PRIORITY] = NoPriority;
profilingState[CURRENT_TASK_ID] = 0;
profilingState[CURRENT_RUN_ID] = 0;
if (eventLog !== null) {
logEvent([TaskYieldEvent, ms * 1000, task.id, runIdCounter]);
}

View File

@@ -13,7 +13,6 @@
'use strict';
let Scheduler;
let sharedProfilingArray;
// let runWithPriority;
let ImmediatePriority;
let UserBlockingPriority;
@@ -44,7 +43,8 @@ function priorityLevelToString(priorityLevel) {
}
describe('Scheduler', () => {
if (!__PROFILE__) {
const {enableProfiling} = require('scheduler/src/SchedulerFeatureFlags');
if (!enableProfiling) {
// The tests in this suite only apply when profiling is on
it('profiling APIs are not available', () => {
Scheduler = require('scheduler');
@@ -58,10 +58,6 @@ describe('Scheduler', () => {
jest.mock('scheduler', () => require('scheduler/unstable_mock'));
Scheduler = require('scheduler');
sharedProfilingArray = new Int32Array(
Scheduler.unstable_Profiling.sharedProfilingBuffer,
);
// runWithPriority = Scheduler.unstable_runWithPriority;
ImmediatePriority = Scheduler.unstable_ImmediatePriority;
UserBlockingPriority = Scheduler.unstable_UserBlockingPriority;
@@ -75,20 +71,6 @@ describe('Scheduler', () => {
// shouldYield = Scheduler.unstable_shouldYield;
});
const PRIORITY = 0;
const CURRENT_TASK_ID = 1;
const CURRENT_RUN_ID = 2;
const QUEUE_SIZE = 3;
afterEach(() => {
if (sharedProfilingArray[QUEUE_SIZE] !== 0) {
throw Error(
'Test exited, but the shared profiling buffer indicates that a task ' +
'is still running',
);
}
});
const TaskStartEvent = 1;
const TaskCompleteEvent = 2;
const TaskErrorEvent = 3;
@@ -271,23 +253,6 @@ describe('Scheduler', () => {
return '\n' + result;
}
function getProfilingInfo() {
const queueSize = sharedProfilingArray[QUEUE_SIZE];
if (queueSize === 0) {
return 'Empty Queue';
}
const priorityLevel = sharedProfilingArray[PRIORITY];
if (priorityLevel === 0) {
return 'Suspended, Queue Size: ' + queueSize;
}
return (
`Task: ${sharedProfilingArray[CURRENT_TASK_ID]}, ` +
`Run: ${sharedProfilingArray[CURRENT_RUN_ID]}, ` +
`Priority: ${priorityLevelToString(priorityLevel)}, ` +
`Queue Size: ${sharedProfilingArray[QUEUE_SIZE]}`
);
}
it('creates a basic flamegraph', () => {
Scheduler.unstable_Profiling.startLoggingProfilingEvents();
@@ -296,35 +261,27 @@ describe('Scheduler', () => {
NormalPriority,
() => {
Scheduler.unstable_advanceTime(300);
Scheduler.unstable_yieldValue(getProfilingInfo());
Scheduler.unstable_yieldValue('Yield 1');
scheduleCallback(
UserBlockingPriority,
() => {
Scheduler.unstable_yieldValue(getProfilingInfo());
Scheduler.unstable_yieldValue('Yield 2');
Scheduler.unstable_advanceTime(300);
},
{label: 'Bar'},
);
Scheduler.unstable_advanceTime(100);
Scheduler.unstable_yieldValue('Yield');
Scheduler.unstable_yieldValue('Yield 3');
return () => {
Scheduler.unstable_yieldValue(getProfilingInfo());
Scheduler.unstable_yieldValue('Yield 4');
Scheduler.unstable_advanceTime(300);
};
},
{label: 'Foo'},
);
expect(Scheduler).toFlushAndYieldThrough([
'Task: 1, Run: 1, Priority: Normal, Queue Size: 1',
'Yield',
]);
expect(Scheduler).toFlushAndYieldThrough(['Yield 1', 'Yield 3']);
Scheduler.unstable_advanceTime(100);
expect(Scheduler).toFlushAndYield([
'Task: 2, Run: 2, Priority: User-blocking, Queue Size: 2',
'Task: 1, Run: 3, Priority: Normal, Queue Size: 1',
]);
expect(getProfilingInfo()).toEqual('Empty Queue');
expect(Scheduler).toFlushAndYield(['Yield 2', 'Yield 4']);
expect(stopProfilingAndPrintFlamegraph()).toEqual(
`
@@ -339,19 +296,16 @@ Task 1 [Normal] │ ████████░░░░░░░
Scheduler.unstable_Profiling.startLoggingProfilingEvents();
const task = scheduleCallback(NormalPriority, () => {
Scheduler.unstable_yieldValue(getProfilingInfo());
Scheduler.unstable_yieldValue('Yield 1');
Scheduler.unstable_advanceTime(300);
Scheduler.unstable_yieldValue('Yield');
Scheduler.unstable_yieldValue('Yield 2');
return () => {
Scheduler.unstable_yieldValue('Continuation');
Scheduler.unstable_advanceTime(200);
};
});
expect(Scheduler).toFlushAndYieldThrough([
'Task: 1, Run: 1, Priority: Normal, Queue Size: 1',
'Yield',
]);
expect(Scheduler).toFlushAndYieldThrough(['Yield 1', 'Yield 2']);
Scheduler.unstable_advanceTime(100);
cancelCallback(task);
@@ -391,28 +345,25 @@ Task 1 [Normal] │██████🡐 errored
Scheduler.unstable_Profiling.startLoggingProfilingEvents();
const task1 = scheduleCallback(NormalPriority, () => {
Scheduler.unstable_yieldValue(getProfilingInfo());
Scheduler.unstable_yieldValue('Yield 1');
Scheduler.unstable_advanceTime(300);
Scheduler.unstable_yieldValue('Yield');
Scheduler.unstable_yieldValue('Yield 2');
return () => {
Scheduler.unstable_yieldValue('Continuation');
Scheduler.unstable_advanceTime(200);
};
});
const task2 = scheduleCallback(NormalPriority, () => {
Scheduler.unstable_yieldValue(getProfilingInfo());
Scheduler.unstable_yieldValue('Yield 3');
Scheduler.unstable_advanceTime(300);
Scheduler.unstable_yieldValue('Yield');
Scheduler.unstable_yieldValue('Yield 4');
return () => {
Scheduler.unstable_yieldValue('Continuation');
Scheduler.unstable_advanceTime(200);
};
});
expect(Scheduler).toFlushAndYieldThrough([
'Task: 1, Run: 1, Priority: Normal, Queue Size: 2',
'Yield',
]);
expect(Scheduler).toFlushAndYieldThrough(['Yield 1', 'Yield 2']);
Scheduler.unstable_advanceTime(100);
cancelCallback(task1);

View File

@@ -6,4 +6,4 @@
*/
// TODO: this is special because it gets imported during build.
export default '17.0.0-alpha.0';
export default '17.0.0';

View File

@@ -1,7 +1,7 @@
{
"name": "use-subscription",
"description": "Reusable hooks",
"version": "1.4.1",
"version": "1.5.0",
"repository": {
"type": "git",
"url": "https://github.com/facebook/react.git",
@@ -19,7 +19,7 @@
"object-assign": "^4.1.1"
},
"peerDependencies": {
"react": "^17.0.0-alpha"
"react": "^17.0.0"
},
"devDependencies": {
"rxjs": "^5.5.6"