Skip to content

Commit 5eb954f

Browse files
Jean Lauliacfacebook-github-bot
Jean Lauliac
authored andcommitted
packager: Module.js: make read()-based API sync
Reviewed By: davidaurelio Differential Revision: D4746218 fbshipit-source-id: 1a36bd00a47a6b871cc77433b2325a11e90035b2
1 parent e22898b commit 5eb954f

File tree

1 file changed

+60
-62
lines changed

1 file changed

+60
-62
lines changed

packager/src/node-haste/Module.js

+60-62
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ export type ConstructorArgs = {
7474
transformCode: ?TransformCode,
7575
};
7676

77+
type DocBlock = {+[key: string]: string};
78+
7779
class Module {
7880

7981
path: string;
@@ -88,9 +90,9 @@ class Module {
8890
_reporter: Reporter;
8991
_globalCache: ?GlobalTransformCache;
9092

91-
_docBlock: Promise<{[key: string]: string}>;
92-
_hasteName: Promise<string | void>;
93-
_readSourceCodePromise: Promise<string>;
93+
_docBlock: ?DocBlock;
94+
_hasteNameCache: ?{+hasteName: ?string};
95+
_sourceCode: ?string;
9496
_readPromises: Map<string, Promise<ReadResult>>;
9597

9698
constructor({
@@ -127,7 +129,7 @@ class Module {
127129
return this._cache.get(
128130
this.path,
129131
'isHaste',
130-
() => this._getHasteName().then(name => !!name),
132+
() => Promise.resolve(this._getHasteName() != null),
131133
);
132134
}
133135

@@ -143,8 +145,9 @@ class Module {
143145
return this._cache.get(
144146
this.path,
145147
'name',
146-
() => this._getHasteName().then(name => {
147-
if (name !== undefined) {
148+
() => Promise.resolve().then(() => {
149+
const name = this._getHasteName();
150+
if (name != null) {
148151
return name;
149152
}
150153

@@ -183,75 +186,71 @@ class Module {
183186
invalidate() {
184187
this._cache.invalidate(this.path);
185188
this._readPromises.clear();
189+
this._sourceCode = null;
190+
this._docBlock = null;
191+
this._hasteNameCache = null;
186192
}
187193

188-
_readSourceCode() {
189-
if (!this._readSourceCodePromise) {
190-
this._readSourceCodePromise = new Promise(
191-
resolve => resolve(fs.readFileSync(this.path, 'utf8'))
192-
);
194+
_readSourceCode(): string {
195+
if (this._sourceCode == null) {
196+
this._sourceCode = fs.readFileSync(this.path, 'utf8');
193197
}
194-
return this._readSourceCodePromise;
198+
return this._sourceCode;
195199
}
196200

197-
_readDocBlock() {
198-
if (!this._docBlock) {
199-
this._docBlock = this._readSourceCode()
200-
.then(source => docblock.parseAsObject(source));
201+
_readDocBlock(): DocBlock {
202+
if (this._docBlock == null) {
203+
this._docBlock = docblock.parseAsObject(this._readSourceCode());
201204
}
202205
return this._docBlock;
203206
}
204207

205-
_getHasteName(): Promise<string | void> {
206-
if (!this._hasteName) {
207-
const hasteImpl = this._options.hasteImpl;
208-
if (hasteImpl === undefined || hasteImpl.enforceHasteNameMatches) {
209-
this._hasteName = this._readDocBlock().then(moduleDocBlock => {
210-
const {providesModule} = moduleDocBlock;
211-
return providesModule
212-
&& !this._depGraphHelpers.isNodeModulesDir(this.path)
213-
? /^\S+/.exec(providesModule)[0]
214-
: undefined;
215-
});
216-
}
217-
if (hasteImpl !== undefined) {
218-
const {enforceHasteNameMatches} = hasteImpl;
219-
if (enforceHasteNameMatches) {
220-
this._hasteName = this._hasteName.then(providesModule => {
221-
enforceHasteNameMatches(
222-
this.path,
223-
providesModule,
224-
);
225-
return hasteImpl.getHasteName(this.path);
226-
});
227-
} else {
228-
this._hasteName = Promise.resolve(hasteImpl.getHasteName(this.path));
229-
}
230-
} else {
231-
// Extract an id for the module if it's using @providesModule syntax
232-
// and if it's NOT in node_modules (and not a whitelisted node_module).
233-
// This handles the case where a project may have a dep that has @providesModule
234-
// docblock comments, but doesn't want it to conflict with whitelisted @providesModule
235-
// modules, such as react-haste, fbjs-haste, or react-native or with non-dependency,
236-
// project-specific code that is using @providesModule.
237-
this._hasteName = this._readDocBlock().then(moduleDocBlock => {
238-
const {providesModule} = moduleDocBlock;
239-
return providesModule
240-
&& !this._depGraphHelpers.isNodeModulesDir(this.path)
241-
? /^\S+/.exec(providesModule)[0]
242-
: undefined;
243-
});
208+
_getHasteName(): ?string {
209+
if (this._hasteNameCache != null) {
210+
return this._hasteNameCache.hasteName;
211+
}
212+
const hasteImpl = this._options.hasteImpl;
213+
if (hasteImpl === undefined || hasteImpl.enforceHasteNameMatches) {
214+
const moduleDocBlock = this._readDocBlock();
215+
const {providesModule} = moduleDocBlock;
216+
this._hasteNameCache = {
217+
hasteName: providesModule && !this._depGraphHelpers.isNodeModulesDir(this.path)
218+
? /^\S+/.exec(providesModule)[0]
219+
: undefined,
220+
};
221+
}
222+
if (hasteImpl !== undefined) {
223+
const {enforceHasteNameMatches} = hasteImpl;
224+
if (enforceHasteNameMatches) {
225+
/* $FlowFixMe: this rely on the above if being executed, that is fragile. Rework the algo. */
226+
enforceHasteNameMatches(this.path, this._hasteNameCache.hasteName);
244227
}
228+
this._hasteNameCache = {hasteName: hasteImpl.getHasteName(this.path)};
229+
} else {
230+
// Extract an id for the module if it's using @providesModule syntax
231+
// and if it's NOT in node_modules (and not a whitelisted node_module).
232+
// This handles the case where a project may have a dep that has @providesModule
233+
// docblock comments, but doesn't want it to conflict with whitelisted @providesModule
234+
// modules, such as react-haste, fbjs-haste, or react-native or with non-dependency,
235+
// project-specific code that is using @providesModule.
236+
const moduleDocBlock = this._readDocBlock();
237+
const {providesModule} = moduleDocBlock;
238+
this._hasteNameCache = {
239+
hasteName:
240+
providesModule && !this._depGraphHelpers.isNodeModulesDir(this.path)
241+
? /^\S+/.exec(providesModule)[0]
242+
: undefined,
243+
};
245244
}
246-
return this._hasteName;
245+
return this._hasteNameCache.hasteName;
247246
}
248247

249248
/**
250249
* To what we read from the cache or worker, we need to add id and source.
251250
*/
252251
_finalizeReadResult(
253252
source: string,
254-
id?: string,
253+
id: ?string,
255254
extern: boolean,
256255
result: TransformedCode,
257256
): ReadResult {
@@ -345,11 +344,10 @@ class Module {
345344
if (promise != null) {
346345
return promise;
347346
}
348-
const freshPromise = Promise.all([
349-
this._readSourceCode(),
350-
this._readDocBlock(),
351-
this._getHasteName(),
352-
]).then(([sourceCode, moduleDocBlock, id]) => {
347+
const freshPromise = Promise.resolve().then(() => {
348+
const sourceCode = this._readSourceCode();
349+
const moduleDocBlock = this._readDocBlock();
350+
const id = this._getHasteName();
353351
// Ignore requires in JSON files or generated code. An example of this
354352
// is prebuilt files like the SourceMap library.
355353
const extern = this.isJSON() || 'extern' in moduleDocBlock;

0 commit comments

Comments
 (0)