Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions fixtures/attribute-behavior/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
/public/react.development.js
/public/react-dom.development.js
/public/react-dom-server.browser.development.js
/public/react-dom-client.development.js
/public/scheduler.development.js

# misc
.DS_Store
Expand Down
88 changes: 69 additions & 19 deletions fixtures/attribute-behavior/AttributeTableSnapshot.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## `about` (on `<div>` inside `<div>`)
## `about` (on `<div>` inside `<div>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `about=(string)`| (changed)| `"a string"` |
Expand Down Expand Up @@ -751,27 +751,27 @@
## `async` (on `<script>` inside `<div>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `async=(string)`| (changed)| `<boolean: true>` |
| `async=(empty string)`| (initial)| `<boolean: false>` |
| `async=(array with string)`| (changed)| `<boolean: true>` |
| `async=(empty array)`| (changed)| `<boolean: true>` |
| `async=(object)`| (changed)| `<boolean: true>` |
| `async=(numeric string)`| (changed)| `<boolean: true>` |
| `async=(-1)`| (changed)| `<boolean: true>` |
| `async=(0)`| (initial)| `<boolean: false>` |
| `async=(integer)`| (changed)| `<boolean: true>` |
| `async=(string)`| (changed, warning, ssr warning)| `<boolean: true>` |
| `async=(empty string)`| (initial, warning, ssr warning)| `<boolean: false>` |
| `async=(array with string)`| (changed, warning, ssr warning)| `<boolean: true>` |
| `async=(empty array)`| (changed, warning, ssr warning)| `<boolean: true>` |
| `async=(object)`| (changed, warning, ssr warning)| `<boolean: true>` |
| `async=(numeric string)`| (changed, warning, ssr warning)| `<boolean: true>` |
| `async=(-1)`| (changed, warning, ssr warning)| `<boolean: true>` |
| `async=(0)`| (initial, warning, ssr warning)| `<boolean: false>` |
| `async=(integer)`| (changed, warning, ssr warning)| `<boolean: true>` |
| `async=(NaN)`| (initial, warning)| `<boolean: false>` |
| `async=(float)`| (changed)| `<boolean: true>` |
| `async=(true)`| (changed)| `<boolean: true>` |
| `async=(false)`| (initial)| `<boolean: false>` |
| `async=(float)`| (changed, warning, ssr warning)| `<boolean: true>` |
| `async=(true)`| (changed, warning, ssr warning)| `<boolean: true>` |
| `async=(false)`| (initial, warning, ssr warning)| `<boolean: false>` |
| `async=(string 'true')`| (changed, warning)| `<boolean: true>` |
| `async=(string 'false')`| (changed, warning)| `<boolean: true>` |
| `async=(string 'on')`| (changed)| `<boolean: true>` |
| `async=(string 'off')`| (changed)| `<boolean: true>` |
| `async=(string 'on')`| (changed, warning, ssr warning)| `<boolean: true>` |
| `async=(string 'off')`| (changed, warning, ssr warning)| `<boolean: true>` |
| `async=(symbol)`| (initial, warning)| `<boolean: false>` |
| `async=(function)`| (initial, warning)| `<boolean: false>` |
| `async=(null)`| (initial)| `<boolean: false>` |
| `async=(undefined)`| (initial)| `<boolean: false>` |
| `async=(null)`| (initial, warning, ssr warning)| `<boolean: false>` |
| `async=(undefined)`| (initial, warning, ssr warning)| `<boolean: false>` |

## `attributeName` (on `<animate>` inside `<svg>`)
| Test Case | Flags | Result |
Expand Down Expand Up @@ -1493,7 +1493,7 @@
| `children=(string 'false')`| (initial)| `[]` |
| `children=(string 'on')`| (initial)| `[]` |
| `children=(string 'off')`| (initial)| `[]` |
| `children=(symbol)`| (initial)| `[]` |
| `children=(symbol)`| (initial, warning)| `[]` |
| `children=(function)`| (initial, warning)| `[]` |
| `children=(null)`| (initial)| `[]` |
| `children=(undefined)`| (initial)| `[]` |
Expand Down Expand Up @@ -2023,6 +2023,56 @@
| `colSpan=(null)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |
| `colSpan=(undefined)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |

