Initial build stuff. Builds, but results don\'t work.

This commit is contained in:
Kevin Frei
2020-05-13 13:39:14 -07:00
parent 5264e3c483
commit bdbe50323f
37 changed files with 6310 additions and 33 deletions

4
.gitignore vendored
View File

@@ -18,6 +18,10 @@ pids
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Output of the GULP build
lib
meta
# Coverage directory used by tools like istanbul
coverage
*.lcov

280
gulpfile.js Normal file
View File

@@ -0,0 +1,280 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
var packageData = require('./package.json');
var moduleMap = require('./scripts/module-map');
var fbjsConfigurePreset = require('babel-preset-fbjs/configure');
var del = require('del');
var gulpCheckDependencies = require('fbjs-scripts/gulp/check-dependencies');
var gulp = require('gulp');
var babel = require('gulp-babel');
var cleanCSS = require('gulp-clean-css');
var concatCSS = require('gulp-concat-css');
var derequire = require('gulp-derequire');
var flatten = require('gulp-flatten');
var header = require('gulp-header');
var gulpif = require('gulp-if');
var rename = require('gulp-rename');
var gulpUtil = require('gulp-util');
var StatsPlugin = require('stats-webpack-plugin');
var through = require('through2');
//var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
var webpackStream = require('webpack-stream');
var paths = {
dist: 'dist',
lib: 'lib',
src: [
'src/**/*.js',
'!src/**/__tests__/**/*.js',
'!src/**/__mocks__/**/*.js',
],
css: ['src/**/*.css'],
};
var babelOptsJS = {
presets: [
fbjsConfigurePreset({
stripDEV: true,
rewriteModules: {map: moduleMap},
}),
],
plugins: [
require('@babel/plugin-proposal-nullish-coalescing-operator'),
require('@babel/plugin-proposal-optional-chaining'),
require('@babel/plugin-proposal-class-properties')
],
};
var babelOptsFlow = {
presets: [
fbjsConfigurePreset({
target: 'flow',
rewriteModules: {map: moduleMap},
}),
],
plugins: [
require('@babel/plugin-proposal-nullish-coalescing-operator'),
require('@babel/plugin-proposal-optional-chaining'),
require('@babel/plugin-proposal-class-properties')
],
};
var COPYRIGHT_HEADER = `/**
* Recoil v<%= version %>
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
`;
var buildDist = function(opts) {
var webpackOpts = {
externals: {
immutable: {
root: 'Immutable',
commonjs2: 'immutable',
commonjs: 'immutable',
amd: 'immutable',
},
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react',
},
'react-dom': {
root: 'ReactDOM',
commonjs2: 'react-dom',
commonjs: 'react-dom',
amd: 'react-dom',
},
},
output: {
filename: opts.output,
libraryTarget: 'umd',
library: 'Recoil',
},
plugins: [
new webpackStream.webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(
opts.debug ? 'development' : 'production',
),
}),
new webpackStream.webpack.LoaderOptionsPlugin({
debug: opts.debug,
}),
new StatsPlugin(`../meta/bundle-size-stats/${opts.output}.json`, {
chunkModules: true,
}),
],
};
/* if (!opts.debug) {
webpackOpts.plugins.push(new UglifyJsPlugin());
}*/
const wpStream = webpackStream(webpackOpts, null, function(err, stats) {
if (err) {
throw new gulpUtil.PluginError('webpack', err);
}
if (stats.compilation.errors.length) {
gulpUtil.log('webpack', '\n' + stats.toString({colors: true}));
}
});
return wpStream;
};
gulp.task(
'clean',
gulp.series(function() {
return del([paths.dist, paths.lib]);
}),
);
gulp.task(
'modules',
gulp.series(function() {
return gulp
.src(paths.src)
.pipe(babel(babelOptsJS))
.pipe(flatten())
.pipe(gulp.dest(paths.lib));
}),
);
gulp.task(
'flow',
gulp.series(function() {
return gulp
.src(paths.src)
.pipe(babel(babelOptsFlow))
.pipe(flatten())
.pipe(rename({extname: '.js.flow'}))
.pipe(gulp.dest(paths.lib));
}),
);
gulp.task(
'css',
gulp.series(function() {
return (
gulp
.src(paths.css)
.pipe(
through.obj(function(file, encoding, callback) {
var contents = file.contents.toString();
var replaced = contents.replace(
// Regex based on MakeHasteCssModuleTransform: ignores comments,
// strings, and URLs
/\/\*.*?\*\/|'(?:\\.|[^'])*'|"(?:\\.|[^"])*"|url\([^)]*\)|(\.(?:public\/)?[\w-]*\/{1,2}[\w-]+)/g,
function(match, cls) {
if (cls) {
return cls.replace(/\//g, '-');
} else {
return match;
}
},
);
replaced = replaced.replace(
// MakeHasteCssVariablesTransform
/\bvar\(([\w-]+)\)/g,
function(match, name) {
var vars = {
'fig-secondary-text': '#9197a3',
'fig-light-20': '#bdc1c9',
};
if (vars[name]) {
return vars[name];
} else {
throw new Error('Unknown CSS variable ' + name);
}
},
);
file.contents = Buffer.from(replaced);
callback(null, file);
}),
)
.pipe(header(COPYRIGHT_HEADER, {version: packageData.version}))
.pipe(gulp.dest(paths.dist))
);
}),
);
gulp.task(
'dist',
gulp.series('modules', 'css', function() {
var opts = {
debug: true,
output: 'Recoil.js',
};
return gulp
.src('./lib/Recoil.js')
.pipe(buildDist(opts))
.pipe(derequire())
.pipe(
gulpif(
'*.js',
header(COPYRIGHT_HEADER, {version: packageData.version}),
),
)
.pipe(gulp.dest(paths.dist));
}),
);
gulp.task(
'dist:min',
gulp.series('modules', function() {
var opts = {
debug: false,
output: 'Recoil.min.js',
};
return gulp
.src('./lib/Recoil.js')
.pipe(buildDist(opts))
.pipe(
gulpif(
'*.js',
header(COPYRIGHT_HEADER, {version: packageData.version}),
),
)
.pipe(gulp.dest(paths.dist));
}),
);
gulp.task(
'check-dependencies',
gulp.series(function() {
return gulp.src('package.json').pipe(gulpCheckDependencies());
}),
);
gulp.task(
'watch',
gulp.series(function() {
gulp.watch(paths.src, gulp.parallel('modules'));
}),
);
gulp.task(
'dev',
gulp.series(function() {
gulp.watch(paths.src, gulp.parallel('dist'));
}),
);
gulp.task(
'default',
gulp.series(
'check-dependencies',
'clean',
gulp.parallel('modules', 'flow'),
gulp.parallel('dist', 'dist:min'),
),
);

