create-expo-cljs-app
Version:
Create a react native application with Expo and Shadow-CLJS!
704 lines (607 loc) • 19.2 kB
JavaScript
/**
* 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.
*
*
* @format
*/
;
function _slicedToArray(arr, i) {
return (
_arrayWithHoles(arr) ||
_iterableToArrayLimit(arr, i) ||
_unsupportedIterableToArray(arr, i) ||
_nonIterableRest()
);
}
function _nonIterableRest() {
throw new TypeError(
"Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
);
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _iterableToArrayLimit(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr)))
return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (
var _i = arr[Symbol.iterator](), _s;
!(_n = (_s = _i.next()).done);
_n = true
) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly)
symbols = symbols.filter(function(sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(Object(source), true).forEach(function(key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function(key) {
Object.defineProperty(
target,
key,
Object.getOwnPropertyDescriptor(source, key)
);
});
}
}
return target;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _asyncToGenerator(fn) {
return function() {
var self = this,
args = arguments;
return new Promise(function(resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
const nullthrows = require("nullthrows");
function getInternalOptions(_ref) {
let transform = _ref.transform,
resolve = _ref.resolve,
onProgress = _ref.onProgress,
experimentalImportBundleSupport = _ref.experimentalImportBundleSupport,
shallow = _ref.shallow;
let numProcessed = 0;
let total = 0;
return {
experimentalImportBundleSupport,
transform,
resolve,
onDependencyAdd: () => onProgress && onProgress(numProcessed, ++total),
onDependencyAdded: () => onProgress && onProgress(++numProcessed, total),
shallow
};
}
/**
* Dependency Traversal logic for the Delta Bundler. This method calculates
* the modules that should be included in the bundle by traversing the
* dependency graph.
* Instead of traversing the whole graph each time, it just calculates the
* difference between runs by only traversing the added/removed dependencies.
* To do so, it uses the passed passed graph dependencies and it mutates it.
* The paths parameter contains the absolute paths of the root files that the
* method should traverse. Normally, these paths should be the modified files
* since the last traversal.
*/
function traverseDependencies(_x, _x2, _x3) {
return _traverseDependencies.apply(this, arguments);
}
function _traverseDependencies() {
_traverseDependencies = _asyncToGenerator(function*(paths, graph, options) {
const delta = {
added: new Set(),
modified: new Set(),
deleted: new Set(),
inverseDependencies: new Map()
};
const internalOptions = getInternalOptions(options);
for (const path of paths) {
// Only process the path if it's part of the dependency graph. It's possible
// that this method receives a path that is no longer part of it (e.g if a
// module gets removed from the dependency graph and just afterwards it gets
// modified), and we have to ignore these cases.
if (graph.dependencies.get(path)) {
delta.modified.add(path);
yield traverseDependenciesForSingleFile(
path,
graph,
delta,
internalOptions
);
}
}
const added = new Map();
const modified = new Map();
const deleted = new Set();
for (const path of delta.deleted) {
// If a dependency has been marked both as added and deleted, it means that
// this is a renamed file (or that dependency has been removed from one path
// but added back in a different path). In this case the addition and
// deletion "get cancelled".
if (!delta.added.has(path)) {
deleted.add(path);
}
delta.modified.delete(path);
delta.added.delete(path);
}
for (const path of delta.added) {
added.set(path, nullthrows(graph.dependencies.get(path)));
}
for (const path of delta.modified) {
// Similarly to the above, a file can be marked as both added and modified
// when its path and dependencies have changed. In this case, we only
// consider the addition.
if (!delta.added.has(path)) {
modified.set(path, nullthrows(graph.dependencies.get(path)));
}
}
return {
added,
modified,
deleted
};
});
return _traverseDependencies.apply(this, arguments);
}
function initialTraverseDependencies(_x4, _x5) {
return _initialTraverseDependencies.apply(this, arguments);
}
function _initialTraverseDependencies() {
_initialTraverseDependencies = _asyncToGenerator(function*(graph, options) {
const delta = {
added: new Set(),
modified: new Set(),
deleted: new Set(),
inverseDependencies: new Map()
};
const internalOptions = getInternalOptions(options);
yield Promise.all(
graph.entryPoints.map(path =>
traverseDependenciesForSingleFile(path, graph, delta, internalOptions)
)
);
reorderGraph(graph, {
shallow: options.shallow
});
return {
added: graph.dependencies,
modified: new Map(),
deleted: new Set()
};
});
return _initialTraverseDependencies.apply(this, arguments);
}
function traverseDependenciesForSingleFile(_x6, _x7, _x8, _x9) {
return _traverseDependenciesForSingleFile.apply(this, arguments);
}
function _traverseDependenciesForSingleFile() {
_traverseDependenciesForSingleFile = _asyncToGenerator(function*(
path,
graph,
delta,
options
) {
options.onDependencyAdd();
yield processModule(path, graph, delta, options);
options.onDependencyAdded();
});
return _traverseDependenciesForSingleFile.apply(this, arguments);
}
function processModule(_x10, _x11, _x12, _x13) {
return _processModule.apply(this, arguments);
}
function _processModule() {
_processModule = _asyncToGenerator(function*(path, graph, delta, options) {
// Transform the file via the given option.
const result = yield options.transform(path); // Get the absolute path of all sub-dependencies (some of them could have been
// moved but maintain the same relative path).
const currentDependencies = resolveDependencies(
path,
result.dependencies,
options
);
const previousModule = graph.dependencies.get(path) || {
inverseDependencies: delta.inverseDependencies.get(path) || new Set(),
path
};
const previousDependencies = previousModule.dependencies || new Map(); // Update the module information.
const module = _objectSpread(
_objectSpread({}, previousModule),
{},
{
dependencies: new Map(),
getSource: result.getSource,
output: result.output
}
);
graph.dependencies.set(module.path, module);
for (const _ref2 of currentDependencies) {
var _ref3 = _slicedToArray(_ref2, 2);
const relativePath = _ref3[0];
const dependency = _ref3[1];
module.dependencies.set(relativePath, dependency);
}
Array.from(previousDependencies.entries())
.filter(_ref4 => {
let _ref5 = _slicedToArray(_ref4, 2),
relativePath = _ref5[0],
dependency = _ref5[1];
return (
!currentDependencies.has(relativePath) ||
nullthrows(currentDependencies.get(relativePath)).absolutePath !==
dependency.absolutePath
);
})
.forEach(_ref6 => {
let _ref7 = _slicedToArray(_ref6, 2),
relativePath = _ref7[0],
dependency = _ref7[1];
return removeDependency(
module,
dependency.absolutePath,
graph,
delta,
new Set()
);
}); // Check all the module dependencies and start traversing the tree from each
// added and removed dependency, to get all the modules that have to be added
// and removed from the dependency graph.
const promises = [];
for (const _ref8 of currentDependencies) {
var _ref9 = _slicedToArray(_ref8, 2);
const relativePath = _ref9[0];
const dependency = _ref9[1];
if (!options.shallow) {
if (
options.experimentalImportBundleSupport &&
dependency.data.data.asyncType != null
) {
graph.importBundleNames.add(dependency.absolutePath);
} else if (
!previousDependencies.has(relativePath) ||
nullthrows(previousDependencies.get(relativePath)).absolutePath !==
dependency.absolutePath
) {
promises.push(
addDependency(
module,
dependency.absolutePath,
graph,
delta,
options
)
);
}
}
}
try {
yield Promise.all(promises);
} catch (err) {
// If there is an error, restore the previous dependency list.
// This ensures we don't skip over them during the next traversal attempt.
module.dependencies = previousDependencies;
throw err;
}
return module;
});
return _processModule.apply(this, arguments);
}
function addDependency(_x14, _x15, _x16, _x17, _x18) {
return _addDependency.apply(this, arguments);
}
/**
* Recursively look up `inverseDependencies` until it is empty,
* returning a set of paths for the last module that does not have
* `inverseDependencies`.
*/
function _addDependency() {
_addDependency = _asyncToGenerator(function*(
parentModule,
path,
graph,
delta,
options
) {
// The new dependency was already in the graph, we don't need to do anything.
const existingModule = graph.dependencies.get(path);
if (existingModule) {
existingModule.inverseDependencies.add(parentModule.path);
return;
} // This module is being transformed at the moment in parallel, so we should
// only mark its parent as an inverse dependency.
const inverse = delta.inverseDependencies.get(path);
if (inverse) {
inverse.add(parentModule.path);
return;
}
delta.added.add(path);
delta.inverseDependencies.set(path, new Set([parentModule.path]));
options.onDependencyAdd();
const module = yield processModule(path, graph, delta, options);
graph.dependencies.set(module.path, module);
module.inverseDependencies.add(parentModule.path);
options.onDependencyAdded();
});
return _addDependency.apply(this, arguments);
}
function getAllTopLevelInverseDependencies(
inverseDependencies,
graph,
currModule,
visited
) {
if (visited.has(currModule)) {
return new Set();
}
visited.add(currModule);
if (!inverseDependencies.size) {
return new Set([currModule]);
}
return Array.from(inverseDependencies)
.filter(inverseDep => graph.dependencies.has(inverseDep))
.reduce((acc, inverseDep) => {
const mod = graph.dependencies.get(inverseDep);
if (!mod) {
return acc;
}
getAllTopLevelInverseDependencies(
mod.inverseDependencies,
graph,
inverseDep,
visited
).forEach(x => {
acc.add(x);
});
return acc;
}, new Set());
}
/**
* Given `inverseDependencies`, tracing back inverse dependencies to
* see if it only leads back to `parentModule`.
*/
function canSafelyRemoveFromParentModule(
inverseDependencies,
parentModule,
graph,
canBeRemovedSafely,
delta
) {
const visited = new Set();
const topInverseDependencies = getAllTopLevelInverseDependencies(
inverseDependencies,
graph,
"", // current module name
visited
);
if (!topInverseDependencies.size) {
/**
* This happens when parentModule and inverseDependencies have a circular dependency.
* This will eventually become an empty set due to the `visited` Set being the
* base case for the recursive call.
*/
return true;
}
const undeletedInverseDependencies = Array.from(
topInverseDependencies
).filter(x => !delta.deleted.has(x));
/**
* We can only mark the `visited` Set of modules to be safely removable if
* 1. We do not have top a level module to compare with parentModule.
* This can happen when trying to see if we can safely remove from
* a module that was deleted. This is why we filtered them out with `delta.deleted`
* 2. We have one top module and it is parentModule
*/
const canSafelyRemove =
!undeletedInverseDependencies.length ||
(undeletedInverseDependencies.length === 1 &&
undeletedInverseDependencies[0] === parentModule);
if (canSafelyRemove) {
visited.forEach(mod => {
canBeRemovedSafely.add(mod);
});
}
return canSafelyRemove;
}
function removeDependency(parentModule, absolutePath, graph, delta) {
let canBeRemovedSafely =
arguments.length > 4 && arguments[4] !== undefined
? arguments[4]
: new Set();
const module = graph.dependencies.get(absolutePath);
if (!module) {
return;
}
module.inverseDependencies.delete(parentModule.path); // Even if there are modules still using parentModule, we want to ensure
// there is no circular dependency. Thus, we check if it can be safely removed
// by tracing back the inverseDependencies.
if (!canBeRemovedSafely.has(module.path)) {
if (
module.inverseDependencies.size &&
!canSafelyRemoveFromParentModule(
module.inverseDependencies,
module.path,
graph,
canBeRemovedSafely,
delta
)
) {
return;
}
}
delta.deleted.add(module.path); // Now we need to iterate through the module dependencies in order to
// clean up everything (we cannot read the module because it may have
// been deleted).
Array.from(module.dependencies.values())
.filter(
dependency =>
!delta.deleted.has(dependency.absolutePath) &&
dependency.absolutePath !== parentModule.path
)
.forEach(dependency =>
removeDependency(
module,
dependency.absolutePath,
graph,
delta,
canBeRemovedSafely
)
); // This module is not used anywhere else!! we can clear it from the bundle
graph.dependencies.delete(module.path);
}
function resolveDependencies(parentPath, dependencies, options) {
const resolve = (parentPath, result) => {
const relativePath = result.name;
try {
return [
relativePath,
{
absolutePath: options.resolve(parentPath, relativePath),
data: result
}
];
} catch (error) {
// Ignore unavailable optional dependencies. They are guarded
// with a try-catch block and will be handled during runtime.
if (result.data.isOptional !== true) {
throw error;
}
}
return undefined;
};
const resolved = dependencies.reduce((list, result) => {
const resolvedPath = resolve(parentPath, result);
if (resolvedPath) {
list.push(resolvedPath);
}
return list;
}, []);
return new Map(resolved);
}
/**
* Re-traverse the dependency graph in DFS order to reorder the modules and
* guarantee the same order between runs. This method mutates the passed graph.
*/
function reorderGraph(graph, options) {
const orderedDependencies = new Map();
graph.entryPoints.forEach(entryPoint => {
const mainModule = graph.dependencies.get(entryPoint);
if (!mainModule) {
throw new ReferenceError("Module not registered in graph: " + entryPoint);
}
reorderDependencies(graph, mainModule, orderedDependencies, options);
});
graph.dependencies = orderedDependencies;
}
function reorderDependencies(graph, module, orderedDependencies, options) {
if (module.path) {
if (orderedDependencies.has(module.path)) {
return;
}
orderedDependencies.set(module.path, module);
}
module.dependencies.forEach(dependency => {
const path = dependency.absolutePath;
const childModule = graph.dependencies.get(path);
if (!childModule) {
if (dependency.data.data.asyncType != null || options.shallow) {
return;
} else {
throw new ReferenceError("Module not registered in graph: " + path);
}
}
reorderDependencies(graph, childModule, orderedDependencies, options);
});
}
module.exports = {
initialTraverseDependencies,
traverseDependencies,
reorderGraph
};