## `command` (on `<button>` inside `<div>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `command=(string)`| (changed)| `"show-popover"` |
| `command=(empty string)`| (initial)| `<empty string>` |
| `command=(array with string)`| (changed)| `"show-popover"` |
| `command=(empty array)`| (initial)| `<empty string>` |
| `command=(object)`| (initial)| `<empty string>` |
| `command=(numeric string)`| (initial)| `<empty string>` |
| `command=(-1)`| (initial)| `<empty string>` |
| `command=(0)`| (initial)| `<empty string>` |
| `command=(integer)`| (initial)| `<empty string>` |
| `command=(NaN)`| (initial, warning)| `<empty string>` |
| `command=(float)`| (initial)| `<empty string>` |
| `command=(true)`| (initial, warning)| `<empty string>` |
| `command=(false)`| (initial, warning)| `<empty string>` |
| `command=(string 'true')`| (initial)| `<empty string>` |
| `command=(string 'false')`| (initial)| `<empty string>` |
| `command=(string 'on')`| (initial)| `<empty string>` |
| `command=(string 'off')`| (initial)| `<empty string>` |
| `command=(symbol)`| (initial, warning)| `<empty string>` |
| `command=(function)`| (initial, warning)| `<empty string>` |
| `command=(null)`| (initial)| `<empty string>` |
| `command=(undefined)`| (initial)| `<empty string>` |

## `commandFor` (on `<button>` inside `<div>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `commandFor=(string)`| (changed)| `<HTMLDivElement>` |
| `commandFor=(empty string)`| (initial)| `<null>` |
| `commandFor=(array with string)`| (changed, warning, ssr warning)| `<HTMLDivElement>` |
| `commandFor=(empty array)`| (initial, warning, ssr warning)| `<null>` |
| `commandFor=(object)`| (initial, warning, ssr warning)| `<null>` |
| `commandFor=(numeric string)`| (initial)| `<null>` |
| `commandFor=(-1)`| (initial)| `<null>` |
| `commandFor=(0)`| (initial)| `<null>` |
| `commandFor=(integer)`| (initial)| `<null>` |
| `commandFor=(NaN)`| (initial, warning)| `<null>` |
| `commandFor=(float)`| (initial)| `<null>` |
| `commandFor=(true)`| (initial, warning)| `<null>` |
| `commandFor=(false)`| (initial, warning)| `<null>` |
| `commandFor=(string 'true')`| (initial)| `<null>` |
| `commandFor=(string 'false')`| (initial)| `<null>` |
| `commandFor=(string 'on')`| (initial)| `<null>` |
| `commandFor=(string 'off')`| (initial)| `<null>` |
| `commandFor=(symbol)`| (initial, warning)| `<null>` |
| `commandFor=(function)`| (initial, warning)| `<null>` |
| `commandFor=(null)`| (initial)| `<null>` |
| `commandFor=(undefined)`| (initial)| `<null>` |

## `content` (on `<meta>` inside `<head>`)
| Test Case | Flags | Result |
| --- | --- | --- |
Expand Down Expand Up @@ -10143,7 +10193,7 @@
| `srcSet=(string 'false')`| (initial)| `<undefined>` |
| `srcSet=(string 'on')`| (initial)| `<undefined>` |
| `srcSet=(string 'off')`| (initial)| `<undefined>` |
| `srcSet=(symbol)`| (initial, warning)| `<undefined>` |
| `srcSet=(symbol)`| (changed, error, warning, ssr mismatch)| `` |
| `srcSet=(function)`| (initial, warning)| `<undefined>` |
| `srcSet=(null)`| (initial)| `<undefined>` |
| `srcSet=(undefined)`| (initial)| `<undefined>` |
Expand Down
2 changes: 1 addition & 1 deletion fixtures/attribute-behavior/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