43
package.json Normal file
View File

@@ -0,0 +1,43 @@
{
"private": true,
"name": "recoil",
"version": "0.0.1",
"description": "Recoil- A React state management library for complex UI's",
"main": "lib/Recoil.js",
"repository": "https://github.com/facebookexperimental/recoil.git",
"license": "MIT",
"scripts": {
"prepublish": "yarn run build",
"build": "gulp",
"dev": "gulp dev"
},
"devDependencies": {
"@babel/core": "^7.9.6",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
"@babel/plugin-proposal-optional-chaining": "^7.9.0",
"@babel/preset-flow": "^7.9.0",
"@babel/preset-react": "^7.9.4",
"babel-preset-fbjs": "^3.3.0",
"del": "^5.1.0",
"fbjs": "^1.0.0",
"fbjs-scripts": "^1.2.0",
"flow-bin": "^0.124.0",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-clean-css": "^4.2.0",
"gulp-concat-css": "^3.1.0",
"gulp-derequire": "^2.1.0",
"gulp-flatten": "^0.4.0",
"gulp-header": "^2.0.9",
"gulp-if": "^3.0.0",
"gulp-rename": "2",
"gulp-util": "^3.0.6",
"stats-webpack-plugin": "^0.7.0",
"webpack-stream": "^5.2.1"
},
"dependencies": {
"react": "^16.13.1",
"react-dom": "^16.13.1"
}
}

