Made transformations literally 10000x faster
This commit is contained in:
parent
f7d7b1c6d3
commit
b4c4540f0b
1275 changed files with 93530 additions and 219 deletions
|
@ -75,7 +75,7 @@ function validateWildcardAplTo(wildcards: string[]): ValidationResultAplTo {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!types) {
|
if (!types) {
|
||||||
errors.push("No types given for value");
|
errors.push("No types given for wildcard " + identifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { env, errors };
|
return { env, errors };
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
proposal DoExpression{
|
proposal DoExpression{
|
||||||
case arrowFunction{
|
case arrowFunction{
|
||||||
applicable to {
|
applicable to {
|
||||||
"let <<ident:Identifier>> = () => {
|
"() => {
|
||||||
<<statements: (Statement && !ReturnStatement)+>>
|
<<statements: (Statement && !ReturnStatement)+>>
|
||||||
return <<returnVal : Expression>>;
|
return <<returnVal : Expression>>;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
}
|
}
|
||||||
transform to {
|
transform to {
|
||||||
"let <<ident>> = do {
|
"(do {
|
||||||
<<statements>>
|
<<statements>>
|
||||||
<<returnVal>>
|
<<returnVal>>
|
||||||
}"
|
})"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case immediatelyInvokedUnnamedFunction {
|
case immediatelyInvokedUnnamedFunction {
|
||||||
applicable to {
|
applicable to {
|
||||||
"let <<ident:Identifier>> = function(){
|
"(function(){
|
||||||
<<statements: (Statement && !ReturnStatement)+>>
|
<<statements: (Statement && !ReturnStatement)+>>
|
||||||
return <<returnVal : Expression>>;
|
return <<returnVal : Expression>>;
|
||||||
}();"
|
})();"
|
||||||
}
|
}
|
||||||
|
|
||||||
transform to {
|
transform to {
|
||||||
"let <<ident>> = do {
|
"(do {
|
||||||
<<statements>>
|
<<statements>>
|
||||||
<<returnVal>>
|
<<returnVal>>
|
||||||
}"
|
})"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,11 +2,11 @@ let aaaa = do {
|
||||||
let g = 100;
|
let g = 100;
|
||||||
let ff = 10;
|
let ff = 10;
|
||||||
let ggg = a(b);
|
let ggg = a(b);
|
||||||
100;
|
100
|
||||||
};
|
};
|
||||||
let bbaaa = do {
|
var bbaaa = do {
|
||||||
let lllll = 1 + 1;
|
let lllll = 1 + 1;
|
||||||
100 + 100;
|
100 + 100;
|
||||||
const aaaaa = aaaa(bb);
|
const aaaaa = aaaa(bb);
|
||||||
lllll;
|
lllll
|
||||||
};
|
};
|
94
output_files/test_2.js
Normal file
94
output_files/test_2.js
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
function parse() {
|
||||||
|
const input = ("input" |> document.getElementById(%)).value;
|
||||||
|
const data = 32 |> input.slice(%);
|
||||||
|
const compressedData = data |> decode_base64(%);
|
||||||
|
const uncompressed = compressedData |> pako.inflate(%, {
|
||||||
|
to: "string"
|
||||||
|
});
|
||||||
|
const json = uncompressed |> JSON.parse(%);
|
||||||
|
json |> console.log(%);
|
||||||
|
json |> convertToDesktop(%);
|
||||||
|
}
|
||||||
|
function convertToDesktop(json) {
|
||||||
|
const newValues = {
|
||||||
|
crb: false,
|
||||||
|
newClanRaidClassId: 0,
|
||||||
|
newClanRaidClassLevel: 0,
|
||||||
|
pendingImmortalSouls: 0,
|
||||||
|
pendingRaidRubies: 0,
|
||||||
|
immortalSouls: 0,
|
||||||
|
lastPurchaseTime: 0,
|
||||||
|
lastRaidAttemptTimestamp: 0,
|
||||||
|
lastRaidRewardCheckTimestamp: 0,
|
||||||
|
shouldShowHZERoster: false,
|
||||||
|
lastBonusRewardCheckTimestamp: 0
|
||||||
|
};
|
||||||
|
const mappedValues = {
|
||||||
|
rubies: json.rubies / 10 |> Math.round(%)
|
||||||
|
};
|
||||||
|
const pcSpecificValues = {
|
||||||
|
readPatchNumber: "1.0e12",
|
||||||
|
saveOrigin: "pc"
|
||||||
|
};
|
||||||
|
const hash = "7a990d405d2c6fb93aa8fbb0ec1a3b23";
|
||||||
|
const newData = {
|
||||||
|
...newValues,
|
||||||
|
...json,
|
||||||
|
...mappedValues,
|
||||||
|
...pcSpecificValues
|
||||||
|
};
|
||||||
|
const compressed = newData |> JSON.stringify(%) |> pako.deflate(%, {
|
||||||
|
to: "string"
|
||||||
|
});
|
||||||
|
const base64 = compressed |> btoa(%);
|
||||||
|
const finalSaveString = hash + base64;
|
||||||
|
("output_output" |> document.getElementById(%)).innerText = finalSaveString;
|
||||||
|
showOutput();
|
||||||
|
}
|
||||||
|
function showOutput() {
|
||||||
|
("outputs" |> document.getElementById(%)).style.visibility = "visible";
|
||||||
|
}
|
||||||
|
function copyOutput() {
|
||||||
|
const output = "output_output" |> document.getElementById(%);
|
||||||
|
output.disabled = false;
|
||||||
|
output.focus();
|
||||||
|
output.select();
|
||||||
|
"copy" |> document.execCommand(%);
|
||||||
|
output.disabled = true;
|
||||||
|
const successElement = "copy_success_msg" |> document.getElementById(%);
|
||||||
|
successElement.style.visibility = "visible";
|
||||||
|
(() => successElement.style.visibility = "hidden") |> setTimeout(%, 4000);
|
||||||
|
}
|
||||||
|
function decode_base64(s) {
|
||||||
|
let e = {},
|
||||||
|
i,
|
||||||
|
k,
|
||||||
|
v = [],
|
||||||
|
r = "",
|
||||||
|
w = String.fromCharCode;
|
||||||
|
let n = [[65, 91], [97, 123], [48, 58], [43, 44], [47, 48]];
|
||||||
|
for (z in n) {
|
||||||
|
for (i = n[z][0]; i < n[z][1]; i++) {
|
||||||
|
i |> w(%) |> v.push(%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
e[v[i]] = i;
|
||||||
|
}
|
||||||
|
for (i = 0; i < s.length; i += 72) {
|
||||||
|
let b = 0,
|
||||||
|
c,
|
||||||
|
x,
|
||||||
|
l = 0,
|
||||||
|
o = i |> s.substring(%, i + 72);
|
||||||
|
for (x = 0; x < o.length; x++) {
|
||||||
|
c = e[x |> o.charAt(%)];
|
||||||
|
b = (b << 6) + c;
|
||||||
|
l += 6;
|
||||||
|
while (l >= 8) {
|
||||||
|
r += (b >>> (l -= 8)) % 256 |> w(%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
500
output_testing/0.eslintrc.js
Normal file
500
output_testing/0.eslintrc.js
Normal file
|
@ -0,0 +1,500 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const {
|
||||||
|
es5Paths,
|
||||||
|
esNextPaths
|
||||||
|
} = './scripts/shared/pathsByLanguageVersion' |> require(%);
|
||||||
|
const restrictedGlobals = 'confusing-browser-globals' |> require(%);
|
||||||
|
const OFF = 0;
|
||||||
|
const WARNING = 1;
|
||||||
|
const ERROR = 2;
|
||||||
|
module.exports = {
|
||||||
|
extends: ['prettier'],
|
||||||
|
// Stop ESLint from looking for a configuration file in parent folders
|
||||||
|
root: true,
|
||||||
|
plugins: ['babel', 'ft-flow', 'jest', 'no-for-of-loops', 'no-function-declare-after-return', 'react', 'react-internal'],
|
||||||
|
parser: 'hermes-eslint',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 9,
|
||||||
|
sourceType: 'script'
|
||||||
|
},
|
||||||
|
// We're stricter than the default config, mostly. We'll override a few rules
|
||||||
|
// and then enable some React specific ones.
|
||||||
|
rules: {
|
||||||
|
'ft-flow/array-style-complex-type': [OFF, 'verbose'],
|
||||||
|
'ft-flow/array-style-simple-type': [OFF, 'verbose'],
|
||||||
|
// TODO should be WARNING
|
||||||
|
'ft-flow/boolean-style': ERROR,
|
||||||
|
'ft-flow/no-dupe-keys': ERROR,
|
||||||
|
'ft-flow/no-primitive-constructor-types': ERROR,
|
||||||
|
'ft-flow/no-types-missing-file-annotation': OFF,
|
||||||
|
// TODO should be ERROR
|
||||||
|
'ft-flow/no-unused-expressions': ERROR,
|
||||||
|
// 'ft-flow/no-weak-types': WARNING,
|
||||||
|
// 'ft-flow/require-valid-file-annotation': ERROR,
|
||||||
|
|
||||||
|
'no-cond-assign': OFF,
|
||||||
|
'no-constant-condition': OFF,
|
||||||
|
'no-control-regex': OFF,
|
||||||
|
'no-debugger': ERROR,
|
||||||
|
'no-dupe-args': ERROR,
|
||||||
|
'no-dupe-keys': ERROR,
|
||||||
|
'no-duplicate-case': WARNING,
|
||||||
|
'no-empty-character-class': WARNING,
|
||||||
|
'no-empty': OFF,
|
||||||
|
'no-ex-assign': WARNING,
|
||||||
|
'no-extra-boolean-cast': WARNING,
|
||||||
|
'no-func-assign': ERROR,
|
||||||
|
'no-invalid-regexp': WARNING,
|
||||||
|
'no-irregular-whitespace': WARNING,
|
||||||
|
'no-negated-in-lhs': ERROR,
|
||||||
|
'no-obj-calls': ERROR,
|
||||||
|
'no-regex-spaces': WARNING,
|
||||||
|
'no-sparse-arrays': ERROR,
|
||||||
|
'no-unreachable': ERROR,
|
||||||
|
'use-isnan': ERROR,
|
||||||
|
'valid-jsdoc': OFF,
|
||||||
|
'block-scoped-var': OFF,
|
||||||
|
complexity: OFF,
|
||||||
|
'default-case': OFF,
|
||||||
|
'guard-for-in': OFF,
|
||||||
|
'no-alert': OFF,
|
||||||
|
'no-caller': ERROR,
|
||||||
|
'no-case-declarations': OFF,
|
||||||
|
'no-div-regex': OFF,
|
||||||
|
'no-else-return': OFF,
|
||||||
|
'no-empty-pattern': WARNING,
|
||||||
|
'no-eq-null': OFF,
|
||||||
|
'no-eval': ERROR,
|
||||||
|
'no-extend-native': WARNING,
|
||||||
|
'no-extra-bind': WARNING,
|
||||||
|
'no-fallthrough': WARNING,
|
||||||
|
'no-implicit-coercion': OFF,
|
||||||
|
'no-implied-eval': ERROR,
|
||||||
|
'no-invalid-this': OFF,
|
||||||
|
'no-iterator': OFF,
|
||||||
|
'no-labels': [ERROR, {
|
||||||
|
allowLoop: true,
|
||||||
|
allowSwitch: true
|
||||||
|
}],
|
||||||
|
'no-lone-blocks': WARNING,
|
||||||
|
'no-loop-func': OFF,
|
||||||
|
'no-magic-numbers': OFF,
|
||||||
|
'no-multi-str': ERROR,
|
||||||
|
'no-native-reassign': [ERROR, {
|
||||||
|
exceptions: ['Map', 'Set']
|
||||||
|
}],
|
||||||
|
'no-new-func': ERROR,
|
||||||
|
'no-new': WARNING,
|
||||||
|
'no-new-wrappers': WARNING,
|
||||||
|
'no-octal-escape': WARNING,
|
||||||
|
'no-octal': WARNING,
|
||||||
|
'no-param-reassign': OFF,
|
||||||
|
'no-process-env': OFF,
|
||||||
|
'no-proto': ERROR,
|
||||||
|
'no-redeclare': OFF,
|
||||||
|
// TODO should be WARNING?
|
||||||
|
'no-return-assign': OFF,
|
||||||
|
'no-script-url': ERROR,
|
||||||
|
'no-self-compare': WARNING,
|
||||||
|
'no-sequences': WARNING,
|
||||||
|
'no-throw-literal': ERROR,
|
||||||
|
'no-useless-call': WARNING,
|
||||||
|
'no-void': OFF,
|
||||||
|
'no-warning-comments': OFF,
|
||||||
|
'no-with': OFF,
|
||||||
|
radix: WARNING,
|
||||||
|
'vars-on-top': OFF,
|
||||||
|
yoda: OFF,
|
||||||
|
'init-declarations': OFF,
|
||||||
|
'no-catch-shadow': ERROR,
|
||||||
|
'no-delete-var': ERROR,
|
||||||
|
'no-label-var': WARNING,
|
||||||
|
'no-shadow-restricted-names': WARNING,
|
||||||
|
'no-undef-init': OFF,
|
||||||
|
'no-undef': ERROR,
|
||||||
|
'no-undefined': OFF,
|
||||||
|
'callback-return': OFF,
|
||||||
|
'global-require': OFF,
|
||||||
|
'handle-callback-err': OFF,
|
||||||
|
'no-mixed-requires': OFF,
|
||||||
|
'no-new-require': OFF,
|
||||||
|
'no-path-concat': OFF,
|
||||||
|
'no-process-exit': OFF,
|
||||||
|
'no-restricted-modules': OFF,
|
||||||
|
'no-sync': OFF,
|
||||||
|
camelcase: [OFF, {
|
||||||
|
properties: 'always'
|
||||||
|
}],
|
||||||
|
'consistent-this': [OFF, 'self'],
|
||||||
|
'func-names': OFF,
|
||||||
|
'func-style': [OFF, 'declaration'],
|
||||||
|
'id-length': OFF,
|
||||||
|
'id-match': OFF,
|
||||||
|
'max-depth': OFF,
|
||||||
|
'max-nested-callbacks': OFF,
|
||||||
|
'max-params': OFF,
|
||||||
|
'max-statements': OFF,
|
||||||
|
'new-cap': OFF,
|
||||||
|
'newline-after-var': OFF,
|
||||||
|
'no-array-constructor': ERROR,
|
||||||
|
'no-continue': OFF,
|
||||||
|
'no-inline-comments': OFF,
|
||||||
|
'no-lonely-if': OFF,
|
||||||
|
'no-negated-condition': OFF,
|
||||||
|
'no-nested-ternary': OFF,
|
||||||
|
'no-new-object': WARNING,
|
||||||
|
'no-plusplus': OFF,
|
||||||
|
'no-ternary': OFF,
|
||||||
|
'no-underscore-dangle': OFF,
|
||||||
|
'no-unneeded-ternary': WARNING,
|
||||||
|
'one-var': [WARNING, {
|
||||||
|
initialized: 'never'
|
||||||
|
}],
|
||||||
|
'operator-assignment': [WARNING, 'always'],
|
||||||
|
'require-jsdoc': OFF,
|
||||||
|
'sort-vars': OFF,
|
||||||
|
'spaced-comment': [OFF, 'always', {
|
||||||
|
exceptions: ['jshint', 'jslint', 'eslint', 'global']
|
||||||
|
}],
|
||||||
|
'constructor-super': ERROR,
|
||||||
|
'no-class-assign': WARNING,
|
||||||
|
'no-const-assign': ERROR,
|
||||||
|
'no-dupe-class-members': ERROR,
|
||||||
|
'no-this-before-super': ERROR,
|
||||||
|
'object-shorthand': OFF,
|
||||||
|
'prefer-const': OFF,
|
||||||
|
'prefer-spread': OFF,
|
||||||
|
'prefer-reflect': OFF,
|
||||||
|
'prefer-template': OFF,
|
||||||
|
'require-yield': OFF,
|
||||||
|
'babel/generator-star-spacing': OFF,
|
||||||
|
'babel/new-cap': OFF,
|
||||||
|
'babel/array-bracket-spacing': OFF,
|
||||||
|
'babel/object-curly-spacing': OFF,
|
||||||
|
'babel/object-shorthand': OFF,
|
||||||
|
'babel/arrow-parens': OFF,
|
||||||
|
'babel/no-await-in-loop': OFF,
|
||||||
|
'babel/flow-object-type': OFF,
|
||||||
|
'react/display-name': OFF,
|
||||||
|
'react/forbid-prop-types': OFF,
|
||||||
|
'react/jsx-closing-bracket-location': OFF,
|
||||||
|
'react/jsx-curly-spacing': OFF,
|
||||||
|
'react/jsx-equals-spacing': WARNING,
|
||||||
|
'react/jsx-filename-extension': OFF,
|
||||||
|
'react/jsx-first-prop-new-line': OFF,
|
||||||
|
'react/jsx-handler-names': OFF,
|
||||||
|
'react/jsx-indent': OFF,
|
||||||
|
'react/jsx-indent-props': OFF,
|
||||||
|
'react/jsx-key': OFF,
|
||||||
|
'react/jsx-max-props-per-line': OFF,
|
||||||
|
'react/jsx-no-bind': OFF,
|
||||||
|
'react/jsx-no-duplicate-props': ERROR,
|
||||||
|
'react/jsx-no-literals': OFF,
|
||||||
|
'react/jsx-no-target-blank': OFF,
|
||||||
|
'react/jsx-pascal-case': OFF,
|
||||||
|
'react/jsx-sort-props': OFF,
|
||||||
|
'react/jsx-uses-vars': ERROR,
|
||||||
|
'react/no-comment-textnodes': OFF,
|
||||||
|
'react/no-danger': OFF,
|
||||||
|
'react/no-deprecated': OFF,
|
||||||
|
'react/no-did-mount-set-state': OFF,
|
||||||
|
'react/no-did-update-set-state': OFF,
|
||||||
|
'react/no-direct-mutation-state': OFF,
|
||||||
|
'react/no-multi-comp': OFF,
|
||||||
|
'react/no-render-return-value': OFF,
|
||||||
|
'react/no-set-state': OFF,
|
||||||
|
'react/no-string-refs': OFF,
|
||||||
|
'react/no-unknown-property': OFF,
|
||||||
|
'react/prefer-es6-class': OFF,
|
||||||
|
'react/prefer-stateless-function': OFF,
|
||||||
|
'react/prop-types': OFF,
|
||||||
|
'react/require-extension': OFF,
|
||||||
|
'react/require-optimization': OFF,
|
||||||
|
'react/require-render-return': OFF,
|
||||||
|
'react/sort-comp': OFF,
|
||||||
|
'react/sort-prop-types': OFF,
|
||||||
|
'accessor-pairs': OFF,
|
||||||
|
'brace-style': [ERROR, '1tbs'],
|
||||||
|
'consistent-return': OFF,
|
||||||
|
'dot-location': [ERROR, 'property'],
|
||||||
|
// We use console['error']() as a signal to not transform it:
|
||||||
|
'dot-notation': [ERROR, {
|
||||||
|
allowPattern: '^(error|warn)$'
|
||||||
|
}],
|
||||||
|
'eol-last': ERROR,
|
||||||
|
eqeqeq: [ERROR, 'allow-null'],
|
||||||
|
indent: OFF,
|
||||||
|
'jsx-quotes': [ERROR, 'prefer-double'],
|
||||||
|
'keyword-spacing': [ERROR, {
|
||||||
|
after: true,
|
||||||
|
before: true
|
||||||
|
}],
|
||||||
|
'no-bitwise': OFF,
|
||||||
|
'no-console': OFF,
|
||||||
|
'no-inner-declarations': [ERROR, 'functions'],
|
||||||
|
'no-multi-spaces': ERROR,
|
||||||
|
'no-restricted-globals': restrictedGlobals |> [ERROR].concat(%),
|
||||||
|
'no-restricted-syntax': [ERROR, 'WithStatement', {
|
||||||
|
selector: 'MemberExpression[property.name=/^(?:substring|substr)$/]',
|
||||||
|
message: 'Prefer string.slice() over .substring() and .substr().'
|
||||||
|
}],
|
||||||
|
'no-shadow': ERROR,
|
||||||
|
'no-unused-vars': [ERROR, {
|
||||||
|
args: 'none'
|
||||||
|
}],
|
||||||
|
'no-use-before-define': OFF,
|
||||||
|
'no-useless-concat': OFF,
|
||||||
|
quotes: [ERROR, 'single', {
|
||||||
|
avoidEscape: true,
|
||||||
|
allowTemplateLiterals: true
|
||||||
|
}],
|
||||||
|
'space-before-blocks': ERROR,
|
||||||
|
'space-before-function-paren': OFF,
|
||||||
|
'valid-typeof': [ERROR, {
|
||||||
|
requireStringLiterals: true
|
||||||
|
}],
|
||||||
|
// Flow fails with non-string literal keys
|
||||||
|
'no-useless-computed-key': OFF,
|
||||||
|
// We apply these settings to files that should run on Node.
|
||||||
|
// They can't use JSX or ES6 modules, and must be in strict mode.
|
||||||
|
// They can, however, use other ES6 features.
|
||||||
|
// (Note these rules are overridden later for source files.)
|
||||||
|
'no-var': ERROR,
|
||||||
|
strict: ERROR,
|
||||||
|
// Enforced by Prettier
|
||||||
|
// TODO: Prettier doesn't handle long strings or long comments. Not a big
|
||||||
|
// deal. But I turned it off because loading the plugin causes some obscure
|
||||||
|
// syntax error and it didn't seem worth investigating.
|
||||||
|
'max-len': OFF,
|
||||||
|
// React & JSX
|
||||||
|
// Our transforms set this automatically
|
||||||
|
'react/jsx-boolean-value': [ERROR, 'always'],
|
||||||
|
'react/jsx-no-undef': ERROR,
|
||||||
|
// We don't care to do this
|
||||||
|
'react/jsx-sort-prop-types': OFF,
|
||||||
|
'react/jsx-space-before-closing': ERROR,
|
||||||
|
'react/jsx-uses-react': ERROR,
|
||||||
|
'react/no-is-mounted': OFF,
|
||||||
|
// This isn't useful in our test code
|
||||||
|
'react/react-in-jsx-scope': ERROR,
|
||||||
|
'react/self-closing-comp': ERROR,
|
||||||
|
// We don't care to do this
|
||||||
|
'react/jsx-wrap-multilines': [ERROR, {
|
||||||
|
declaration: false,
|
||||||
|
assignment: false
|
||||||
|
}],
|
||||||
|
// Prevent for...of loops because they require a Symbol polyfill.
|
||||||
|
// You can disable this rule for code that isn't shipped (e.g. build scripts and tests).
|
||||||
|
'no-for-of-loops/no-for-of-loops': ERROR,
|
||||||
|
// Prevent function declarations after return statements
|
||||||
|
'no-function-declare-after-return/no-function-declare-after-return': ERROR,
|
||||||
|
// CUSTOM RULES
|
||||||
|
// the second argument of warning/invariant should be a literal string
|
||||||
|
'react-internal/no-primitive-constructors': ERROR,
|
||||||
|
'react-internal/safe-string-coercion': [ERROR, {
|
||||||
|
isProductionUserAppCode: true
|
||||||
|
}],
|
||||||
|
'react-internal/no-to-warn-dev-within-to-throw': ERROR,
|
||||||
|
'react-internal/warning-args': ERROR,
|
||||||
|
'react-internal/no-production-logging': ERROR
|
||||||
|
},
|
||||||
|
overrides: [{
|
||||||
|
// By default, anything error message that appears the packages directory
|
||||||
|
// must have a corresponding error code. The exceptions are defined
|
||||||
|
// in the next override entry.
|
||||||
|
files: ['packages/**/*.js'],
|
||||||
|
rules: {
|
||||||
|
'react-internal/prod-error-codes': ERROR
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// These are files where it's OK to have unminified error messages. These
|
||||||
|
// are environments where bundle size isn't a concern, like tests
|
||||||
|
// or Node.
|
||||||
|
files: ['packages/react-dom/src/test-utils/**/*.js', 'packages/react-devtools-shared/**/*.js', 'packages/react-noop-renderer/**/*.js', 'packages/react-refresh/**/*.js', 'packages/react-server-dom-esm/**/*.js', 'packages/react-server-dom-webpack/**/*.js', 'packages/react-server-dom-turbopack/**/*.js', 'packages/react-server-dom-fb/**/*.js', 'packages/react-test-renderer/**/*.js', 'packages/react-debug-tools/**/*.js', 'packages/react-devtools-extensions/**/*.js', 'packages/react-devtools-timeline/**/*.js', 'packages/react-native-renderer/**/*.js', 'packages/eslint-plugin-react-hooks/**/*.js', 'packages/jest-react/**/*.js', 'packages/internal-test-utils/**/*.js', 'packages/**/__tests__/*.js', 'packages/**/npm/*.js'],
|
||||||
|
rules: {
|
||||||
|
'react-internal/prod-error-codes': OFF
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// We apply these settings to files that we ship through npm.
|
||||||
|
// They must be ES5.
|
||||||
|
files: es5Paths,
|
||||||
|
parser: 'espree',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 5,
|
||||||
|
sourceType: 'script'
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'no-var': OFF,
|
||||||
|
strict: ERROR
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// We apply these settings to the source files that get compiled.
|
||||||
|
// They can use all features including JSX (but shouldn't use `var`).
|
||||||
|
files: esNextPaths,
|
||||||
|
parser: 'hermes-eslint',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 8,
|
||||||
|
sourceType: 'module'
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'no-var': ERROR,
|
||||||
|
'prefer-const': ERROR,
|
||||||
|
strict: OFF
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
files: ['**/__tests__/*.js'],
|
||||||
|
rules: {
|
||||||
|
// https://github.com/jest-community/eslint-plugin-jest
|
||||||
|
'jest/no-focused-tests': ERROR,
|
||||||
|
'jest/valid-expect': ERROR,
|
||||||
|
'jest/valid-expect-in-promise': ERROR
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
// disable no focused tests for test setup helper files even if they are inside __tests__ directory
|
||||||
|
files: ['**/setupTests.js'],
|
||||||
|
rules: {
|
||||||
|
'jest/no-focused-tests': OFF
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
files: ['**/__tests__/**/*.js', 'scripts/**/*.js', 'packages/*/npm/**/*.js', 'packages/dom-event-testing-library/**/*.js', 'packages/react-devtools*/**/*.js', 'dangerfile.js', 'fixtures', 'packages/react-dom/src/test-utils/*.js'],
|
||||||
|
rules: {
|
||||||
|
'react-internal/no-production-logging': OFF,
|
||||||
|
'react-internal/warning-args': OFF,
|
||||||
|
'react-internal/safe-string-coercion': [ERROR, {
|
||||||
|
isProductionUserAppCode: false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
files: ['scripts/eslint-rules/*.js', 'packages/eslint-plugin-react-hooks/src/*.js'],
|
||||||
|
plugins: ['eslint-plugin'],
|
||||||
|
rules: {
|
||||||
|
'eslint-plugin/prefer-object-rule': ERROR,
|
||||||
|
'eslint-plugin/require-meta-fixable': [ERROR, {
|
||||||
|
catchNoFixerButFixableProperty: true
|
||||||
|
}],
|
||||||
|
'eslint-plugin/require-meta-has-suggestions': ERROR
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
files: ['packages/react-native-renderer/**/*.js'],
|
||||||
|
globals: {
|
||||||
|
nativeFabricUIManager: 'readonly',
|
||||||
|
RN$enableMicrotasksInReact: 'readonly'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
files: ['packages/react-server-dom-webpack/**/*.js'],
|
||||||
|
globals: {
|
||||||
|
__webpack_chunk_load__: 'readonly',
|
||||||
|
__webpack_require__: 'readonly'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
files: ['packages/react-server-dom-turbopack/**/*.js'],
|
||||||
|
globals: {
|
||||||
|
__turbopack_load__: 'readonly',
|
||||||
|
__turbopack_require__: 'readonly'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
files: ['packages/scheduler/**/*.js'],
|
||||||
|
globals: {
|
||||||
|
TaskController: 'readonly'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
files: ['packages/react-devtools-extensions/**/*.js'],
|
||||||
|
globals: {
|
||||||
|
__IS_CHROME__: 'readonly',
|
||||||
|
__IS_FIREFOX__: 'readonly',
|
||||||
|
__IS_EDGE__: 'readonly',
|
||||||
|
__IS_INTERNAL_VERSION__: 'readonly'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
files: ['packages/react-devtools-shared/**/*.js'],
|
||||||
|
globals: {
|
||||||
|
__IS_INTERNAL_VERSION__: 'readonly'
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
es6: true,
|
||||||
|
node: true,
|
||||||
|
jest: true
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
$Call: 'readonly',
|
||||||
|
$ElementType: 'readonly',
|
||||||
|
$Flow$ModuleRef: 'readonly',
|
||||||
|
$FlowFixMe: 'readonly',
|
||||||
|
$Keys: 'readonly',
|
||||||
|
$NonMaybeType: 'readonly',
|
||||||
|
$PropertyType: 'readonly',
|
||||||
|
$ReadOnly: 'readonly',
|
||||||
|
$ReadOnlyArray: 'readonly',
|
||||||
|
$ArrayBufferView: 'readonly',
|
||||||
|
$Shape: 'readonly',
|
||||||
|
ReturnType: 'readonly',
|
||||||
|
AnimationFrameID: 'readonly',
|
||||||
|
// For Flow type annotation. Only `BigInt` is valid at runtime.
|
||||||
|
bigint: 'readonly',
|
||||||
|
BigInt: 'readonly',
|
||||||
|
BigInt64Array: 'readonly',
|
||||||
|
BigUint64Array: 'readonly',
|
||||||
|
Class: 'readonly',
|
||||||
|
ClientRect: 'readonly',
|
||||||
|
CopyInspectedElementPath: 'readonly',
|
||||||
|
DOMHighResTimeStamp: 'readonly',
|
||||||
|
EventListener: 'readonly',
|
||||||
|
Iterable: 'readonly',
|
||||||
|
AsyncIterable: 'readonly',
|
||||||
|
$AsyncIterable: 'readonly',
|
||||||
|
$AsyncIterator: 'readonly',
|
||||||
|
Iterator: 'readonly',
|
||||||
|
AsyncIterator: 'readonly',
|
||||||
|
IteratorResult: 'readonly',
|
||||||
|
JSONValue: 'readonly',
|
||||||
|
JSResourceReference: 'readonly',
|
||||||
|
MouseEventHandler: 'readonly',
|
||||||
|
PropagationPhases: 'readonly',
|
||||||
|
PropertyDescriptor: 'readonly',
|
||||||
|
React$AbstractComponent: 'readonly',
|
||||||
|
React$Component: 'readonly',
|
||||||
|
React$ComponentType: 'readonly',
|
||||||
|
React$Config: 'readonly',
|
||||||
|
React$Context: 'readonly',
|
||||||
|
React$Element: 'readonly',
|
||||||
|
React$ElementConfig: 'readonly',
|
||||||
|
React$ElementProps: 'readonly',
|
||||||
|
React$ElementRef: 'readonly',
|
||||||
|
React$ElementType: 'readonly',
|
||||||
|
React$Key: 'readonly',
|
||||||
|
React$Node: 'readonly',
|
||||||
|
React$Portal: 'readonly',
|
||||||
|
React$Ref: 'readonly',
|
||||||
|
ReadableStreamController: 'readonly',
|
||||||
|
ReadableStreamReader: 'readonly',
|
||||||
|
RequestInfo: 'readonly',
|
||||||
|
RequestOptions: 'readonly',
|
||||||
|
StoreAsGlobal: 'readonly',
|
||||||
|
symbol: 'readonly',
|
||||||
|
SyntheticEvent: 'readonly',
|
||||||
|
SyntheticMouseEvent: 'readonly',
|
||||||
|
Thenable: 'readonly',
|
||||||
|
TimeoutID: 'readonly',
|
||||||
|
WheelEventHandler: 'readonly',
|
||||||
|
FinalizationRegistry: 'readonly',
|
||||||
|
spyOnDev: 'readonly',
|
||||||
|
spyOnDevAndProd: 'readonly',
|
||||||
|
spyOnProd: 'readonly',
|
||||||
|
__DEV__: 'readonly',
|
||||||
|
__EXPERIMENTAL__: 'readonly',
|
||||||
|
__EXTENSION__: 'readonly',
|
||||||
|
__PROFILE__: 'readonly',
|
||||||
|
__TEST__: 'readonly',
|
||||||
|
__VARIANT__: 'readonly',
|
||||||
|
__unmockReact: 'readonly',
|
||||||
|
gate: 'readonly',
|
||||||
|
trustedTypes: 'readonly',
|
||||||
|
IS_REACT_ACT_ENVIRONMENT: 'readonly',
|
||||||
|
AsyncLocalStorage: 'readonly',
|
||||||
|
async_hooks: 'readonly',
|
||||||
|
globalThis: 'readonly'
|
||||||
|
}
|
||||||
|
};
|
27
output_testing/1.prettierrc.js
Normal file
27
output_testing/1.prettierrc.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const {
|
||||||
|
esNextPaths,
|
||||||
|
typescriptPaths
|
||||||
|
} = './scripts/shared/pathsByLanguageVersion' |> require(%);
|
||||||
|
module.exports = {
|
||||||
|
bracketSpacing: false,
|
||||||
|
singleQuote: true,
|
||||||
|
bracketSameLine: true,
|
||||||
|
trailingComma: 'es5',
|
||||||
|
printWidth: 80,
|
||||||
|
parser: 'flow',
|
||||||
|
arrowParens: 'avoid',
|
||||||
|
overrides: [{
|
||||||
|
files: esNextPaths,
|
||||||
|
options: {
|
||||||
|
trailingComma: 'all'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
files: typescriptPaths,
|
||||||
|
options: {
|
||||||
|
trailingComma: 'all',
|
||||||
|
parser: 'typescript'
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { throwInput } from "shared-runtime";
|
||||||
|
function Component(props) {
|
||||||
|
const object = {
|
||||||
|
foo() {
|
||||||
|
try {
|
||||||
|
[props.value] |> throwInput(%);
|
||||||
|
} catch (e) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return object.foo();
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
value: 42
|
||||||
|
}]
|
||||||
|
};
|
21
output_testing/1001object-shorthand-method-1.js
Normal file
21
output_testing/1001object-shorthand-method-1.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { createHookWrapper } from "shared-runtime";
|
||||||
|
function useHook({
|
||||||
|
a,
|
||||||
|
b
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
x: function () {
|
||||||
|
return [a];
|
||||||
|
},
|
||||||
|
y() {
|
||||||
|
return [b];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: useHook |> createHookWrapper(%),
|
||||||
|
params: [{
|
||||||
|
a: 1,
|
||||||
|
b: 2
|
||||||
|
}]
|
||||||
|
};
|
11
output_testing/1002lambda-mutate-shadowed-object.js
Normal file
11
output_testing/1002lambda-mutate-shadowed-object.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
function Component() {
|
||||||
|
const x = {};
|
||||||
|
{
|
||||||
|
const x = [];
|
||||||
|
const fn = function () {
|
||||||
|
x |> mutate(%);
|
||||||
|
};
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
return x; // should return {}
|
||||||
|
}
|
9
output_testing/1003alias-nested-member-path-mutate.js
Normal file
9
output_testing/1003alias-nested-member-path-mutate.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
function component() {
|
||||||
|
let z = [];
|
||||||
|
let y = {};
|
||||||
|
y.z = z;
|
||||||
|
let x = {};
|
||||||
|
x.y = y;
|
||||||
|
x.y.z |> mutate(%);
|
||||||
|
return x;
|
||||||
|
}
|
8
output_testing/1004error.invalid-mutation-in-closure.js
Normal file
8
output_testing/1004error.invalid-mutation-in-closure.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
function useInvalidMutation(options) {
|
||||||
|
function test() {
|
||||||
|
// error should not point on this line
|
||||||
|
options.foo |> foo(%);
|
||||||
|
options.foo = "bar";
|
||||||
|
}
|
||||||
|
return test;
|
||||||
|
}
|
10
output_testing/1005do-while-conditional-break.js
Normal file
10
output_testing/1005do-while-conditional-break.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
function Component(props) {
|
||||||
|
let x = [0, 1, 2, 3];
|
||||||
|
do {
|
||||||
|
if (x === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
x |> mutate(%);
|
||||||
|
} while (props.cond);
|
||||||
|
return x;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { identity } from "shared-runtime";
|
||||||
|
const SCALE = 2;
|
||||||
|
function Component(props) {
|
||||||
|
const key = SCALE;
|
||||||
|
const context = {
|
||||||
|
[key]: [props.value] |> identity(%)
|
||||||
|
};
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
key: "Sathya",
|
||||||
|
value: "Compiler"
|
||||||
|
}]
|
||||||
|
};
|
24
output_testing/1007object-shorthand-method-2.js
Normal file
24
output_testing/1007object-shorthand-method-2.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { createHookWrapper } from "shared-runtime";
|
||||||
|
function useHook({
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
c
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
x: [a],
|
||||||
|
y() {
|
||||||
|
return [b];
|
||||||
|
},
|
||||||
|
z: {
|
||||||
|
c
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: useHook |> createHookWrapper(%),
|
||||||
|
params: [{
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
c: 2
|
||||||
|
}]
|
||||||
|
};
|
52
output_testing/1008early-return-within-reactive-scope.js
Normal file
52
output_testing/1008early-return-within-reactive-scope.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import { makeArray } from "shared-runtime";
|
||||||
|
function Component(props) {
|
||||||
|
let x = [];
|
||||||
|
if (props.cond) {
|
||||||
|
// oops no memo!
|
||||||
|
props.a |> x.push(%);
|
||||||
|
return x;
|
||||||
|
} else {
|
||||||
|
return props.b |> makeArray(%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [],
|
||||||
|
sequentialRenders: [
|
||||||
|
// pattern 1
|
||||||
|
{
|
||||||
|
cond: true,
|
||||||
|
a: 42
|
||||||
|
}, {
|
||||||
|
cond: true,
|
||||||
|
a: 42
|
||||||
|
},
|
||||||
|
// pattern 2
|
||||||
|
{
|
||||||
|
cond: false,
|
||||||
|
b: 3.14
|
||||||
|
}, {
|
||||||
|
cond: false,
|
||||||
|
b: 3.14
|
||||||
|
},
|
||||||
|
// pattern 1
|
||||||
|
{
|
||||||
|
cond: true,
|
||||||
|
a: 42
|
||||||
|
},
|
||||||
|
// pattern 2
|
||||||
|
{
|
||||||
|
cond: false,
|
||||||
|
b: 3.14
|
||||||
|
},
|
||||||
|
// pattern 1
|
||||||
|
{
|
||||||
|
cond: true,
|
||||||
|
a: 42
|
||||||
|
},
|
||||||
|
// pattern 2
|
||||||
|
{
|
||||||
|
cond: false,
|
||||||
|
b: 3.14
|
||||||
|
}]
|
||||||
|
};
|
11
output_testing/1009simple-alias.js
Normal file
11
output_testing/1009simple-alias.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
function mutate() {}
|
||||||
|
function foo() {
|
||||||
|
let a = {};
|
||||||
|
let b = {};
|
||||||
|
let c = {};
|
||||||
|
a = b;
|
||||||
|
b = c;
|
||||||
|
c = a;
|
||||||
|
a |> mutate(%, b);
|
||||||
|
return c;
|
||||||
|
}
|
617
output_testing/100build.js
Normal file
617
output_testing/100build.js
Normal file
|
@ -0,0 +1,617 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const rollup = 'rollup' |> require(%);
|
||||||
|
const babel = ('@rollup/plugin-babel' |> require(%)).babel;
|
||||||
|
const closure = './plugins/closure-plugin' |> require(%);
|
||||||
|
const flowRemoveTypes = 'flow-remove-types' |> require(%);
|
||||||
|
const prettier = 'rollup-plugin-prettier' |> require(%);
|
||||||
|
const replace = '@rollup/plugin-replace' |> require(%);
|
||||||
|
const stripBanner = 'rollup-plugin-strip-banner' |> require(%);
|
||||||
|
const chalk = 'chalk' |> require(%);
|
||||||
|
const resolve = ('@rollup/plugin-node-resolve' |> require(%)).nodeResolve;
|
||||||
|
const fs = 'fs' |> require(%);
|
||||||
|
const argv = ('minimist' |> require(%))(2 |> process.argv.slice(%));
|
||||||
|
const Modules = './modules' |> require(%);
|
||||||
|
const Bundles = './bundles' |> require(%);
|
||||||
|
const Stats = './stats' |> require(%);
|
||||||
|
const Sync = './sync' |> require(%);
|
||||||
|
const sizes = './plugins/sizes-plugin' |> require(%);
|
||||||
|
const useForks = './plugins/use-forks-plugin' |> require(%);
|
||||||
|
const dynamicImports = './plugins/dynamic-imports' |> require(%);
|
||||||
|
const Packaging = './packaging' |> require(%);
|
||||||
|
const {
|
||||||
|
asyncRimRaf
|
||||||
|
} = './utils' |> require(%);
|
||||||
|
const codeFrame = '@babel/code-frame' |> require(%);
|
||||||
|
const Wrappers = './wrappers' |> require(%);
|
||||||
|
const RELEASE_CHANNEL = process.env.RELEASE_CHANNEL;
|
||||||
|
|
||||||
|
// Default to building in experimental mode. If the release channel is set via
|
||||||
|
// an environment variable, then check if it's "experimental".
|
||||||
|
const __EXPERIMENTAL__ = typeof RELEASE_CHANNEL === 'string' ? RELEASE_CHANNEL === 'experimental' : true;
|
||||||
|
|
||||||
|
// Errors in promises should be fatal.
|
||||||
|
let loggedErrors = new Set();
|
||||||
|
'unhandledRejection' |> process.on(%, err => {
|
||||||
|
if (err |> loggedErrors.has(%)) {
|
||||||
|
// No need to print it twice.
|
||||||
|
1 |> process.exit(%);
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
const {
|
||||||
|
NODE_ES2015,
|
||||||
|
ESM_DEV,
|
||||||
|
ESM_PROD,
|
||||||
|
NODE_DEV,
|
||||||
|
NODE_PROD,
|
||||||
|
NODE_PROFILING,
|
||||||
|
BUN_DEV,
|
||||||
|
BUN_PROD,
|
||||||
|
FB_WWW_DEV,
|
||||||
|
FB_WWW_PROD,
|
||||||
|
FB_WWW_PROFILING,
|
||||||
|
RN_OSS_DEV,
|
||||||
|
RN_OSS_PROD,
|
||||||
|
RN_OSS_PROFILING,
|
||||||
|
RN_FB_DEV,
|
||||||
|
RN_FB_PROD,
|
||||||
|
RN_FB_PROFILING,
|
||||||
|
BROWSER_SCRIPT
|
||||||
|
} = Bundles.bundleTypes;
|
||||||
|
const {
|
||||||
|
getFilename
|
||||||
|
} = Bundles;
|
||||||
|
function parseRequestedNames(names, toCase) {
|
||||||
|
let result = [];
|
||||||
|
for (let i = 0; i < names.length; i++) {
|
||||||
|
let splitNames = ',' |> names[i].split(%);
|
||||||
|
for (let j = 0; j < splitNames.length; j++) {
|
||||||
|
let name = splitNames[j].trim();
|
||||||
|
if (!name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (toCase === 'uppercase') {
|
||||||
|
name = name.toUpperCase();
|
||||||
|
} else if (toCase === 'lowercase') {
|
||||||
|
name = name.toLowerCase();
|
||||||
|
}
|
||||||
|
name |> result.push(%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const requestedBundleTypes = argv.type ? [argv.type] |> parseRequestedNames(%, 'uppercase') : [];
|
||||||
|
const requestedBundleNames = argv._ |> parseRequestedNames(%, 'lowercase');
|
||||||
|
const forcePrettyOutput = argv.pretty;
|
||||||
|
const isWatchMode = argv.watch;
|
||||||
|
const syncFBSourcePath = argv['sync-fbsource'];
|
||||||
|
const syncWWWPath = argv['sync-www'];
|
||||||
|
|
||||||
|
// Non-ES2015 stuff applied before closure compiler.
|
||||||
|
const babelPlugins = [
|
||||||
|
// These plugins filter out non-ES2015.
|
||||||
|
['@babel/plugin-proposal-class-properties', {
|
||||||
|
loose: true
|
||||||
|
}], 'syntax-trailing-function-commas',
|
||||||
|
// These use loose mode which avoids embedding a runtime.
|
||||||
|
// TODO: Remove object spread from the source. Prefer Object.assign instead.
|
||||||
|
['@babel/plugin-proposal-object-rest-spread', {
|
||||||
|
loose: true,
|
||||||
|
useBuiltIns: true
|
||||||
|
}], ['@babel/plugin-transform-template-literals', {
|
||||||
|
loose: true
|
||||||
|
}],
|
||||||
|
// TODO: Remove for...of from the source. It requires a runtime to be embedded.
|
||||||
|
'@babel/plugin-transform-for-of',
|
||||||
|
// TODO: Remove array spread from the source. Prefer .apply instead.
|
||||||
|
['@babel/plugin-transform-spread', {
|
||||||
|
loose: true,
|
||||||
|
useBuiltIns: true
|
||||||
|
}], '@babel/plugin-transform-parameters',
|
||||||
|
// TODO: Remove array destructuring from the source. Requires runtime.
|
||||||
|
['@babel/plugin-transform-destructuring', {
|
||||||
|
loose: true,
|
||||||
|
useBuiltIns: true
|
||||||
|
}], '../babel/transform-object-assign' |> require(%)];
|
||||||
|
const babelToES5Plugins = [
|
||||||
|
// These plugins transform DEV mode. Closure compiler deals with these in PROD.
|
||||||
|
'@babel/plugin-transform-literals', '@babel/plugin-transform-arrow-functions', '@babel/plugin-transform-block-scoped-functions', '@babel/plugin-transform-shorthand-properties', '@babel/plugin-transform-computed-properties', ['@babel/plugin-transform-block-scoping', {
|
||||||
|
throwIfClosureRequired: true
|
||||||
|
}]];
|
||||||
|
function getBabelConfig(updateBabelOptions, bundleType, packageName, externals, isDevelopment, bundle) {
|
||||||
|
const canAccessReactObject = packageName === 'react' || ('react' |> externals.indexOf(%)) !== -1;
|
||||||
|
let options = {
|
||||||
|
exclude: '/**/node_modules/**',
|
||||||
|
babelrc: false,
|
||||||
|
configFile: false,
|
||||||
|
presets: [],
|
||||||
|
plugins: [...babelPlugins],
|
||||||
|
babelHelpers: 'bundled',
|
||||||
|
sourcemap: false
|
||||||
|
};
|
||||||
|
if (isDevelopment) {
|
||||||
|
options.plugins.push(...babelToES5Plugins,
|
||||||
|
// Turn console.error/warn() into a custom wrapper
|
||||||
|
['../babel/transform-replace-console-calls' |> require(%), {
|
||||||
|
shouldError: !canAccessReactObject
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
if (updateBabelOptions) {
|
||||||
|
options = options |> updateBabelOptions(%);
|
||||||
|
}
|
||||||
|
// Controls whether to replace error messages with error codes in production.
|
||||||
|
// By default, error messages are replaced in production.
|
||||||
|
if (!isDevelopment && bundle.minifyWithProdErrorCodes !== false) {
|
||||||
|
'../error-codes/transform-error-messages' |> require(%) |> options.plugins.push(%);
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
let getRollupInteropValue = id => {
|
||||||
|
// We're setting Rollup to assume that imports are ES modules unless otherwise specified.
|
||||||
|
// However, we also compile ES import syntax to `require()` using Babel.
|
||||||
|
// This causes Rollup to turn uses of `import SomeDefaultImport from 'some-module' into
|
||||||
|
// references to `SomeDefaultImport.default` due to CJS/ESM interop.
|
||||||
|
// Some CJS modules don't have a `.default` export, and the rewritten import is incorrect.
|
||||||
|
// Specifying `interop: 'default'` instead will have Rollup use the imported variable as-is,
|
||||||
|
// without adding a `.default` to the reference.
|
||||||
|
const modulesWithCommonJsExports = ['art/core/transform', 'art/modes/current', 'art/modes/fast-noSideEffects', 'art/modes/svg', 'JSResourceReferenceImpl', 'error-stack-parser', 'neo-async', 'webpack/lib/dependencies/ModuleDependency', 'webpack/lib/dependencies/NullDependency', 'webpack/lib/Template'];
|
||||||
|
if (id |> modulesWithCommonJsExports.includes(%)) {
|
||||||
|
return 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
// For all other modules, handle imports without any import helper utils
|
||||||
|
return 'esModule';
|
||||||
|
};
|
||||||
|
function getRollupOutputOptions(outputPath, format, globals, globalName, bundleType) {
|
||||||
|
const isProduction = bundleType |> isProductionBundleType(%);
|
||||||
|
return {
|
||||||
|
file: outputPath,
|
||||||
|
format,
|
||||||
|
globals,
|
||||||
|
freeze: !isProduction,
|
||||||
|
interop: getRollupInteropValue,
|
||||||
|
name: globalName,
|
||||||
|
sourcemap: false,
|
||||||
|
esModule: false,
|
||||||
|
exports: 'auto'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function getFormat(bundleType) {
|
||||||
|
switch (bundleType) {
|
||||||
|
case NODE_ES2015:
|
||||||
|
case NODE_DEV:
|
||||||
|
case NODE_PROD:
|
||||||
|
case NODE_PROFILING:
|
||||||
|
case BUN_DEV:
|
||||||
|
case BUN_PROD:
|
||||||
|
case FB_WWW_DEV:
|
||||||
|
case FB_WWW_PROD:
|
||||||
|
case FB_WWW_PROFILING:
|
||||||
|
case RN_OSS_DEV:
|
||||||
|
case RN_OSS_PROD:
|
||||||
|
case RN_OSS_PROFILING:
|
||||||
|
case RN_FB_DEV:
|
||||||
|
case RN_FB_PROD:
|
||||||
|
case RN_FB_PROFILING:
|
||||||
|
return `cjs`;
|
||||||
|
case ESM_DEV:
|
||||||
|
case ESM_PROD:
|
||||||
|
return `es`;
|
||||||
|
case BROWSER_SCRIPT:
|
||||||
|
return `iife`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isProductionBundleType(bundleType) {
|
||||||
|
switch (bundleType) {
|
||||||
|
case NODE_ES2015:
|
||||||
|
return true;
|
||||||
|
case ESM_DEV:
|
||||||
|
case NODE_DEV:
|
||||||
|
case BUN_DEV:
|
||||||
|
case FB_WWW_DEV:
|
||||||
|
case RN_OSS_DEV:
|
||||||
|
case RN_FB_DEV:
|
||||||
|
return false;
|
||||||
|
case ESM_PROD:
|
||||||
|
case NODE_PROD:
|
||||||
|
case BUN_PROD:
|
||||||
|
case NODE_PROFILING:
|
||||||
|
case FB_WWW_PROD:
|
||||||
|
case FB_WWW_PROFILING:
|
||||||
|
case RN_OSS_PROD:
|
||||||
|
case RN_OSS_PROFILING:
|
||||||
|
case RN_FB_PROD:
|
||||||
|
case RN_FB_PROFILING:
|
||||||
|
case BROWSER_SCRIPT:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown type: ${bundleType}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isProfilingBundleType(bundleType) {
|
||||||
|
switch (bundleType) {
|
||||||
|
case NODE_ES2015:
|
||||||
|
case FB_WWW_DEV:
|
||||||
|
case FB_WWW_PROD:
|
||||||
|
case NODE_DEV:
|
||||||
|
case NODE_PROD:
|
||||||
|
case BUN_DEV:
|
||||||
|
case BUN_PROD:
|
||||||
|
case RN_FB_DEV:
|
||||||
|
case RN_FB_PROD:
|
||||||
|
case RN_OSS_DEV:
|
||||||
|
case RN_OSS_PROD:
|
||||||
|
case ESM_DEV:
|
||||||
|
case ESM_PROD:
|
||||||
|
case BROWSER_SCRIPT:
|
||||||
|
return false;
|
||||||
|
case FB_WWW_PROFILING:
|
||||||
|
case NODE_PROFILING:
|
||||||
|
case RN_FB_PROFILING:
|
||||||
|
case RN_OSS_PROFILING:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown type: ${bundleType}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getBundleTypeFlags(bundleType) {
|
||||||
|
const isFBWWWBundle = bundleType === FB_WWW_DEV || bundleType === FB_WWW_PROD || bundleType === FB_WWW_PROFILING;
|
||||||
|
const isRNBundle = bundleType === RN_OSS_DEV || bundleType === RN_OSS_PROD || bundleType === RN_OSS_PROFILING || bundleType === RN_FB_DEV || bundleType === RN_FB_PROD || bundleType === RN_FB_PROFILING;
|
||||||
|
const isFBRNBundle = bundleType === RN_FB_DEV || bundleType === RN_FB_PROD || bundleType === RN_FB_PROFILING;
|
||||||
|
const shouldStayReadable = isFBWWWBundle || isRNBundle || forcePrettyOutput;
|
||||||
|
return {
|
||||||
|
isFBWWWBundle,
|
||||||
|
isRNBundle,
|
||||||
|
isFBRNBundle,
|
||||||
|
shouldStayReadable
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function forbidFBJSImports() {
|
||||||
|
return {
|
||||||
|
name: 'forbidFBJSImports',
|
||||||
|
resolveId(importee, importer) {
|
||||||
|
if (importee |> /^fbjs\//.test(%)) {
|
||||||
|
throw new Error(`Don't import ${importee} (found in ${importer}). ` + `Use the utilities in packages/shared/ instead.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function getPlugins(entry, externals, updateBabelOptions, filename, packageName, bundleType, globalName, moduleType, pureExternalModules, bundle) {
|
||||||
|
try {
|
||||||
|
const forks = Modules.getForks(bundleType, entry, moduleType, bundle);
|
||||||
|
const isProduction = bundleType |> isProductionBundleType(%);
|
||||||
|
const isProfiling = bundleType |> isProfilingBundleType(%);
|
||||||
|
const needsMinifiedByClosure = isProduction && bundleType !== ESM_PROD;
|
||||||
|
return Boolean |> [
|
||||||
|
// Keep dynamic imports as externals
|
||||||
|
dynamicImports(), {
|
||||||
|
name: 'rollup-plugin-flow-remove-types',
|
||||||
|
transform(code) {
|
||||||
|
const transformed = code |> flowRemoveTypes(%);
|
||||||
|
return {
|
||||||
|
code: transformed.toString(),
|
||||||
|
map: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, forks |> useForks(%),
|
||||||
|
// Ensure we don't try to bundle any fbjs modules.
|
||||||
|
forbidFBJSImports(), {
|
||||||
|
// skip: externals, // TODO: options.skip was removed in @rollup/plugin-node-resolve 3.0.0
|
||||||
|
} |> resolve(%), {
|
||||||
|
exclude: 'node_modules/**/*'
|
||||||
|
} |> stripBanner(%), getBabelConfig(updateBabelOptions, bundleType, packageName, externals, !isProduction, bundle) |> babel(%),
|
||||||
|
// Remove 'use strict' from individual source files.
|
||||||
|
{
|
||||||
|
name: "remove 'use strict'",
|
||||||
|
transform(source) {
|
||||||
|
return /['"]use strict["']/g |> source.replace(%, '');
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
preventAssignment: true,
|
||||||
|
values: {
|
||||||
|
__DEV__: isProduction ? 'false' : 'true',
|
||||||
|
__PROFILE__: isProfiling || !isProduction ? 'true' : 'false',
|
||||||
|
'process.env.NODE_ENV': isProduction ? "'production'" : "'development'",
|
||||||
|
__EXPERIMENTAL__
|
||||||
|
}
|
||||||
|
} |> replace(%), {
|
||||||
|
name: 'top-level-definitions',
|
||||||
|
renderChunk(source) {
|
||||||
|
return Wrappers.wrapWithTopLevelDefinitions(source, bundleType, globalName, filename, moduleType, bundle.wrapWithModuleBoundaries);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// For production builds, compile with Closure. We do this even for the
|
||||||
|
// "non-minified" production builds because Closure is much better at
|
||||||
|
// minification than what most applications use. During this step, we do
|
||||||
|
// preserve the original symbol names, though, so the resulting code is
|
||||||
|
// relatively readable.
|
||||||
|
//
|
||||||
|
// For the minified builds, the names will be mangled later.
|
||||||
|
//
|
||||||
|
// We don't bother with sourcemaps at this step. The sourcemaps we publish
|
||||||
|
// are only for whitespace and symbol renaming; they don't map back to
|
||||||
|
// before Closure was applied.
|
||||||
|
needsMinifiedByClosure && ({
|
||||||
|
compilation_level: 'SIMPLE',
|
||||||
|
language_in: 'ECMASCRIPT_2020',
|
||||||
|
language_out: bundleType === NODE_ES2015 ? 'ECMASCRIPT_2020' : bundleType === BROWSER_SCRIPT ? 'ECMASCRIPT5' : 'ECMASCRIPT5_STRICT',
|
||||||
|
emit_use_strict: bundleType !== BROWSER_SCRIPT && bundleType !== ESM_PROD && bundleType !== ESM_DEV,
|
||||||
|
env: 'CUSTOM',
|
||||||
|
warning_level: 'QUIET',
|
||||||
|
source_map_include_content: true,
|
||||||
|
use_types_for_optimization: false,
|
||||||
|
process_common_js_modules: false,
|
||||||
|
rewrite_polyfills: false,
|
||||||
|
inject_libraries: false,
|
||||||
|
allow_dynamic_import: true,
|
||||||
|
// Don't let it create global variables in the browser.
|
||||||
|
// https://github.com/facebook/react/issues/10909
|
||||||
|
assume_function_wrapper: true,
|
||||||
|
// Don't rename symbols (variable names, functions, etc). We leave
|
||||||
|
// this up to the application to handle, if they want. Otherwise gzip
|
||||||
|
// takes care of it.
|
||||||
|
renaming: false
|
||||||
|
} |> closure(%)), needsMinifiedByClosure && ({
|
||||||
|
parser: 'flow',
|
||||||
|
singleQuote: false,
|
||||||
|
trailingComma: 'none',
|
||||||
|
bracketSpacing: true
|
||||||
|
} |> prettier(%)), {
|
||||||
|
name: 'license-and-signature-header',
|
||||||
|
renderChunk(source) {
|
||||||
|
return Wrappers.wrapWithLicenseHeader(source, bundleType, globalName, filename, moduleType);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
getSize: (size, gzip) => {
|
||||||
|
const currentSizes = Stats.currentBuildResults.bundleSizes;
|
||||||
|
const recordIndex = (record => record.filename === filename && record.bundleType === bundleType) |> currentSizes.findIndex(%);
|
||||||
|
const index = recordIndex !== -1 ? recordIndex : currentSizes.length;
|
||||||
|
currentSizes[index] = {
|
||||||
|
filename,
|
||||||
|
bundleType,
|
||||||
|
packageName,
|
||||||
|
size,
|
||||||
|
gzip
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} |> sizes(%)].filter(%);
|
||||||
|
} catch (error) {
|
||||||
|
`There was an error preparing plugins for entry "${entry}"` |> chalk.red(%) |> console.error(%);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function shouldSkipBundle(bundle, bundleType) {
|
||||||
|
const shouldSkipBundleType = (bundleType |> bundle.bundleTypes.indexOf(%)) === -1;
|
||||||
|
if (shouldSkipBundleType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (requestedBundleTypes.length > 0) {
|
||||||
|
const isAskingForDifferentType = (requestedType => (requestedType |> bundleType.indexOf(%)) === -1) |> requestedBundleTypes.every(%);
|
||||||
|
if (isAskingForDifferentType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (requestedBundleNames.length > 0) {
|
||||||
|
// If the name ends with `something/index` we only match if the
|
||||||
|
// entry ends in something. Such as `react-dom/index` only matches
|
||||||
|
// `react-dom` but not `react-dom/server`. Everything else is fuzzy
|
||||||
|
// search.
|
||||||
|
const entryLowerCase = bundle.entry.toLowerCase() + '/index.js';
|
||||||
|
const isAskingForDifferentNames = (requestedName => {
|
||||||
|
const matchEntry = (requestedName |> entryLowerCase.indexOf(%)) !== -1;
|
||||||
|
if (!bundle.name) {
|
||||||
|
return !matchEntry;
|
||||||
|
}
|
||||||
|
const matchName = (requestedName |> bundle.name.toLowerCase().indexOf(%)) !== -1;
|
||||||
|
return !matchEntry && !matchName;
|
||||||
|
}) |> requestedBundleNames.every(%);
|
||||||
|
if (isAskingForDifferentNames) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function resolveEntryFork(resolvedEntry, isFBBundle) {
|
||||||
|
// Pick which entry point fork to use:
|
||||||
|
// .modern.fb.js
|
||||||
|
// .classic.fb.js
|
||||||
|
// .fb.js
|
||||||
|
// .stable.js
|
||||||
|
// .experimental.js
|
||||||
|
// .js
|
||||||
|
|
||||||
|
if (isFBBundle) {
|
||||||
|
const resolvedFBEntry = '.js' |> resolvedEntry.replace(%, __EXPERIMENTAL__ ? '.modern.fb.js' : '.classic.fb.js');
|
||||||
|
if (resolvedFBEntry |> fs.existsSync(%)) {
|
||||||
|
return resolvedFBEntry;
|
||||||
|
}
|
||||||
|
const resolvedGenericFBEntry = '.js' |> resolvedEntry.replace(%, '.fb.js');
|
||||||
|
if (resolvedGenericFBEntry |> fs.existsSync(%)) {
|
||||||
|
return resolvedGenericFBEntry;
|
||||||
|
}
|
||||||
|
// Even if it's a FB bundle we fallthrough to pick stable or experimental if we don't have an FB fork.
|
||||||
|
}
|
||||||
|
const resolvedForkedEntry = '.js' |> resolvedEntry.replace(%, __EXPERIMENTAL__ ? '.experimental.js' : '.stable.js');
|
||||||
|
if (resolvedForkedEntry |> fs.existsSync(%)) {
|
||||||
|
return resolvedForkedEntry;
|
||||||
|
}
|
||||||
|
// Just use the plain .js one.
|
||||||
|
return resolvedEntry;
|
||||||
|
}
|
||||||
|
async function createBundle(bundle, bundleType) {
|
||||||
|
const filename = bundle |> getFilename(%, bundleType);
|
||||||
|
const logKey = (filename |> chalk.white.bold(%)) + (` (${bundleType.toLowerCase()})` |> chalk.dim(%));
|
||||||
|
const format = bundleType |> getFormat(%);
|
||||||
|
const packageName = bundle.entry |> Packaging.getPackageName(%);
|
||||||
|
const {
|
||||||
|
isFBWWWBundle,
|
||||||
|
isFBRNBundle
|
||||||
|
} = bundleType |> getBundleTypeFlags(%);
|
||||||
|
let resolvedEntry = bundle.entry |> require.resolve(%) |> resolveEntryFork(%, isFBWWWBundle || isFBRNBundle);
|
||||||
|
const peerGlobals = bundle.externals |> Modules.getPeerGlobals(%, bundleType);
|
||||||
|
let externals = peerGlobals |> Object.keys(%);
|
||||||
|
const deps = bundleType |> Modules.getDependencies(%, bundle.entry);
|
||||||
|
externals = deps |> externals.concat(%);
|
||||||
|
const importSideEffects = Modules.getImportSideEffects();
|
||||||
|
const pureExternalModules = (module => !importSideEffects[module]) |> (importSideEffects |> Object.keys(%)).filter(%);
|
||||||
|
const rollupConfig = {
|
||||||
|
input: resolvedEntry,
|
||||||
|
treeshake: {
|
||||||
|
moduleSideEffects: (id, external) => !(external && (id |> pureExternalModules.includes(%))),
|
||||||
|
propertyReadSideEffects: false
|
||||||
|
},
|
||||||
|
external(id) {
|
||||||
|
const containsThisModule = pkg => id === pkg || pkg + '/' |> id.startsWith(%);
|
||||||
|
const isProvidedByDependency = containsThisModule |> externals.some(%);
|
||||||
|
if (isProvidedByDependency) {
|
||||||
|
if (('/src/' |> id.indexOf(%)) !== -1) {
|
||||||
|
throw 'You are trying to import ' + id + ' but ' + (containsThisModule |> externals.find(%)) + ' is one of npm dependencies, ' + 'so it will not contain that source file. You probably want ' + 'to create a new bundle entry point for it instead.' |> Error(%);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return !!peerGlobals[id];
|
||||||
|
},
|
||||||
|
onwarn: handleRollupWarning,
|
||||||
|
plugins: getPlugins(bundle.entry, externals, bundle.babel, filename, packageName, bundleType, bundle.global, bundle.moduleType, pureExternalModules, bundle),
|
||||||
|
output: {
|
||||||
|
externalLiveBindings: false,
|
||||||
|
freeze: false,
|
||||||
|
interop: getRollupInteropValue,
|
||||||
|
esModule: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const mainOutputPath = Packaging.getBundleOutputPath(bundle, bundleType, filename, packageName);
|
||||||
|
const rollupOutputOptions = getRollupOutputOptions(mainOutputPath, format, peerGlobals, bundle.global, bundleType);
|
||||||
|
if (isWatchMode) {
|
||||||
|
rollupConfig.output = [rollupOutputOptions];
|
||||||
|
const watcher = rollupConfig |> rollup.watch(%);
|
||||||
|
'event' |> watcher.on(%, async event => {
|
||||||
|
switch (event.code) {
|
||||||
|
case 'BUNDLE_START':
|
||||||
|
`${' BUILDING ' |> chalk.bgYellow.black(%)} ${logKey}` |> console.log(%);
|
||||||
|
break;
|
||||||
|
case 'BUNDLE_END':
|
||||||
|
`${' COMPLETE ' |> chalk.bgGreen.black(%)} ${logKey}\n` |> console.log(%);
|
||||||
|
break;
|
||||||
|
case 'ERROR':
|
||||||
|
case 'FATAL':
|
||||||
|
`${' OH NOES! ' |> chalk.bgRed.black(%)} ${logKey}\n` |> console.log(%);
|
||||||
|
event.error |> handleRollupError(%);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
`${' BUILDING ' |> chalk.bgYellow.black(%)} ${logKey}` |> console.log(%);
|
||||||
|
try {
|
||||||
|
const result = await (rollupConfig |> rollup.rollup(%));
|
||||||
|
await (rollupOutputOptions |> result.write(%));
|
||||||
|
} catch (error) {
|
||||||
|
`${' OH NOES! ' |> chalk.bgRed.black(%)} ${logKey}\n` |> console.log(%);
|
||||||
|
error |> handleRollupError(%);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
`${' COMPLETE ' |> chalk.bgGreen.black(%)} ${logKey}\n` |> console.log(%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleRollupWarning(warning) {
|
||||||
|
if (warning.code === 'UNUSED_EXTERNAL_IMPORT') {
|
||||||
|
const match = /external module "([^"]+)"/ |> warning.message.match(%);
|
||||||
|
if (!match || typeof match[1] !== 'string') {
|
||||||
|
throw new Error('Could not parse a Rollup warning. ' + 'Fix this method.');
|
||||||
|
}
|
||||||
|
const importSideEffects = Modules.getImportSideEffects();
|
||||||
|
const externalModule = match[1];
|
||||||
|
if (typeof importSideEffects[externalModule] !== 'boolean') {
|
||||||
|
throw new Error('An external module "' + externalModule + '" is used in a DEV-only code path ' + 'but we do not know if it is safe to omit an unused require() to it in production. ' + 'Please add it to the `importSideEffects` list in `scripts/rollup/modules.js`.');
|
||||||
|
}
|
||||||
|
// Don't warn. We will remove side effectless require() in a later pass.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (warning.code === 'CIRCULAR_DEPENDENCY') {
|
||||||
|
// Ignored
|
||||||
|
} else if (typeof warning.code === 'string') {
|
||||||
|
// This is a warning coming from Rollup itself.
|
||||||
|
// These tend to be important (e.g. clashes in namespaced exports)
|
||||||
|
// so we'll fail the build on any of them.
|
||||||
|
console.error();
|
||||||
|
warning.message || warning |> console.error(%);
|
||||||
|
console.error();
|
||||||
|
1 |> process.exit(%);
|
||||||
|
} else {
|
||||||
|
// The warning is from one of the plugins.
|
||||||
|
// Maybe it's not important, so just print it.
|
||||||
|
warning.message || warning |> console.warn(%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleRollupError(error) {
|
||||||
|
error |> loggedErrors.add(%);
|
||||||
|
if (!error.code) {
|
||||||
|
error |> console.error(%);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
`\x1b[31m-- ${error.code}${error.plugin ? ` (${error.plugin})` : ''} --` |> console.error(%);
|
||||||
|
error.stack |> console.error(%);
|
||||||
|
if (error.loc && error.loc.file) {
|
||||||
|
const {
|
||||||
|
file,
|
||||||
|
line,
|
||||||
|
column
|
||||||
|
} = error.loc;
|
||||||
|
// This looks like an error from Rollup, e.g. missing export.
|
||||||
|
// We'll use the accurate line numbers provided by Rollup but
|
||||||
|
// use Babel code frame because it looks nicer.
|
||||||
|
const rawLines = file |> fs.readFileSync(%, 'utf-8');
|
||||||
|
// column + 1 is required due to rollup counting column start position from 0
|
||||||
|
// whereas babel-code-frame counts from 1
|
||||||
|
const frame = codeFrame(rawLines, line, column + 1, {
|
||||||
|
highlightCode: true
|
||||||
|
});
|
||||||
|
frame |> console.error(%);
|
||||||
|
} else if (error.codeFrame) {
|
||||||
|
// This looks like an error from a plugin (e.g. Babel).
|
||||||
|
// In this case we'll resort to displaying the provided code frame
|
||||||
|
// because we can't be sure the reported location is accurate.
|
||||||
|
error.codeFrame |> console.error(%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function buildEverything() {
|
||||||
|
if (!argv['unsafe-partial']) {
|
||||||
|
await ('build' |> asyncRimRaf(%));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run them serially for better console output
|
||||||
|
// and to avoid any potential race conditions.
|
||||||
|
|
||||||
|
let bundles = [];
|
||||||
|
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||||
|
for (const bundle of Bundles.bundles) {
|
||||||
|
bundles.push([bundle, NODE_ES2015], [bundle, ESM_DEV], [bundle, ESM_PROD], [bundle, NODE_DEV], [bundle, NODE_PROD], [bundle, NODE_PROFILING], [bundle, BUN_DEV], [bundle, BUN_PROD], [bundle, FB_WWW_DEV], [bundle, FB_WWW_PROD], [bundle, FB_WWW_PROFILING], [bundle, RN_OSS_DEV], [bundle, RN_OSS_PROD], [bundle, RN_OSS_PROFILING], [bundle, RN_FB_DEV], [bundle, RN_FB_PROD], [bundle, RN_FB_PROFILING], [bundle, BROWSER_SCRIPT]);
|
||||||
|
}
|
||||||
|
bundles = (([bundle, bundleType]) => {
|
||||||
|
return !(bundle |> shouldSkipBundle(%, bundleType));
|
||||||
|
}) |> bundles.filter(%);
|
||||||
|
if (process.env.CIRCLE_NODE_TOTAL) {
|
||||||
|
// In CI, parallelize bundles across multiple tasks.
|
||||||
|
const nodeTotal = process.env.CIRCLE_NODE_TOTAL |> parseInt(%, 10);
|
||||||
|
const nodeIndex = process.env.CIRCLE_NODE_INDEX |> parseInt(%, 10);
|
||||||
|
bundles = ((_, i) => i % nodeTotal === nodeIndex) |> bundles.filter(%);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||||
|
for (const [bundle, bundleType] of bundles) {
|
||||||
|
await (bundle |> createBundle(%, bundleType));
|
||||||
|
}
|
||||||
|
await Packaging.copyAllShims();
|
||||||
|
await Packaging.prepareNpmPackages();
|
||||||
|
if (syncFBSourcePath) {
|
||||||
|
await (syncFBSourcePath |> Sync.syncReactNative(%));
|
||||||
|
} else if (syncWWWPath) {
|
||||||
|
await ('build/facebook-www' |> Sync.syncReactDom(%, syncWWWPath));
|
||||||
|
}
|
||||||
|
Stats.printResults() |> console.log(%);
|
||||||
|
if (!forcePrettyOutput) {
|
||||||
|
Stats.saveResults();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buildEverything();
|
18
output_testing/1010merged-scopes-are-valid-effect-deps.js
Normal file
18
output_testing/1010merged-scopes-are-valid-effect-deps.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// @validateMemoizedEffectDependencies
|
||||||
|
|
||||||
|
import { useEffect } from "react";
|
||||||
|
function Component(props) {
|
||||||
|
const y = [[props.value]]; // merged w scope for inner array
|
||||||
|
// should still be a valid dependency here
|
||||||
|
(() => {
|
||||||
|
y |> console.log(%);
|
||||||
|
}) |> useEffect(%, [y]);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
value: 42
|
||||||
|
}],
|
||||||
|
isComponent: false
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
function Component(props) {
|
||||||
|
// a can be independently memoized, is not mutated later
|
||||||
|
// but a is a dependnecy of b, which is a dependency of c.
|
||||||
|
// we have to memoize a to avoid breaking memoization of b,
|
||||||
|
// to avoid breaking memoization of c.
|
||||||
|
const a = [props.a];
|
||||||
|
|
||||||
|
// a can be independently memoized, is not mutated later,
|
||||||
|
// but is a dependency of d which is part of c's scope.
|
||||||
|
// we have to memoize b to avoid breaking memoization of c.
|
||||||
|
const b = [a];
|
||||||
|
|
||||||
|
// c and d are interleaved and grouped into a single scope,
|
||||||
|
// but they are independent values. d does not escape, but
|
||||||
|
// we need to ensure that b is memoized or else b will invalidate
|
||||||
|
// on every render since a is a dependency. we also need to
|
||||||
|
// ensure that a is memoized, since it's a dependency of b.
|
||||||
|
const c = [];
|
||||||
|
const d = {};
|
||||||
|
d.b = b;
|
||||||
|
props.b |> c.push(%);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: ["TodoAdd"],
|
||||||
|
isComponent: "TodoAdd"
|
||||||
|
};
|
16
output_testing/1012capturing-variable-in-nested-function.js
Normal file
16
output_testing/1012capturing-variable-in-nested-function.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
function component(a) {
|
||||||
|
let z = {
|
||||||
|
a
|
||||||
|
};
|
||||||
|
let x = function () {
|
||||||
|
(function () {
|
||||||
|
z |> console.log(%);
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: component,
|
||||||
|
params: ["TodoAdd"],
|
||||||
|
isComponent: "TodoAdd"
|
||||||
|
};
|
12
output_testing/1013inadvertent-mutability-readonly-lambda.js
Normal file
12
output_testing/1013inadvertent-mutability-readonly-lambda.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
function Component(props) {
|
||||||
|
const [value, setValue] = null |> useState(%);
|
||||||
|
// NOTE: this lambda does not capture any mutable values (only the state setter)
|
||||||
|
// and thus should be treated as readonly
|
||||||
|
const onChange = e => (value => value + e.target.value) |> setValue(%);
|
||||||
|
useOtherHook();
|
||||||
|
|
||||||
|
// x should be independently memoizeable, since foo(x, onChange) cannot modify onChange
|
||||||
|
const x = {};
|
||||||
|
x |> foo(%, onChange);
|
||||||
|
return x;
|
||||||
|
}
|
16
output_testing/1014overlapping-scopes-within-block.js
Normal file
16
output_testing/1014overlapping-scopes-within-block.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
function foo(a, b, c) {
|
||||||
|
let x = [];
|
||||||
|
if (a) {
|
||||||
|
let y = [];
|
||||||
|
if (b) {
|
||||||
|
c |> y.push(%);
|
||||||
|
}
|
||||||
|
y |> x.push(%);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: foo,
|
||||||
|
params: ["TodoAdd"],
|
||||||
|
isComponent: "TodoAdd"
|
||||||
|
};
|
9
output_testing/1015primitive-as-dep.js
Normal file
9
output_testing/1015primitive-as-dep.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// props.b + 1 is an non-allocating expression, which means Forget can
|
||||||
|
// emit it trivially and repeatedly (e.g. no need to memoize props.b + 1
|
||||||
|
// separately from props.b)
|
||||||
|
// Correctness:
|
||||||
|
// y depends on either props.b or props.b + 1
|
||||||
|
function PrimitiveAsDep(props) {
|
||||||
|
let y = props.b + 1 |> foo(%);
|
||||||
|
return y;
|
||||||
|
}
|
15
output_testing/1016capturing-function-decl.js
Normal file
15
output_testing/1016capturing-function-decl.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
function component(a) {
|
||||||
|
let t = {
|
||||||
|
a
|
||||||
|
};
|
||||||
|
function x() {
|
||||||
|
t.foo();
|
||||||
|
}
|
||||||
|
t |> x(%);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: component,
|
||||||
|
params: ["TodoAdd"],
|
||||||
|
isComponent: "TodoAdd"
|
||||||
|
};
|
|
@ -0,0 +1,36 @@
|
||||||
|
function Component(props) {
|
||||||
|
// x is mutated conditionally based on a reactive value,
|
||||||
|
// so it needs to be considered reactive
|
||||||
|
let x = [];
|
||||||
|
if (props.cond) {
|
||||||
|
1 |> x.push(%);
|
||||||
|
}
|
||||||
|
// Since x is reactive, y is now reactively controlled too:
|
||||||
|
let y = false;
|
||||||
|
if (x[0]) {
|
||||||
|
y = true;
|
||||||
|
}
|
||||||
|
// Thus this value should be reactive on `y`:
|
||||||
|
return [y];
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [],
|
||||||
|
sequentialRenders: [{
|
||||||
|
cond: true
|
||||||
|
}, {
|
||||||
|
cond: true
|
||||||
|
}, {
|
||||||
|
cond: false
|
||||||
|
}, {
|
||||||
|
cond: false
|
||||||
|
}, {
|
||||||
|
cond: true
|
||||||
|
}, {
|
||||||
|
cond: false
|
||||||
|
}, {
|
||||||
|
cond: true
|
||||||
|
}, {
|
||||||
|
cond: false
|
||||||
|
}]
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
// @debug
|
||||||
|
function Component(a, b) {
|
||||||
|
let x = [];
|
||||||
|
let y = [];
|
||||||
|
let z = a |> foo(%);
|
||||||
|
if (FLAG) {
|
||||||
|
x = z |> bar(%);
|
||||||
|
y = b |> baz(%);
|
||||||
|
}
|
||||||
|
return [x, y];
|
||||||
|
}
|
13
output_testing/1019hoisting-nested-block-statements.js
Normal file
13
output_testing/1019hoisting-nested-block-statements.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { print } from "shared-runtime";
|
||||||
|
function hoisting(cond) {
|
||||||
|
if (cond) {
|
||||||
|
const x = 1;
|
||||||
|
x |> print(%);
|
||||||
|
}
|
||||||
|
const x = 2;
|
||||||
|
x |> print(%);
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: hoisting,
|
||||||
|
params: [false]
|
||||||
|
};
|
37
output_testing/101sync.js
Normal file
37
output_testing/101sync.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const asyncCopyTo = ('./utils' |> require(%)).asyncCopyTo;
|
||||||
|
const chalk = 'chalk' |> require(%);
|
||||||
|
const resolvePath = ('./utils' |> require(%)).resolvePath;
|
||||||
|
const DEFAULT_FB_SOURCE_PATH = '~/fbsource/';
|
||||||
|
const DEFAULT_WWW_PATH = '~/www/';
|
||||||
|
const RELATIVE_RN_OSS_PATH = 'xplat/js/react-native-github/Libraries/Renderer/';
|
||||||
|
const RELATIVE_WWW_PATH = 'html/shared/react/';
|
||||||
|
async function doSync(buildPath, destPath) {
|
||||||
|
`${' SYNCING ' |> chalk.bgYellow.black(%)} React to ${destPath}` |> console.log(%);
|
||||||
|
await (buildPath |> asyncCopyTo(%, destPath));
|
||||||
|
`${' SYNCED ' |> chalk.bgGreen.black(%)} React to ${destPath}` |> console.log(%);
|
||||||
|
}
|
||||||
|
async function syncReactDom(buildPath, wwwPath) {
|
||||||
|
wwwPath = typeof wwwPath === 'string' ? wwwPath : DEFAULT_WWW_PATH;
|
||||||
|
if ((wwwPath.length - 1 |> wwwPath.charAt(%)) !== '/') {
|
||||||
|
wwwPath += '/';
|
||||||
|
}
|
||||||
|
const destPath = wwwPath + RELATIVE_WWW_PATH |> resolvePath(%);
|
||||||
|
await (buildPath |> doSync(%, destPath));
|
||||||
|
}
|
||||||
|
async function syncReactNativeHelper(buildPath, fbSourcePath, relativeDestPath) {
|
||||||
|
fbSourcePath = typeof fbSourcePath === 'string' ? fbSourcePath : DEFAULT_FB_SOURCE_PATH;
|
||||||
|
if ((fbSourcePath.length - 1 |> fbSourcePath.charAt(%)) !== '/') {
|
||||||
|
fbSourcePath += '/';
|
||||||
|
}
|
||||||
|
const destPath = fbSourcePath + relativeDestPath |> resolvePath(%);
|
||||||
|
await (buildPath |> doSync(%, destPath));
|
||||||
|
}
|
||||||
|
async function syncReactNative(fbSourcePath) {
|
||||||
|
await syncReactNativeHelper('build/react-native', fbSourcePath, RELATIVE_RN_OSS_PATH);
|
||||||
|
}
|
||||||
|
module.exports = {
|
||||||
|
syncReactDom,
|
||||||
|
syncReactNative
|
||||||
|
};
|
19
output_testing/1020for-loop-let-undefined-decl.js
Normal file
19
output_testing/1020for-loop-let-undefined-decl.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// These variables are unknown to useFoo, as they are
|
||||||
|
// defined at module scope or implicit globals
|
||||||
|
const isSelected = false;
|
||||||
|
const isCurrent = true;
|
||||||
|
function useFoo() {
|
||||||
|
for (let i = 0; i <= 5; i++) {
|
||||||
|
let color;
|
||||||
|
if (isSelected) {
|
||||||
|
color = isCurrent ? "#FFCC22" : "#FF5050";
|
||||||
|
} else {
|
||||||
|
color = isCurrent ? "#CCFF03" : "#CCCCCC";
|
||||||
|
}
|
||||||
|
color |> console.log(%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
params: [],
|
||||||
|
fn: useFoo
|
||||||
|
};
|
27
output_testing/1021repro-dce-circular-reference.js
Normal file
27
output_testing/1021repro-dce-circular-reference.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { identity } from "shared-runtime";
|
||||||
|
function Component({
|
||||||
|
data
|
||||||
|
}) {
|
||||||
|
let x = 0;
|
||||||
|
for (const item of data) {
|
||||||
|
const {
|
||||||
|
current,
|
||||||
|
other
|
||||||
|
} = item;
|
||||||
|
x += current;
|
||||||
|
other |> identity(%);
|
||||||
|
}
|
||||||
|
return [x];
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
data: [{
|
||||||
|
current: 2,
|
||||||
|
other: 3
|
||||||
|
}, {
|
||||||
|
current: 4,
|
||||||
|
other: 5
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
};
|
|
@ -0,0 +1,9 @@
|
||||||
|
function Component(props) {
|
||||||
|
const mutate = (object, key, value) => {
|
||||||
|
object.updated = true;
|
||||||
|
object[key] = value;
|
||||||
|
};
|
||||||
|
const x = props |> makeObject(%);
|
||||||
|
x |> mutate(%);
|
||||||
|
return x;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
// @validateNoSetStateInRender
|
||||||
|
function Component(props) {
|
||||||
|
const [x, setX] = 0 |> useState(%);
|
||||||
|
const aliased = setX;
|
||||||
|
1 |> setX(%);
|
||||||
|
2 |> aliased(%);
|
||||||
|
return x;
|
||||||
|
}
|
6
output_testing/1024simple.js
Normal file
6
output_testing/1024simple.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export default function foo(x, y) {
|
||||||
|
if (x) {
|
||||||
|
return false |> foo(%, y);
|
||||||
|
}
|
||||||
|
return [y * 10];
|
||||||
|
}
|
6
output_testing/1025optional-receiver-method-call.js
Normal file
6
output_testing/1025optional-receiver-method-call.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
function Component(props) {
|
||||||
|
const x = props |> makeOptionalObject(%);
|
||||||
|
const y = props |> makeObject(%);
|
||||||
|
const z = x?.method(y.a, props.a, y.b |> foo(%), props.b |> bar(%));
|
||||||
|
return z;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { createHookWrapper, mutate, mutateAndReturn } from "shared-runtime";
|
||||||
|
function useHook({
|
||||||
|
value
|
||||||
|
}) {
|
||||||
|
const x = {
|
||||||
|
value
|
||||||
|
} |> mutateAndReturn(%);
|
||||||
|
const obj = {
|
||||||
|
getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
x |> mutate(%);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: useHook |> createHookWrapper(%),
|
||||||
|
params: [{
|
||||||
|
value: 0
|
||||||
|
}]
|
||||||
|
};
|
16
output_testing/1027object-literal-method-in-ternary-test.js
Normal file
16
output_testing/1027object-literal-method-in-ternary-test.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { createHookWrapper, CONST_STRING0, CONST_STRING1 } from "shared-runtime";
|
||||||
|
function useHook({
|
||||||
|
value
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
getValue() {
|
||||||
|
return value |> identity(%);
|
||||||
|
}
|
||||||
|
} ? CONST_STRING0 : CONST_STRING1;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: useHook |> createHookWrapper(%),
|
||||||
|
params: [{
|
||||||
|
value: 0
|
||||||
|
}]
|
||||||
|
};
|
16
output_testing/1028constant-prop-colliding-identifier.js
Normal file
16
output_testing/1028constant-prop-colliding-identifier.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { invoke } from "shared-runtime";
|
||||||
|
function Component() {
|
||||||
|
let x = 2;
|
||||||
|
const fn = () => {
|
||||||
|
return {
|
||||||
|
x: "value"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
fn |> invoke(%);
|
||||||
|
x = 3;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{}]
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
function Component(props) {
|
||||||
|
// a and b are independent but their mutations are interleaved, so
|
||||||
|
// they get grouped in a reactive scope. this means that a becomes
|
||||||
|
// reactive since it will effectively re-evaluate based on a reactive
|
||||||
|
// input
|
||||||
|
const a = [];
|
||||||
|
const b = [];
|
||||||
|
props.cond |> b.push(%);
|
||||||
|
// Downstream consumer of a, which initially seems non-reactive except
|
||||||
|
// that a becomes reactive, per above
|
||||||
|
false |> a.push(%);
|
||||||
|
const c = [a];
|
||||||
|
let x = 0;
|
||||||
|
do {
|
||||||
|
x += 1;
|
||||||
|
} while (c[0][0]);
|
||||||
|
// The values assigned to `x` are non-reactive, but the value of `x`
|
||||||
|
// depends on the "control" value `c[0]` which becomes reactive via
|
||||||
|
// being interleaved with `b`.
|
||||||
|
// Therefore x should be treated as reactive too.
|
||||||
|
return [x];
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
cond: true
|
||||||
|
}]
|
||||||
|
};
|
89
output_testing/102stats.js
Normal file
89
output_testing/102stats.js
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Table = 'cli-table' |> require(%);
|
||||||
|
const filesize = 'filesize' |> require(%);
|
||||||
|
const chalk = 'chalk' |> require(%);
|
||||||
|
const join = ('path' |> require(%)).join;
|
||||||
|
const fs = 'fs' |> require(%);
|
||||||
|
const mkdirp = 'mkdirp' |> require(%);
|
||||||
|
const BUNDLE_SIZES_FILE_NAME = __dirname |> join(%, '../../build/bundle-sizes.json');
|
||||||
|
const prevBuildResults = BUNDLE_SIZES_FILE_NAME |> fs.existsSync(%) ? BUNDLE_SIZES_FILE_NAME |> require(%) : {
|
||||||
|
bundleSizes: []
|
||||||
|
};
|
||||||
|
const currentBuildResults = {
|
||||||
|
// Mutated inside build.js during a build run.
|
||||||
|
bundleSizes: []
|
||||||
|
};
|
||||||
|
function saveResults() {
|
||||||
|
if (process.env.CIRCLE_NODE_TOTAL) {
|
||||||
|
// In CI, write the bundle sizes to a subdirectory and append the node index
|
||||||
|
// to the filename. A downstream job will consolidate these into a
|
||||||
|
// single file.
|
||||||
|
const nodeIndex = process.env.CIRCLE_NODE_INDEX;
|
||||||
|
'build/sizes' |> mkdirp.sync(%);
|
||||||
|
join('build', 'sizes', `bundle-sizes-${nodeIndex}.json`) |> fs.writeFileSync(%, JSON.stringify(currentBuildResults, null, 2));
|
||||||
|
} else {
|
||||||
|
// Write all the bundle sizes to a single JSON file.
|
||||||
|
BUNDLE_SIZES_FILE_NAME |> fs.writeFileSync(%, JSON.stringify(currentBuildResults, null, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function fractionalChange(prev, current) {
|
||||||
|
return (current - prev) / prev;
|
||||||
|
}
|
||||||
|
function percentChangeString(change) {
|
||||||
|
if (!(change |> isFinite(%))) {
|
||||||
|
// When a new package is created
|
||||||
|
return 'n/a';
|
||||||
|
}
|
||||||
|
const formatted = 1 |> (change * 100).toFixed(%);
|
||||||
|
if (formatted |> /^-|^0(?:\.0+)$/.test(%)) {
|
||||||
|
return `${formatted}%`;
|
||||||
|
} else {
|
||||||
|
return `+${formatted}%`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const resultsHeaders = ['Bundle', 'Prev Size', 'Current Size', 'Diff', 'Prev Gzip', 'Current Gzip', 'Diff'];
|
||||||
|
function generateResultsArray(current, prevResults) {
|
||||||
|
return (f => f) |> ((result => {
|
||||||
|
const prev = ((res => res.filename === result.filename && res.bundleType === result.bundleType) |> prevResults.bundleSizes.filter(%))[0];
|
||||||
|
if (result === prev) {
|
||||||
|
// We didn't rebuild this bundle.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const size = result.size;
|
||||||
|
const gzip = result.gzip;
|
||||||
|
let prevSize = prev ? prev.size : 0;
|
||||||
|
let prevGzip = prev ? prev.gzip : 0;
|
||||||
|
return {
|
||||||
|
filename: result.filename,
|
||||||
|
bundleType: result.bundleType,
|
||||||
|
packageName: result.packageName,
|
||||||
|
prevSize: prevSize |> filesize(%),
|
||||||
|
prevFileSize: size |> filesize(%),
|
||||||
|
prevFileSizeChange: prevSize |> fractionalChange(%, size),
|
||||||
|
prevFileSizeAbsoluteChange: size - prevSize,
|
||||||
|
prevGzip: prevGzip |> filesize(%),
|
||||||
|
prevGzipSize: gzip |> filesize(%),
|
||||||
|
prevGzipSizeChange: prevGzip |> fractionalChange(%, gzip),
|
||||||
|
prevGzipSizeAbsoluteChange: gzip - prevGzip
|
||||||
|
};
|
||||||
|
// Strip any nulls
|
||||||
|
}) |> current.bundleSizes.map(%)).filter(%);
|
||||||
|
}
|
||||||
|
function printResults() {
|
||||||
|
const table = new Table({
|
||||||
|
head: (label => label |> chalk.gray.yellow(%)) |> resultsHeaders.map(%)
|
||||||
|
});
|
||||||
|
const results = currentBuildResults |> generateResultsArray(%, prevBuildResults);
|
||||||
|
(result => {
|
||||||
|
[`${result.filename} (${result.bundleType})` |> chalk.white.bold(%), result.prevSize |> chalk.gray.bold(%), result.prevFileSize |> chalk.white.bold(%), result.prevFileSizeChange |> percentChangeString(%), result.prevGzip |> chalk.gray.bold(%), result.prevGzipSize |> chalk.white.bold(%), result.prevGzipSizeChange |> percentChangeString(%)] |> table.push(%);
|
||||||
|
}) |> results.forEach(%);
|
||||||
|
return table.toString();
|
||||||
|
}
|
||||||
|
module.exports = {
|
||||||
|
currentBuildResults,
|
||||||
|
generateResultsArray,
|
||||||
|
printResults,
|
||||||
|
saveResults,
|
||||||
|
resultsHeaders
|
||||||
|
};
|
5
output_testing/1030await-side-effecting-promise.js
Normal file
5
output_testing/1030await-side-effecting-promise.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
async function Component(props) {
|
||||||
|
const x = [];
|
||||||
|
await (props.id |> populateData(%, x));
|
||||||
|
return x;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
// @validateMemoizedEffectDependencies
|
||||||
|
import { useInsertionEffect } from "react";
|
||||||
|
function Component(props) {
|
||||||
|
const data = {};
|
||||||
|
(() => {
|
||||||
|
props.value |> console.log(%);
|
||||||
|
}) |> useInsertionEffect(%, [data]);
|
||||||
|
data |> mutate(%);
|
||||||
|
return data;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
function foo() {
|
||||||
|
const a = [[1]];
|
||||||
|
const first = 0 |> a.at(%);
|
||||||
|
0 |> first.set(%, 2);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: foo,
|
||||||
|
params: [],
|
||||||
|
isComponent: false
|
||||||
|
};
|
16
output_testing/1033hoisting-nested-const-declaration-2.js
Normal file
16
output_testing/1033hoisting-nested-const-declaration-2.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
function hoisting(cond) {
|
||||||
|
let items = [];
|
||||||
|
if (cond) {
|
||||||
|
const foo = () => {
|
||||||
|
bar() |> items.push(%);
|
||||||
|
};
|
||||||
|
const bar = () => true;
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: hoisting,
|
||||||
|
params: [true],
|
||||||
|
isComponent: false
|
||||||
|
};
|
16
output_testing/1034capturing-nested-member-expr.js
Normal file
16
output_testing/1034capturing-nested-member-expr.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
function component(a) {
|
||||||
|
let z = {
|
||||||
|
a: {
|
||||||
|
a
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let x = function () {
|
||||||
|
z.a.a |> console.log(%);
|
||||||
|
};
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: component,
|
||||||
|
params: ["TodoAdd"],
|
||||||
|
isComponent: "TodoAdd"
|
||||||
|
};
|
13
output_testing/1035reactive-scope-grouping.js
Normal file
13
output_testing/1035reactive-scope-grouping.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
function foo() {
|
||||||
|
let x = {};
|
||||||
|
let y = [];
|
||||||
|
let z = {};
|
||||||
|
z |> y.push(%);
|
||||||
|
x.y = y;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: foo,
|
||||||
|
params: [],
|
||||||
|
isComponent: false
|
||||||
|
};
|
|
@ -0,0 +1,14 @@
|
||||||
|
function hoisting() {
|
||||||
|
function addOne(b) {
|
||||||
|
// a is undefined (only the declaration is hoisted, not the init) but shouldn't throw
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
const result = 2 |> addOne(%);
|
||||||
|
var a = 1;
|
||||||
|
return result; // OK: returns NaN. The code is semantically wrong but technically correct
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: hoisting,
|
||||||
|
params: [],
|
||||||
|
isComponent: false
|
||||||
|
};
|
|
@ -0,0 +1,6 @@
|
||||||
|
function component(a, b) {
|
||||||
|
let x = (async () => {
|
||||||
|
await a;
|
||||||
|
}) |> React.useMemo(%, []);
|
||||||
|
return x;
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
function Component(props) {
|
||||||
|
let x;
|
||||||
|
for (const key in props.values) {
|
||||||
|
const i = key |> parseInt(%, 10);
|
||||||
|
if (i > 10) {
|
||||||
|
x = 10;
|
||||||
|
} else {
|
||||||
|
x = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The values assigned to `x` are non-reactive, but the value of `x`
|
||||||
|
// depends on the "control" variable `i`, whose value is derived from
|
||||||
|
// `props.values` which is reactive.
|
||||||
|
// Therefore x should be treated as reactive too.
|
||||||
|
return [x];
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [],
|
||||||
|
sequentialRenders: [{
|
||||||
|
values: {
|
||||||
|
"12": true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
values: {
|
||||||
|
"12": true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
values: {
|
||||||
|
"1": true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
values: {
|
||||||
|
"1": true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
values: {
|
||||||
|
"12": true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
values: {
|
||||||
|
"1": true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
values: {
|
||||||
|
"12": true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
values: {
|
||||||
|
"1": true
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
|
@ -0,0 +1,13 @@
|
||||||
|
// @validateNoSetStateInRender
|
||||||
|
function Component(props) {
|
||||||
|
const [state, setState] = false |> useState(%);
|
||||||
|
for (const _ of props) {
|
||||||
|
if (props.cond) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true |> setState(%);
|
||||||
|
return state;
|
||||||
|
}
|
310
output_testing/103forks.js
Normal file
310
output_testing/103forks.js
Normal file
|
@ -0,0 +1,310 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fs = 'node:fs' |> require(%);
|
||||||
|
const {
|
||||||
|
bundleTypes,
|
||||||
|
moduleTypes
|
||||||
|
} = './bundles' |> require(%);
|
||||||
|
const inlinedHostConfigs = '../shared/inlinedHostConfigs' |> require(%);
|
||||||
|
const {
|
||||||
|
FB_WWW_DEV,
|
||||||
|
FB_WWW_PROD,
|
||||||
|
FB_WWW_PROFILING,
|
||||||
|
RN_OSS_DEV,
|
||||||
|
RN_OSS_PROD,
|
||||||
|
RN_OSS_PROFILING,
|
||||||
|
RN_FB_DEV,
|
||||||
|
RN_FB_PROD,
|
||||||
|
RN_FB_PROFILING
|
||||||
|
} = bundleTypes;
|
||||||
|
const {
|
||||||
|
RENDERER,
|
||||||
|
RECONCILER
|
||||||
|
} = moduleTypes;
|
||||||
|
const RELEASE_CHANNEL = process.env.RELEASE_CHANNEL;
|
||||||
|
|
||||||
|
// Default to building in experimental mode. If the release channel is set via
|
||||||
|
// an environment variable, then check if it's "experimental".
|
||||||
|
const __EXPERIMENTAL__ = typeof RELEASE_CHANNEL === 'string' ? RELEASE_CHANNEL === 'experimental' : true;
|
||||||
|
function findNearestExistingForkFile(path, segmentedIdentifier, suffix) {
|
||||||
|
const segments = '-' |> segmentedIdentifier.split(%);
|
||||||
|
while (segments.length) {
|
||||||
|
const candidate = '-' |> segments.join(%);
|
||||||
|
const forkPath = path + candidate + suffix;
|
||||||
|
try {
|
||||||
|
forkPath |> fs.statSync(%);
|
||||||
|
return forkPath;
|
||||||
|
} catch (error) {
|
||||||
|
// Try the next candidate.
|
||||||
|
}
|
||||||
|
segments.pop();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If you need to replace a file with another file for a specific environment,
|
||||||
|
// add it to this list with the logic for choosing the right replacement.
|
||||||
|
|
||||||
|
// Fork paths are relative to the project root. They must include the full path,
|
||||||
|
// including the extension. We intentionally don't use Node's module resolution
|
||||||
|
// algorithm because 1) require.resolve doesn't work with ESM modules, and 2)
|
||||||
|
// the behavior is easier to predict.
|
||||||
|
const forks = {
|
||||||
|
// Without this fork, importing `shared/ReactSharedInternals` inside
|
||||||
|
// the `react` package itself would not work due to a cyclical dependency.
|
||||||
|
'./packages/shared/ReactSharedInternals.js': (bundleType, entry, dependencies, _moduleType, bundle) => {
|
||||||
|
if (entry === 'react') {
|
||||||
|
return './packages/react/src/ReactSharedInternalsClient.js';
|
||||||
|
}
|
||||||
|
if (entry === 'react/src/ReactServer.js') {
|
||||||
|
return './packages/react/src/ReactSharedInternalsServer.js';
|
||||||
|
}
|
||||||
|
if (bundle.condition === 'react-server') {
|
||||||
|
return './packages/react-server/src/ReactSharedInternalsServer.js';
|
||||||
|
}
|
||||||
|
if (!('react/' |> entry.startsWith(%)) && ('react' |> dependencies.indexOf(%)) === -1) {
|
||||||
|
// React internals are unavailable if we can't reference the package.
|
||||||
|
// We return an error because we only want to throw if this module gets used.
|
||||||
|
return new Error('Cannot use a module that depends on ReactSharedInternals ' + 'from "' + entry + '" because it does not declare "react" in the package ' + 'dependencies or peerDependencies.');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
// Without this fork, importing `shared/ReactDOMSharedInternals` inside
|
||||||
|
// the `react-dom` package itself would not work due to a cyclical dependency.
|
||||||
|
'./packages/shared/ReactDOMSharedInternals.js': (bundleType, entry, dependencies) => {
|
||||||
|
if (entry === 'react-dom' || entry === 'react-dom/src/ReactDOMFB.js' || entry === 'react-dom/src/ReactDOMTestingFB.js' || entry === 'react-dom/src/ReactDOMServer.js') {
|
||||||
|
if (bundleType === FB_WWW_DEV || bundleType === FB_WWW_PROD || bundleType === FB_WWW_PROFILING) {
|
||||||
|
return './packages/react-dom/src/ReactDOMSharedInternalsFB.js';
|
||||||
|
} else {
|
||||||
|
return './packages/react-dom/src/ReactDOMSharedInternals.js';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!('react-dom/' |> entry.startsWith(%)) && ('react-dom' |> dependencies.indexOf(%)) === -1) {
|
||||||
|
// React DOM internals are unavailable if we can't reference the package.
|
||||||
|
// We return an error because we only want to throw if this module gets used.
|
||||||
|
return new Error('Cannot use a module that depends on ReactDOMSharedInternals ' + 'from "' + entry + '" because it does not declare "react-dom" in the package ' + 'dependencies or peerDependencies.');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
// We have a few forks for different environments.
|
||||||
|
'./packages/shared/ReactFeatureFlags.js': (bundleType, entry) => {
|
||||||
|
switch (entry) {
|
||||||
|
case 'react-native-renderer':
|
||||||
|
switch (bundleType) {
|
||||||
|
case RN_FB_DEV:
|
||||||
|
case RN_FB_PROD:
|
||||||
|
case RN_FB_PROFILING:
|
||||||
|
return './packages/shared/forks/ReactFeatureFlags.native-fb.js';
|
||||||
|
case RN_OSS_DEV:
|
||||||
|
case RN_OSS_PROD:
|
||||||
|
case RN_OSS_PROFILING:
|
||||||
|
return './packages/shared/forks/ReactFeatureFlags.native-oss.js';
|
||||||
|
default:
|
||||||
|
throw `Unexpected entry (${entry}) and bundleType (${bundleType})` |> Error(%);
|
||||||
|
}
|
||||||
|
case 'react-native-renderer/fabric':
|
||||||
|
switch (bundleType) {
|
||||||
|
case RN_FB_DEV:
|
||||||
|
case RN_FB_PROD:
|
||||||
|
case RN_FB_PROFILING:
|
||||||
|
return './packages/shared/forks/ReactFeatureFlags.native-fb.js';
|
||||||
|
case RN_OSS_DEV:
|
||||||
|
case RN_OSS_PROD:
|
||||||
|
case RN_OSS_PROFILING:
|
||||||
|
return './packages/shared/forks/ReactFeatureFlags.native-oss.js';
|
||||||
|
default:
|
||||||
|
throw `Unexpected entry (${entry}) and bundleType (${bundleType})` |> Error(%);
|
||||||
|
}
|
||||||
|
case 'react-test-renderer':
|
||||||
|
switch (bundleType) {
|
||||||
|
case RN_FB_DEV:
|
||||||
|
case RN_FB_PROD:
|
||||||
|
case RN_FB_PROFILING:
|
||||||
|
return './packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js';
|
||||||
|
case FB_WWW_DEV:
|
||||||
|
case FB_WWW_PROD:
|
||||||
|
case FB_WWW_PROFILING:
|
||||||
|
return './packages/shared/forks/ReactFeatureFlags.test-renderer.www.js';
|
||||||
|
}
|
||||||
|
return './packages/shared/forks/ReactFeatureFlags.test-renderer.js';
|
||||||
|
default:
|
||||||
|
switch (bundleType) {
|
||||||
|
case FB_WWW_DEV:
|
||||||
|
case FB_WWW_PROD:
|
||||||
|
case FB_WWW_PROFILING:
|
||||||
|
return './packages/shared/forks/ReactFeatureFlags.www.js';
|
||||||
|
case RN_FB_DEV:
|
||||||
|
case RN_FB_PROD:
|
||||||
|
case RN_FB_PROFILING:
|
||||||
|
return './packages/shared/forks/ReactFeatureFlags.native-fb.js';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
'./packages/scheduler/src/SchedulerFeatureFlags.js': (bundleType, entry, dependencies) => {
|
||||||
|
if (bundleType === FB_WWW_DEV || bundleType === FB_WWW_PROD || bundleType === FB_WWW_PROFILING) {
|
||||||
|
return './packages/scheduler/src/forks/SchedulerFeatureFlags.www.js';
|
||||||
|
}
|
||||||
|
return './packages/scheduler/src/SchedulerFeatureFlags.js';
|
||||||
|
},
|
||||||
|
'./packages/shared/consoleWithStackDev.js': (bundleType, entry) => {
|
||||||
|
switch (bundleType) {
|
||||||
|
case FB_WWW_DEV:
|
||||||
|
return './packages/shared/forks/consoleWithStackDev.www.js';
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'./packages/react-reconciler/src/ReactFiberConfig.js': (bundleType, entry, dependencies, moduleType) => {
|
||||||
|
if (('react-reconciler' |> dependencies.indexOf(%)) !== -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (moduleType !== RENDERER && moduleType !== RECONCILER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||||
|
for (let rendererInfo of inlinedHostConfigs) {
|
||||||
|
if ((entry |> rendererInfo.entryPoints.indexOf(%)) !== -1) {
|
||||||
|
const foundFork = findNearestExistingForkFile('./packages/react-reconciler/src/forks/ReactFiberConfig.', rendererInfo.shortName, '.js');
|
||||||
|
if (foundFork) {
|
||||||
|
return foundFork;
|
||||||
|
}
|
||||||
|
// fall through to error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('Expected ReactFiberConfig to always be replaced with a shim, but ' + `found no mention of "${entry}" entry point in ./scripts/shared/inlinedHostConfigs.js. ` + 'Did you mean to add it there to associate it with a specific renderer?');
|
||||||
|
},
|
||||||
|
'./packages/react-server/src/ReactServerStreamConfig.js': (bundleType, entry, dependencies, moduleType) => {
|
||||||
|
if (('react-server' |> dependencies.indexOf(%)) !== -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (moduleType !== RENDERER && moduleType !== RECONCILER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||||
|
for (let rendererInfo of inlinedHostConfigs) {
|
||||||
|
if ((entry |> rendererInfo.entryPoints.indexOf(%)) !== -1) {
|
||||||
|
if (!rendererInfo.isServerSupported) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const foundFork = findNearestExistingForkFile('./packages/react-server/src/forks/ReactServerStreamConfig.', rendererInfo.shortName, '.js');
|
||||||
|
if (foundFork) {
|
||||||
|
return foundFork;
|
||||||
|
}
|
||||||
|
// fall through to error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('Expected ReactServerStreamConfig to always be replaced with a shim, but ' + `found no mention of "${entry}" entry point in ./scripts/shared/inlinedHostConfigs.js. ` + 'Did you mean to add it there to associate it with a specific renderer?');
|
||||||
|
},
|
||||||
|
'./packages/react-server/src/ReactFizzConfig.js': (bundleType, entry, dependencies, moduleType) => {
|
||||||
|
if (('react-server' |> dependencies.indexOf(%)) !== -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (moduleType !== RENDERER && moduleType !== RECONCILER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||||
|
for (let rendererInfo of inlinedHostConfigs) {
|
||||||
|
if ((entry |> rendererInfo.entryPoints.indexOf(%)) !== -1) {
|
||||||
|
if (!rendererInfo.isServerSupported) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const foundFork = findNearestExistingForkFile('./packages/react-server/src/forks/ReactFizzConfig.', rendererInfo.shortName, '.js');
|
||||||
|
if (foundFork) {
|
||||||
|
return foundFork;
|
||||||
|
}
|
||||||
|
// fall through to error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('Expected ReactFizzConfig to always be replaced with a shim, but ' + `found no mention of "${entry}" entry point in ./scripts/shared/inlinedHostConfigs.js. ` + 'Did you mean to add it there to associate it with a specific renderer?');
|
||||||
|
},
|
||||||
|
'./packages/react-server/src/ReactFlightServerConfig.js': (bundleType, entry, dependencies, moduleType) => {
|
||||||
|
if (('react-server' |> dependencies.indexOf(%)) !== -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (moduleType !== RENDERER && moduleType !== RECONCILER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||||
|
for (let rendererInfo of inlinedHostConfigs) {
|
||||||
|
if ((entry |> rendererInfo.entryPoints.indexOf(%)) !== -1) {
|
||||||
|
if (!rendererInfo.isServerSupported) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (rendererInfo.isFlightSupported === false) {
|
||||||
|
return new Error(`Expected not to use ReactFlightServerConfig with "${entry}" entry point ` + 'in ./scripts/shared/inlinedHostConfigs.js. Update the renderer config to ' + 'activate flight suppport and add a matching fork implementation for ReactFlightServerConfig.');
|
||||||
|
}
|
||||||
|
const foundFork = findNearestExistingForkFile('./packages/react-server/src/forks/ReactFlightServerConfig.', rendererInfo.shortName, '.js');
|
||||||
|
if (foundFork) {
|
||||||
|
return foundFork;
|
||||||
|
}
|
||||||
|
// fall through to error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('Expected ReactFlightServerConfig to always be replaced with a shim, but ' + `found no mention of "${entry}" entry point in ./scripts/shared/inlinedHostConfigs.js. ` + 'Did you mean to add it there to associate it with a specific renderer?');
|
||||||
|
},
|
||||||
|
'./packages/react-client/src/ReactFlightClientConfig.js': (bundleType, entry, dependencies, moduleType) => {
|
||||||
|
if (('react-client' |> dependencies.indexOf(%)) !== -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (moduleType !== RENDERER && moduleType !== RECONCILER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||||
|
for (let rendererInfo of inlinedHostConfigs) {
|
||||||
|
if ((entry |> rendererInfo.entryPoints.indexOf(%)) !== -1) {
|
||||||
|
if (!rendererInfo.isServerSupported) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (rendererInfo.isFlightSupported === false) {
|
||||||
|
return new Error(`Expected not to use ReactFlightClientConfig with "${entry}" entry point ` + 'in ./scripts/shared/inlinedHostConfigs.js. Update the renderer config to ' + 'activate flight suppport and add a matching fork implementation for ReactFlightClientConfig.');
|
||||||
|
}
|
||||||
|
const foundFork = findNearestExistingForkFile('./packages/react-client/src/forks/ReactFlightClientConfig.', rendererInfo.shortName, '.js');
|
||||||
|
if (foundFork) {
|
||||||
|
return foundFork;
|
||||||
|
}
|
||||||
|
// fall through to error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('Expected ReactFlightClientConfig to always be replaced with a shim, but ' + `found no mention of "${entry}" entry point in ./scripts/shared/inlinedHostConfigs.js. ` + 'Did you mean to add it there to associate it with a specific renderer?');
|
||||||
|
},
|
||||||
|
// We wrap top-level listeners into guards on www.
|
||||||
|
'./packages/react-dom-bindings/src/events/EventListener.js': (bundleType, entry) => {
|
||||||
|
switch (bundleType) {
|
||||||
|
case FB_WWW_DEV:
|
||||||
|
case FB_WWW_PROD:
|
||||||
|
case FB_WWW_PROFILING:
|
||||||
|
if (__EXPERIMENTAL__) {
|
||||||
|
// In modern builds we don't use the indirection. We just use raw DOM.
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
// Use the www fork which is integrated with TimeSlice profiling.
|
||||||
|
return './packages/react-dom-bindings/src/events/forks/EventListener-www.js';
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'./packages/use-sync-external-store/src/useSyncExternalStore.js': (bundleType, entry) => {
|
||||||
|
if ('use-sync-external-store/shim' |> entry.startsWith(%)) {
|
||||||
|
return './packages/use-sync-external-store/src/forks/useSyncExternalStore.forward-to-shim.js';
|
||||||
|
}
|
||||||
|
if (entry !== 'use-sync-external-store') {
|
||||||
|
// Internal modules that aren't shims should use the native API from the
|
||||||
|
// react package.
|
||||||
|
return './packages/use-sync-external-store/src/forks/useSyncExternalStore.forward-to-built-in.js';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
'./packages/use-sync-external-store/src/isServerEnvironment.js': (bundleType, entry) => {
|
||||||
|
if ('.native' |> entry.endsWith(%)) {
|
||||||
|
return './packages/use-sync-external-store/src/forks/isServerEnvironment.native.js';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} |> Object.freeze(%);
|
||||||
|
module.exports = forks;
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { identity, mutate, mutateAndReturn } from "shared-runtime";
|
||||||
|
function Component(props) {
|
||||||
|
const key = {};
|
||||||
|
const context = {
|
||||||
|
[key |> mutateAndReturn(%)]: [props.value] |> identity(%)
|
||||||
|
};
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
value: 42
|
||||||
|
}]
|
||||||
|
};
|
14
output_testing/1041array-map-noAlias-escaping-function.js
Normal file
14
output_testing/1041array-map-noAlias-escaping-function.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
function Component(props) {
|
||||||
|
const f = item => item;
|
||||||
|
const x = f |> [...props.items].map(%); // `f` doesn't escape here...
|
||||||
|
return [x, f]; // ...but it does here so it's memoized
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
items: [{
|
||||||
|
id: 1
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
isComponent: false
|
||||||
|
};
|
|
@ -0,0 +1,10 @@
|
||||||
|
// @validateMemoizedEffectDependencies
|
||||||
|
import { useLayoutEffect } from "react";
|
||||||
|
function Component(props) {
|
||||||
|
const data = {};
|
||||||
|
(() => {
|
||||||
|
props.value |> console.log(%);
|
||||||
|
}) |> useLayoutEffect(%, [data]);
|
||||||
|
data |> mutate(%);
|
||||||
|
return data;
|
||||||
|
}
|
16
output_testing/1043hoisting-recursive-call-within-lambda.js
Normal file
16
output_testing/1043hoisting-recursive-call-within-lambda.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
function Foo({}) {
|
||||||
|
const outer = val => {
|
||||||
|
const fact = x => {
|
||||||
|
if (x <= 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return x * (x - 1 |> fact(%));
|
||||||
|
};
|
||||||
|
return val |> fact(%);
|
||||||
|
};
|
||||||
|
return 3 |> outer(%);
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Foo,
|
||||||
|
params: [{}]
|
||||||
|
};
|
14
output_testing/1044do-while-compound-test.js
Normal file
14
output_testing/1044do-while-compound-test.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
function Component(props) {
|
||||||
|
let x = [1, 2, 3];
|
||||||
|
let ret = [];
|
||||||
|
do {
|
||||||
|
let item = x.pop();
|
||||||
|
item * 2 |> ret.push(%);
|
||||||
|
} while (x.length && props.cond);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: ["TodoAdd"],
|
||||||
|
isComponent: "TodoAdd"
|
||||||
|
};
|
9
output_testing/1045destructuring-property-inference.js
Normal file
9
output_testing/1045destructuring-property-inference.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
function Component(props) {
|
||||||
|
const x = [];
|
||||||
|
props.value |> x.push(%);
|
||||||
|
const {
|
||||||
|
length: y
|
||||||
|
} = x;
|
||||||
|
y |> foo(%);
|
||||||
|
return [x, y];
|
||||||
|
}
|
14
output_testing/1046capturing-member-expr.js
Normal file
14
output_testing/1046capturing-member-expr.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
function component(a) {
|
||||||
|
let z = {
|
||||||
|
a
|
||||||
|
};
|
||||||
|
let x = function () {
|
||||||
|
z.a |> console.log(%);
|
||||||
|
};
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: component,
|
||||||
|
params: ["TodoAdd"],
|
||||||
|
isComponent: "TodoAdd"
|
||||||
|
};
|
|
@ -0,0 +1,10 @@
|
||||||
|
// @validateMemoizedEffectDependencies
|
||||||
|
import { useEffect } from "react";
|
||||||
|
function Component(props) {
|
||||||
|
const data = {};
|
||||||
|
(() => {
|
||||||
|
props.value |> console.log(%);
|
||||||
|
}) |> useEffect(%, [data]);
|
||||||
|
data |> mutate(%);
|
||||||
|
return data;
|
||||||
|
}
|
18
output_testing/1048capturing-func-simple-alias-iife.js
Normal file
18
output_testing/1048capturing-func-simple-alias-iife.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
const {
|
||||||
|
mutate
|
||||||
|
} = "shared-runtime" |> require(%);
|
||||||
|
function component(a) {
|
||||||
|
let x = {
|
||||||
|
a
|
||||||
|
};
|
||||||
|
let y = {};
|
||||||
|
(function () {
|
||||||
|
y = x;
|
||||||
|
})();
|
||||||
|
y |> mutate(%);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: component,
|
||||||
|
params: ["foo"]
|
||||||
|
};
|
|
@ -0,0 +1,10 @@
|
||||||
|
function Component(props) {
|
||||||
|
let x = cond ? someGlobal : props.foo;
|
||||||
|
const mutatePhiThatCouldBeProps = () => {
|
||||||
|
x.y = true;
|
||||||
|
};
|
||||||
|
const indirectMutateProps = () => {
|
||||||
|
mutatePhiThatCouldBeProps();
|
||||||
|
};
|
||||||
|
(() => indirectMutateProps()) |> useEffect(%, []);
|
||||||
|
}
|
272
output_testing/104build-all-release-channels.js
Normal file
272
output_testing/104build-all-release-channels.js
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* eslint-disable no-for-of-loops/no-for-of-loops */
|
||||||
|
const crypto = 'node:crypto' |> require(%);
|
||||||
|
const fs = 'fs' |> require(%);
|
||||||
|
const fse = 'fs-extra' |> require(%);
|
||||||
|
const {
|
||||||
|
spawnSync
|
||||||
|
} = 'child_process' |> require(%);
|
||||||
|
const path = 'path' |> require(%);
|
||||||
|
const tmp = 'tmp' |> require(%);
|
||||||
|
const shell = 'shelljs' |> require(%);
|
||||||
|
const {
|
||||||
|
ReactVersion,
|
||||||
|
stablePackages,
|
||||||
|
experimentalPackages,
|
||||||
|
canaryChannelLabel
|
||||||
|
} = '../../ReactVersions' |> require(%);
|
||||||
|
|
||||||
|
// Runs the build script for both stable and experimental release channels,
|
||||||
|
// by configuring an environment variable.
|
||||||
|
|
||||||
|
const sha = (('git' |> spawnSync(%, ['show', '-s', '--no-show-signature', '--format=%h'])).stdout |> String(%)).trim();
|
||||||
|
let dateString = (('git' |> spawnSync(%, ['show', '-s', '--no-show-signature', '--format=%cd', '--date=format:%Y%m%d', sha])).stdout |> String(%)).trim();
|
||||||
|
|
||||||
|
// On CI environment, this string is wrapped with quotes '...'s
|
||||||
|
if ("'" |> dateString.startsWith(%)) {
|
||||||
|
dateString = 1 |> dateString.slice(%, 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the artifacts using a placeholder React version. We'll then do a string
|
||||||
|
// replace to swap it with the correct version per release channel.
|
||||||
|
const PLACEHOLDER_REACT_VERSION = ReactVersion + '-PLACEHOLDER';
|
||||||
|
|
||||||
|
// TODO: We should inject the React version using a build-time parameter
|
||||||
|
// instead of overwriting the source files.
|
||||||
|
'./packages/shared/ReactVersion.js' |> fs.writeFileSync(%, `export default '${PLACEHOLDER_REACT_VERSION}';\n`);
|
||||||
|
if (process.env.CIRCLE_NODE_TOTAL) {
|
||||||
|
// In CI, we use multiple concurrent processes. Allocate half the processes to
|
||||||
|
// build the stable channel, and the other half for experimental. Override
|
||||||
|
// the environment variables to "trick" the underlying build script.
|
||||||
|
const total = process.env.CIRCLE_NODE_TOTAL |> parseInt(%, 10);
|
||||||
|
const halfTotal = total / 2 |> Math.floor(%);
|
||||||
|
const index = process.env.CIRCLE_NODE_INDEX |> parseInt(%, 10);
|
||||||
|
if (index < halfTotal) {
|
||||||
|
const nodeTotal = halfTotal;
|
||||||
|
const nodeIndex = index;
|
||||||
|
buildForChannel('stable', nodeTotal, nodeIndex);
|
||||||
|
'./build' |> processStable(%);
|
||||||
|
} else {
|
||||||
|
const nodeTotal = total - halfTotal;
|
||||||
|
const nodeIndex = index - halfTotal;
|
||||||
|
buildForChannel('experimental', nodeTotal, nodeIndex);
|
||||||
|
'./build' |> processExperimental(%);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Running locally, no concurrency. Move each channel's build artifacts into
|
||||||
|
// a temporary directory so that they don't conflict.
|
||||||
|
buildForChannel('stable', '', '');
|
||||||
|
const stableDir = tmp.dirSync().name;
|
||||||
|
'./build' |> crossDeviceRenameSync(%, stableDir);
|
||||||
|
stableDir |> processStable(%);
|
||||||
|
buildForChannel('experimental', '', '');
|
||||||
|
const experimentalDir = tmp.dirSync().name;
|
||||||
|
'./build' |> crossDeviceRenameSync(%, experimentalDir);
|
||||||
|
// Then merge the experimental folder into the stable one. processExperimental
|
||||||
|
// will have already removed conflicting files.
|
||||||
|
//
|
||||||
|
// In CI, merging is handled automatically by CircleCI's workspace feature.
|
||||||
|
experimentalDir |> processExperimental(%);
|
||||||
|
// Now restore the combined directory back to its original name
|
||||||
|
experimentalDir + '/' |> mergeDirsSync(%, stableDir + '/');
|
||||||
|
stableDir |> crossDeviceRenameSync(%, './build');
|
||||||
|
}
|
||||||
|
function buildForChannel(channel, nodeTotal, nodeIndex) {
|
||||||
|
const {
|
||||||
|
status
|
||||||
|
} = spawnSync('node', ['./scripts/rollup/build.js', ...(2 |> process.argv.slice(%))], {
|
||||||
|
stdio: ['pipe', process.stdout, process.stderr],
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
RELEASE_CHANNEL: channel,
|
||||||
|
CIRCLE_NODE_TOTAL: nodeTotal,
|
||||||
|
CIRCLE_NODE_INDEX: nodeIndex
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (status !== 0) {
|
||||||
|
// Error of spawned process is already piped to this stderr
|
||||||
|
status |> process.exit(%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function processStable(buildDir) {
|
||||||
|
if (buildDir + '/node_modules' |> fs.existsSync(%)) {
|
||||||
|
// Identical to `oss-stable` but with real, semver versions. This is what
|
||||||
|
// will get published to @latest.
|
||||||
|
shell.cp('-r', buildDir + '/node_modules', buildDir + '/oss-stable-semver');
|
||||||
|
const defaultVersionIfNotFound = '0.0.0' + '-' + sha + '-' + dateString;
|
||||||
|
const versionsMap = new Map();
|
||||||
|
for (const moduleName in stablePackages) {
|
||||||
|
const version = stablePackages[moduleName];
|
||||||
|
versionsMap.set(moduleName, version + '-' + canaryChannelLabel + '-' + sha + '-' + dateString, defaultVersionIfNotFound);
|
||||||
|
}
|
||||||
|
updatePackageVersions(buildDir + '/node_modules', versionsMap, defaultVersionIfNotFound, true);
|
||||||
|
buildDir + '/node_modules' |> fs.renameSync(%, buildDir + '/oss-stable');
|
||||||
|
// Now do the semver ones
|
||||||
|
buildDir + '/oss-stable' |> updatePlaceholderReactVersionInCompiledArtifacts(%, ReactVersion + '-' + canaryChannelLabel + '-' + sha + '-' + dateString);
|
||||||
|
const semverVersionsMap = new Map();
|
||||||
|
for (const moduleName in stablePackages) {
|
||||||
|
const version = stablePackages[moduleName];
|
||||||
|
moduleName |> semverVersionsMap.set(%, version);
|
||||||
|
}
|
||||||
|
updatePackageVersions(buildDir + '/oss-stable-semver', semverVersionsMap, defaultVersionIfNotFound, false);
|
||||||
|
buildDir + '/oss-stable-semver' |> updatePlaceholderReactVersionInCompiledArtifacts(%, ReactVersion);
|
||||||
|
}
|
||||||
|
if (buildDir + '/facebook-www' |> fs.existsSync(%)) {
|
||||||
|
for (const fileName of (buildDir + '/facebook-www' |> fs.readdirSync(%)).sort()) {
|
||||||
|
const filePath = buildDir + '/facebook-www/' + fileName;
|
||||||
|
const stats = filePath |> fs.statSync(%);
|
||||||
|
if (!stats.isDirectory()) {
|
||||||
|
filePath |> fs.renameSync(%, '.js' |> filePath.replace(%, '.classic.js'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buildDir + '/facebook-www' |> updatePlaceholderReactVersionInCompiledArtifacts(%, ReactVersion + '-www-classic-%FILEHASH%');
|
||||||
|
}
|
||||||
|
// Update remaining placeholders with canary channel version
|
||||||
|
(reactNativeBuildDir => {
|
||||||
|
if (reactNativeBuildDir |> fs.existsSync(%)) {
|
||||||
|
reactNativeBuildDir |> updatePlaceholderReactVersionInCompiledArtifacts(%, ReactVersion + '-' + canaryChannelLabel + '-%FILEHASH%');
|
||||||
|
}
|
||||||
|
}) |> [buildDir + '/react-native/implementations/', buildDir + '/facebook-react-native/'].forEach(%);
|
||||||
|
buildDir |> updatePlaceholderReactVersionInCompiledArtifacts(%, ReactVersion + '-' + canaryChannelLabel + '-' + sha + '-' + dateString);
|
||||||
|
if (buildDir + '/sizes' |> fs.existsSync(%)) {
|
||||||
|
buildDir + '/sizes' |> fs.renameSync(%, buildDir + '/sizes-stable');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function processExperimental(buildDir, version) {
|
||||||
|
if (buildDir + '/node_modules' |> fs.existsSync(%)) {
|
||||||
|
const defaultVersionIfNotFound = '0.0.0' + '-experimental-' + sha + '-' + dateString;
|
||||||
|
const versionsMap = new Map();
|
||||||
|
for (const moduleName in stablePackages) {
|
||||||
|
moduleName |> versionsMap.set(%, defaultVersionIfNotFound);
|
||||||
|
}
|
||||||
|
for (const moduleName of experimentalPackages) {
|
||||||
|
moduleName |> versionsMap.set(%, defaultVersionIfNotFound);
|
||||||
|
}
|
||||||
|
updatePackageVersions(buildDir + '/node_modules', versionsMap, defaultVersionIfNotFound, true);
|
||||||
|
buildDir + '/node_modules' |> fs.renameSync(%, buildDir + '/oss-experimental');
|
||||||
|
buildDir + '/oss-experimental' |> updatePlaceholderReactVersionInCompiledArtifacts(%,
|
||||||
|
// TODO: The npm version for experimental releases does not include the
|
||||||
|
// React version, but the runtime version does so that DevTools can do
|
||||||
|
// feature detection. Decide what to do about this later.
|
||||||
|
ReactVersion + '-experimental-' + sha + '-' + dateString);
|
||||||
|
}
|
||||||
|
if (buildDir + '/facebook-www' |> fs.existsSync(%)) {
|
||||||
|
for (const fileName of (buildDir + '/facebook-www' |> fs.readdirSync(%)).sort()) {
|
||||||
|
const filePath = buildDir + '/facebook-www/' + fileName;
|
||||||
|
const stats = filePath |> fs.statSync(%);
|
||||||
|
if (!stats.isDirectory()) {
|
||||||
|
filePath |> fs.renameSync(%, '.js' |> filePath.replace(%, '.modern.js'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buildDir + '/facebook-www' |> updatePlaceholderReactVersionInCompiledArtifacts(%, ReactVersion + '-www-modern-%FILEHASH%');
|
||||||
|
}
|
||||||
|
// Update remaining placeholders with canary channel version
|
||||||
|
(reactNativeBuildDir => {
|
||||||
|
if (reactNativeBuildDir |> fs.existsSync(%)) {
|
||||||
|
reactNativeBuildDir |> updatePlaceholderReactVersionInCompiledArtifacts(%, ReactVersion + '-' + canaryChannelLabel + '-%FILEHASH%');
|
||||||
|
}
|
||||||
|
}) |> [buildDir + '/react-native/implementations/', buildDir + '/facebook-react-native/'].forEach(%);
|
||||||
|
buildDir |> updatePlaceholderReactVersionInCompiledArtifacts(%, ReactVersion + '-' + canaryChannelLabel + '-' + sha + '-' + dateString);
|
||||||
|
if (buildDir + '/sizes' |> fs.existsSync(%)) {
|
||||||
|
buildDir + '/sizes' |> fs.renameSync(%, buildDir + '/sizes-experimental');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete all other artifacts that weren't handled above. We assume they are
|
||||||
|
// duplicates of the corresponding artifacts in the stable channel. Ideally,
|
||||||
|
// the underlying build script should not have produced these files in the
|
||||||
|
// first place.
|
||||||
|
for (const pathName of buildDir |> fs.readdirSync(%)) {
|
||||||
|
if (pathName !== 'oss-experimental' && pathName !== 'facebook-www' && pathName !== 'sizes-experimental') {
|
||||||
|
'rm' |> spawnSync(%, ['-rm', buildDir + '/' + pathName]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function crossDeviceRenameSync(source, destination) {
|
||||||
|
return fse.moveSync(source, destination, {
|
||||||
|
overwrite: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Grabs the built packages in ${tmp_build_dir}/node_modules and updates the
|
||||||
|
* `version` key in their package.json to 0.0.0-${date}-${commitHash} for the commit
|
||||||
|
* you're building. Also updates the dependencies and peerDependencies
|
||||||
|
* to match this version for all of the 'React' packages
|
||||||
|
* (packages available in this repo).
|
||||||
|
*/
|
||||||
|
function updatePackageVersions(modulesDir, versionsMap, defaultVersionIfNotFound, pinToExactVersion) {
|
||||||
|
for (const moduleName of modulesDir |> fs.readdirSync(%)) {
|
||||||
|
let version = moduleName |> versionsMap.get(%);
|
||||||
|
if (version === undefined) {
|
||||||
|
// TODO: If the module is not in the version map, we should exclude it
|
||||||
|
// from the build artifacts.
|
||||||
|
version = defaultVersionIfNotFound;
|
||||||
|
}
|
||||||
|
const packageJSONPath = path.join(modulesDir, moduleName, 'package.json');
|
||||||
|
const stats = packageJSONPath |> fs.statSync(%);
|
||||||
|
if (stats.isFile()) {
|
||||||
|
const packageInfo = packageJSONPath |> fs.readFileSync(%) |> JSON.parse(%);
|
||||||
|
|
||||||
|
// Update version
|
||||||
|
packageInfo.version = version;
|
||||||
|
if (packageInfo.dependencies) {
|
||||||
|
for (const dep of packageInfo.dependencies |> Object.keys(%)) {
|
||||||
|
const depVersion = dep |> versionsMap.get(%);
|
||||||
|
if (depVersion !== undefined) {
|
||||||
|
packageInfo.dependencies[dep] = pinToExactVersion ? depVersion : '^' + depVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (packageInfo.peerDependencies) {
|
||||||
|
if (!pinToExactVersion && (moduleName === 'use-sync-external-store' || moduleName === 'use-subscription')) {
|
||||||
|
// use-sync-external-store supports older versions of React, too, so
|
||||||
|
// we don't override to the latest version. We should figure out some
|
||||||
|
// better way to handle this.
|
||||||
|
// TODO: Remove this special case.
|
||||||
|
} else {
|
||||||
|
for (const dep of packageInfo.peerDependencies |> Object.keys(%)) {
|
||||||
|
const depVersion = dep |> versionsMap.get(%);
|
||||||
|
if (depVersion !== undefined) {
|
||||||
|
packageInfo.peerDependencies[dep] = pinToExactVersion ? depVersion : '^' + depVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write out updated package.json
|
||||||
|
packageJSONPath |> fs.writeFileSync(%, JSON.stringify(packageInfo, null, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function updatePlaceholderReactVersionInCompiledArtifacts(artifactsDirectory, newVersion) {
|
||||||
|
// Update the version of React in the compiled artifacts by searching for
|
||||||
|
// the placeholder string and replacing it with a new one.
|
||||||
|
const artifactFilenames = (filename => '.js' |> filename.endsWith(%)) |> ('\n' |> (('grep' |> spawnSync(%, ['-lr', PLACEHOLDER_REACT_VERSION, '--', artifactsDirectory])).stdout |> String(%)).trim().split(%)).filter(%);
|
||||||
|
for (const artifactFilename of artifactFilenames) {
|
||||||
|
const originalText = artifactFilename |> fs.readFileSync(%, 'utf8');
|
||||||
|
const fileHash = 'sha1' |> crypto.createHash(%);
|
||||||
|
originalText |> fileHash.update(%);
|
||||||
|
const replacedText = PLACEHOLDER_REACT_VERSION |> originalText.replaceAll(%, /%FILEHASH%/g |> newVersion.replace(%, 0 |> ('hex' |> fileHash.digest(%)).slice(%, 8)));
|
||||||
|
artifactFilename |> fs.writeFileSync(%, replacedText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cross-platform alternative to `rsync -ar`
|
||||||
|
* @param {string} source
|
||||||
|
* @param {string} destination
|
||||||
|
*/
|
||||||
|
function mergeDirsSync(source, destination) {
|
||||||
|
for (const sourceFileBaseName of source |> fs.readdirSync(%)) {
|
||||||
|
const sourceFileName = source |> path.join(%, sourceFileBaseName);
|
||||||
|
const targetFileName = destination |> path.join(%, sourceFileBaseName);
|
||||||
|
const sourceFile = sourceFileName |> fs.statSync(%);
|
||||||
|
if (sourceFile.isDirectory()) {
|
||||||
|
targetFileName |> fse.ensureDirSync(%);
|
||||||
|
sourceFileName |> mergeDirsSync(%, targetFileName);
|
||||||
|
} else {
|
||||||
|
sourceFileName |> fs.copyFileSync(%, targetFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
output_testing/1050optional-call-logical.js
Normal file
4
output_testing/1050optional-call-logical.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
function Component(props) {
|
||||||
|
const item = graphql`...` |> useFragment(%, props.item);
|
||||||
|
return item.items?.map(item => item |> renderItem(%)) ?? [];
|
||||||
|
}
|
23
output_testing/1051useMemo-multiple-if-else.js
Normal file
23
output_testing/1051useMemo-multiple-if-else.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import { useMemo } from "react";
|
||||||
|
function Component(props) {
|
||||||
|
const x = (() => {
|
||||||
|
let y = [];
|
||||||
|
if (props.cond) {
|
||||||
|
props.a |> y.push(%);
|
||||||
|
}
|
||||||
|
if (props.cond2) {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
props.b |> y.push(%);
|
||||||
|
return y;
|
||||||
|
}) |> useMemo(%);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
cond2: false
|
||||||
|
}]
|
||||||
|
};
|
12
output_testing/1052noAlias-filter-on-array-prop.js
Normal file
12
output_testing/1052noAlias-filter-on-array-prop.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
function Component(props) {
|
||||||
|
const filtered = (item => item != null) |> props.items.filter(%);
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
items: [{
|
||||||
|
a: true
|
||||||
|
}, null, true, false, null, "string", 3.14, null, [null]]
|
||||||
|
}]
|
||||||
|
};
|
10
output_testing/1053frozen-after-alias.js
Normal file
10
output_testing/1053frozen-after-alias.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
function Component() {
|
||||||
|
const a = [];
|
||||||
|
const b = a;
|
||||||
|
a |> useFreeze(%);
|
||||||
|
// should be readonly, value is guaranteed frozen via alias
|
||||||
|
b |> foo(%);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
function useFreeze() {}
|
||||||
|
function foo(x) {}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { identity } from "shared-runtime";
|
||||||
|
function Component(x = [() => {}, true, 42, "hello"] |> identity(%)) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: []
|
||||||
|
};
|
14
output_testing/1055capturing-function-renamed-ref.js
Normal file
14
output_testing/1055capturing-function-renamed-ref.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
function component(a, b) {
|
||||||
|
let z = {
|
||||||
|
a
|
||||||
|
};
|
||||||
|
{
|
||||||
|
let z = {
|
||||||
|
b
|
||||||
|
};
|
||||||
|
(function () {
|
||||||
|
z |> mutate(%);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
return z;
|
||||||
|
}
|
19
output_testing/1056object-method-shorthand-3.js
Normal file
19
output_testing/1056object-method-shorthand-3.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { createHookWrapper, mutate } from "shared-runtime";
|
||||||
|
function useHook(a) {
|
||||||
|
const x = {
|
||||||
|
a
|
||||||
|
};
|
||||||
|
let obj = {
|
||||||
|
method() {
|
||||||
|
x |> mutate(%);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return obj.method();
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: useHook |> createHookWrapper(%),
|
||||||
|
params: [{
|
||||||
|
x: 1
|
||||||
|
}]
|
||||||
|
};
|
61
output_testing/1057conditional-early-return.js
Normal file
61
output_testing/1057conditional-early-return.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/**
|
||||||
|
* props.b does *not* influence `a`
|
||||||
|
*/
|
||||||
|
function ComponentA(props) {
|
||||||
|
const a_DEBUG = [];
|
||||||
|
props.a |> a_DEBUG.push(%);
|
||||||
|
if (props.b) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
props.d |> a_DEBUG.push(%);
|
||||||
|
return a_DEBUG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* props.b *does* influence `a`
|
||||||
|
*/
|
||||||
|
function ComponentB(props) {
|
||||||
|
const a = [];
|
||||||
|
props.a |> a.push(%);
|
||||||
|
if (props.b) {
|
||||||
|
props.c |> a.push(%);
|
||||||
|
}
|
||||||
|
props.d |> a.push(%);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* props.b *does* influence `a`, but only in a way that is never observable
|
||||||
|
*/
|
||||||
|
function ComponentC(props) {
|
||||||
|
const a = [];
|
||||||
|
props.a |> a.push(%);
|
||||||
|
if (props.b) {
|
||||||
|
props.c |> a.push(%);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
props.d |> a.push(%);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* props.b *does* influence `a`
|
||||||
|
*/
|
||||||
|
function ComponentD(props) {
|
||||||
|
const a = [];
|
||||||
|
props.a |> a.push(%);
|
||||||
|
if (props.b) {
|
||||||
|
props.c |> a.push(%);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
props.d |> a.push(%);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: ComponentA,
|
||||||
|
params: [{
|
||||||
|
a: 1,
|
||||||
|
b: false,
|
||||||
|
d: 3
|
||||||
|
}]
|
||||||
|
};
|
|
@ -0,0 +1,6 @@
|
||||||
|
function Foo(props) {
|
||||||
|
const onFoo = (reason => {
|
||||||
|
props.router.location |> log(%);
|
||||||
|
}) |> useCallback(%, [props.router.location]);
|
||||||
|
return onFoo;
|
||||||
|
}
|
6
output_testing/1059array-join.js
Normal file
6
output_testing/1059array-join.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
function Component(props) {
|
||||||
|
const x = [{}, [], props.value];
|
||||||
|
const y = (() => "this closure gets stringified, not called") |> x.join(%);
|
||||||
|
y |> foo(%);
|
||||||
|
return [x, y];
|
||||||
|
}
|
25
output_testing/105listChangedFiles.js
Normal file
25
output_testing/105listChangedFiles.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const execFileSync = ('child_process' |> require(%)).execFileSync;
|
||||||
|
const exec = (command, args) => {
|
||||||
|
'> ' + (' ' |> (args |> [command].concat(%)).join(%)) |> console.log(%);
|
||||||
|
const options = {
|
||||||
|
cwd: process.cwd(),
|
||||||
|
env: process.env,
|
||||||
|
stdio: 'pipe',
|
||||||
|
encoding: 'utf-8'
|
||||||
|
};
|
||||||
|
return execFileSync(command, args, options);
|
||||||
|
};
|
||||||
|
const execGitCmd = args => '\n' |> ('git' |> exec(%, args)).trim().toString().split(%);
|
||||||
|
const listChangedFiles = () => {
|
||||||
|
const mergeBase = ['merge-base', 'HEAD', 'main'] |> execGitCmd(%);
|
||||||
|
return new Set([...(['diff', '--name-only', '--diff-filter=ACMRTUB', mergeBase] |> execGitCmd(%)), ...(['ls-files', '--others', '--exclude-standard'] |> execGitCmd(%))]);
|
||||||
|
};
|
||||||
|
module.exports = listChangedFiles;
|
15
output_testing/1060useMemo-inlining-block-return.js
Normal file
15
output_testing/1060useMemo-inlining-block-return.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
function component(a, b) {
|
||||||
|
let x = (() => {
|
||||||
|
if (a) {
|
||||||
|
return {
|
||||||
|
b
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}) |> useMemo(%, [a, b]);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: component,
|
||||||
|
params: ["TodoAdd"],
|
||||||
|
isComponent: "TodoAdd"
|
||||||
|
};
|
20
output_testing/1061useMemo-switch-no-fallthrough.js
Normal file
20
output_testing/1061useMemo-switch-no-fallthrough.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
function Component(props) {
|
||||||
|
const x = (() => {
|
||||||
|
switch (props.key) {
|
||||||
|
case "key":
|
||||||
|
{
|
||||||
|
return props.value;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return props.defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) |> useMemo(%);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: ["TodoAdd"],
|
||||||
|
isComponent: "TodoAdd"
|
||||||
|
};
|
9
output_testing/1062array-at-effect.js
Normal file
9
output_testing/1062array-at-effect.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// arrayInstance.at should have the following effects:
|
||||||
|
// - read on arg0
|
||||||
|
// - read on receiver
|
||||||
|
// - mutate on lvalue
|
||||||
|
function ArrayAtTest(props) {
|
||||||
|
const arr = [props.x |> foo(%)];
|
||||||
|
const result = props.y |> bar(%) |> arr.at(%);
|
||||||
|
return result;
|
||||||
|
}
|
18
output_testing/1063object-expression-computed-key.js
Normal file
18
output_testing/1063object-expression-computed-key.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { identity } from "shared-runtime";
|
||||||
|
const SCALE = 2;
|
||||||
|
function Component(props) {
|
||||||
|
const {
|
||||||
|
key
|
||||||
|
} = props;
|
||||||
|
const context = {
|
||||||
|
[key]: [props.value, SCALE] |> identity(%)
|
||||||
|
};
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
key: "Sathya",
|
||||||
|
value: "Compiler"
|
||||||
|
}]
|
||||||
|
};
|
7
output_testing/1064unknown-hooks-do-not-assert.js
Normal file
7
output_testing/1064unknown-hooks-do-not-assert.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// Forget currently bails out when it detects a potential mutation (Effect.Mutate)
|
||||||
|
// to an immutable value. This should not apply to unknown / untyped hooks.
|
||||||
|
function Component(props) {
|
||||||
|
const x = props |> useUnknownHook1(%);
|
||||||
|
const y = x |> useUnknownHook2(%);
|
||||||
|
return y;
|
||||||
|
}
|
22
output_testing/1065phi-type-inference-array-push.js
Normal file
22
output_testing/1065phi-type-inference-array-push.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
function Component(props) {
|
||||||
|
const x = {};
|
||||||
|
let y;
|
||||||
|
if (props.cond) {
|
||||||
|
y = [props.value];
|
||||||
|
} else {
|
||||||
|
y = [];
|
||||||
|
}
|
||||||
|
// This should be inferred as `<store> y` s.t. `x` can still
|
||||||
|
// be independently memoized. *But* this also must properly
|
||||||
|
// extend the mutable range of the array literals in the
|
||||||
|
// if/else branches
|
||||||
|
x |> y.push(%);
|
||||||
|
return [x, y];
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
cond: true,
|
||||||
|
value: 42
|
||||||
|
}]
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
function component(a, b) {
|
||||||
|
let x = (c => a) |> useMemo(%, []);
|
||||||
|
return x;
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { identity } from "shared-runtime";
|
||||||
|
function Component(props) {
|
||||||
|
let [x] = props.value;
|
||||||
|
const foo = () => {
|
||||||
|
x = props.value[0] |> identity(%);
|
||||||
|
};
|
||||||
|
foo();
|
||||||
|
return {
|
||||||
|
x
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
value: [42]
|
||||||
|
}]
|
||||||
|
};
|
|
@ -0,0 +1,24 @@
|
||||||
|
function Component(props) {
|
||||||
|
let x = [];
|
||||||
|
if (props.cond) {
|
||||||
|
props.a |> x.push(%);
|
||||||
|
if (props.b) {
|
||||||
|
const y = [props.b];
|
||||||
|
// oops no memo!
|
||||||
|
y |> x.push(%);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
// oops no memo!
|
||||||
|
return x;
|
||||||
|
} else {
|
||||||
|
return foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{
|
||||||
|
cond: true,
|
||||||
|
a: 42,
|
||||||
|
b: 3.14
|
||||||
|
}]
|
||||||
|
};
|
32
output_testing/1069merge-consecutive-scopes-objects.js
Normal file
32
output_testing/1069merge-consecutive-scopes-objects.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Stringify } from "shared-runtime";
|
||||||
|
|
||||||
|
// This is a translation of the original merge-consecutive-scopes which uses plain objects
|
||||||
|
// to describe the UI instead of JSX. The JSXText elements in that fixture happen to
|
||||||
|
// prevent scome scopes from merging, which concealed a bug with the merging logic.
|
||||||
|
// By avoiding JSX we eliminate extraneous instructions and more accurately test the merging.
|
||||||
|
function Component(props) {
|
||||||
|
let [state, setState] = 0 |> useState(%);
|
||||||
|
return [{
|
||||||
|
component: Stringify,
|
||||||
|
props: {
|
||||||
|
text: "Counter"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
component: "span",
|
||||||
|
props: {
|
||||||
|
children: [state]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
component: "button",
|
||||||
|
props: {
|
||||||
|
"data-testid": "button",
|
||||||
|
onClick: () => state + 1 |> setState(%),
|
||||||
|
children: ["increment"]
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{}]
|
||||||
|
};
|
55
output_testing/106evalToString.js
Normal file
55
output_testing/106evalToString.js
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function evalStringConcat(ast) {
|
||||||
|
switch (ast.type) {
|
||||||
|
case 'StringLiteral':
|
||||||
|
case 'Literal':
|
||||||
|
// ESLint
|
||||||
|
return ast.value;
|
||||||
|
case 'BinaryExpression':
|
||||||
|
// `+`
|
||||||
|
if (ast.operator !== '+') {
|
||||||
|
throw new Error('Unsupported binary operator ' + ast.operator);
|
||||||
|
}
|
||||||
|
return (ast.left |> evalStringConcat(%)) + (ast.right |> evalStringConcat(%));
|
||||||
|
default:
|
||||||
|
throw new Error('Unsupported type ' + ast.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.evalStringConcat = evalStringConcat;
|
||||||
|
function evalStringAndTemplateConcat(ast, args) {
|
||||||
|
switch (ast.type) {
|
||||||
|
case 'StringLiteral':
|
||||||
|
return ast.value;
|
||||||
|
case 'BinaryExpression':
|
||||||
|
// `+`
|
||||||
|
if (ast.operator !== '+') {
|
||||||
|
throw new Error('Unsupported binary operator ' + ast.operator);
|
||||||
|
}
|
||||||
|
return (ast.left |> evalStringAndTemplateConcat(%, args)) + (ast.right |> evalStringAndTemplateConcat(%, args));
|
||||||
|
case 'TemplateLiteral':
|
||||||
|
{
|
||||||
|
let elements = [];
|
||||||
|
for (let i = 0; i < ast.quasis.length; i++) {
|
||||||
|
const elementNode = ast.quasis[i];
|
||||||
|
if (elementNode.type !== 'TemplateElement') {
|
||||||
|
throw new Error('Unsupported type ' + ast.type);
|
||||||
|
}
|
||||||
|
elementNode.value.cooked |> elements.push(%);
|
||||||
|
}
|
||||||
|
args.push(...ast.expressions);
|
||||||
|
return '%s' |> elements.join(%);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// Anything that's not a string is interpreted as an argument.
|
||||||
|
ast |> args.push(%);
|
||||||
|
return '%s';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.evalStringAndTemplateConcat = evalStringAndTemplateConcat;
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { makeArray } from "shared-runtime";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This fixture tests what happens when a reactive has no declarations (other than an early return),
|
||||||
|
* no reassignments, and no dependencies. In this case the only thing we can use to decide if we
|
||||||
|
* should take the if or else branch is the early return declaration. But if that uses the same
|
||||||
|
* sentinel as the memo cache sentinel, then if the previous execution did not early return it will
|
||||||
|
* look like we didn't execute the memo block yet, and we'll needlessly re-execute instead of skipping
|
||||||
|
* to the else branch.
|
||||||
|
*
|
||||||
|
* We have to use a distinct sentinel for the early return value.
|
||||||
|
*
|
||||||
|
* Here the fixture will always take the "else" branch and never early return. Logging (not included)
|
||||||
|
* confirms that the scope for `x` only executes once, on the first render of the component.
|
||||||
|
*/
|
||||||
|
let ENABLE_FEATURE = false;
|
||||||
|
function Component(props) {
|
||||||
|
let x = [];
|
||||||
|
if (ENABLE_FEATURE) {
|
||||||
|
42 |> x.push(%);
|
||||||
|
return x;
|
||||||
|
} else {
|
||||||
|
"fallthrough" |> console.log(%);
|
||||||
|
}
|
||||||
|
return props.a |> makeArray(%);
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [],
|
||||||
|
sequentialRenders: [{
|
||||||
|
a: 42
|
||||||
|
}, {
|
||||||
|
a: 42
|
||||||
|
}, {
|
||||||
|
a: 3.14
|
||||||
|
}, {
|
||||||
|
a: 3.14
|
||||||
|
}, {
|
||||||
|
a: 42
|
||||||
|
}, {
|
||||||
|
a: 3.14
|
||||||
|
}, {
|
||||||
|
a: 42
|
||||||
|
}, {
|
||||||
|
a: 3.14
|
||||||
|
}]
|
||||||
|
};
|
|
@ -0,0 +1,13 @@
|
||||||
|
function component(a) {
|
||||||
|
let x = {
|
||||||
|
a
|
||||||
|
};
|
||||||
|
let y = {};
|
||||||
|
const f0 = function () {
|
||||||
|
let a = y;
|
||||||
|
a["x"] = x;
|
||||||
|
};
|
||||||
|
f0();
|
||||||
|
y |> mutate(%);
|
||||||
|
return y;
|
||||||
|
}
|
10
output_testing/1072conflicting-dollar-sign-variable.js
Normal file
10
output_testing/1072conflicting-dollar-sign-variable.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { identity } from "shared-runtime";
|
||||||
|
function Component(props) {
|
||||||
|
const $ = "jQuery" |> identity(%);
|
||||||
|
const t0 = [$] |> identity(%);
|
||||||
|
return t0;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{}]
|
||||||
|
};
|
|
@ -0,0 +1,9 @@
|
||||||
|
function Component() {
|
||||||
|
function callback(x) {
|
||||||
|
if (x == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return x - 1 |> callback(%);
|
||||||
|
}
|
||||||
|
return 10 |> callback(%);
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
function Component(props) {
|
||||||
|
const mutateProps = () => {
|
||||||
|
props.value = true;
|
||||||
|
};
|
||||||
|
const indirectMutateProps = () => {
|
||||||
|
mutateProps();
|
||||||
|
};
|
||||||
|
(() => indirectMutateProps()) |> useEffect(%, []);
|
||||||
|
}
|
27
output_testing/1075ssa-renaming-via-destructuring.js
Normal file
27
output_testing/1075ssa-renaming-via-destructuring.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
function foo(props) {
|
||||||
|
let {
|
||||||
|
x
|
||||||
|
} = {
|
||||||
|
x: []
|
||||||
|
};
|
||||||
|
props.bar |> x.push(%);
|
||||||
|
if (props.cond) {
|
||||||
|
({
|
||||||
|
x
|
||||||
|
} = {
|
||||||
|
x: {}
|
||||||
|
});
|
||||||
|
({
|
||||||
|
x
|
||||||
|
} = {
|
||||||
|
x: []
|
||||||
|
});
|
||||||
|
props.foo |> x.push(%);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: foo,
|
||||||
|
params: ["TodoAdd"],
|
||||||
|
isComponent: "TodoAdd"
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
function Component(props) {
|
||||||
|
let x = makeObject();
|
||||||
|
([[x]] = makeObject()) |> x.foo(%);
|
||||||
|
return x;
|
||||||
|
}
|
6
output_testing/1077nested-optional-member-expr.js
Normal file
6
output_testing/1077nested-optional-member-expr.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// We should codegen nested optional properties correctly
|
||||||
|
// (i.e. placing `?` in the correct PropertyLoad)
|
||||||
|
function Component(props) {
|
||||||
|
let x = props.a?.b.c.d |> foo(%);
|
||||||
|
return x;
|
||||||
|
}
|
5
output_testing/1078error.invalid-assign-hook-to-local.js
Normal file
5
output_testing/1078error.invalid-assign-hook-to-local.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
function Component(props) {
|
||||||
|
const x = useState;
|
||||||
|
const state = null |> x(%);
|
||||||
|
return state[0];
|
||||||
|
}
|
13
output_testing/1079ssa-property-call.js
Normal file
13
output_testing/1079ssa-property-call.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
function foo() {
|
||||||
|
const x = [];
|
||||||
|
const y = {
|
||||||
|
x: x
|
||||||
|
};
|
||||||
|
[] |> y.x.push(%);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: foo,
|
||||||
|
params: [],
|
||||||
|
isComponent: false
|
||||||
|
};
|
311
output_testing/107jest-cli.js
Normal file
311
output_testing/107jest-cli.js
Normal file
|
@ -0,0 +1,311 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const {
|
||||||
|
spawn
|
||||||
|
} = 'child_process' |> require(%);
|
||||||
|
const chalk = 'chalk' |> require(%);
|
||||||
|
const yargs = 'yargs' |> require(%);
|
||||||
|
const fs = 'fs' |> require(%);
|
||||||
|
const path = 'path' |> require(%);
|
||||||
|
const semver = 'semver' |> require(%);
|
||||||
|
const ossConfig = './scripts/jest/config.source.js';
|
||||||
|
const wwwConfig = './scripts/jest/config.source-www.js';
|
||||||
|
const devToolsConfig = './scripts/jest/config.build-devtools.js';
|
||||||
|
|
||||||
|
// TODO: These configs are separate but should be rolled into the configs above
|
||||||
|
// so that the CLI can provide them as options for any of the configs.
|
||||||
|
const persistentConfig = './scripts/jest/config.source-persistent.js';
|
||||||
|
const buildConfig = './scripts/jest/config.build.js';
|
||||||
|
const argv = ({
|
||||||
|
debug: {
|
||||||
|
alias: 'd',
|
||||||
|
describe: 'Run with node debugger attached.',
|
||||||
|
requiresArg: false,
|
||||||
|
type: 'boolean',
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
project: {
|
||||||
|
alias: 'p',
|
||||||
|
describe: 'Run the given project.',
|
||||||
|
requiresArg: true,
|
||||||
|
type: 'string',
|
||||||
|
default: 'default',
|
||||||
|
choices: ['default', 'devtools']
|
||||||
|
},
|
||||||
|
releaseChannel: {
|
||||||
|
alias: 'r',
|
||||||
|
describe: 'Run with the given release channel.',
|
||||||
|
requiresArg: true,
|
||||||
|
type: 'string',
|
||||||
|
default: 'experimental',
|
||||||
|
choices: ['experimental', 'stable', 'www-classic', 'www-modern']
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
alias: 'e',
|
||||||
|
describe: 'Run with the given node environment.',
|
||||||
|
requiresArg: true,
|
||||||
|
type: 'string',
|
||||||
|
choices: ['development', 'production']
|
||||||
|
},
|
||||||
|
prod: {
|
||||||
|
describe: 'Run with NODE_ENV=production.',
|
||||||
|
requiresArg: false,
|
||||||
|
type: 'boolean',
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
dev: {
|
||||||
|
describe: 'Run with NODE_ENV=development.',
|
||||||
|
requiresArg: false,
|
||||||
|
type: 'boolean',
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
variant: {
|
||||||
|
alias: 'v',
|
||||||
|
describe: 'Run with www variant set to true.',
|
||||||
|
requiresArg: false,
|
||||||
|
type: 'boolean'
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
alias: 'b',
|
||||||
|
describe: 'Run tests on builds.',
|
||||||
|
requiresArg: false,
|
||||||
|
type: 'boolean',
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
persistent: {
|
||||||
|
alias: 'n',
|
||||||
|
describe: 'Run with persistence.',
|
||||||
|
requiresArg: false,
|
||||||
|
type: 'boolean',
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
ci: {
|
||||||
|
describe: 'Run tests in CI',
|
||||||
|
requiresArg: false,
|
||||||
|
type: 'boolean',
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
compactConsole: {
|
||||||
|
alias: 'c',
|
||||||
|
describe: 'Compact console output (hide file locations).',
|
||||||
|
requiresArg: false,
|
||||||
|
type: 'boolean',
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
reactVersion: {
|
||||||
|
describe: 'DevTools testing for specific version of React',
|
||||||
|
requiresArg: true,
|
||||||
|
type: 'string'
|
||||||
|
},
|
||||||
|
sourceMaps: {
|
||||||
|
describe: 'Enable inline source maps when transforming source files with Jest. Useful for debugging, but makes it slower.',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
} |> (yargs.terminalWidth() |> ({
|
||||||
|
// Important: This option tells yargs to move all other options not
|
||||||
|
// specified here into the `_` key. We use this to send all of the
|
||||||
|
// Jest options that we don't use through to Jest (like --watch).
|
||||||
|
'unknown-options-as-args': true
|
||||||
|
} |> yargs.parserConfiguration(%)).wrap(%)).options(%)).argv;
|
||||||
|
function logError(message) {
|
||||||
|
`\n${message}` |> chalk.red(%) |> console.error(%);
|
||||||
|
}
|
||||||
|
function isWWWConfig() {
|
||||||
|
return (argv.releaseChannel === 'www-classic' || argv.releaseChannel === 'www-modern') && argv.project !== 'devtools';
|
||||||
|
}
|
||||||
|
function isOSSConfig() {
|
||||||
|
return argv.releaseChannel === 'stable' || argv.releaseChannel === 'experimental';
|
||||||
|
}
|
||||||
|
function validateOptions() {
|
||||||
|
let success = true;
|
||||||
|
if (argv.project === 'devtools') {
|
||||||
|
if (argv.prod) {
|
||||||
|
'DevTool tests do not support --prod. Remove this option to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (argv.dev) {
|
||||||
|
'DevTool tests do not support --dev. Remove this option to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (argv.env) {
|
||||||
|
'DevTool tests do not support --env. Remove this option to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (argv.persistent) {
|
||||||
|
'DevTool tests do not support --persistent. Remove this option to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (argv.variant) {
|
||||||
|
'DevTool tests do not support --variant. Remove this option to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (!argv.build) {
|
||||||
|
'DevTool tests require --build.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (argv.reactVersion && !(argv.reactVersion |> semver.validRange(%))) {
|
||||||
|
success = false;
|
||||||
|
'please specify a valid version range for --reactVersion' |> logError(%);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (argv.compactConsole) {
|
||||||
|
'Only DevTool tests support compactConsole flag.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (argv.reactVersion) {
|
||||||
|
'Only DevTools tests supports the --reactVersion flag.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isWWWConfig()) {
|
||||||
|
if (argv.variant === undefined) {
|
||||||
|
// Turn internal experiments on by default
|
||||||
|
argv.variant = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (argv.variant) {
|
||||||
|
'Variant is only supported for the www release channels. Update these options to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argv.build && argv.persistent) {
|
||||||
|
'Persistence is not supported for build targets. Update these options to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (!isOSSConfig() && argv.persistent) {
|
||||||
|
'Persistence only supported for oss release channels. Update these options to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (argv.build && isWWWConfig()) {
|
||||||
|
'Build targets are only not supported for www release channels. Update these options to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (argv.env && argv.env !== 'production' && argv.prod) {
|
||||||
|
'Build type does not match --prod. Update these options to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (argv.env && argv.env !== 'development' && argv.dev) {
|
||||||
|
'Build type does not match --dev. Update these options to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (argv.prod && argv.dev) {
|
||||||
|
'Cannot supply both --prod and --dev. Remove one of these options to continue.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (argv.build) {
|
||||||
|
// TODO: We could build this if it hasn't been built yet.
|
||||||
|
const buildDir = './build' |> path.resolve(%);
|
||||||
|
if (!(buildDir |> fs.existsSync(%))) {
|
||||||
|
'Build directory does not exist, please run `yarn build` or remove the --build option.' |> logError(%);
|
||||||
|
success = false;
|
||||||
|
} else if (Date.now() - (buildDir |> fs.statSync(%)).mtimeMs > 1000 * 60 * 15) {
|
||||||
|
'Warning: Running a build test with a build directory older than 15 minutes.\nPlease remember to run `yarn build` when using --build.' |> logError(%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
|
// Extra newline.
|
||||||
|
'' |> console.log(%);
|
||||||
|
1 |> process.exit(%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getCommandArgs() {
|
||||||
|
// Add the correct Jest config.
|
||||||
|
const args = ['./scripts/jest/jest.js', '--config'];
|
||||||
|
if (argv.project === 'devtools') {
|
||||||
|
devToolsConfig |> args.push(%);
|
||||||
|
} else if (argv.build) {
|
||||||
|
buildConfig |> args.push(%);
|
||||||
|
} else if (argv.persistent) {
|
||||||
|
persistentConfig |> args.push(%);
|
||||||
|
} else if (isWWWConfig()) {
|
||||||
|
wwwConfig |> args.push(%);
|
||||||
|
} else if (isOSSConfig()) {
|
||||||
|
ossConfig |> args.push(%);
|
||||||
|
} else {
|
||||||
|
// We should not get here.
|
||||||
|
'Unrecognized release channel' |> logError(%);
|
||||||
|
1 |> process.exit(%);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the debug options, if necessary.
|
||||||
|
if (argv.debug) {
|
||||||
|
'--inspect-brk' |> args.unshift(%);
|
||||||
|
// Prevent console logs from being hidden until test completes.
|
||||||
|
'--runInBand' |> args.push(%);
|
||||||
|
'--useStderr' |> args.push(%);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CI Environments have limited workers.
|
||||||
|
if (argv.ci) {
|
||||||
|
'--maxWorkers=2' |> args.push(%);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the remaining args onto the command.
|
||||||
|
// This will send args like `--watch` to Jest.
|
||||||
|
args.push(...argv._);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
function getEnvars() {
|
||||||
|
const envars = {
|
||||||
|
NODE_ENV: argv.env || 'development',
|
||||||
|
RELEASE_CHANNEL: /modern|experimental/ |> argv.releaseChannel.match(%) ? 'experimental' : 'stable',
|
||||||
|
// Pass this flag through to the config environment
|
||||||
|
// so the base config can conditionally load the console setup file.
|
||||||
|
compactConsole: argv.compactConsole
|
||||||
|
};
|
||||||
|
if (argv.prod) {
|
||||||
|
envars.NODE_ENV = 'production';
|
||||||
|
}
|
||||||
|
if (argv.dev) {
|
||||||
|
envars.NODE_ENV = 'development';
|
||||||
|
}
|
||||||
|
if (argv.variant) {
|
||||||
|
envars.VARIANT = true;
|
||||||
|
}
|
||||||
|
if (argv.reactVersion) {
|
||||||
|
envars.REACT_VERSION = argv.reactVersion |> semver.coerce(%);
|
||||||
|
}
|
||||||
|
if (argv.sourceMaps) {
|
||||||
|
// This is off by default because it slows down the test runner, but it's
|
||||||
|
// super useful when running the debugger.
|
||||||
|
envars.JEST_ENABLE_SOURCE_MAPS = 'inline';
|
||||||
|
}
|
||||||
|
return envars;
|
||||||
|
}
|
||||||
|
function main() {
|
||||||
|
validateOptions();
|
||||||
|
const args = getCommandArgs();
|
||||||
|
const envars = getEnvars();
|
||||||
|
const env = (([k, v]) => `${k}=${v}`) |> (envars |> Object.entries(%)).map(%);
|
||||||
|
|
||||||
|
// Print the full command we're actually running.
|
||||||
|
const command = `$ ${' ' |> env.join(%)} node ${' ' |> args.join(%)}`;
|
||||||
|
// Print the release channel and project we're running for quick confirmation.
|
||||||
|
command |> chalk.dim(%) |> console.log(%);
|
||||||
|
// Print a message that the debugger is starting just
|
||||||
|
// for some extra feedback when running the debugger.
|
||||||
|
`\nRunning tests for ${argv.project} (${argv.releaseChannel})...` |> chalk.blue(%) |> console.log(%);
|
||||||
|
if (argv.debug) {
|
||||||
|
'\nStarting debugger...' |> chalk.green(%) |> console.log(%);
|
||||||
|
'Open chrome://inspect and press "inspect"\n' |> chalk.green(%) |> console.log(%);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run Jest.
|
||||||
|
const jest = spawn('node', args, {
|
||||||
|
stdio: 'inherit',
|
||||||
|
env: {
|
||||||
|
...envars,
|
||||||
|
...process.env
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ensure we close our process when we get a failure case.
|
||||||
|
'close' |> jest.on(%, code => {
|
||||||
|
// Forward the exit code from the Jest process.
|
||||||
|
if (code === 1) {
|
||||||
|
1 |> process.exit(%);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
main();
|
7
output_testing/1080ssa-property-mutate-2.js
Normal file
7
output_testing/1080ssa-property-mutate-2.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
function foo() {
|
||||||
|
const x = [];
|
||||||
|
const y = {};
|
||||||
|
y.x = x;
|
||||||
|
x |> mutate(%);
|
||||||
|
return y;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
// @enablePreserveExistingMemoizationGuarantees:false
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import { identity, makeObject_Primitives, mutate } from "shared-runtime";
|
||||||
|
function Component(props) {
|
||||||
|
const object = (() => makeObject_Primitives()) |> useMemo(%, []);
|
||||||
|
object |> identity(%);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [{}]
|
||||||
|
};
|
10
output_testing/1082hook-property-load-local.js
Normal file
10
output_testing/1082hook-property-load-local.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
function useFoo() {}
|
||||||
|
function Foo() {
|
||||||
|
let name = useFoo.name;
|
||||||
|
name |> console.log(%);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Foo,
|
||||||
|
params: []
|
||||||
|
};
|
10
output_testing/1083globals-Boolean.js
Normal file
10
output_testing/1083globals-Boolean.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
function Component(props) {
|
||||||
|
const x = {};
|
||||||
|
const y = x |> Boolean(%);
|
||||||
|
return [x, y];
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: ["TodoAdd"],
|
||||||
|
isComponent: "TodoAdd"
|
||||||
|
};
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { identity } from "shared-runtime";
|
||||||
|
function Component(props) {
|
||||||
|
let x;
|
||||||
|
// Reassign `x` based on a reactive value, but inside a function expression
|
||||||
|
// to make it a context variable
|
||||||
|
const f = () => {
|
||||||
|
if (props.cond) {
|
||||||
|
x = 1;
|
||||||
|
} else {
|
||||||
|
x = 2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Pass `f` through a function to prevent IIFE inlining optimizations
|
||||||
|
const f2 = f |> identity(%);
|
||||||
|
f2();
|
||||||
|
|
||||||
|
// The values assigned to `x` are non-reactive, but the value of `x`
|
||||||
|
// depends on the "control" value `props.cond` which is reactive.
|
||||||
|
// Therefore x should be treated as reactive too.
|
||||||
|
return [x];
|
||||||
|
}
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [],
|
||||||
|
sequentialRenders: [{
|
||||||
|
cond: true
|
||||||
|
}, {
|
||||||
|
cond: true
|
||||||
|
}, {
|
||||||
|
cond: false
|
||||||
|
}, {
|
||||||
|
cond: false
|
||||||
|
}, {
|
||||||
|
cond: true
|
||||||
|
}, {
|
||||||
|
cond: false
|
||||||
|
}, {
|
||||||
|
cond: true
|
||||||
|
}, {
|
||||||
|
cond: false
|
||||||
|
}]
|
||||||
|
};
|
6
output_testing/1085error.modify-state.js
Normal file
6
output_testing/1085error.modify-state.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { useState } from "react";
|
||||||
|
function Foo() {
|
||||||
|
let [state, setState] = {} |> useState(%);
|
||||||
|
state.foo = 1;
|
||||||
|
return state;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue