mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary:
There's quite a bit of code scattered around the packager regarding ignoring the `providesModule` Haste pragma in any file that isn't in `react-native`, `react-tools` or `parse`. There is even a (passing) test case.
However, there's an edge case.
Take, for example, `fbjs`. It has a module inside of it called `ErrorUtils`. `react-relay` requires this file normally, in Common.JS style, by doing `require('fbjs/libs/ErrorUtils')`. But when `react-native` attempts to require `ErrorUtils` using the HasteModule format (in it's JavaScript initialization), it resolves the `fbjs` `ErrorUtils` module, instead of RN's `ErrorUtils`.
This happens, it turns out, because when a module is read (in `Module._read`), it's not caring about whether or not it should pay attention to `providesModule`, and is just assigning the `providesModule` value as the id of the module no matter what. Then when `Module.getName` is called, it will always use that `data.id` that was set, thus creating the wrong dependency tree.
This
Closes https://github.com/facebook/react-native/pull/3625
Reviewed By: svcscm
Differential Revision: D2632317
Pulled By: vjeux
fb-gh-sync-id: efd8066eaf6f18fcf79698beab36cab90bf5cd6d
101 lines
2.2 KiB
JavaScript
101 lines
2.2 KiB
JavaScript
'use strict';
|
|
|
|
const isAbsolutePath = require('absolute-path');
|
|
const path = require('path');
|
|
|
|
class Package {
|
|
|
|
constructor({ file, fastfs, cache }) {
|
|
this.path = path.resolve(file);
|
|
this.root = path.dirname(this.path);
|
|
this._fastfs = fastfs;
|
|
this.type = 'Package';
|
|
this._cache = cache;
|
|
}
|
|
|
|
getMain() {
|
|
return this.read().then(json => {
|
|
var replacements = getReplacements(json);
|
|
if (typeof replacements === 'string') {
|
|
return path.join(this.root, replacements);
|
|
}
|
|
|
|
let main = json.main || 'index';
|
|
|
|
if (replacements && typeof replacements === 'object') {
|
|
main = replacements[main] ||
|
|
replacements[main + '.js'] ||
|
|
replacements[main + '.json'] ||
|
|
replacements[main.replace(/(\.js|\.json)$/, '')] ||
|
|
main;
|
|
}
|
|
|
|
return path.join(this.root, main);
|
|
});
|
|
}
|
|
|
|
isHaste() {
|
|
return this._cache.get(this.path, 'package-haste', () =>
|
|
this.read().then(json => !!json.name)
|
|
);
|
|
}
|
|
|
|
getName() {
|
|
return this._cache.get(this.path, 'package-name', () =>
|
|
this.read().then(json => json.name)
|
|
);
|
|
}
|
|
|
|
invalidate() {
|
|
this._cache.invalidate(this.path);
|
|
}
|
|
|
|
redirectRequire(name) {
|
|
return this.read().then(json => {
|
|
var replacements = getReplacements(json);
|
|
|
|
if (!replacements || typeof replacements !== 'object') {
|
|
return name;
|
|
}
|
|
|
|
if (name[0] !== '/') {
|
|
return replacements[name] || name;
|
|
}
|
|
|
|
if (!isAbsolutePath(name)) {
|
|
throw new Error(`Expected ${name} to be absolute path`);
|
|
}
|
|
|
|
const relPath = './' + path.relative(this.root, name);
|
|
const redirect = replacements[relPath] ||
|
|
replacements[relPath + '.js'] ||
|
|
replacements[relPath + '.json'];
|
|
if (redirect) {
|
|
return path.join(
|
|
this.root,
|
|
redirect
|
|
);
|
|
}
|
|
|
|
return name;
|
|
});
|
|
}
|
|
|
|
read() {
|
|
if (!this._reading) {
|
|
this._reading = this._fastfs.readFile(this.path)
|
|
.then(jsonStr => JSON.parse(jsonStr));
|
|
}
|
|
|
|
return this._reading;
|
|
}
|
|
}
|
|
|
|
function getReplacements(pkg) {
|
|
return pkg['react-native'] == null
|
|
? pkg.browser
|
|
: pkg['react-native'];
|
|
}
|
|
|
|
module.exports = Package;
|