## Instructions

`yarn build --type=UMD_DEV react/index,react-dom && cd fixtures/attribute-behavior && yarn install && yarn dev`
`yarn build --type=NODE_DEV react/index,react-dom,scheduler && cd fixtures/attribute-behavior && yarn install && yarn dev`

## Interpretation

Expand Down
2 changes: 1 addition & 1 deletion fixtures/attribute-behavior/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"scripts": {
"predev":
"cp ../../build/oss-experimental/react/umd/react.development.js public/ && cp ../../build/oss-experimental/react-dom/umd/react-dom.development.js public/ && cp ../../build/oss-experimental/react-dom/umd/react-dom-server.browser.development.js public/",
"cp ../../build/oss-experimental/react/cjs/react.development.js public/ && cp ../../build/oss-experimental/react-dom/cjs/react-dom.development.js public/ && cp ../../build/oss-experimental/react-dom/cjs/react-dom-client.development.js public/ && cp ../../build/oss-experimental/react-dom/cjs/react-dom-server.browser.development.js public/ && cp ../../build/oss-experimental/scheduler/cjs/scheduler.development.js public/",
"dev": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
Expand Down
1 change: 1 addition & 0 deletions fixtures/attribute-behavior/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<script src="https://unpkg.com/requirejs@latest/require.js" crossorigin="anonymous" async></script>
</head>
<body>
<noscript>
Expand Down
111 changes: 91 additions & 20 deletions fixtures/attribute-behavior/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,15 @@ const UNKNOWN_HTML_TAGS = new Set(['keygen', 'time', 'command']);
async function getRenderedAttributeValue(
react,
renderer,
clientRenderer,
serverRenderer,
attribute,
type
) {
const originalConsoleError = console.error;
console.error = warn;
const originalConsoleWarn = console.warn;
console.warn = warn;

const containerTagName = attribute.containerTagName || 'div';
const tagName = attribute.tagName || 'div';
Expand Down Expand Up @@ -303,7 +306,7 @@ async function getRenderedAttributeValue(
try {
let container = createContainer();
renderer.flushSync(() => {
renderer
clientRenderer
.createRoot(container)
.render(react.createElement(tagName, baseProps));
});
Expand All @@ -313,7 +316,7 @@ async function getRenderedAttributeValue(
container = createContainer();

renderer.flushSync(() => {
renderer
clientRenderer
.createRoot(container)
.render(react.createElement(tagName, props));
});
Expand Down Expand Up @@ -386,6 +389,7 @@ async function getRenderedAttributeValue(
}

console.error = originalConsoleError;
console.warn = originalConsoleWarn;

if (hasTagMismatch) {
throw new Error('Tag mismatch. Expected: ' + tagName);
Expand Down Expand Up @@ -433,21 +437,25 @@ async function prepareState(initGlobals) {
const {
ReactStable,
ReactDOMStable,
ReactDOMClientStable,
ReactDOMServerStable,
ReactNext,
ReactDOMNext,
ReactDOMClientNext,
ReactDOMServerNext,
} = initGlobals(attribute, type);
} = await initGlobals(attribute, type);
const reactStableValue = await getRenderedAttributeValue(
ReactStable,
ReactDOMStable,
ReactDOMClientStable,
ReactDOMServerStable,
attribute,
type
);
const reactNextValue = await getRenderedAttributeValue(
ReactNext,
ReactDOMNext,
ReactDOMClientNext,
ReactDOMServerNext,
attribute,
type
Expand Down Expand Up @@ -799,23 +807,69 @@ class App extends React.Component {
};

async componentDidMount() {
const sources = {
ReactStable: 'https://unpkg.com/react@latest/umd/react.development.js',
ReactDOMStable:
'https://unpkg.com/react-dom@latest/umd/react-dom.development.js',
ReactDOMServerStable:
'https://unpkg.com/react-dom@latest/umd/react-dom-server.browser.development.js',
ReactNext: '/react.development.js',
ReactDOMNext: '/react-dom.development.js',
ReactDOMServerNext: '/react-dom-server.browser.development.js',
};
const codePromises = Object.values(sources).map(src =>
fetch(src).then(res => res.text())
/**
* @type (readonly {namespace: string; specifier: string; url: string}[])
*/
const sources = [
{
namespace: 'SchedulerStable',
specifier: 'scheduler',
url: 'https://unpkg.com/scheduler@latest/cjs/scheduler.development.js',
},
{
namespace: 'ReactStable',
specifier: 'react',
url: 'https://unpkg.com/react@latest/cjs/react.development.js',
},
{
namespace: 'ReactDOMStable',
specifier: 'react-dom',
url: 'https://unpkg.com/react-dom@latest/cjs/react-dom.development.js',
},
{
namespace: 'ReactDOMClientStable',
specifier: 'react-dom/client',
url: 'https://unpkg.com/react-dom@latest/cjs/react-dom-client.development.js',
},
{
namespace: 'ReactDOMServerStable',
specifier: 'react-dom/server',
url: 'https://unpkg.com/react-dom@latest/cjs/react-dom-server.browser.development.js',
},
{
namespace: 'SchedulerNext',
specifier: 'scheduler',
url: '/scheduler.development.js',
},
{
namespace: 'ReactNext',
specifier: 'react',
url: '/react.development.js',
},
{
namespace: 'ReactDOMNext',
specifier: 'react-dom',
url: '/react-dom.development.js',
},
{
namespace: 'ReactDOMClientNext',
specifier: 'react-dom/client',
url: '/react-dom-client.development.js',
},
{
namespace: 'ReactDOMServerNext',
specifier: 'react-dom/server',
url: '/react-dom-server.browser.development.js',
},
];

const codePromises = sources.map(({url}) =>
fetch(url).then(res => res.text())
);
const codesByIndex = await Promise.all(codePromises);

const pool = [];
function initGlobals(attribute, type) {
async function initGlobals(attribute, type) {
if (useFastMode) {
// Note: this is not giving correct results for warnings.
// But it's much faster.
Expand All @@ -838,10 +892,27 @@ class App extends React.Component {
}

let globals = {};
Object.keys(sources).forEach((name, i) => {
eval.call(window, codesByIndex[i]); // eslint-disable-line
globals[name] = window[name.replace(/Stable|Next/g, '')];
});

for (let i = 0; i < sources.length; i++) {
const {namespace, specifier} = sources[i];
const code = codesByIndex[i].replaceAll(
'process.env.NODE_ENV',
'"development"'
);

window.requirejs.undef(specifier);
// eslint-disable-next-line no-eval
eval.call(
window,
`window.define("${specifier}", function (require, exports, module) {${code}});`
);

await new Promise(resolve => {
window.require([specifier], resolve);
}).then(module => {
globals[namespace] = module;
});
}

// Cache for future use (for different attributes).
pool.push({
Expand Down
15 changes: 15 additions & 0 deletions fixtures/attribute-behavior/src/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,21 @@ const attributes = [
},
{name: 'cols', tagName: 'textarea'},
{name: 'colSpan', containerTagName: 'tr', tagName: 'td'},
{name: 'command', overrideStringValue: 'show-popover', tagName: 'button'},
{
name: 'commandFor',
read: element => {
document.body.appendChild(element);
try {
// trigger and target need to be connected for `commandForElement` to read the actual value.
return element.commandForElement;
} finally {
document.body.removeChild(element);
}
},
overrideStringValue: 'popover-target',
tagName: 'button',
},
{name: 'content', containerTagName: 'head', tagName: 'meta'},
{name: 'contentEditable'},
{
Expand Down
Loading
Loading