Compare commits
130 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c67be212d | ||
|
|
93e0bdf2ee | ||
|
|
a684f09e58 | ||
|
|
7268d97d2b | ||
|
|
0fc0446798 | ||
|
|
36db538226 | ||
|
|
6938dcaacb | ||
|
|
fa65c58e15 | ||
|
|
d9a3cc070c | ||
|
|
d9659e499e | ||
|
|
0648ca618d | ||
|
|
4dd772ac10 | ||
|
|
98bab66c35 | ||
|
|
8ced545e3d | ||
|
|
b738ced477 | ||
|
|
55b8279423 | ||
|
|
dac9202a9c | ||
|
|
4f0bd45905 | ||
|
|
7685b55d27 | ||
|
|
21a79a1d9f | ||
|
|
9ea4bc6ed6 | ||
|
|
4773fdf7cd | ||
|
|
c9be16f5b6 | ||
|
|
3b7ee26925 | ||
|
|
8ca8a594e6 | ||
|
|
6d5d250bef | ||
|
|
4a635785f5 | ||
|
|
d270db1c38 | ||
|
|
a165cf7473 | ||
|
|
30b6076157 | ||
|
|
a68ca9a5b5 | ||
|
|
0af8199709 | ||
|
|
c73497c3c7 | ||
|
|
101ea6b84d | ||
|
|
1a57dc6689 | ||
|
|
77f8dfd81e | ||
|
|
9abb9cd50a | ||
|
|
8af6728c6f | ||
|
|
f47a958ea8 | ||
|
|
b2cea9078d | ||
|
|
e2e7cb9f4c | ||
|
|
d83601080a | ||
|
|
40a521aa72 | ||
|
|
605ab10a4a | ||
|
|
acc7f404ce | ||
|
|
cbc2240288 | ||
|
|
4eabeef11b | ||
|
|
95a3e1c2e7 | ||
|
|
96bcae9d50 | ||
|
|
5c783ee751 | ||
|
|
36c5d69caa | ||
|
|
3e9a5de888 | ||
|
|
3c60f32747 | ||
|
|
8315a30b9b | ||
|
|
ce96e2df4d | ||
|
|
c5212646f8 | ||
|
|
806eebdaee | ||
|
|
a0733fe13d | ||
|
|
4d17c3f051 | ||
|
|
469005d87b | ||
|
|
0dc0ddc1ef | ||
|
|
7601c37654 | ||
|
|
d0c0ec98ef | ||
|
|
4b68a6498b | ||
|
|
f305d2a489 | ||
|
|
970a34baed | ||
|
|
13965b4d30 | ||
|
|
17e703cb96 | ||
|
|
a775a767a1 | ||
|
|
2c7b78f216 | ||
|
|
e1a067dea0 | ||
|
|
518812eeb8 | ||
|
|
eeb817785c | ||
|
|
7ea3ca1d13 | ||
|
|
9b70816642 | ||
|
|
db9d51b65c | ||
|
|
0823f845cf | ||
|
|
bec2ddaf15 | ||
|
|
789e714bd7 | ||
|
|
4269fafb0a | ||
|
|
4380f9ba17 | ||
|
|
72fad84e76 | ||
|
|
39f93f7987 | ||
|
|
c3fad5acf8 | ||
|
|
dd91205617 | ||
|
|
42d12317a7 | ||
|
|
21ceb19ea0 | ||
|
|
489614c4fc | ||
|
|
351c9015c8 | ||
|
|
a210b5b440 | ||
|
|
2f54a0467b | ||
|
|
1d8a75fef0 | ||
|
|
d92114b98e | ||
|
|
0c9c591bfb | ||
|
|
9f819a5ea9 | ||
|
|
9c961c0a27 | ||
|
|
8bc0bcabe7 | ||
|
|
b488a5d9c5 | ||
|
|
4bcee56210 | ||
|
|
9a6c5ba72d | ||
|
|
72217d0819 | ||
|
|
cc66a1aa23 | ||
|
|
8b93a60c5e | ||
|
|
7a5eecc073 | ||
|
|
ecbf7af40b | ||
|
|
2282400850 | ||
|
|
a079011f95 | ||
|
|
a7bd7c3c04 | ||
|
|
7204b636ee | ||
|
|
d3bbfe09cc | ||
|
|
1b2646a403 | ||
|
|
dde0645fcf | ||
|
|
e49f3ca08e | ||
|
|
f6fb03edff | ||
|
|
54bfab5d6d | ||
|
|
ade5e69288 | ||
|
|
f260b14a8f | ||
|
|
4a40d76245 | ||
|
|
03ab1efeb4 | ||
|
|
144328fe81 | ||
|
|
8a8d973d3c | ||
|
|
7d1169b2d7 | ||
|
|
8d1038fc6d | ||
|
|
b87aabdfe1 | ||
|
|
12f3a5475f | ||
|
|
c6dcf46d65 | ||
|
|
7bcc0778fd | ||
|
|
d66505dbc7 | ||
|
|
e417e0bf7c | ||
|
|
8f45a685be |
@@ -37,6 +37,7 @@ module.exports = {
|
||||
'no-shadow': ERROR,
|
||||
'no-unused-expressions': ERROR,
|
||||
'no-unused-vars': [ERROR, {args: 'none'}],
|
||||
'no-use-before-define': [ERROR, {functions: false, variables: false}],
|
||||
'no-useless-concat': OFF,
|
||||
'quotes': [ERROR, 'single', {avoidEscape: true, allowTemplateLiterals: true }],
|
||||
'space-before-blocks': ERROR,
|
||||
|
||||
38
CHANGELOG.md
38
CHANGELOG.md
@@ -7,12 +7,44 @@
|
||||
|
||||
</details>
|
||||
|
||||
## 16.5.2 (September 18, 2018)
|
||||
|
||||
### React DOM
|
||||
|
||||
* Fixed a recent `<iframe>` regression ([@JSteunou](https://github.com/JSteunou) in [#13650](https://github.com/facebook/react/pull/13650))
|
||||
* Fix `updateWrapper` so that `<textarea>`s no longer re-render when data is unchanged ([@joelbarbosa](https://github.com/joelbarbosa) in [#13643](https://github.com/facebook/react/pull/13643))
|
||||
|
||||
### Schedule (Experimental)
|
||||
|
||||
* Renaming "tracking" API to "tracing" ([@bvaughn](https://github.com/bvaughn) in [#13641](https://github.com/facebook/react/pull/13641))
|
||||
* Add UMD production+profiling entry points ([@bvaughn](https://github.com/bvaughn) in [#13642](https://github.com/facebook/react/pull/13642))
|
||||
* Refactored `schedule` to remove some React-isms and improve performance for when deferred updates time out ([@acdlite](https://github.com/acdlite) in [#13582](https://github.com/facebook/react/pull/13582))
|
||||
|
||||
## 16.5.1 (September 13, 2018)
|
||||
|
||||
### React
|
||||
|
||||
* Improve the warning when `React.forwardRef` receives an unexpected number of arguments. ([@andresroberto](https://github.com/andresroberto) in [#13636](https://github.com/facebook/react/issues/13636))
|
||||
|
||||
### React DOM
|
||||
|
||||
* Fix a regression in unstable exports used by React Native Web. ([@aweary](https://github.com/aweary) in [#13598](https://github.com/facebook/react/issues/13598))
|
||||
* Fix a crash when component defines a method called `isReactComponent`. ([@gaearon](https://github.com/gaearon) in [#13608](https://github.com/facebook/react/issues/13608))
|
||||
* Fix a crash in development mode in IE9 when printing a warning. ([@link-alex](https://github.com/link-alex) in [#13620](https://github.com/facebook/react/issues/13620))
|
||||
* Provide a better error message when running `react-dom/profiling` with `schedule/tracking`. ([@bvaughn](https://github.com/bvaughn) in [#13605](https://github.com/facebook/react/issues/13605))
|
||||
* If a `ForwardRef` component defines a `displayName`, use it in warnings. ([@probablyup](https://github.com/probablyup) in [#13615](https://github.com/facebook/react/issues/13615))
|
||||
|
||||
### Schedule (Experimental)
|
||||
|
||||
* Add a separate profiling entry point at `schedule/tracking-profiling`. ([@bvaughn](https://github.com/bvaughn) in [#13605](https://github.com/facebook/react/issues/13605))
|
||||
|
||||
## 16.5.0 (September 5, 2018)
|
||||
|
||||
### React
|
||||
|
||||
* Add a warning if `React.forwardRef` render function doesn't take exactly two arguments ([@bvaughn](https://github.com/bvaughn) in [#13168](https://github.com/facebook/react/issues/13168))
|
||||
* Improve the error message when passing an element to `createElement` by mistake ([@DCtheTall](https://github.com/DCtheTall) in [#13131](https://github.com/facebook/react/issues/13131))
|
||||
* Don't call profiler `onRender` until after mutations ([@bvaughn](https://github.com/bvaughn) in [#13572](https://github.com/facebook/react/issues/13572))
|
||||
|
||||
### React DOM
|
||||
|
||||
@@ -23,12 +55,12 @@
|
||||
* Add `tangentialPressure` and `twist` fields to pointer events ([@motiz88](https://github.com/motiz88) in [#13374](https://github.com/facebook/react/issues/13374))
|
||||
* Minimally support iframes (nested browsing contexts) in selection event handling ([@acusti](https://github.com/acusti) in [#12037](https://github.com/facebook/react/issues/12037))
|
||||
* Support passing booleans to the `focusable` SVG attribute ([@gaearon](https://github.com/gaearon) in [#13339](https://github.com/facebook/react/issues/13339))
|
||||
* Ignore `<noscript>` on the client when when hydrating ([@Ephem](https://github.com/Ephem) in [#13537](https://github.com/facebook/react/issues/13537))
|
||||
* Ignore `<noscript>` on the client when hydrating ([@Ephem](https://github.com/Ephem) in [#13537](https://github.com/facebook/react/issues/13537))
|
||||
* Fix `gridArea` to be treated as a unitless CSS property ([@mgol](https://github.com/mgol) in [#13550](https://github.com/facebook/react/issues/13550))
|
||||
* Fix incorrect data in `compositionend` event when typing Korean on IE11 ([@robbertbrak](https://github.com/robbertbrak) in [#10217](https://github.com/facebook/react/issues/10217))
|
||||
* Fix incorrect data in `compositionend` event when typing Korean on IE11 ([@crux153](https://github.com/crux153) in [#12563](https://github.com/facebook/react/issues/12563))
|
||||
* Fix a crash when using dynamic `children` in the `<option>` tag ([@Slowyn](https://github.com/Slowyn) in [#13261](https://github.com/facebook/react/issues/13261), [@gaearon](https://github.com/gaearon) in [#13465](https://github.com/facebook/react/pull/13465))
|
||||
* Fix the `checked` attribute not getting initially set on the `input` ([@dilidili](https://github.com/dilidili) in [#13114](https://github.com/facebook/react/issues/13114))
|
||||
* Fix hydration of `dangerousSetInnerHTML` when `__html` is not a string ([@gaearon](https://github.com/gaearon) in [#13353](https://github.com/facebook/react/issues/13353))
|
||||
* Fix hydration of `dangerouslySetInnerHTML` when `__html` is not a string ([@gaearon](https://github.com/gaearon) in [#13353](https://github.com/facebook/react/issues/13353))
|
||||
* Fix a warning about missing controlled `onChange` to fire on falsy values too ([@nicolevy](https://github.com/nicolevy) in [#12628](https://github.com/facebook/react/issues/12628))
|
||||
* Fix `submit` and `reset` buttons getting an empty label ([@ellsclytn](https://github.com/ellsclytn) in [#12780](https://github.com/facebook/react/issues/12780))
|
||||
* Fix the `onSelect` event not being triggered after drag and drop ([@gaearon](https://github.com/gaearon) in [#13422](https://github.com/facebook/react/issues/13422))
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013-present, Facebook, Inc.
|
||||
Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
1
fixtures/dom/.gitignore
vendored
1
fixtures/dom/.gitignore
vendored
@@ -10,6 +10,7 @@ coverage
|
||||
build
|
||||
public/react.development.js
|
||||
public/react-dom.development.js
|
||||
public/react-dom-server.browser.development.js
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
"react-scripts": "^1.0.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/standalone": "^7.0.0",
|
||||
"classnames": "^2.2.5",
|
||||
"codemirror": "^5.40.0",
|
||||
"core-js": "^2.4.1",
|
||||
"prop-types": "^15.6.0",
|
||||
"query-string": "^4.2.3",
|
||||
@@ -16,7 +18,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"prestart": "cp ../../build/dist/react.development.js public/ && cp ../../build/dist/react-dom.development.js public/",
|
||||
"prestart": "cp ../../build/dist/react.development.js ../../build/dist/react-dom.development.js ../../build/dist/react-dom-server.browser.development.js public/",
|
||||
"build": "react-scripts build && cp build/index.html build/200.html",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
|
||||
86
fixtures/dom/public/renderer.html
Normal file
86
fixtures/dom/public/renderer.html
Normal file
@@ -0,0 +1,86 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Renderer</title>
|
||||
<style>
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: 32px;
|
||||
}
|
||||
|
||||
#status {
|
||||
font-size: 12px;
|
||||
left: 8px;
|
||||
letter-spacing: 0.05em;
|
||||
line-height: 16px;
|
||||
margin: -8px 0 0;
|
||||
max-width: 50%;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
top: 50%;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#output {
|
||||
margin: 16px;
|
||||
}
|
||||
|
||||
.header {
|
||||
background: white;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
padding: 4px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.button {
|
||||
background: #eee;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #aaa;
|
||||
font-size: 11px;
|
||||
padding: 4px 6px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="header">
|
||||
<p id="status">Loading</p>
|
||||
|
||||
<menu class="controls">
|
||||
<button class="button" id="hydrate">Hydrate</button>
|
||||
<button class="button" id="reload">Reload</button>
|
||||
</menu>
|
||||
</header>
|
||||
|
||||
<div id="output"></div>
|
||||
|
||||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
141
fixtures/dom/public/renderer.js
Normal file
141
fixtures/dom/public/renderer.js
Normal file
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Supports render.html, a piece of the hydration fixture. See /hydration
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
(function() {
|
||||
var Fixture = null;
|
||||
var output = document.getElementById('output');
|
||||
var status = document.getElementById('status');
|
||||
var hydrate = document.getElementById('hydrate');
|
||||
var reload = document.getElementById('reload');
|
||||
var renders = 0;
|
||||
var failed = false;
|
||||
|
||||
function getQueryParam(key) {
|
||||
var pattern = new RegExp(key + '=([^&]+)(&|$)');
|
||||
var matches = window.location.search.match(pattern);
|
||||
|
||||
if (matches) {
|
||||
return decodeURIComponent(matches[1]);
|
||||
}
|
||||
|
||||
handleError(new Error('No key found for' + key));
|
||||
}
|
||||
|
||||
function getBooleanQueryParam(key) {
|
||||
return getQueryParam(key) === 'true';
|
||||
}
|
||||
|
||||
function setStatus(label) {
|
||||
status.innerHTML = label;
|
||||
}
|
||||
|
||||
function prerender() {
|
||||
setStatus('Generating markup');
|
||||
|
||||
output.innerHTML = ReactDOMServer.renderToString(
|
||||
React.createElement(Fixture)
|
||||
);
|
||||
|
||||
setStatus('Markup only (No React)');
|
||||
}
|
||||
|
||||
function render() {
|
||||
setStatus('Hydrating');
|
||||
|
||||
if (ReactDOM.hydrate) {
|
||||
ReactDOM.hydrate(React.createElement(Fixture), output);
|
||||
} else {
|
||||
ReactDOM.render(React.createElement(Fixture), output);
|
||||
}
|
||||
|
||||
setStatus(renders > 0 ? 'Re-rendered (' + renders + 'x)' : 'Hydrated');
|
||||
renders += 1;
|
||||
hydrate.innerHTML = 'Re-render';
|
||||
}
|
||||
|
||||
function handleError(error) {
|
||||
console.log(error);
|
||||
failed = true;
|
||||
setStatus('Javascript Error');
|
||||
output.innerHTML = error;
|
||||
}
|
||||
|
||||
function loadScript(src) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = src;
|
||||
|
||||
script.onload = resolve;
|
||||
script.onerror = function(error) {
|
||||
reject(new Error('Unable to load ' + src));
|
||||
};
|
||||
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
function injectFixture(src) {
|
||||
Fixture = new Function(src + '\nreturn Fixture;')();
|
||||
|
||||
if (typeof Fixture === 'undefined') {
|
||||
setStatus('Failed');
|
||||
output.innerHTML = 'Please name your root component "Fixture"';
|
||||
} else {
|
||||
prerender();
|
||||
|
||||
if (getBooleanQueryParam('hydrate')) {
|
||||
render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function reloadFixture(code) {
|
||||
renders = 0;
|
||||
ReactDOM.unmountComponentAtNode(output);
|
||||
injectFixture(code);
|
||||
}
|
||||
|
||||
window.onerror = handleError;
|
||||
|
||||
reload.onclick = function() {
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
hydrate.onclick = render;
|
||||
|
||||
loadScript(getQueryParam('reactPath'))
|
||||
.then(function() {
|
||||
return getBooleanQueryParam('needsReactDOM')
|
||||
? loadScript(getQueryParam('reactDOMPath'))
|
||||
: null;
|
||||
})
|
||||
.then(function() {
|
||||
return loadScript(getQueryParam('reactDOMServerPath'));
|
||||
})
|
||||
.then(function() {
|
||||
if (failed) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('message', function(event) {
|
||||
var data = JSON.parse(event.data);
|
||||
|
||||
switch (data.type) {
|
||||
case 'code':
|
||||
reloadFixture(data.payload);
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
'Renderer Error: Unrecognized message "' + data.type + '"'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
window.parent.postMessage(JSON.stringify({type: 'ready'}), '*');
|
||||
})
|
||||
.catch(handleError);
|
||||
})();
|
||||
@@ -8,9 +8,7 @@ function App() {
|
||||
return (
|
||||
<div>
|
||||
<Header />
|
||||
<div className="container">
|
||||
<Fixtures />
|
||||
</div>
|
||||
<Fixtures />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ class FixtureSet extends React.Component {
|
||||
const {title, description, children} = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="container">
|
||||
<h1>{title}</h1>
|
||||
{description && <p>{description}</p>}
|
||||
|
||||
|
||||
@@ -48,7 +48,8 @@ class Header extends React.Component {
|
||||
<select
|
||||
value={window.location.pathname}
|
||||
onChange={this.handleFixtureChange}>
|
||||
<option value="/">Select a Fixture</option>
|
||||
<option value="/">Home</option>
|
||||
<option value="/hydration">Hydration</option>
|
||||
<option value="/range-inputs">Range Inputs</option>
|
||||
<option value="/text-inputs">Text Inputs</option>
|
||||
<option value="/number-inputs">Number Input</option>
|
||||
@@ -67,6 +68,7 @@ class Header extends React.Component {
|
||||
<option value="/pointer-events">Pointer Events</option>
|
||||
<option value="/mouse-events">Mouse Events</option>
|
||||
<option value="/selection-events">Selection Events</option>
|
||||
<option value="/suspense">Suspense</option>
|
||||
</select>
|
||||
</label>
|
||||
<label htmlFor="react_version">
|
||||
|
||||
@@ -2,7 +2,7 @@ const React = window.React;
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<main>
|
||||
<main className="container">
|
||||
<h1>DOM Test Fixtures</h1>
|
||||
<p>
|
||||
Use this site to test browser quirks and other behavior that can not be
|
||||
|
||||
85
fixtures/dom/src/components/fixtures/hydration/Code.js
Normal file
85
fixtures/dom/src/components/fixtures/hydration/Code.js
Normal file
@@ -0,0 +1,85 @@
|
||||
const React = window.React;
|
||||
|
||||
export class CodeEditor extends React.Component {
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// Important: CodeMirror incorrectly lays out the editor
|
||||
// if it executes before CSS has loaded
|
||||
// https://github.com/graphql/graphiql/issues/33#issuecomment-318188555
|
||||
Promise.all([
|
||||
import('codemirror'),
|
||||
import('codemirror/mode/jsx/jsx'),
|
||||
import('codemirror/lib/codemirror.css'),
|
||||
import('./codemirror-paraiso-dark.css'),
|
||||
]).then(([CodeMirror]) => this.install(CodeMirror));
|
||||
}
|
||||
|
||||
install(CodeMirror) {
|
||||
if (!this.textarea) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {onChange} = this.props;
|
||||
|
||||
this.editor = CodeMirror.fromTextArea(this.textarea, {
|
||||
mode: 'jsx',
|
||||
theme: 'paraiso-dark',
|
||||
lineNumbers: true,
|
||||
});
|
||||
|
||||
this.editor.on('change', function(doc) {
|
||||
onChange(doc.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.editor) {
|
||||
this.editor.toTextArea();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<textarea
|
||||
ref={ref => (this.textarea = ref)}
|
||||
defaultValue={this.props.code}
|
||||
autoComplete="off"
|
||||
hidden={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent IE9 from raising an error on an unrecognized element:
|
||||
* See https://github.com/facebook/react/issues/13610
|
||||
*/
|
||||
const supportsDetails = !(
|
||||
document.createElement('details') instanceof HTMLUnknownElement
|
||||
);
|
||||
|
||||
export class CodeError extends React.Component {
|
||||
render() {
|
||||
const {error, className} = this.props;
|
||||
|
||||
if (!error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (supportsDetails) {
|
||||
const [summary, ...body] = error.message.split(/\n+/g);
|
||||
|
||||
return (
|
||||
<details className={className}>
|
||||
<summary>{summary}</summary>
|
||||
{body.join('\n')}
|
||||
</details>
|
||||
);
|
||||
}
|
||||
|
||||
return <div className={className}>{error.message}</div>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Babel works across all browsers, however it requires many polyfills.
|
||||
*/
|
||||
|
||||
import 'core-js/es6/weak-map';
|
||||
import 'core-js/es6/weak-set';
|
||||
import 'core-js/es6/number';
|
||||
import 'core-js/es6/string';
|
||||
import 'core-js/es6/array';
|
||||
import 'core-js/modules/es6.object.set-prototype-of';
|
||||
|
||||
import {transform} from '@babel/standalone';
|
||||
|
||||
const presets = ['es2015', 'stage-3', 'react'];
|
||||
|
||||
export function compile(raw) {
|
||||
return transform(raw, {presets}).code;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Name: Paraíso (Dark)
|
||||
* Author: Jan T. Sott
|
||||
* License: Creative Commons Attribution-ShareAlike 4.0 Unported License.
|
||||
* https://creativecommons.org/licenses/by-sa/4.0/deed.en_US
|
||||
*
|
||||
* Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror)
|
||||
* Inspired by the art of Rubens LP (http://www.rubenslp.com.br)
|
||||
*/
|
||||
|
||||
.cm-s-paraiso-dark.CodeMirror { background: #2f1e2e; color: #b9b6b0; }
|
||||
.cm-s-paraiso-dark div.CodeMirror-selected { background: #41323f; }
|
||||
.cm-s-paraiso-dark .CodeMirror-line::selection, .cm-s-paraiso-dark .CodeMirror-line > span::selection, .cm-s-paraiso-dark .CodeMirror-line > span > span::selection { background: rgba(65, 50, 63, .99); }
|
||||
.cm-s-paraiso-dark .CodeMirror-line::-moz-selection, .cm-s-paraiso-dark .CodeMirror-line > span::-moz-selection, .cm-s-paraiso-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(65, 50, 63, .99); }
|
||||
.cm-s-paraiso-dark .CodeMirror-gutters { background: #2f1e2e; border-right: 0px; }
|
||||
.cm-s-paraiso-dark .CodeMirror-guttermarker { color: #ef6155; }
|
||||
.cm-s-paraiso-dark .CodeMirror-guttermarker-subtle { color: #776e71; }
|
||||
.cm-s-paraiso-dark .CodeMirror-linenumber { color: #776e71; }
|
||||
.cm-s-paraiso-dark .CodeMirror-cursor { border-left: 1px solid #8d8687; }
|
||||
|
||||
.cm-s-paraiso-dark span.cm-comment { color: #e96ba8; }
|
||||
.cm-s-paraiso-dark span.cm-atom { color: #815ba4; }
|
||||
.cm-s-paraiso-dark span.cm-number { color: #815ba4; }
|
||||
|
||||
.cm-s-paraiso-dark span.cm-property, .cm-s-paraiso-dark span.cm-attribute { color: #48b685; }
|
||||
.cm-s-paraiso-dark span.cm-keyword { color: #ef6155; }
|
||||
.cm-s-paraiso-dark span.cm-string { color: #fec418; }
|
||||
|
||||
.cm-s-paraiso-dark span.cm-variable { color: #48b685; }
|
||||
.cm-s-paraiso-dark span.cm-variable-2 { color: #06b6ef; }
|
||||
.cm-s-paraiso-dark span.cm-def { color: #f99b15; }
|
||||
.cm-s-paraiso-dark span.cm-bracket { color: #b9b6b0; }
|
||||
.cm-s-paraiso-dark span.cm-tag { color: #ef6155; }
|
||||
.cm-s-paraiso-dark span.cm-link { color: #815ba4; }
|
||||
.cm-s-paraiso-dark span.cm-error { background: #ef6155; color: #8d8687; }
|
||||
|
||||
.cm-s-paraiso-dark .CodeMirror-activeline-background { background: #4D344A; }
|
||||
.cm-s-paraiso-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
|
||||
22
fixtures/dom/src/components/fixtures/hydration/data.js
Normal file
22
fixtures/dom/src/components/fixtures/hydration/data.js
Normal file
@@ -0,0 +1,22 @@
|
||||
export const SAMPLE_CODE = `
|
||||
class Fixture extends React.Component {
|
||||
state = {
|
||||
value: 'asdf'
|
||||
}
|
||||
|
||||
onChange(event) {
|
||||
this.setState({ value: event.target.value });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { value } = this.state;
|
||||
|
||||
return (
|
||||
<form>
|
||||
<input value={value} onChange={this.onChange.bind(this)} />
|
||||
<p>Value: {value}</p>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
`.trim();
|
||||
68
fixtures/dom/src/components/fixtures/hydration/hydration.css
Normal file
68
fixtures/dom/src/components/fixtures/hydration/hydration.css
Normal file
@@ -0,0 +1,68 @@
|
||||
.hydration {
|
||||
background: #2f1e2e;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
height: calc(100vh - 40px); /* height of header */
|
||||
overflow: auto;
|
||||
padding-top: 32px;
|
||||
}
|
||||
|
||||
.hydration-options {
|
||||
background: #171717;
|
||||
border-top: 1px dashed rgba(215, 235, 255, 0.12);
|
||||
color: #def5ff;
|
||||
height: 32px;
|
||||
line-height: 28px;
|
||||
padding: 0 8px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.hydration-options label {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.hydration-options input[type=checkbox] {
|
||||
display: inline-block;
|
||||
margin-right: 4px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.hydration .CodeMirror {
|
||||
font-size: 13px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 68px;
|
||||
height: calc(100vh - 72px);
|
||||
width: 55%;
|
||||
}
|
||||
|
||||
.hydration-sandbox {
|
||||
background: white;
|
||||
border-radius: 2px;
|
||||
border: 0;
|
||||
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.54);
|
||||
height: calc(100% - 34px);
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 16px;
|
||||
width: calc(45% - 24px);
|
||||
}
|
||||
|
||||
.hydration-code-error {
|
||||
background: #df3f3f;
|
||||
border-radius: 2px;
|
||||
bottom: 18px;
|
||||
color: white;
|
||||
font-family: monospace;
|
||||
font-size: 13px;
|
||||
left: 16px;
|
||||
line-height: 1.25;
|
||||
overflow: auto;
|
||||
padding: 12px;
|
||||
position: fixed;
|
||||
white-space: pre;
|
||||
max-width: calc(55% - 26px);
|
||||
z-index: 10;
|
||||
}
|
||||
109
fixtures/dom/src/components/fixtures/hydration/index.js
Normal file
109
fixtures/dom/src/components/fixtures/hydration/index.js
Normal file
@@ -0,0 +1,109 @@
|
||||
import './hydration.css';
|
||||
import {SAMPLE_CODE} from './data';
|
||||
import {CodeEditor, CodeError} from './Code';
|
||||
import {compile} from './code-transformer';
|
||||
import {reactPaths} from '../../../react-loader';
|
||||
import qs from 'query-string';
|
||||
|
||||
const React = window.React;
|
||||
|
||||
class Hydration extends React.Component {
|
||||
state = {
|
||||
error: null,
|
||||
code: SAMPLE_CODE,
|
||||
hydrate: true,
|
||||
};
|
||||
|
||||
ready = false;
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('message', this.handleMessage);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('message', this.handleMessage);
|
||||
}
|
||||
|
||||
handleMessage = event => {
|
||||
var data = JSON.parse(event.data);
|
||||
|
||||
switch (data.type) {
|
||||
case 'ready':
|
||||
this.ready = true;
|
||||
this.injectCode();
|
||||
break;
|
||||
default:
|
||||
throw new Error(
|
||||
'Editor Error: Unrecognized message "' + data.type + '"'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
injectCode = () => {
|
||||
try {
|
||||
this.send({
|
||||
type: 'code',
|
||||
payload: compile(this.state.code),
|
||||
});
|
||||
|
||||
this.setState({error: null});
|
||||
} catch (error) {
|
||||
this.setState({error});
|
||||
}
|
||||
};
|
||||
|
||||
send = message => {
|
||||
if (this.ready) {
|
||||
this.frame.contentWindow.postMessage(JSON.stringify(message), '*');
|
||||
}
|
||||
};
|
||||
|
||||
setFrame = frame => {
|
||||
this.frame = frame;
|
||||
};
|
||||
|
||||
setCode = code => {
|
||||
this.setState({code}, this.injectCode);
|
||||
};
|
||||
|
||||
setCheckbox = event => {
|
||||
this.setState({
|
||||
[event.target.name]: event.target.checked,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const {code, error, hydrate} = this.state;
|
||||
const src = '/renderer.html?' + qs.stringify({hydrate, ...reactPaths()});
|
||||
|
||||
return (
|
||||
<div className="hydration">
|
||||
<header className="hydration-options">
|
||||
<label htmlFor="hydrate">
|
||||
<input
|
||||
id="hydrate"
|
||||
name="hydrate"
|
||||
type="checkbox"
|
||||
checked={hydrate}
|
||||
onChange={this.setCheckbox}
|
||||
/>
|
||||
Auto-Hydrate
|
||||
</label>
|
||||
</header>
|
||||
|
||||
<CodeEditor code={code} onChange={this.setCode} />
|
||||
|
||||
<CodeError error={error} className="hydration-code-error" />
|
||||
|
||||
<iframe
|
||||
ref={this.setFrame}
|
||||
className="hydration-sandbox"
|
||||
title="Hydration Preview"
|
||||
src={src}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Hydration;
|
||||
@@ -1,3 +1,5 @@
|
||||
import FixtureSet from '../../FixtureSet';
|
||||
|
||||
const React = window.React;
|
||||
|
||||
class RangeInputs extends React.Component {
|
||||
@@ -7,22 +9,26 @@ class RangeInputs extends React.Component {
|
||||
};
|
||||
render() {
|
||||
return (
|
||||
<form>
|
||||
<fieldset>
|
||||
<legend>Controlled</legend>
|
||||
<input
|
||||
type="range"
|
||||
value={this.state.value}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
<span className="hint">Value: {this.state.value}</span>
|
||||
</fieldset>
|
||||
<FixtureSet
|
||||
title="Range Inputs"
|
||||
description="Note: Range inputs are not supported in IE9.">
|
||||
<form>
|
||||
<fieldset>
|
||||
<legend>Controlled</legend>
|
||||
<input
|
||||
type="range"
|
||||
value={this.state.value}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
<span className="hint">Value: {this.state.value}</span>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Uncontrolled</legend>
|
||||
<input type="range" defaultValue={0.5} />
|
||||
</fieldset>
|
||||
</form>
|
||||
<fieldset>
|
||||
<legend>Uncontrolled</legend>
|
||||
<input type="range" defaultValue={0.5} />
|
||||
</fieldset>
|
||||
</form>
|
||||
</FixtureSet>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
321
fixtures/dom/src/components/fixtures/suspense/index.js
Normal file
321
fixtures/dom/src/components/fixtures/suspense/index.js
Normal file
@@ -0,0 +1,321 @@
|
||||
import Fixture from '../../Fixture';
|
||||
import FixtureSet from '../../FixtureSet';
|
||||
import TestCase from '../../TestCase';
|
||||
|
||||
const React = window.React;
|
||||
const ReactDOM = window.ReactDOM;
|
||||
|
||||
const Suspense = React.unstable_Suspense;
|
||||
|
||||
let cache = new Set();
|
||||
|
||||
function AsyncStep({text, ms}) {
|
||||
if (!cache.has(text)) {
|
||||
throw new Promise(resolve =>
|
||||
setTimeout(() => {
|
||||
cache.add(text);
|
||||
resolve();
|
||||
}, ms)
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
let suspendyTreeIdCounter = 0;
|
||||
class SuspendyTreeChild extends React.Component {
|
||||
id = suspendyTreeIdCounter++;
|
||||
state = {
|
||||
step: 1,
|
||||
isHidden: false,
|
||||
};
|
||||
increment = () => this.setState(s => ({step: s.step + 1}));
|
||||
|
||||
componentDidMount() {
|
||||
document.addEventListener('keydown', this.onKeydown);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('keydown', this.onKeydown);
|
||||
}
|
||||
|
||||
onKeydown = event => {
|
||||
if (event.metaKey && event.key === 'Enter') {
|
||||
this.increment();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Suspense fallback={<div>(display: none)</div>}>
|
||||
<div>
|
||||
<AsyncStep text={`${this.state.step} + ${this.id}`} ms={500} />
|
||||
{this.props.children}
|
||||
</div>
|
||||
</Suspense>
|
||||
<button onClick={this.increment}>Hide</button>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SuspendyTree extends React.Component {
|
||||
parentContainer = React.createRef(null);
|
||||
container = React.createRef(null);
|
||||
componentDidMount() {
|
||||
this.setState({});
|
||||
document.addEventListener('keydown', this.onKeydown);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('keydown', this.onKeydown);
|
||||
}
|
||||
onKeydown = event => {
|
||||
if (event.metaKey && event.key === '/') {
|
||||
this.removeAndRestore();
|
||||
}
|
||||
};
|
||||
removeAndRestore = () => {
|
||||
const parentContainer = this.parentContainer.current;
|
||||
const container = this.container.current;
|
||||
parentContainer.removeChild(container);
|
||||
parentContainer.textContent = '(removed from DOM)';
|
||||
setTimeout(() => {
|
||||
parentContainer.textContent = '';
|
||||
parentContainer.appendChild(container);
|
||||
}, 500);
|
||||
};
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div ref={this.parentContainer}>
|
||||
<div ref={this.container} />
|
||||
</div>
|
||||
<div>
|
||||
{this.container.current !== null
|
||||
? ReactDOM.createPortal(
|
||||
<React.Fragment>
|
||||
<SuspendyTreeChild>{this.props.children}</SuspendyTreeChild>
|
||||
<button onClick={this.removeAndRestore}>Remove</button>
|
||||
</React.Fragment>,
|
||||
this.container.current
|
||||
)
|
||||
: null}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TextInputFixtures extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<FixtureSet
|
||||
title="Suspense"
|
||||
description="Preserving the state of timed-out children">
|
||||
<p>
|
||||
Clicking "Hide" will hide the fixture context using{' '}
|
||||
<code>display: none</code> for 0.5 seconds, then restore. This is the
|
||||
built-in behavior for timed-out children. Each fixture tests whether
|
||||
the state of the DOM is preserved. Clicking "Remove" will remove the
|
||||
fixture content from the DOM for 0.5 seconds, then restore. This is{' '}
|
||||
<strong>not</strong> how timed-out children are hidden, but is
|
||||
included for comparison purposes.
|
||||
</p>
|
||||
<div className="footnote">
|
||||
As a shortcut, you can use Command + Enter (or Control + Enter on
|
||||
Windows, Linux) to "Hide" all the fixtures, or Command + / to "Remove"
|
||||
them.
|
||||
</div>
|
||||
<TestCase title="Text selection where entire range times out">
|
||||
<TestCase.Steps>
|
||||
<li>Use your cursor to select the text below.</li>
|
||||
<li>Click "Hide" or "Remove".</li>
|
||||
</TestCase.Steps>
|
||||
|
||||
<TestCase.ExpectedResult>
|
||||
Text selection is preserved when hiding, but not when removing.
|
||||
</TestCase.ExpectedResult>
|
||||
|
||||
<Fixture>
|
||||
<SuspendyTree>
|
||||
Select this entire sentence (and only this sentence).
|
||||
</SuspendyTree>
|
||||
</Fixture>
|
||||
</TestCase>
|
||||
<TestCase title="Text selection that extends outside timed-out subtree">
|
||||
<TestCase.Steps>
|
||||
<li>
|
||||
Use your cursor to select a range that includes both the text and
|
||||
the "Go" button.
|
||||
</li>
|
||||
<li>Click "Hide" or "Remove".</li>
|
||||
</TestCase.Steps>
|
||||
|
||||
<TestCase.ExpectedResult>
|
||||
Text selection is preserved when hiding, but not when removing.
|
||||
</TestCase.ExpectedResult>
|
||||
|
||||
<Fixture>
|
||||
<SuspendyTree>
|
||||
Select a range that includes both this sentence and the "Go"
|
||||
button.
|
||||
</SuspendyTree>
|
||||
</Fixture>
|
||||
</TestCase>
|
||||
<TestCase title="Focus">
|
||||
<TestCase.Steps>
|
||||
<li>
|
||||
Use your cursor to select a range that includes both the text and
|
||||
the "Go" button.
|
||||
</li>
|
||||
<li>
|
||||
Intead of clicking "Go", which switches focus, press Command +
|
||||
Enter (or Control + Enter on Windows, Linux).
|
||||
</li>
|
||||
</TestCase.Steps>
|
||||
|
||||
<TestCase.ExpectedResult>
|
||||
The ideal behavior is that the focus would not be lost, but
|
||||
currently it is (both when hiding and removing).
|
||||
</TestCase.ExpectedResult>
|
||||
|
||||
<Fixture>
|
||||
<SuspendyTree>
|
||||
<button>Focus me</button>
|
||||
</SuspendyTree>
|
||||
</Fixture>
|
||||
</TestCase>
|
||||
<TestCase title="Uncontrolled form input">
|
||||
<TestCase.Steps>
|
||||
<li>Type something ("Hello") into the text input.</li>
|
||||
<li>Click "Hide" or "Remove".</li>
|
||||
</TestCase.Steps>
|
||||
|
||||
<TestCase.ExpectedResult>
|
||||
Input is preserved when hiding, but not when removing.
|
||||
</TestCase.ExpectedResult>
|
||||
|
||||
<Fixture>
|
||||
<SuspendyTree>
|
||||
<input type="text" />
|
||||
</SuspendyTree>
|
||||
</Fixture>
|
||||
</TestCase>
|
||||
<TestCase title="Image flicker">
|
||||
<TestCase.Steps>
|
||||
<li>Click "Hide" or "Remove".</li>
|
||||
</TestCase.Steps>
|
||||
|
||||
<TestCase.ExpectedResult>
|
||||
The image should reappear without flickering. The text should not
|
||||
reflow.
|
||||
</TestCase.ExpectedResult>
|
||||
|
||||
<Fixture>
|
||||
<SuspendyTree>
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/e/ee/Atom_%282%29.png" />React
|
||||
is cool
|
||||
</SuspendyTree>
|
||||
</Fixture>
|
||||
</TestCase>
|
||||
<TestCase title="Iframe">
|
||||
<TestCase.Steps>
|
||||
<li>
|
||||
The iframe shows a nested version of this fixtures app. Navigate
|
||||
to the "Text inputs" page.
|
||||
</li>
|
||||
<li>Select one of the checkboxes.</li>
|
||||
<li>Click "Hide" or "Remove".</li>
|
||||
</TestCase.Steps>
|
||||
|
||||
<TestCase.ExpectedResult>
|
||||
When removing, the iframe is reloaded. When hiding, the iframe
|
||||
should still be on the "Text inputs" page. The checkbox should still
|
||||
be checked. (Unfortunately, scroll position is lost.)
|
||||
</TestCase.ExpectedResult>
|
||||
|
||||
<Fixture>
|
||||
<SuspendyTree>
|
||||
<iframe width="500" height="300" src="/" />
|
||||
</SuspendyTree>
|
||||
</Fixture>
|
||||
</TestCase>
|
||||
<TestCase title="Video playback">
|
||||
<TestCase.Steps>
|
||||
<li>Start playing the video, or seek to a specific position.</li>
|
||||
<li>Click "Hide" or "Remove".</li>
|
||||
</TestCase.Steps>
|
||||
|
||||
<TestCase.ExpectedResult>
|
||||
The playback position should stay the same. When hiding, the video
|
||||
plays in the background for the entire duration. When removing, the
|
||||
video stops playing, but the position is not lost.
|
||||
</TestCase.ExpectedResult>
|
||||
|
||||
<Fixture>
|
||||
<SuspendyTree>
|
||||
<video controls>
|
||||
<source
|
||||
src="http://techslides.com/demos/sample-videos/small.webm"
|
||||
type="video/webm"
|
||||
/>
|
||||
<source
|
||||
src="http://techslides.com/demos/sample-videos/small.ogv"
|
||||
type="video/ogg"
|
||||
/>
|
||||
<source
|
||||
src="http://techslides.com/demos/sample-videos/small.mp4"
|
||||
type="video/mp4"
|
||||
/>
|
||||
<source
|
||||
src="http://techslides.com/demos/sample-videos/small.3gp"
|
||||
type="video/3gp"
|
||||
/>
|
||||
</video>
|
||||
</SuspendyTree>
|
||||
</Fixture>
|
||||
</TestCase>
|
||||
<TestCase title="Audio playback">
|
||||
<TestCase.Steps>
|
||||
<li>Start playing the audio, or seek to a specific position.</li>
|
||||
<li>Click "Hide" or "Remove".</li>
|
||||
</TestCase.Steps>
|
||||
|
||||
<TestCase.ExpectedResult>
|
||||
The playback position should stay the same. When hiding, the audio
|
||||
plays in the background for the entire duration. When removing, the
|
||||
audio stops playing, but the position is not lost.
|
||||
</TestCase.ExpectedResult>
|
||||
<Fixture>
|
||||
<SuspendyTree>
|
||||
<audio controls={true}>
|
||||
<source src="https://upload.wikimedia.org/wikipedia/commons/e/ec/Mozart_K448.ogg" />
|
||||
</audio>
|
||||
</SuspendyTree>
|
||||
</Fixture>
|
||||
</TestCase>
|
||||
<TestCase title="Scroll position">
|
||||
<TestCase.Steps>
|
||||
<li>Scroll to a position in the list.</li>
|
||||
<li>Click "Hide" or "Remove".</li>
|
||||
</TestCase.Steps>
|
||||
|
||||
<TestCase.ExpectedResult>
|
||||
Scroll position is preserved when hiding, but not when removing.
|
||||
</TestCase.ExpectedResult>
|
||||
<Fixture>
|
||||
<SuspendyTree>
|
||||
<div style={{height: 200, overflow: 'scroll'}}>
|
||||
{Array(20)
|
||||
.fill()
|
||||
.map((_, i) => <h2 key={i}>{i + 1}</h2>)}
|
||||
</div>
|
||||
</SuspendyTree>
|
||||
</Fixture>
|
||||
</TestCase>
|
||||
</FixtureSet>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TextInputFixtures;
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'core-js/es6/symbol';
|
||||
import 'core-js/es6/promise';
|
||||
import 'core-js/es6/set';
|
||||
import 'core-js/es6/map';
|
||||
|
||||
31
fixtures/dom/src/react-loader.js
vendored
31
fixtures/dom/src/react-loader.js
vendored
@@ -36,9 +36,10 @@ function loadScript(src) {
|
||||
});
|
||||
}
|
||||
|
||||
export default function loadReact() {
|
||||
let REACT_PATH = 'react.development.js';
|
||||
let DOM_PATH = 'react-dom.development.js';
|
||||
export function reactPaths() {
|
||||
let reactPath = 'react.development.js';
|
||||
let reactDOMPath = 'react-dom.development.js';
|
||||
let reactDOMServerPath = 'react-dom-server.browser.development.js';
|
||||
|
||||
let query = parseQuery(window.location.search);
|
||||
let version = query.version || 'local';
|
||||
@@ -49,25 +50,37 @@ export default function loadReact() {
|
||||
// The file structure was updated in 16. This wasn't the case for alphas.
|
||||
// Load the old module location for anything less than 16 RC
|
||||
if (major >= 16 && !(minor === 0 && preReleaseStage === 'alpha')) {
|
||||
REACT_PATH =
|
||||
reactPath =
|
||||
'https://unpkg.com/react@' + version + '/umd/react.development.js';
|
||||
DOM_PATH =
|
||||
reactDOMPath =
|
||||
'https://unpkg.com/react-dom@' +
|
||||
version +
|
||||
'/umd/react-dom.development.js';
|
||||
reactDOMServerPath =
|
||||
'https://unpkg.com/react-dom@' +
|
||||
version +
|
||||
'/umd/react-dom-server.browser.development';
|
||||
} else {
|
||||
REACT_PATH = 'https://unpkg.com/react@' + version + '/dist/react.js';
|
||||
DOM_PATH =
|
||||
reactPath = 'https://unpkg.com/react@' + version + '/dist/react.js';
|
||||
reactDOMPath =
|
||||
'https://unpkg.com/react-dom@' + version + '/dist/react-dom.js';
|
||||
reactDOMServerPath =
|
||||
'https://unpkg.com/react-dom@' + version + '/dist/react-dom-server.js';
|
||||
}
|
||||
}
|
||||
|
||||
const needsReactDOM = version === 'local' || parseFloat(version, 10) > 0.13;
|
||||
|
||||
let request = loadScript(REACT_PATH);
|
||||
return {reactPath, reactDOMPath, reactDOMServerPath, needsReactDOM};
|
||||
}
|
||||
|
||||
export default function loadReact() {
|
||||
const {reactPath, reactDOMPath, needsReactDOM} = reactPaths();
|
||||
|
||||
let request = loadScript(reactPath);
|
||||
|
||||
if (needsReactDOM) {
|
||||
request = request.then(() => loadScript(DOM_PATH));
|
||||
request = request.then(() => loadScript(reactDOMPath));
|
||||
} else {
|
||||
// Aliasing React to ReactDOM for compatibility.
|
||||
request = request.then(() => {
|
||||
|
||||
@@ -79,7 +79,6 @@ textarea {
|
||||
|
||||
.header {
|
||||
background: #171717;
|
||||
box-shadow: inset 0 -1px 3px #000;
|
||||
overflow: hidden;
|
||||
padding: 8px;
|
||||
}
|
||||
@@ -102,7 +101,6 @@ textarea {
|
||||
.header__inner {
|
||||
display: table;
|
||||
margin: 0 auto;
|
||||
max-width: 1000px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/standalone@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.0.0.tgz#856446641620c1c5f0ca775621d478324ebd1f52"
|
||||
|
||||
abab@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d"
|
||||
@@ -1556,6 +1560,10 @@ code-point-at@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
|
||||
codemirror@^5.40.0:
|
||||
version "5.40.0"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.40.0.tgz#2f5ed47366e514f41349ba0fe34daaa39be4e257"
|
||||
|
||||
color-convert@^1.3.0:
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.8.2.tgz#be868184d7c8631766d54e7078e2672d7c7e3339"
|
||||
|
||||
@@ -42,51 +42,51 @@
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>browserify (dev)</h2>
|
||||
<iframe src="/fixtures/packaging/browserify/dev/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/browserify/dev/"></iframe>
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>browserify (prod)</h2>
|
||||
<iframe src="/fixtures/packaging/browserify/prod/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/browserify/prod/"></iframe>
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>brunch (dev)</h2>
|
||||
<iframe src="/fixtures/packaging/brunch/dev/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/brunch/dev/"></iframe>
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>brunch (prod)</h2>
|
||||
<iframe src="/fixtures/packaging/brunch/prod/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/brunch/prod/"></iframe>
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>rjs (dev)</h2>
|
||||
<iframe src="/fixtures/packaging/rjs/dev/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/rjs/dev/"></iframe>
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>rjs (prod)</h2>
|
||||
<iframe src="/fixtures/packaging/rjs/prod/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/rjs/prod/"></iframe>
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>systemjs-builder (dev)</h2>
|
||||
<iframe src="/fixtures/packaging/systemjs-builder/dev/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/systemjs-builder/dev/"></iframe>
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>systemjs-builder (prod)</h2>
|
||||
<iframe src="/fixtures/packaging/systemjs-builder/prod/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/systemjs-builder/prod/"></iframe>
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>webpack (dev)</h2>
|
||||
<iframe src="/fixtures/packaging/webpack/dev/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/webpack/dev/"></iframe>
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>webpack (prod)</h2>
|
||||
<iframe src="/fixtures/packaging/webpack/prod/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/webpack/prod/"></iframe>
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>webpack-alias (dev)</h2>
|
||||
<iframe src="/fixtures/packaging/webpack-alias/dev/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/webpack-alias/dev/"></iframe>
|
||||
</div>
|
||||
<div class="frame">
|
||||
<h2>webpack-alias (prod)</h2>
|
||||
<iframe src="/fixtures/packaging/webpack-alias/prod/index.html"></iframe>
|
||||
<iframe src="/fixtures/packaging/webpack-alias/prod/"></iframe>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,8 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html style="width: 100%; height: 100%;">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Schedule Test Page</title>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Scheduler Test Page</title>
|
||||
<style>
|
||||
.correct {
|
||||
border: solid green 2px;
|
||||
@@ -11,92 +12,94 @@
|
||||
border: dashed red 2px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Schedule Fixture</h1>
|
||||
<p>
|
||||
This fixture is for manual testing purposes, and the patterns used in
|
||||
implementing it should not be used as a model. This is mainly for anyone
|
||||
working on making changes to the `schedule` module.
|
||||
</p>
|
||||
<h2>Tests:</h2>
|
||||
<ol>
|
||||
<li>
|
||||
<button onClick="runTestOne()">Run Test 1</button>
|
||||
<p>Calls the callback within the frame when not blocked:</p>
|
||||
<div><b>Expected:</b></div>
|
||||
<div id="test-1-expected">
|
||||
</div>
|
||||
<div> -------------------------------------------------</div>
|
||||
<div> If you see the same above and below it's correct.
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Scheduler Fixture</h1>
|
||||
<p>
|
||||
This fixture is for manual testing purposes, and the patterns used in
|
||||
implementing it should not be used as a model. This is mainly for anyone
|
||||
working on making changes to the `schedule` module.
|
||||
</p>
|
||||
<h2>Tests:</h2>
|
||||
<ol>
|
||||
<li>
|
||||
<button onClick="runTestOne()">Run Test 1</button>
|
||||
<p>Calls the callback within the frame when not blocked:</p>
|
||||
<div><b>Expected:</b></div>
|
||||
<div id="test-1-expected">
|
||||
</div>
|
||||
<div> -------------------------------------------------</div>
|
||||
<div> If you see the same above and below it's correct.
|
||||
<div> -------------------------------------------------</div>
|
||||
<div><b>Actual:</b></div>
|
||||
<div id="test-1"></div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Accepts multiple callbacks and calls within frame when not blocked</p>
|
||||
<button onClick="runTestTwo()">Run Test 2</button>
|
||||
<div><b>Expected:</b></div>
|
||||
<div id="test-2-expected">
|
||||
</div>
|
||||
<div> -------------------------------------------------</div>
|
||||
<div> If you see the same above and below it's correct.
|
||||
</li>
|
||||
<li>
|
||||
<p>Accepts multiple callbacks and calls within frame when not blocked</p>
|
||||
<button onClick="runTestTwo()">Run Test 2</button>
|
||||
<div><b>Expected:</b></div>
|
||||
<div id="test-2-expected">
|
||||
</div>
|
||||
<div> -------------------------------------------------</div>
|
||||
<div> If you see the same above and below it's correct.
|
||||
<div> -------------------------------------------------</div>
|
||||
<div><b>Actual:</b></div>
|
||||
<div id="test-2"></div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Schedules callbacks in correct order when they use scheduleWork to schedule themselves</p>
|
||||
<button onClick="runTestThree()">Run Test 3</button>
|
||||
<div><b>Expected:</b></div>
|
||||
<div id="test-3-expected">
|
||||
</div>
|
||||
<div> -------------------------------------------------</div>
|
||||
<div> If you see the same above and below it's correct.
|
||||
</li>
|
||||
<li>
|
||||
<p>Schedules callbacks in correct order when they use scheduleWork to schedule themselves</p>
|
||||
<button onClick="runTestThree()">Run Test 3</button>
|
||||
<div><b>Expected:</b></div>
|
||||
<div id="test-3-expected">
|
||||
</div>
|
||||
<div> -------------------------------------------------</div>
|
||||
<div> If you see the same above and below it's correct.
|
||||
<div> -------------------------------------------------</div>
|
||||
<div><b>Actual:</b></div>
|
||||
<div id="test-3"></div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Calls timed out callbacks and then any more pending callbacks, defers others if time runs out</p>
|
||||
<button onClick="runTestFour()">Run Test 4</button>
|
||||
<div><b>Expected:</b></div>
|
||||
<div id="test-4-expected">
|
||||
</div>
|
||||
<div> -------------------------------------------------</div>
|
||||
<div> If you see the same above and below it's correct.
|
||||
</li>
|
||||
<li>
|
||||
<p>Calls timed out callbacks and then any more pending callbacks, defers others if time runs out</p>
|
||||
<button onClick="runTestFour()">Run Test 4</button>
|
||||
<div><b>Expected:</b></div>
|
||||
<div id="test-4-expected">
|
||||
</div>
|
||||
<div> -------------------------------------------------</div>
|
||||
<div> If you see the same above and below it's correct.
|
||||
<div> -------------------------------------------------</div>
|
||||
<div><b>Actual:</b></div>
|
||||
<div id="test-4"></div>
|
||||
</li>
|
||||
<li>
|
||||
<p>When some callbacks throw errors, still calls them all within the same frame</p>
|
||||
<p><b>IMPORTANT:</b> Open the console when you run this! Inspect the logs there!</p>
|
||||
<button onClick="runTestFive()">Run Test 5</button>
|
||||
</li>
|
||||
<li>
|
||||
<p>When some callbacks throw errors <b> and some also time out</b>, still calls them all within the same frame</p>
|
||||
<p><b>IMPORTANT:</b> Open the console when you run this! Inspect the logs there!</p>
|
||||
<button onClick="runTestSix()">Run Test 6</button>
|
||||
</li>
|
||||
<li>
|
||||
<p>Continues calling callbacks even when user switches away from this tab</p>
|
||||
<button onClick="runTestSeven()">Run Test 7</button>
|
||||
<div><b>Click the button above, observe the counter, then switch to
|
||||
another tab and switch back:</b></div>
|
||||
<div id="test-7">
|
||||
</div>
|
||||
<div> If the counter advanced while you were away from this tab, it's correct.</div>
|
||||
</li>
|
||||
</ol>
|
||||
<script src="../../build/dist/schedule.development.js"></script>
|
||||
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
|
||||
<script type="text/babel">
|
||||
</li>
|
||||
<li>
|
||||
<p>When some callbacks throw errors, still calls them all within the same frame</p>
|
||||
<p><b>IMPORTANT:</b> Open the console when you run this! Inspect the logs there!</p>
|
||||
<button onClick="runTestFive()">Run Test 5</button>
|
||||
</li>
|
||||
<li>
|
||||
<p>When some callbacks throw errors <b> and some also time out</b>, still calls them all within the same frame</p>
|
||||
<p><b>IMPORTANT:</b> Open the console when you run this! Inspect the logs there!</p>
|
||||
<button onClick="runTestSix()">Run Test 6</button>
|
||||
</li>
|
||||
<li>
|
||||
<p>Continues calling callbacks even when user switches away from this tab</p>
|
||||
<button onClick="runTestSeven()">Run Test 7</button>
|
||||
<div><b>Click the button above, observe the counter, then switch to
|
||||
another tab and switch back:</b></div>
|
||||
<div id="test-7">
|
||||
</div>
|
||||
<div> If the counter advanced while you were away from this tab, it's correct.</div>
|
||||
</li>
|
||||
</ol>
|
||||
<script src="../../build/dist/react.development.js"></script>
|
||||
<script src="../../build/node_modules/scheduler/umd/scheduler.development.js"></script>
|
||||
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
|
||||
<script type="text/babel">
|
||||
const {
|
||||
unstable_scheduleWork: scheduleWork,
|
||||
unstable_cancelWork: cancelWork,
|
||||
unstable_scheduleCallback: scheduleCallback,
|
||||
unstable_cancelCallback: cancelCallback,
|
||||
unstable_now: now
|
||||
} = Schedule;
|
||||
} = Scheduler;
|
||||
function displayTestResult(testNumber) {
|
||||
const expectationNode = document.getElementById('test-' + testNumber + '-expected');
|
||||
const resultNode = document.getElementById('test-' + testNumber);
|
||||
@@ -495,4 +498,4 @@ function runTestSeven() {
|
||||
}
|
||||
</script type="text/babel">
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -2,7 +2,7 @@
|
||||
<html style="width: 100%; height: 100%;">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test tracking UMD</title>
|
||||
<title>Test tracing UMD</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
@@ -36,9 +36,9 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Test tracking UMD</h1>
|
||||
<h1>Test tracing UMD</h1>
|
||||
<p>
|
||||
This fixture tests that the new tracking API is accessible via UMD build using the UMD shim.
|
||||
This fixture tests that the new tracing API is accessible via UMD build using the UMD shim.
|
||||
It does not exhaustively test API functionality, only that the forwarded methods can be called.
|
||||
</p>
|
||||
<p>
|
||||
@@ -52,19 +52,19 @@
|
||||
<li id="checkSchedulerAPI" data-value="...">
|
||||
<strong>Test scheduler API</strong>
|
||||
</li>
|
||||
<li id="checkSchedulerTrackingAPI" data-value="...">
|
||||
<strong>Test tracking API</strong>
|
||||
<li id="checkSchedulerTracingAPI" data-value="...">
|
||||
<strong>Test tracing API</strong>
|
||||
</li>
|
||||
<li id="checkSchedulerTrackingSubscriptionsAPI" data-value="...">
|
||||
<strong>Test tracking subscriptions API</strong>
|
||||
<li id="checkSchedulerTracingSubscriptionsAPI" data-value="...">
|
||||
<strong>Test tracing subscriptions API</strong>
|
||||
</li>
|
||||
<li id="checkEndToEndIntegration" data-value="...">
|
||||
<strong>Test end-to-end integration</strong>
|
||||
</li>
|
||||
</ol>
|
||||
<!-- Load the tracking API before react to test that it's lazily evaluated -->
|
||||
<script src="../../build/node_modules/schedule/umd/schedule.development.js"></script>
|
||||
<script src="../../build/node_modules/schedule/umd/schedule-tracking.development.js"></script>
|
||||
<!-- Load the tracing API before react to test that it's lazily evaluated -->
|
||||
<script src="../../build/node_modules/scheduler/umd/scheduler.development.js"></script>
|
||||
<script src="../../build/node_modules/scheduler/umd/scheduler-tracing.development.js"></script>
|
||||
<script src="../../build/node_modules/react/umd/react.development.js"></script>
|
||||
<script src="../../build/node_modules/react-dom/umd/react-dom.development.js"></script>
|
||||
<script src="./script.js"></script>
|
||||
@@ -14,10 +14,10 @@ function runAllTests() {
|
||||
checkSchedulerAPI();
|
||||
} finally {
|
||||
try {
|
||||
checkSchedulerTrackingAPI();
|
||||
checkSchedulerTracingAPI();
|
||||
} finally {
|
||||
try {
|
||||
checkSchedulerTrackingSubscriptionsAPI();
|
||||
checkSchedulerTracingSubscriptionsAPI();
|
||||
} finally {
|
||||
checkEndToEndIntegration();
|
||||
}
|
||||
@@ -28,15 +28,15 @@ function runAllTests() {
|
||||
function checkSchedulerAPI() {
|
||||
runTest(document.getElementById('checkSchedulerAPI'), () => {
|
||||
if (
|
||||
typeof Schedule === 'undefined' ||
|
||||
typeof Schedule.unstable_now !== 'function' ||
|
||||
typeof Schedule.unstable_scheduleWork !== 'function' ||
|
||||
typeof Schedule.unstable_cancelScheduledWork !== 'function'
|
||||
typeof Scheduler === 'undefined' ||
|
||||
typeof Scheduler.unstable_now !== 'function' ||
|
||||
typeof Scheduler.unstable_scheduleCallback !== 'function' ||
|
||||
typeof Scheduler.unstable_cancelCallback !== 'function'
|
||||
) {
|
||||
throw 'API is not defined';
|
||||
}
|
||||
|
||||
if (Schedule.unstable_now() !== performance.now()) {
|
||||
if (Scheduler.unstable_now() !== performance.now()) {
|
||||
throw 'API does not work';
|
||||
}
|
||||
|
||||
@@ -44,23 +44,23 @@ function checkSchedulerAPI() {
|
||||
});
|
||||
}
|
||||
|
||||
function checkSchedulerTrackingAPI() {
|
||||
runTest(document.getElementById('checkSchedulerTrackingAPI'), () => {
|
||||
function checkSchedulerTracingAPI() {
|
||||
runTest(document.getElementById('checkSchedulerTracingAPI'), () => {
|
||||
if (
|
||||
typeof ScheduleTracking === 'undefined' ||
|
||||
typeof ScheduleTracking.unstable_clear !== 'function' ||
|
||||
typeof ScheduleTracking.unstable_getCurrent !== 'function' ||
|
||||
typeof ScheduleTracking.unstable_getThreadID !== 'function' ||
|
||||
typeof ScheduleTracking.unstable_track !== 'function' ||
|
||||
typeof ScheduleTracking.unstable_wrap !== 'function'
|
||||
typeof SchedulerTracing === 'undefined' ||
|
||||
typeof SchedulerTracing.unstable_clear !== 'function' ||
|
||||
typeof SchedulerTracing.unstable_getCurrent !== 'function' ||
|
||||
typeof SchedulerTracing.unstable_getThreadID !== 'function' ||
|
||||
typeof SchedulerTracing.unstable_trace !== 'function' ||
|
||||
typeof SchedulerTracing.unstable_wrap !== 'function'
|
||||
) {
|
||||
throw 'API is not defined';
|
||||
}
|
||||
|
||||
try {
|
||||
let interactionsSet;
|
||||
ScheduleTracking.unstable_track('test', 123, () => {
|
||||
interactionsSet = ScheduleTracking.unstable_getCurrent();
|
||||
SchedulerTracing.unstable_trace('test', 123, () => {
|
||||
interactionsSet = SchedulerTracing.unstable_getCurrent();
|
||||
});
|
||||
if (interactionsSet.size !== 1) {
|
||||
throw null;
|
||||
@@ -73,32 +73,32 @@ function checkSchedulerTrackingAPI() {
|
||||
throw 'API does not work';
|
||||
}
|
||||
|
||||
const ForwardedSchedulerTracking =
|
||||
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ScheduleTracking;
|
||||
const ForwardedSchedulerTracing =
|
||||
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.SchedulerTracing;
|
||||
|
||||
if (
|
||||
ScheduleTracking.unstable_getThreadID() ===
|
||||
ForwardedSchedulerTracking.unstable_getThreadID()
|
||||
SchedulerTracing.unstable_getThreadID() ===
|
||||
ForwardedSchedulerTracing.unstable_getThreadID()
|
||||
) {
|
||||
throw 'API forwarding is broken';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function checkSchedulerTrackingSubscriptionsAPI() {
|
||||
function checkSchedulerTracingSubscriptionsAPI() {
|
||||
runTest(
|
||||
document.getElementById('checkSchedulerTrackingSubscriptionsAPI'),
|
||||
document.getElementById('checkSchedulerTracingSubscriptionsAPI'),
|
||||
() => {
|
||||
if (
|
||||
typeof ScheduleTracking === 'undefined' ||
|
||||
typeof ScheduleTracking.unstable_subscribe !== 'function' ||
|
||||
typeof ScheduleTracking.unstable_unsubscribe !== 'function'
|
||||
typeof SchedulerTracing === 'undefined' ||
|
||||
typeof SchedulerTracing.unstable_subscribe !== 'function' ||
|
||||
typeof SchedulerTracing.unstable_unsubscribe !== 'function'
|
||||
) {
|
||||
throw 'API is not defined';
|
||||
}
|
||||
|
||||
const onInteractionScheduledWorkCompletedCalls = [];
|
||||
const onInteractionTrackedCalls = [];
|
||||
const onInteractionTracedCalls = [];
|
||||
const onWorkCanceledCalls = [];
|
||||
const onWorkScheduledCalls = [];
|
||||
const onWorkStartedCalls = [];
|
||||
@@ -106,7 +106,7 @@ function checkSchedulerTrackingSubscriptionsAPI() {
|
||||
const subscriber = {
|
||||
onInteractionScheduledWorkCompleted: (...args) =>
|
||||
onInteractionScheduledWorkCompletedCalls.push(args),
|
||||
onInteractionTracked: (...args) => onInteractionTrackedCalls.push(args),
|
||||
onInteractionTraced: (...args) => onInteractionTracedCalls.push(args),
|
||||
onWorkCanceled: (...args) => onWorkCanceledCalls.push(args),
|
||||
onWorkScheduled: (...args) => onWorkScheduledCalls.push(args),
|
||||
onWorkStarted: (...args) => onWorkStartedCalls.push(args),
|
||||
@@ -114,38 +114,38 @@ function checkSchedulerTrackingSubscriptionsAPI() {
|
||||
};
|
||||
|
||||
try {
|
||||
ScheduleTracking.unstable_subscribe(subscriber);
|
||||
ScheduleTracking.unstable_track('foo', 123, () => {});
|
||||
ScheduleTracking.unstable_unsubscribe(subscriber);
|
||||
if (onInteractionTrackedCalls.length !== 1) {
|
||||
SchedulerTracing.unstable_subscribe(subscriber);
|
||||
SchedulerTracing.unstable_trace('foo', 123, () => {});
|
||||
SchedulerTracing.unstable_unsubscribe(subscriber);
|
||||
if (onInteractionTracedCalls.length !== 1) {
|
||||
throw null;
|
||||
}
|
||||
const interaction = onInteractionTrackedCalls[0][0];
|
||||
const interaction = onInteractionTracedCalls[0][0];
|
||||
if (interaction.name !== 'foo' || interaction.timestamp !== 123) {
|
||||
throw null;
|
||||
}
|
||||
ScheduleTracking.unstable_track('bar', 456, () => {});
|
||||
if (onInteractionTrackedCalls.length !== 1) {
|
||||
SchedulerTracing.unstable_trace('bar', 456, () => {});
|
||||
if (onInteractionTracedCalls.length !== 1) {
|
||||
throw null;
|
||||
}
|
||||
} catch (error) {
|
||||
throw 'API does not forward methods';
|
||||
}
|
||||
|
||||
const ForwardedSchedulerTracking =
|
||||
const ForwardedSchedulerTracing =
|
||||
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
|
||||
.ScheduleTracking;
|
||||
.SchedulerTracing;
|
||||
|
||||
try {
|
||||
ForwardedSchedulerTracking.unstable_subscribe(subscriber);
|
||||
ScheduleTracking.unstable_track('foo', 123, () => {});
|
||||
ForwardedSchedulerTracking.unstable_track('bar', 456, () => {});
|
||||
ScheduleTracking.unstable_unsubscribe(subscriber);
|
||||
if (onInteractionTrackedCalls.length !== 3) {
|
||||
ForwardedSchedulerTracing.unstable_subscribe(subscriber);
|
||||
SchedulerTracing.unstable_trace('foo', 123, () => {});
|
||||
ForwardedSchedulerTracing.unstable_trace('bar', 456, () => {});
|
||||
SchedulerTracing.unstable_unsubscribe(subscriber);
|
||||
if (onInteractionTracedCalls.length !== 3) {
|
||||
throw null;
|
||||
}
|
||||
const interactionFoo = onInteractionTrackedCalls[1][0];
|
||||
const interactionBar = onInteractionTrackedCalls[2][0];
|
||||
const interactionFoo = onInteractionTracedCalls[1][0];
|
||||
const interactionBar = onInteractionTracedCalls[2][0];
|
||||
if (
|
||||
interactionFoo.name !== 'foo' ||
|
||||
interactionFoo.timestamp !== 123 ||
|
||||
@@ -154,8 +154,8 @@ function checkSchedulerTrackingSubscriptionsAPI() {
|
||||
) {
|
||||
throw null;
|
||||
}
|
||||
ForwardedSchedulerTracking.unstable_track('baz', 789, () => {});
|
||||
if (onInteractionTrackedCalls.length !== 3) {
|
||||
ForwardedSchedulerTracing.unstable_trace('baz', 789, () => {});
|
||||
if (onInteractionTracedCalls.length !== 3) {
|
||||
throw null;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -172,7 +172,7 @@ function checkEndToEndIntegration() {
|
||||
const onRender = (...args) => onRenderCalls.push(args);
|
||||
const container = document.createElement('div');
|
||||
|
||||
ScheduleTracking.unstable_track('render', 123, () => {
|
||||
SchedulerTracing.unstable_trace('render', 123, () => {
|
||||
ReactDOM.render(
|
||||
React.createElement(
|
||||
React.unstable_Profiler,
|
||||
21
fixtures/tracing/test.html
Normal file
21
fixtures/tracing/test.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html style="width: 100%; height: 100%;">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test tracing UMD</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<!-- Load the tracing API before react to test that it's lazily evaluated -->
|
||||
<script src="../../build/node_modules/scheduler/umd/scheduler.development.js"></script>
|
||||
<script src="../../build/node_modules/scheduler/umd/scheduler-tracing.development.js"></script>
|
||||
<script src="../../build/node_modules/react/umd/react.development.js"></script>
|
||||
<script src="../../build/node_modules/react-dom/umd/react-dom.development.js"></script>
|
||||
<script src="./test.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
103
fixtures/tracing/test.js
Normal file
103
fixtures/tracing/test.js
Normal file
@@ -0,0 +1,103 @@
|
||||
const {createElement, Component, Placeholder} = React;
|
||||
const {unstable_createRoot: createRoot} = ReactDOM;
|
||||
const {
|
||||
unstable_subscribe: subscribe,
|
||||
unstable_trace: trace,
|
||||
unstable_wrap: wrap,
|
||||
} = SchedulerTracing;
|
||||
|
||||
const createLogger = (backgroundColor, color, enabled) => (
|
||||
message,
|
||||
...args
|
||||
) => {
|
||||
if (enabled === false) return;
|
||||
console.groupCollapsed(
|
||||
`%c${message}`,
|
||||
`background-color: ${backgroundColor}; color: ${color}; padding: 2px 4px;`,
|
||||
...args
|
||||
);
|
||||
console.log(
|
||||
new Error('stack').stack
|
||||
.split('\n')
|
||||
.slice(2)
|
||||
.join('\n')
|
||||
);
|
||||
console.groupEnd();
|
||||
};
|
||||
|
||||
window.log = {
|
||||
app: createLogger('#37474f', '#fff'),
|
||||
interaction: createLogger('#6a1b9a', '#fff'),
|
||||
react: createLogger('#ff5722', '#fff'),
|
||||
tracing: createLogger('#2962ff', '#fff'),
|
||||
work: createLogger('#e1bee7', '#000'),
|
||||
};
|
||||
|
||||
// Fake suspense
|
||||
const resolvedValues = {};
|
||||
const read = key => {
|
||||
if (!resolvedValues[key]) {
|
||||
log.app(`Suspending for "${key}" ...`);
|
||||
throw new Promise(
|
||||
wrap(resolve => {
|
||||
setTimeout(
|
||||
wrap(() => {
|
||||
log.app(`Loaded "${key}" ...`);
|
||||
resolvedValues[key] = true;
|
||||
resolve(key);
|
||||
}),
|
||||
1000
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
return key;
|
||||
};
|
||||
|
||||
const TestApp = () =>
|
||||
createElement(
|
||||
Placeholder,
|
||||
{delayMs: 100, fallback: createElement(PlaceholderText)},
|
||||
createElement(SuspendingChild, {text: 'foo'}),
|
||||
createElement(SuspendingChild, {text: 'bar'}),
|
||||
createElement(SuspendingChild, {text: 'baz'})
|
||||
);
|
||||
|
||||
const PlaceholderText = () => 'Loading ...';
|
||||
|
||||
const SuspendingChild = ({text}) => {
|
||||
const resolvedValue = read(text);
|
||||
return resolvedValue;
|
||||
};
|
||||
|
||||
subscribe({
|
||||
onInteractionScheduledWorkCompleted: interaction =>
|
||||
log.interaction(
|
||||
'onInteractionScheduledWorkCompleted',
|
||||
JSON.stringify(interaction)
|
||||
),
|
||||
onInteractionTraced: interaction =>
|
||||
log.interaction('onInteractionTraced', JSON.stringify(interaction)),
|
||||
onWorkCanceled: interactions =>
|
||||
log.work('onWorkCanceled', JSON.stringify(Array.from(interactions))),
|
||||
onWorkScheduled: interactions =>
|
||||
log.work('onWorkScheduled', JSON.stringify(Array.from(interactions))),
|
||||
onWorkStarted: interactions =>
|
||||
log.work('onWorkStarted', JSON.stringify(Array.from(interactions))),
|
||||
onWorkStopped: interactions =>
|
||||
log.work('onWorkStopped', JSON.stringify(Array.from(interactions))),
|
||||
});
|
||||
|
||||
const element = document.getElementById('root');
|
||||
trace('initial_render', performance.now(), () => {
|
||||
const root = createRoot(element);
|
||||
const batch = root.createBatch();
|
||||
log.app('batch.render()');
|
||||
batch.render(createElement(TestApp));
|
||||
batch.then(
|
||||
wrap(() => {
|
||||
log.app('batch.commit()');
|
||||
batch.commit();
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -14,19 +14,13 @@ No. The APIs being tested here are unstable and some of them have still not been
|
||||
|
||||
Clone the React repository.
|
||||
|
||||
First, open this file locally:
|
||||
|
||||
* `packages/shared/ReactFeatureFlags.js` (make sure you didn't open a similarly named file!)
|
||||
|
||||
Set [the `enableSuspense` flag](https://github.com/facebook/react/blob/d79238f1eeb6634ba7a3df23c3b2709b56cbb8b2/packages/shared/ReactFeatureFlags.js#L19) to `true` and save the file.
|
||||
|
||||
**After you've done that,** follow these steps:
|
||||
Follow these steps:
|
||||
|
||||
```shell
|
||||
# 1: Build react from source
|
||||
cd /path/to/react
|
||||
yarn
|
||||
yarn build dom,core,interaction,simple-cache-provider --type=NODE
|
||||
yarn build dom-client,core,react-cache,scheduler --type=NODE
|
||||
|
||||
# 2: Install fixture dependencies
|
||||
cd fixtures/unstable-async/suspense/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {createCache} from 'simple-cache-provider';
|
||||
import {createCache} from 'react-cache';
|
||||
|
||||
export let cache;
|
||||
function initCache() {
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
import React, {Placeholder, PureComponent} from 'react';
|
||||
import {unstable_scheduleWork} from 'schedule';
|
||||
import React, {lazy, unstable_Suspense as Suspense, PureComponent} from 'react';
|
||||
import {unstable_scheduleCallback} from 'scheduler';
|
||||
import {
|
||||
unstable_track as track,
|
||||
unstable_trace as trace,
|
||||
unstable_wrap as wrap,
|
||||
} from 'schedule/tracking';
|
||||
import {createResource} from 'simple-cache-provider';
|
||||
import {cache} from '../cache';
|
||||
} from 'scheduler/tracing';
|
||||
import Spinner from './Spinner';
|
||||
import ContributorListPage from './ContributorListPage';
|
||||
|
||||
const UserPageResource = createResource(() => import('./UserPage'));
|
||||
|
||||
function UserPageLoader(props) {
|
||||
const UserPage = UserPageResource.read(cache).default;
|
||||
return <UserPage {...props} />;
|
||||
}
|
||||
const UserPage = lazy(() => import('./UserPage'));
|
||||
|
||||
export default class App extends PureComponent {
|
||||
state = {
|
||||
@@ -32,15 +25,15 @@ export default class App extends PureComponent {
|
||||
}
|
||||
|
||||
handleUserClick = id => {
|
||||
track(`View ${id}`, performance.now(), () => {
|
||||
track(`View ${id} (high-pri)`, performance.now(), () =>
|
||||
trace(`View ${id}`, performance.now(), () => {
|
||||
trace(`View ${id} (high-pri)`, performance.now(), () =>
|
||||
this.setState({
|
||||
currentId: id,
|
||||
})
|
||||
);
|
||||
unstable_scheduleWork(
|
||||
unstable_scheduleCallback(
|
||||
wrap(() =>
|
||||
track(`View ${id} (low-pri)`, performance.now(), () =>
|
||||
trace(`View ${id} (low-pri)`, performance.now(), () =>
|
||||
this.setState({
|
||||
showDetail: true,
|
||||
})
|
||||
@@ -51,7 +44,7 @@ export default class App extends PureComponent {
|
||||
};
|
||||
|
||||
handleBackClick = () =>
|
||||
track('View list', performance.now(), () =>
|
||||
trace('View list', performance.now(), () =>
|
||||
this.setState({
|
||||
currentId: null,
|
||||
showDetail: false,
|
||||
@@ -76,21 +69,21 @@ export default class App extends PureComponent {
|
||||
}}>
|
||||
Return to list
|
||||
</button>
|
||||
<Placeholder delayMs={2000} fallback={<Spinner size="large" />}>
|
||||
<UserPageLoader id={id} />
|
||||
</Placeholder>
|
||||
<Suspense maxDuration={2000} fallback={<Spinner size="large" />}>
|
||||
<UserPage id={id} />
|
||||
</Suspense>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderList(loadingId) {
|
||||
return (
|
||||
<Placeholder delayMs={1500} fallback={<Spinner size="large" />}>
|
||||
<Suspense maxDuration={1500} fallback={<Spinner size="large" />}>
|
||||
<ContributorListPage
|
||||
loadingId={loadingId}
|
||||
onUserClick={this.handleUserClick}
|
||||
/>
|
||||
</Placeholder>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, {Fragment} from 'react';
|
||||
import {createResource} from 'simple-cache-provider';
|
||||
import {createResource} from 'react-cache';
|
||||
import {cache} from '../cache';
|
||||
import Spinner from './Spinner';
|
||||
import {fetchCoreContributorListJSON} from '../api';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, {Placeholder} from 'react';
|
||||
import {createResource} from 'simple-cache-provider';
|
||||
import React, {unstable_Suspense as Suspense} from 'react';
|
||||
import {createResource} from 'react-cache';
|
||||
import Spinner from './Spinner';
|
||||
import {cache} from '../cache';
|
||||
import {fetchUserProfileJSON, fetchUserRepositoriesListJSON} from '../api';
|
||||
@@ -14,9 +14,9 @@ export default function UserPage({id}) {
|
||||
alignItems: 'start',
|
||||
}}>
|
||||
<UserDetails id={id} />
|
||||
<Placeholder delayMs={1000} fallback={<Spinner size="medium" />}>
|
||||
<Suspense maxDuration={1000} fallback={<Spinner size="medium" />}>
|
||||
<Repositories id={id} />
|
||||
</Placeholder>
|
||||
</Suspense>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ function Img({src, alt, ...rest}) {
|
||||
|
||||
function UserPicture({source}) {
|
||||
return (
|
||||
<Placeholder delayMs={1500} fallback={<img src={source} alt="poster" />}>
|
||||
<Suspense maxDuration={1500} fallback={<img src={source} alt="poster" />}>
|
||||
<Img
|
||||
src={source}
|
||||
alt="profile picture"
|
||||
@@ -128,7 +128,7 @@ function UserPicture({source}) {
|
||||
borderRadius: '0.5rem',
|
||||
}}
|
||||
/>
|
||||
</Placeholder>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, {Fragment, PureComponent} from 'react';
|
||||
import {unstable_createRoot, render} from 'react-dom';
|
||||
import {unstable_track as track} from 'schedule/tracking';
|
||||
import {unstable_trace as trace} from 'scheduler/tracing';
|
||||
import {cache} from './cache';
|
||||
import {
|
||||
setFakeRequestTime,
|
||||
@@ -65,7 +65,7 @@ class Debugger extends PureComponent {
|
||||
}
|
||||
|
||||
handleReset = () => {
|
||||
track('Clear cache', () => {
|
||||
trace('Clear cache', () => {
|
||||
cache.invalidate();
|
||||
this.setState(state => ({
|
||||
requests: {},
|
||||
|
||||
@@ -18,7 +18,7 @@ There are also known bugs and inefficiencies in master so **don't use this fixtu
|
||||
# 1: Build react from source
|
||||
cd /path/to/react
|
||||
yarn
|
||||
yarn build dom,core,interaction,simple-cache-provider --type=NODE
|
||||
yarn build dom-client,core,react-cache,scheduler --type=NODE
|
||||
|
||||
# 2: Install fixture dependencies
|
||||
cd fixtures/unstable-async/time-slicing/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, {PureComponent} from 'react';
|
||||
import {flushSync, render} from 'react-dom';
|
||||
import {unstable_scheduleWork} from 'schedule';
|
||||
import {unstable_scheduleCallback} from 'scheduler';
|
||||
import _ from 'lodash';
|
||||
import Charts from './Charts';
|
||||
import Clock from './Clock';
|
||||
@@ -67,7 +67,7 @@ class App extends PureComponent {
|
||||
}
|
||||
this._ignoreClick = true;
|
||||
|
||||
unstable_scheduleWork(() => {
|
||||
unstable_scheduleCallback(() => {
|
||||
this.setState({showDemo: true}, () => {
|
||||
this._ignoreClick = false;
|
||||
});
|
||||
@@ -107,7 +107,7 @@ class App extends PureComponent {
|
||||
this.debouncedHandleChange(value);
|
||||
break;
|
||||
case 'async':
|
||||
unstable_scheduleWork(() => {
|
||||
unstable_scheduleCallback(() => {
|
||||
this.setState({value});
|
||||
});
|
||||
break;
|
||||
@@ -147,8 +147,8 @@ class App extends PureComponent {
|
||||
|
||||
const container = document.getElementById('root');
|
||||
render(
|
||||
<React.unstable_AsyncMode>
|
||||
<React.unstable_ConcurrentMode>
|
||||
<App />
|
||||
</React.unstable_AsyncMode>,
|
||||
</React.unstable_ConcurrentMode>,
|
||||
container
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "16.5.0",
|
||||
"version": "16.6.0-alpha.8af6728",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
@@ -9,7 +9,7 @@
|
||||
"babel-cli": "^6.6.5",
|
||||
"babel-code-frame": "^6.26.0",
|
||||
"babel-core": "^6.0.0",
|
||||
"babel-eslint": "^8.0.0",
|
||||
"babel-eslint": "^10.0.0",
|
||||
"babel-jest": "^23.0.1",
|
||||
"babel-plugin-check-es2015-constants": "^6.5.0",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
@@ -99,7 +99,9 @@
|
||||
"postinstall": "node node_modules/fbjs-scripts/node/check-dev-engines.js package.json && node ./scripts/flow/createFlowConfigs.js",
|
||||
"debug-test": "cross-env NODE_ENV=development node --inspect-brk node_modules/.bin/jest --config ./scripts/jest/config.source.js --runInBand",
|
||||
"test": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source.js",
|
||||
"test-fire": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source-fire.js",
|
||||
"test-prod": "cross-env NODE_ENV=production jest --config ./scripts/jest/config.source.js",
|
||||
"test-fire-prod": "cross-env NODE_ENV=production jest --config ./scripts/jest/config.source-fire.js",
|
||||
"test-prod-build": "yarn test-build-prod",
|
||||
"test-build": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.build.js",
|
||||
"test-build-prod": "cross-env NODE_ENV=production jest --config ./scripts/jest/config.build.js",
|
||||
|
||||
@@ -8,7 +8,7 @@ This utility should be used for subscriptions to a single value that are typical
|
||||
|
||||
Other cases have **better long-term solutions**:
|
||||
* Redux/Flux stores should use the [context API](https://reactjs.org/docs/context.html) instead.
|
||||
* I/O subscriptions (e.g. notifications) that update infrequently should use [`simple-cache-provider`](https://github.com/facebook/react/blob/master/packages/simple-cache-provider/README.md) instead.
|
||||
* I/O subscriptions (e.g. notifications) that update infrequently should use [`react-cache`](https://github.com/facebook/react/blob/master/packages/react-cache/README.md) instead.
|
||||
* Complex libraries like Relay/Apollo should manage subscriptions manually with the same techniques which this library uses under the hood (as referenced [here](https://gist.github.com/bvaughn/d569177d70b50b58bff69c3c4a5353f3)) in a way that is most optimized for their library usage.
|
||||
|
||||
## Limitations in async mode
|
||||
@@ -19,7 +19,7 @@ However, [it achieves correctness by sometimes de-opting to synchronous mode](ht
|
||||
|
||||
The effect of de-opting to sync mode is that the main thread may periodically be blocked (in the case of CPU-bound work), and placeholders may appear earlier than desired (in the case of IO-bound work).
|
||||
|
||||
For **full compatibility** with asynchronous rendering, including both **time-slicing** and **React Suspense**, the suggested longer term solution is to move to one of the patterns described in the previous section.
|
||||
For **full compatibility** with asynchronous rendering, including both **time-slicing** and **React Suspense**, the suggested longer-term solution is to move to one of the patterns described in the previous section.
|
||||
|
||||
## What types of subscriptions can this support?
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "create-subscription",
|
||||
"description": "utility for subscribing to external data sources inside React components",
|
||||
"version": "16.5.0",
|
||||
"version": "16.6.0-alpha.8af6728",
|
||||
"repository": "facebook/react",
|
||||
"files": [
|
||||
"LICENSE",
|
||||
@@ -10,7 +10,7 @@
|
||||
"cjs/"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"react": "^16.3.0"
|
||||
"react": "^16.3.0 || 16.6.0-alpha.8af6728"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rxjs": "^5.5.6"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
@@ -12,12 +12,21 @@
|
||||
const {HostComponent} = require('shared/ReactWorkTags');
|
||||
|
||||
let EventPluginHub;
|
||||
let EventPluginUtils;
|
||||
let ResponderEventPlugin;
|
||||
|
||||
const touch = function(nodeHandle, i) {
|
||||
return {target: nodeHandle, identifier: i};
|
||||
};
|
||||
|
||||
function injectComponentTree(ComponentTree) {
|
||||
EventPluginUtils.setComponentTree(
|
||||
ComponentTree.getFiberCurrentPropsFromNode,
|
||||
ComponentTree.getInstanceFromNode,
|
||||
ComponentTree.getNodeFromInstance,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NodeHandle} nodeHandle @see NodeHandle. Handle of target.
|
||||
* @param {Array<Touch>} touches All active touches.
|
||||
@@ -395,8 +404,7 @@ describe('ResponderEventPlugin', () => {
|
||||
|
||||
const ReactDOMUnstableNativeDependencies = require('react-dom/unstable-native-dependencies');
|
||||
EventPluginHub = require('events/EventPluginHub');
|
||||
const injectComponentTree =
|
||||
ReactDOMUnstableNativeDependencies.injectComponentTree;
|
||||
EventPluginUtils = require('events/EventPluginUtils');
|
||||
ResponderEventPlugin =
|
||||
ReactDOMUnstableNativeDependencies.ResponderEventPlugin;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
3
packages/jest-react/README.md
Normal file
3
packages/jest-react/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# `jest-react`
|
||||
|
||||
Jest matchers and utilities for testing React Test Renderer.
|
||||
@@ -1,12 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
export * from './src/SimpleCacheProvider';
|
||||
export * from './src/JestReact';
|
||||
7
packages/jest-react/npm/index.js
Normal file
7
packages/jest-react/npm/index.js
Normal file
@@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
module.exports = require('./cjs/jest-react.production.min.js');
|
||||
} else {
|
||||
module.exports = require('./cjs/jest-react.development.js');
|
||||
}
|
||||
28
packages/jest-react/package.json
Normal file
28
packages/jest-react/package.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "jest-react",
|
||||
"version": "0.3.0-alpha.8af6728",
|
||||
"description": "Jest matchers and utilities for testing React components.",
|
||||
"main": "index.js",
|
||||
"repository": "facebook/react",
|
||||
"keywords": [
|
||||
"react",
|
||||
"jest",
|
||||
"react-testing"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/facebook/react/issues"
|
||||
},
|
||||
"homepage": "https://reactjs.org/",
|
||||
"peerDependencies": {
|
||||
"jest": "^23.0.1",
|
||||
"react": "^16.0.0 || 16.6.0-alpha.8af6728",
|
||||
"react-test-renderer": "^16.0.0"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"index.js",
|
||||
"cjs/"
|
||||
]
|
||||
}
|
||||
169
packages/jest-react/src/JestReact.js
Normal file
169
packages/jest-react/src/JestReact.js
Normal file
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols';
|
||||
|
||||
import invariant from 'shared/invariant';
|
||||
|
||||
function captureAssertion(fn) {
|
||||
// Trick to use a Jest matcher inside another Jest matcher. `fn` contains an
|
||||
// assertion; if it throws, we capture the error and return it, so the stack
|
||||
// trace presented to the user points to the original assertion in the
|
||||
// test file.
|
||||
try {
|
||||
fn();
|
||||
} catch (error) {
|
||||
return {
|
||||
pass: false,
|
||||
message: () => error.message,
|
||||
};
|
||||
}
|
||||
return {pass: true};
|
||||
}
|
||||
|
||||
function assertYieldsWereCleared(root) {
|
||||
const actualYields = root.unstable_clearYields();
|
||||
invariant(
|
||||
actualYields.length === 0,
|
||||
'Log of yielded values is not empty. ' +
|
||||
'Call expect(ReactTestRenderer).toHaveYielded(...) first.',
|
||||
);
|
||||
}
|
||||
|
||||
export function toFlushAndYield(root, expectedYields) {
|
||||
return captureAssertion(() => {
|
||||
assertYieldsWereCleared(root);
|
||||
const actualYields = root.unstable_flushAll();
|
||||
expect(actualYields).toEqual(expectedYields);
|
||||
});
|
||||
}
|
||||
|
||||
export function toFlushAndYieldThrough(root, expectedYields) {
|
||||
return captureAssertion(() => {
|
||||
assertYieldsWereCleared(root);
|
||||
const actualYields = root.unstable_flushNumberOfYields(
|
||||
expectedYields.length,
|
||||
);
|
||||
expect(actualYields).toEqual(expectedYields);
|
||||
});
|
||||
}
|
||||
|
||||
export function toFlushWithoutYielding(root) {
|
||||
return toFlushAndYield(root, []);
|
||||
}
|
||||
|
||||
export function toHaveYielded(ReactTestRenderer, expectedYields) {
|
||||
return captureAssertion(() => {
|
||||
if (
|
||||
ReactTestRenderer === null ||
|
||||
typeof ReactTestRenderer !== 'object' ||
|
||||
typeof ReactTestRenderer.unstable_setNowImplementation !== 'function'
|
||||
) {
|
||||
invariant(
|
||||
false,
|
||||
'The matcher `toHaveYielded` expects an instance of React Test ' +
|
||||
'Renderer.\n\nTry: ' +
|
||||
'expect(ReactTestRenderer).toHaveYielded(expectedYields)',
|
||||
);
|
||||
}
|
||||
const actualYields = ReactTestRenderer.unstable_clearYields();
|
||||
expect(actualYields).toEqual(expectedYields);
|
||||
});
|
||||
}
|
||||
|
||||
export function toFlushAndThrow(root, ...rest) {
|
||||
return captureAssertion(() => {
|
||||
assertYieldsWereCleared(root);
|
||||
expect(() => {
|
||||
root.unstable_flushAll();
|
||||
}).toThrow(...rest);
|
||||
});
|
||||
}
|
||||
|
||||
export function toMatchRenderedOutput(root, expectedJSX) {
|
||||
assertYieldsWereCleared(root);
|
||||
const actualJSON = root.toJSON();
|
||||
|
||||
let actualJSX;
|
||||
if (actualJSON === null || typeof actualJSON === 'string') {
|
||||
actualJSX = actualJSON;
|
||||
} else if (Array.isArray(actualJSON)) {
|
||||
if (actualJSON.length === 0) {
|
||||
actualJSX = null;
|
||||
} else if (actualJSON.length === 1) {
|
||||
actualJSX = jsonChildToJSXChild(actualJSON[0]);
|
||||
} else {
|
||||
const actualJSXChildren = jsonChildrenToJSXChildren(actualJSON);
|
||||
if (actualJSXChildren === null || typeof actualJSXChildren === 'string') {
|
||||
actualJSX = actualJSXChildren;
|
||||
} else {
|
||||
actualJSX = {
|
||||
$$typeof: REACT_ELEMENT_TYPE,
|
||||
type: REACT_FRAGMENT_TYPE,
|
||||
key: null,
|
||||
ref: null,
|
||||
props: {
|
||||
children: actualJSXChildren,
|
||||
},
|
||||
_owner: null,
|
||||
_store: __DEV__ ? {} : undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
actualJSX = jsonChildToJSXChild(actualJSON);
|
||||
}
|
||||
|
||||
return captureAssertion(() => {
|
||||
expect(actualJSX).toEqual(expectedJSX);
|
||||
});
|
||||
}
|
||||
|
||||
function jsonChildToJSXChild(jsonChild) {
|
||||
if (jsonChild === null || typeof jsonChild === 'string') {
|
||||
return jsonChild;
|
||||
} else {
|
||||
const jsxChildren = jsonChildrenToJSXChildren(jsonChild.children);
|
||||
return {
|
||||
$$typeof: REACT_ELEMENT_TYPE,
|
||||
type: jsonChild.type,
|
||||
key: null,
|
||||
ref: null,
|
||||
props:
|
||||
jsxChildren === null
|
||||
? jsonChild.props
|
||||
: {...jsonChild.props, children: jsxChildren},
|
||||
_owner: null,
|
||||
_store: __DEV__ ? {} : undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function jsonChildrenToJSXChildren(jsonChildren) {
|
||||
if (jsonChildren !== null) {
|
||||
if (jsonChildren.length === 1) {
|
||||
return jsonChildToJSXChild(jsonChildren[0]);
|
||||
} else if (jsonChildren.length > 1) {
|
||||
let jsxChildren = [];
|
||||
let allJSXChildrenAreStrings = true;
|
||||
let jsxChildrenString = '';
|
||||
for (let i = 0; i < jsonChildren.length; i++) {
|
||||
const jsxChild = jsonChildToJSXChild(jsonChildren[i]);
|
||||
jsxChildren.push(jsxChild);
|
||||
if (allJSXChildrenAreStrings) {
|
||||
if (typeof jsxChild === 'string') {
|
||||
jsxChildrenString += jsxChild;
|
||||
} else if (jsxChild !== null) {
|
||||
allJSXChildrenAreStrings = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return allJSXChildrenAreStrings ? jsxChildrenString : jsxChildren;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
2
packages/react-art/Circle.js
vendored
2
packages/react-art/Circle.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
2
packages/react-art/Rectangle.js
vendored
2
packages/react-art/Rectangle.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
2
packages/react-art/Wedge.js
vendored
2
packages/react-art/Wedge.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
2
packages/react-art/index.js
vendored
2
packages/react-art/index.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
2
packages/react-art/npm/Circle.js
vendored
2
packages/react-art/npm/Circle.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
2
packages/react-art/npm/Rectangle.js
vendored
2
packages/react-art/npm/Rectangle.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
2
packages/react-art/npm/Wedge.js
vendored
2
packages/react-art/npm/Wedge.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -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": "16.5.0",
|
||||
"version": "16.6.0-alpha.8af6728",
|
||||
"main": "index.js",
|
||||
"repository": "facebook/react",
|
||||
"keywords": [
|
||||
@@ -23,10 +23,10 @@
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"schedule": "^0.3.0"
|
||||
"scheduler": "^0.10.0-alpha.8af6728"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.0.0"
|
||||
"react": "^16.0.0 || 16.6.0-alpha.8af6728"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
|
||||
2
packages/react-art/src/ReactART.js
vendored
2
packages/react-art/src/ReactART.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
26
packages/react-art/src/ReactARTHostConfig.js
vendored
26
packages/react-art/src/ReactARTHostConfig.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
export {
|
||||
unstable_now as now,
|
||||
unstable_scheduleWork as scheduleDeferredCallback,
|
||||
unstable_cancelScheduledWork as cancelDeferredCallback,
|
||||
} from 'schedule';
|
||||
unstable_scheduleCallback as scheduleDeferredCallback,
|
||||
unstable_cancelCallback as cancelDeferredCallback,
|
||||
} from 'scheduler';
|
||||
import Transform from 'art/core/transform';
|
||||
import Mode from 'art/modes/current';
|
||||
import invariant from 'shared/invariant';
|
||||
@@ -405,3 +405,21 @@ export function commitUpdate(
|
||||
) {
|
||||
instance._applyProps(instance, newProps, oldProps);
|
||||
}
|
||||
|
||||
export function hideInstance(instance) {
|
||||
instance.hide();
|
||||
}
|
||||
|
||||
export function hideTextInstance(textInstance) {
|
||||
// Noop
|
||||
}
|
||||
|
||||
export function unhideInstance(instance, props) {
|
||||
if (props.visible == null || props.visible) {
|
||||
instance.show();
|
||||
}
|
||||
}
|
||||
|
||||
export function unhideTextInstance(textInstance, text): void {
|
||||
// Noop
|
||||
}
|
||||
|
||||
2
packages/react-art/src/ReactARTInternals.js
vendored
2
packages/react-art/src/ReactARTInternals.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# simple-cache-provider
|
||||
# react-cache
|
||||
|
||||
A basic cache for React applications. It also serves as a reference for more
|
||||
advanced caching implementations.
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
@@ -9,4 +9,4 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
export * from './src/Schedule';
|
||||
export * from './src/ReactCache';
|
||||
7
packages/react-cache/npm/index.js
vendored
Normal file
7
packages/react-cache/npm/index.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
module.exports = require('./cjs/react-cache.production.min.js');
|
||||
} else {
|
||||
module.exports = require('./cjs/react-cache.development.js');
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "simple-cache-provider",
|
||||
"name": "react-cache",
|
||||
"description": "A basic cache for React applications",
|
||||
"version": "0.8.0",
|
||||
"version": "16.6.0-alpha.8af6728",
|
||||
"repository": "facebook/react",
|
||||
"files": [
|
||||
"LICENSE",
|
||||
@@ -10,6 +10,6 @@
|
||||
"cjs/"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"react": "^16.3.0-alpha.1"
|
||||
"react": "^16.3.0-alpha.1 || 16.6.0-alpha.8af6728"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
@@ -400,4 +400,4 @@ export function createResource<V, K, H: primitive>(
|
||||
|
||||
// Global cache has no eviction policy (except for, ya know, a browser refresh).
|
||||
const globalCache = createCache(noop);
|
||||
export const SimpleCache = React.createContext(globalCache);
|
||||
export const ReactCache = React.createContext(globalCache);
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
@@ -9,16 +9,16 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
let SimpleCacheProvider;
|
||||
let ReactCache;
|
||||
|
||||
describe('SimpleCacheProvider', () => {
|
||||
describe('ReactCache', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
SimpleCacheProvider = require('simple-cache-provider');
|
||||
ReactCache = require('react-cache');
|
||||
});
|
||||
|
||||
it('throws a promise if the requested value is not in the cache', async () => {
|
||||
const {createCache, createResource} = SimpleCacheProvider;
|
||||
const {createCache, createResource} = ReactCache;
|
||||
|
||||
function loadUpperCase(text) {
|
||||
return Promise.resolve(text.toUpperCase());
|
||||
@@ -39,7 +39,7 @@ describe('SimpleCacheProvider', () => {
|
||||
});
|
||||
|
||||
it('throws an error on the subsequent read if the promise is rejected', async () => {
|
||||
const {createCache, createResource} = SimpleCacheProvider;
|
||||
const {createCache, createResource} = ReactCache;
|
||||
|
||||
let shouldFail = true;
|
||||
function loadUpperCase(text) {
|
||||
@@ -83,7 +83,7 @@ describe('SimpleCacheProvider', () => {
|
||||
});
|
||||
|
||||
it('can preload data ahead of time', async () => {
|
||||
const {createCache, createResource} = SimpleCacheProvider;
|
||||
const {createCache, createResource} = ReactCache;
|
||||
|
||||
function loadUpperCase(text) {
|
||||
return Promise.resolve(text.toUpperCase());
|
||||
@@ -99,7 +99,7 @@ describe('SimpleCacheProvider', () => {
|
||||
});
|
||||
|
||||
it('does not throw if preloaded promise rejects', async () => {
|
||||
const {createCache, createResource} = SimpleCacheProvider;
|
||||
const {createCache, createResource} = ReactCache;
|
||||
|
||||
function loadUpperCase(text) {
|
||||
return Promise.reject(new Error('uh oh'));
|
||||
@@ -115,7 +115,7 @@ describe('SimpleCacheProvider', () => {
|
||||
});
|
||||
|
||||
it('accepts custom hash function', async () => {
|
||||
const {createCache, createResource} = SimpleCacheProvider;
|
||||
const {createCache, createResource} = ReactCache;
|
||||
|
||||
function loadSum([a, b]) {
|
||||
return Promise.resolve(a + b);
|
||||
@@ -138,7 +138,7 @@ describe('SimpleCacheProvider', () => {
|
||||
});
|
||||
|
||||
it('warns if resourceType is a string or number', () => {
|
||||
const {createCache} = SimpleCacheProvider;
|
||||
const {createCache} = ReactCache;
|
||||
|
||||
spyOnDev(console, 'error');
|
||||
const cache = createCache();
|
||||
@@ -166,7 +166,7 @@ describe('SimpleCacheProvider', () => {
|
||||
});
|
||||
|
||||
it('warns if non-primitive key is passed to a resource without a hash function', () => {
|
||||
const {createCache, createResource} = SimpleCacheProvider;
|
||||
const {createCache, createResource} = ReactCache;
|
||||
|
||||
spyOnDev(console, 'error');
|
||||
|
||||
@@ -197,7 +197,7 @@ describe('SimpleCacheProvider', () => {
|
||||
});
|
||||
|
||||
it('stays within maximum capacity by evicting the least recently used record', async () => {
|
||||
const {createCache, createResource} = SimpleCacheProvider;
|
||||
const {createCache, createResource} = ReactCache;
|
||||
|
||||
function loadIntegerString(int) {
|
||||
return Promise.resolve(int + '');
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
2
packages/react-dom/index.js
vendored
2
packages/react-dom/index.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-dom",
|
||||
"version": "16.5.0",
|
||||
"version": "16.6.0-alpha.8af6728",
|
||||
"description": "React package for working with the DOM.",
|
||||
"main": "index.js",
|
||||
"repository": "facebook/react",
|
||||
@@ -16,10 +16,10 @@
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"schedule": "^0.3.0"
|
||||
"scheduler": "^0.10.0-alpha.8af6728"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.0.0"
|
||||
"react": "^16.0.0 || 16.6.0-alpha.8af6728"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
2
packages/react-dom/server.js
vendored
2
packages/react-dom/server.js
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
// Set by `yarn test-fire`.
|
||||
const {disableInputAttributeSyncing} = require('shared/ReactFeatureFlags');
|
||||
|
||||
describe('DOMPropertyOperations', () => {
|
||||
let React;
|
||||
let ReactDOM;
|
||||
@@ -80,7 +83,11 @@ describe('DOMPropertyOperations', () => {
|
||||
it('should not remove empty attributes for special input properties', () => {
|
||||
const container = document.createElement('div');
|
||||
ReactDOM.render(<input value="" onChange={() => {}} />, container);
|
||||
expect(container.firstChild.getAttribute('value')).toBe('');
|
||||
if (disableInputAttributeSyncing) {
|
||||
expect(container.firstChild.hasAttribute('value')).toBe(false);
|
||||
} else {
|
||||
expect(container.firstChild.getAttribute('value')).toBe('');
|
||||
}
|
||||
expect(container.firstChild.value).toBe('');
|
||||
});
|
||||
|
||||
@@ -165,7 +172,11 @@ describe('DOMPropertyOperations', () => {
|
||||
<input type="text" value="foo" onChange={function() {}} />,
|
||||
container,
|
||||
);
|
||||
expect(container.firstChild.getAttribute('value')).toBe('foo');
|
||||
if (disableInputAttributeSyncing) {
|
||||
expect(container.firstChild.hasAttribute('value')).toBe(false);
|
||||
} else {
|
||||
expect(container.firstChild.getAttribute('value')).toBe('foo');
|
||||
}
|
||||
expect(container.firstChild.value).toBe('foo');
|
||||
expect(() =>
|
||||
ReactDOM.render(
|
||||
@@ -175,7 +186,11 @@ describe('DOMPropertyOperations', () => {
|
||||
).toWarnDev(
|
||||
'A component is changing a controlled input of type text to be uncontrolled',
|
||||
);
|
||||
expect(container.firstChild.getAttribute('value')).toBe('foo');
|
||||
if (disableInputAttributeSyncing) {
|
||||
expect(container.firstChild.hasAttribute('value')).toBe(false);
|
||||
} else {
|
||||
expect(container.firstChild.getAttribute('value')).toBe('foo');
|
||||
}
|
||||
expect(container.firstChild.value).toBe('foo');
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user