21
scripts/module-map.js Normal file
View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = Object.assign(
{
immutable: 'immutable',
React: 'react',
ReactDOM: 'react-dom',
ReactDOMComet: 'react-dom',
'object-assign': 'object-assign',
ReactTestUtils: 'react-dom/lib/ReactTestUtils',
reactComponentExpect: 'react-dom/lib/reactComponentExpect',
},
require('fbjs/module-map'),
require('fbjs-scripts/third-party-module-map')
);

View File

@@ -14,9 +14,10 @@
import type {TreeState} from 'Recoil_State';
const gkx = require('gkx');
const isPromise = require('isPromise');
const nullthrows = require('nullthrows');
const isPromise = require('Recoil_isPromise');
const nullthrows = require('Recoil_nullthrows');
const gkx = require('Recoil_gkx');
// TODO Convert Loadable to a Class to allow for runtime type detection.
// Containing static factories of withValue(), withError(), withPromise(), and all()

View File

@@ -0,0 +1,24 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
import type ArrayKeyedMap from 'Recoil_ArrayKeyedMap';
export type ScopeMap<T> = ArrayKeyedMap<T>;
export type ScopedValue<T> = $ReadOnlyArray<[number, ScopeMap<T>]>;
class ScopedAtomTaggedValue<T> {
entries: ScopedValue<T>;
constructor(entries: ScopedValue<T>) {
this.entries = entries;
}
}
module.exports = ScopedAtomTaggedValue;

View File

