mirror of
https://github.com/zhigang1992/Recoil.git
synced 2026-01-12 17:43:22 +08:00
Initial build stuff. Builds, but results don\'t work.
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -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
280
gulpfile.js
Normal 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
43
package.json
Normal 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
21
scripts/module-map.js
Normal 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')
|
||||
);
|
||||
@@ -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()
|
||||
|
||||
24
src/adt/Recoil_ScopedAtomTaggedValue.js
Normal file
24
src/adt/Recoil_ScopedAtomTaggedValue.js
Normal 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;
|
||||
@@ -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?: ({
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
268
src/recoil_values/Recoil_ScopedAtom.js
Normal file
268
src/recoil_values/Recoil_ScopedAtom.js
Normal 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};
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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>(
|
||||
|
||||
@@ -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>(
|
||||
|
||||
11
src/util/Recoil_PerformanceTimings.js
Normal file
11
src/util/Recoil_PerformanceTimings.js
Normal 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 };
|
||||
7
src/util/Recoil__debug.js
Normal file
7
src/util/Recoil__debug.js
Normal 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 = { };
|
||||
@@ -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:
|
||||
|
||||
34
src/util/Recoil_differenceSets.js
Normal file
34
src/util/Recoil_differenceSets.js
Normal 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;
|
||||
23
src/util/Recoil_equalsSet.js
Normal file
23
src/util/Recoil_equalsSet.js
Normal 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;
|
||||
32
src/util/Recoil_everySet.js
Normal file
32
src/util/Recoil_everySet.js
Normal 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;
|
||||
21
src/util/Recoil_expectationViolation.js
Normal file
21
src/util/Recoil_expectationViolation.js
Normal 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;
|
||||
29
src/util/Recoil_filterMap.js
Normal file
29
src/util/Recoil_filterMap.js
Normal 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
21
src/util/Recoil_gkx.js
Normal 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;
|
||||
32
src/util/Recoil_intersectSets.js
Normal file
32
src/util/Recoil_intersectSets.js
Normal 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;
|
||||
19
src/util/Recoil_invariant.js
Normal file
19
src/util/Recoil_invariant.js
Normal 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
25
src/util/Recoil_isNode.js
Normal 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;
|
||||
21
src/util/Recoil_isPromise.js
Normal file
21
src/util/Recoil_isPromise.js
Normal 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;
|
||||
27
src/util/Recoil_mapIterable.js
Normal file
27
src/util/Recoil_mapIterable.js
Normal 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
27
src/util/Recoil_mapMap.js
Normal 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;
|
||||
29
src/util/Recoil_mergeMaps.js
Normal file
29
src/util/Recoil_mergeMaps.js
Normal 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;
|
||||
18
src/util/Recoil_nullthrows.js
Normal file
18
src/util/Recoil_nullthrows.js
Normal 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;
|
||||
22
src/util/Recoil_recoverableViolation.js
Normal file
22
src/util/Recoil_recoverableViolation.js
Normal 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;
|
||||
16
src/util/Recoil_sprintf.js
Normal file
16
src/util/Recoil_sprintf.js
Normal 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;
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const isPromise = require('isPromise');
|
||||
const isPromise = require('Recoil_isPromise');
|
||||
|
||||
const TIME_WARNING_THRESHOLD_MS = 15;
|
||||
|
||||
|
||||
7
src/util/SchedulerTracing.js
Normal file
7
src/util/SchedulerTracing.js
Normal 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 = { };
|
||||
Reference in New Issue
Block a user