@@ -23,9 +23,9 @@ const {
setNodeValue,
setUnvalidatedAtomValue,
} = require('Recoil_FunctionalCore');
const nullthrows = require('Recoil_nullthrows');
const Queue = require('Recoil_Queue');
const nullthrows = require('nullthrows');
type Props = {
initializeState?: ({

View File

@@ -13,8 +13,8 @@ import type {NodeKey, Store, TreeState} from 'Recoil_State';
const RecoilValueInterface = require('Recoil_RecoilValue');
const expectationViolation = require('expectationViolation');
const recoverableViolation = require('recoverableViolation');
const expectationViolation = require('Recoil_expectationViolation');
const recoverableViolation = require('Recoil_recoverableViolation');
class DefaultValue {}
const DEFAULT_VALUE: DefaultValue = new DefaultValue();
@@ -70,7 +70,7 @@ function registerNode<T>(node: Node<T>): RecoilValue<T> {
production. But it is safe to ignore this warning if it occured because of
hot module replacement.`;
if (__DEV__) {
const isAcceptingUpdate = require('__debug').isAcceptingUpdate;
const isAcceptingUpdate = require('Recoil__debug').isAcceptingUpdate;
if (typeof isAcceptingUpdate !== 'function' || !isAcceptingUpdate()) {
expectationViolation(message, 'recoil');
}

View File

@@ -41,15 +41,15 @@ const {
} = require('Recoil_RecoilValue');
const Tracing = require('Recoil_Tracing');
const differenceSets = require('differenceSets');
const expectationViolation = require('expectationViolation');
const filterMap = require('filterMap');
const gkx = require('gkx');
const intersectSets = require('intersectSets');
const invariant = require('invariant');
const mapMap = require('mapMap');
const mergeMaps = require('mergeMaps');
const recoverableViolation = require('recoverableViolation');
const differenceSets = require('Recoil_differenceSets');
const expectationViolation = require('Recoil_expectationViolation');
const filterMap = require('Recoil_filterMap');
const gkx = require('Recoil_gkx');
const intersectSets = require('Recoil_intersectSets');
const invariant = require('Recoil_invariant');
const mapMap = require('Recoil_mapMap');
const mergeMaps = require('Recoil_mergeMaps');
const recoverableViolation = require('Recoil_recoverableViolation');
function cloneState(state: TreeState, opts): TreeState {
return {

View File

@@ -0,0 +1,268 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* A scoped atom's value depends on other parts of the application state.
* A separate value of the atom is stored for every value of the state that it
* depends on. The dependencies may be changed without breaking existing URLs --
* it uses whatever rule was current when the URL was written. Values written
* under the newer rules are overlaid atop the previously-written values just for
* those states in which the write occured, with reads falling back to the older
* values in other states, and eventually to a fallback.
*
* The scopedRules_APPEND_ONLY_READ_THE_DOCS parameter is a list of rules;
* it should start with a single entry. This list must only be appended to:
* existing entries must never be deleted or modified. Each rule is an atom
* or selector whose value is some arbitrary key. A different value of the
* scoped atom will be stored for each key. To change the scope rule, simply add
* a new function to the list.
*
* Ordinary atoms may be upgraded to scoped atoms. To un-scope an atom, add a new
* scope rule consisting of a constant.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
import type {AtomOptions, PersistenceSettings} from 'Recoil_atom';
import type {Parameter, ParameterizedScopeRules} from 'Recoil_atomFamily';
import type {RecoilState, RecoilValue} from 'Recoil_RecoilValue';
import type {ScopedValue, ScopeMap} from 'Recoil_ScopedAtomTaggedValue';
const ArrayKeyedMap = require('Recoil_ArrayKeyedMap');
const atom = require('Recoil_atom');
const {DEFAULT_VALUE, DefaultValue} = require('Recoil_Node');
const ScopedAtomTaggedValue = require('Recoil_ScopedAtomTaggedValue');
const selector = require('Recoil_selector');
const selectorFamily = require('Recoil_selectorFamily');
const stableStringify = require('Recoil_stableStringify');
const {waitForAll} = require('Recoil_WaitFor');
const mapIterable = require('Recoil_mapIterable');
type Primitive = number | string | boolean | null | void;
type StoredBaseValue<T> = ScopedAtomTaggedValue<T | DefaultValue> | T;
function cloneEntries<T>(
entries: ScopedValue<T>,
): Array<[number, ScopeMap<T>]> {
return entries.map(([i, map]) => [i, new ArrayKeyedMap(map)]);
}
function computeRuleLabel(
scopeKey: $ReadOnlyArray<mixed>,
): $ReadOnlyArray<Primitive> {
return scopeKey.map(value =>
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'boolean' ||
value == null
? value
: stableStringify(value),
);
}
// flowlint unclear-type:off
export type ScopeRules = $ReadOnlyArray<
RecoilValue<$ReadOnlyArray<any>> | $ReadOnlyArray<RecoilValue<any>>,
>;
// flowlint unclear-type:error
function getCurrentValue<T>(
defaultValue: T,
baseValue: StoredBaseValue<T>,
scopeRuleValues: $ReadOnlyArray<$ReadOnlyArray<mixed>>,
): T {
if (!(baseValue instanceof ScopedAtomTaggedValue)) {
// Fall back to raw value as this is an atom that was upgraded from
// non-scoped to scoped:
return baseValue;
}
// Use the first scope rule with a recorded state whose scope obtains:
for (const [ruleIndex, map] of baseValue.entries) {
const value = map.get(computeRuleLabel(scopeRuleValues[ruleIndex]));
if (value !== undefined) {
return value instanceof DefaultValue ? defaultValue : value;
}
}
return defaultValue;
}
// Update the baseValue with the new value set.
// If setting to a DefaultValue it will actually write that placeholder instead
// of deleting from the ParameterizedAtomTaggedValue. This is to properly support
// chaining of backward compatibility.
function baseValueByWritingToBaseValue<T>(
newValue: T | DefaultValue,
baseValue: StoredBaseValue<T>,
scopeRuleValues,
): ScopedAtomTaggedValue<T | DefaultValue> {
const entries =
baseValue instanceof ScopedAtomTaggedValue ? baseValue.entries : [];
const latestRuleIndex = scopeRuleValues.length - 1;
const latestRuleValue = computeRuleLabel(scopeRuleValues[latestRuleIndex]);
const newEntries = cloneEntries(entries);
if (entries.length > 0 && entries[0][0] === latestRuleIndex) {
// Current value was saved under latest rule; update that rule's map:
newEntries[0][1].set(latestRuleValue, newValue);
} else {
// Value was saved under old rule; add new entry with latest rule:
newEntries.unshift([
latestRuleIndex,
new ArrayKeyedMap().set(latestRuleValue, newValue),
]);
}
return new ScopedAtomTaggedValue(newEntries);
}
function mapPersistenceSettings<T>(
settings: ?PersistenceSettings<T>,
atomDefault: T,
): PersistenceSettings<StoredBaseValue<T>> | void {
if (settings === null || settings === undefined) {
return undefined;
}
const nonNullSettings: PersistenceSettings<T> = settings; // WTF flow?
return {
...settings,
validator: storedValue => {
if (storedValue instanceof ScopedAtomTaggedValue) {
return new ScopedAtomTaggedValue(
storedValue.entries
.filter(
([i, map]) =>
typeof i === 'number' && map instanceof ArrayKeyedMap,
)
.map(([i, map]) => [
i,
new ArrayKeyedMap(
mapIterable(map.entries(), ([k, v]) => {
const validatedValue = nonNullSettings.validator(
v,
DEFAULT_VALUE,
);
return [
k,
validatedValue instanceof DefaultValue
? atomDefault
: validatedValue,
];
}),
),
]),
);
} else {
return nonNullSettings.validator(storedValue, DEFAULT_VALUE);
}
},
};
}
function scopedAtom<T>(
options: $ReadOnly<{
...AtomOptions<T>,
default: T,
scopeRules_APPEND_ONLY_READ_THE_DOCS: ScopeRules,
}>,
): RecoilState<T> {
// Normalize the scope rules to an array of RecoilValues of an array of scope keys.
const scopeRules: $ReadOnlyArray<
RecoilValue<$ReadOnlyArray<mixed>>,
> = options.scopeRules_APPEND_ONLY_READ_THE_DOCS.map(rule =>
Array.isArray(rule) ? waitForAll(rule) : rule,
);
const base = atom<ScopedAtomTaggedValue<T | DefaultValue> | T>({
key: options.key,
default: new ScopedAtomTaggedValue<T | DefaultValue>([]),
persistence_UNSTABLE: mapPersistenceSettings<T>(
options.persistence_UNSTABLE,
options.default,
),
dangerouslyAllowMutability: options.dangerouslyAllowMutability,
});
return selector<T>({
key: `${options.key}__scopedAtom`,
get: ({get}) =>
getCurrentValue<T>(
options.default,
get(base),
// TODO Only get the rules that we actually need to compute the value
get(waitForAll(scopeRules)),
),
set: ({set, get}, newValue) =>
set(base, oldValue =>
baseValueByWritingToBaseValue(
newValue,
oldValue,
get(waitForAll(scopeRules)),
),
),
dangerouslyAllowMutability: options.dangerouslyAllowMutability,
});
}
function normalizeParameterizedScopeRules<P: Parameter>(
scopeRules: ParameterizedScopeRules<P>,
): $ReadOnlyArray<(P) => RecoilValue<$ReadOnlyArray<mixed>>> {
return scopeRules.map(rule =>
Array.isArray(rule)
? // create a selector that combines the atom values into an array and forwards any params:
param =>
waitForAll(
rule.map(entry =>
typeof entry === 'function' ? entry(param) : entry,
),
)
: () => rule,
);
}
// This atom is only needed to represent the legacy persisted value of an atom
// that was upgraded to a parameterized and scoped atom in case one of the
// scope rules contains a parameterized callback entry.
function parameterizedScopedAtomLegacy<T, P: Parameter>(
options: $ReadOnly<{
...AtomOptions<T>,
default: T,
scopeRules_APPEND_ONLY_READ_THE_DOCS: ParameterizedScopeRules<P>,
}>,
): P => RecoilState<T> {
const scopeRules = normalizeParameterizedScopeRules(
options.scopeRules_APPEND_ONLY_READ_THE_DOCS,
);
const base = atom<ScopedAtomTaggedValue<T | DefaultValue> | T>({
key: options.key,
default: new ScopedAtomTaggedValue<T | DefaultValue>([]),
persistence_UNSTABLE: mapPersistenceSettings<T>(
options.persistence_UNSTABLE,
options.default,
),
dangerouslyAllowMutability: options.dangerouslyAllowMutability,
});
return selectorFamily<T, P>({
key: `${options.key}__scopedAtom`,
get: params => ({get}) =>
getCurrentValue<T>(
options.default,
get(base),
// TODO Only get the rules that we actually need to compute the value
get(waitForAll(scopeRules.map(rule => rule(params)))),
),
set: params => ({set, get}, newValue) =>
set(base, oldValue =>
baseValueByWritingToBaseValue(
newValue,
oldValue,
get(waitForAll(scopeRules.map(rule => rule(params)))),
),
),
dangerouslyAllowMutability: options.dangerouslyAllowMutability,
});
}
module.exports = {scopedAtom, parameterizedScopedAtomLegacy};

View File

@@ -17,8 +17,8 @@ const {
} = require('Recoil_Loadable');
const selectorFamily = require('Recoil_selectorFamily');
const gkx = require('gkx');
const isPromise = require('isPromise');
const gkx = require('Recoil_gkx');
const isPromise = require('Recoil_isPromise');
/////////////////
// TRUTH TABLE

View File

@@ -68,9 +68,9 @@ const {DEFAULT_VALUE, DefaultValue, registerNode} = require('Recoil_Node');
const {isRecoilValue} = require('Recoil_RecoilValue');
const {scopedAtom} = require('Recoil_ScopedAtom');
const expectationViolation = require('expectationViolation');
const isPromise = require('isPromise');
const nullthrows = require('nullthrows');
const expectationViolation = require('Recoil_expectationViolation');
const isPromise = require('Recoil_isPromise');
const nullthrows = require('Recoil_nullthrows');
// It would be nice if this didn't have to be defined at the Recoil level, but I don't want to make
// the api cumbersome. One way to do this would be to have a selector mark the atom as persisted.

View File

@@ -53,7 +53,7 @@
const newSelector = require('Recoil_selector_NEW');
const oldSelector = require('Recoil_selector_OLD');
const gkx = require('gkx');
const gkx = require('Recoil_gkx');
export type * from 'Recoil_selector_NEW';

View File

@@ -87,10 +87,10 @@ const {startPerfBlock} = require('Recoil_PerformanceTimings');
const {isRecoilValue} = require('Recoil_RecoilValue');
const traverseDepGraph = require('Recoil_traverseDepGraph');
const differenceSets = require('differenceSets');
const equalsSet = require('equalsSet');
const isPromise = require('isPromise');
const nullthrows = require('nullthrows');
const differenceSets = require('Recoil_differenceSets');
const equalsSet = require('Recoil_equalsSet');
const isPromise = require('Recoil_isPromise');
const nullthrows = require('Recoil_nullthrows');
export type GetRecoilValue = <T>(RecoilValue<T>) => T;
export type SetRecoilState = <T>(

View File

@@ -86,10 +86,10 @@ const {
const {startPerfBlock} = require('Recoil_PerformanceTimings');
const {isRecoilValue} = require('Recoil_RecoilValue');
const differenceSets = require('differenceSets');
const equalsSet = require('equalsSet');
const isPromise = require('isPromise');
const nullthrows = require('nullthrows');
const differenceSets = require('Recoil_differenceSets');
const equalsSet = require('Recoil_equalsSet');
const isPromise = require('Recoil_isPromise');
const nullthrows = require('Recoil_nullthrows');
export type GetRecoilValue = <T>(RecoilValue<T>) => T;
export type SetRecoilState = <T>(

View File

@@ -0,0 +1,11 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* This is a stub for some integration into FB internal stuff
*/
function startPerfBlock(id) {
return () => {};
}
module.exports = { startPerfBlock };

View File

@@ -0,0 +1,7 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* This is a stub for some integration into FB internal stuff
*/
module.exports = { };

View File

@@ -11,8 +11,8 @@
*/
'use strict';
const isNode = require('isNode');
const isPromise = require('isPromise');
const isNode = require('Recoil_isNode');
const isPromise = require('Recoil_isPromise');
function shouldNotBeFrozen(value: mixed): boolean {
// Primitives and functions:

View File

@@ -0,0 +1,34 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
/**
* Returns a set containing all of the values from the first set that are not
* present in any of the subsequent sets.
*
* Note: this is written procedurally (i.e., without filterSet) for performant
* use in tight loops.
*/
function differenceSets<TValue>(
set: $ReadOnlySet<TValue>,
...setsWithValuesToRemove: $ReadOnlyArray<$ReadOnlySet<TValue>>
): Set<TValue> {
const ret = new Set();
FIRST: for (const value of set) {
for (const otherSet of setsWithValuesToRemove) {
if (otherSet.has(value)) {
continue FIRST;
}
}
ret.add(value);
}
return ret;
}
module.exports = differenceSets;

View File

@@ -0,0 +1,23 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
const everySet = require('Recoil_everySet');
/**
* Checks if two sets are equal
*/
function equalsSet<T>(one: $ReadOnlySet<T>, two: $ReadOnlySet<T>): boolean {
if (one.size !== two.size) {
return false;
}
return everySet(one, value => two.has(value));
}
module.exports = equalsSet;

View File

@@ -0,0 +1,32 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
/**
* The everySet() method tests whether all elements in the given Set pass the
* test implemented by the provided function.
*/
function everySet<T>(
set: $ReadOnlySet<T>,
callback: (value: T, key: T, set: $ReadOnlySet<T>) => boolean,
context?: mixed,
): boolean {
const iterator = set.entries();
let current = iterator.next();
while (!current.done) {
const entry = current.value;
if (!callback.call(context, entry[1], entry[0], set)) {
return false;
}
current = iterator.next();
}
return true;
}
module.exports = everySet;

View File

@@ -0,0 +1,21 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
const sprintf = require('Recoil_sprintf');
function expectationViolation(format: string, ...args: $ReadOnlyArray<mixed>) {
if (__DEV__) {
const message = sprintf.call(null, format, ...args);
const error = new Error(message);
error.name = 'Expectation Violation';
console.error(error);
}
}
module.exports = expectationViolation;

View File

@@ -0,0 +1,29 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
/**
* Returns a map containing all of the keys + values from the original map where
* the given callback returned true.
*/
function filterMap<TKey, TValue>(
map: $ReadOnlyMap<TKey, TValue>,
callback: (value: TValue, key: TKey) => boolean,
): Map<TKey, TValue> {
const result = new Map();
for (const [key, value] of map) {
if (callback(value, key)) {
result.set(key, value);
}
}
return result;
}
module.exports = filterMap;

21
src/util/Recoil_gkx.js Normal file
View File

@@ -0,0 +1,21 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
let pass = false;
function Recoil_gkx(_gk: string): boolean {
return pass;
}
Recoil_gkx.setPass = (_gk: string): void => {
pass = true;
}
module.exports = Recoil_gkx;

View File

@@ -0,0 +1,32 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* Returns the set of values that are present in all the given sets, preserving
* the order of the first set.
*
* Note: this is written procedurally (i.e., without filterSet) for performant
* use in tight loops.
*
* @flow strict
* @format
*/
'use strict';
function intersectSets<T>(
first: $ReadOnlySet<T>,
...rest: Array<$ReadOnlySet<T>>
): Set<T> {
const ret = new Set();
FIRST: for (const value of first) {
for (const otherSet of rest) {
if (!otherSet.has(value)) {
continue FIRST;
}
}
ret.add(value);
}
return ret;
}
module.exports = intersectSets;

View File

@@ -0,0 +1,19 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
const invariant = require('invariant'); // @fb-only
// @oss-only function invariant(condition: boolean, message: string) {
// @oss-only if (!condition) {
// @oss-only throw new Error(message);
// @oss-only }
// @oss-only }
module.exports = invariant;

25
src/util/Recoil_isNode.js Normal file
View File

@@ -0,0 +1,25 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
function isNode(object: mixed): boolean {
const doc =
object != null ? (object: $FlowFixMe).ownerDocument ?? object : document;
const defaultView = doc.defaultView ?? window;
return !!(
object != null &&
(typeof defaultView.Node === 'function'
? object instanceof defaultView.Node
: typeof object === 'object' &&
typeof object.nodeType === 'number' &&
typeof object.nodeName === 'string')
);
}
module.exports = isNode;

View File

@@ -0,0 +1,21 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict
* @format
*/
'use strict';
declare function isPromise(p: mixed): boolean %checks(p instanceof Promise);
// Split declaration and implementation to allow this function to pretend to
// check for actual instance of Promise instead of something with a `then`
// method.
// eslint-disable-next-line no-redeclare
function isPromise(p: $FlowFixMe): boolean {
return !!p && typeof p.then === 'function';
}
module.exports = isPromise;

View File

@@ -0,0 +1,27 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @flow strict
* @format
*/
'use strict';
/**
* Creates a new iterable whose output is generated by passing the input
* iterable's values through the mapper function.
*/
function mapIterable<T, K>(
iterable: Iterable<T>,
callback: (v: T, index: number) => K,
): Iterable<K> {
// Use generator to create iterable/iterator
return (function*() {
let index = 0;
for (const value of iterable) {
yield callback(value, index++);
}
})();
}
module.exports = mapIterable;

27
src/util/Recoil_mapMap.js Normal file
View File

@@ -0,0 +1,27 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
/**
* Returns a new Map object with the same keys as the original, but with the
* values replaced with the output of the given callback function.
*/
function mapMap<TKey, TValue, TValueOut>(
map: $ReadOnlyMap<TKey, TValue>,
callback: (value: TValue, key: TKey) => TValueOut,
): Map<TKey, TValueOut> {
const result = new Map();
map.forEach((value, key) => {
result.set(key, callback(value, key));
});
return result;
}
module.exports = mapMap;

View File

@@ -0,0 +1,29 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
function mergeMaps<TKey, TValue>(
...maps: $ReadOnlyArray<$ReadOnlyMap<TKey, TValue>>
): Map<TKey, TValue> {
const result = new Map();
for (let i = 0; i < maps.length; i++) {
const iterator = maps[i].keys();
let nextKey;
while (!(nextKey = iterator.next()).done) {
// $FlowFixMe - map/iterator knows nothing about flow types
result.set(nextKey.value, maps[i].get(nextKey.value));
}
}
/* $FlowFixMe(>=0.66.0 site=www,mobile) This comment suppresses an error
* found when Flow v0.66 was deployed. To see the error delete this comment
* and run Flow. */
return result;
}
module.exports = mergeMaps;

View File

@@ -0,0 +1,18 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict
* @format
*/
'use strict';
function nullthrows<T>(x: ?T, message: ?string): T {
if (x != null) {
return x;
}
throw new Error(message ?? 'Got unexpected null or undefined');
}
module.exports = nullthrows;

View File

@@ -0,0 +1,22 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
function recoverableViolation(
message: string,
projectName: 'recoil',
{error}: {|error?: Error|},
): null {
if (__DEV__) {
console.error(message, error);
}
return null;
}
module.exports = recoverableViolation;

View File

@@ -0,0 +1,16 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
*
* @emails oncall+perf_viz
* @flow strict-local
* @format
*/
'use strict';
function sprintf(format: string, ...args: Array<mixed>): string {
let index = 0;
return format.replace(/%s/g, () => String(args[index++]));
}
module.exports = sprintf;

View File

@@ -7,7 +7,7 @@
*/
'use strict';
const isPromise = require('isPromise');
const isPromise = require('Recoil_isPromise');
const TIME_WARNING_THRESHOLD_MS = 15;

View File

@@ -0,0 +1,7 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* This is a stub for some integration into FB internal stuff
*/
module.exports = { };

5215
yarn.lock Normal file

File diff suppressed because it is too large Load Diff