Skip to content

Commit d6a4df3

Browse files
devongovettyamadapc
andcommittedFeb 3, 2025·
Fix dev dep request missing 'invalidateOnCreate'
Fixes #8375 Ported from Atlaspack: atlassian-labs/atlaspack#185 Co-authored-by: Pedro Yamada <tacla.yamada@gmail.com>
1 parent b50bc79 commit d6a4df3

File tree

8 files changed

+123
-18
lines changed

8 files changed

+123
-18
lines changed
 

‎packages/core/core/src/PackagerRunner.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {
1414
Bundle as InternalBundle,
1515
Config,
1616
DevDepRequest,
17+
DevDepRequestRef,
1718
ParcelOptions,
1819
ReportFn,
1920
RequestInvalidation,
@@ -74,7 +75,7 @@ type Opts = {|
7475
export type RunPackagerRunnerResult = {|
7576
bundleInfo: BundleInfo[],
7677
configRequests: Array<ConfigRequest>,
77-
devDepRequests: Array<DevDepRequest>,
78+
devDepRequests: Array<DevDepRequest | DevDepRequestRef>,
7879
invalidations: Array<RequestInvalidation>,
7980
|};
8081

@@ -107,7 +108,7 @@ export default class PackagerRunner {
107108
distExists: Set<FilePath>;
108109
report: ReportFn;
109110
previousDevDeps: Map<string, string>;
110-
devDepRequests: Map<string, DevDepRequest>;
111+
devDepRequests: Map<string, DevDepRequest | DevDepRequestRef>;
111112
invalidations: Map<string, RequestInvalidation>;
112113
previousInvalidations: Array<RequestInvalidation>;
113114

‎packages/core/core/src/Transformation.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {
1515
TransformationRequest,
1616
Config,
1717
DevDepRequest,
18+
DevDepRequestRef,
1819
ParcelOptions,
1920
InternalDevDepOptions,
2021
Invalidations,
@@ -89,13 +90,13 @@ export type TransformationResult = {|
8990
error?: Array<Diagnostic>,
9091
configRequests: Array<ConfigRequest>,
9192
invalidations: Invalidations,
92-
devDepRequests: Array<DevDepRequest>,
93+
devDepRequests: Array<DevDepRequest | DevDepRequestRef>,
9394
|};
9495

9596
export default class Transformation {
9697
request: TransformationRequest;
9798
configs: Map<string, Config>;
98-
devDepRequests: Map<string, DevDepRequest>;
99+
devDepRequests: Map<string, DevDepRequest | DevDepRequestRef>;
99100
pluginDevDeps: Array<InternalDevDepOptions>;
100101
options: ParcelOptions;
101102
pluginOptions: PluginOptions;

‎packages/core/core/src/applyRuntimes.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
Bundle as InternalBundle,
1010
Config,
1111
DevDepRequest,
12+
DevDepRequestRef,
1213
ParcelOptions,
1314
} from './types';
1415
import type ParcelConfig from './ParcelConfig';
@@ -59,7 +60,7 @@ export default async function applyRuntimes<TResult: RequestResult>({
5960
pluginOptions: PluginOptions,
6061
api: RunAPI<TResult>,
6162
previousDevDeps: Map<string, string>,
62-
devDepRequests: Map<string, DevDepRequest>,
63+
devDepRequests: Map<string, DevDepRequest | DevDepRequestRef>,
6364
configs: Map<string, Config>,
6465
|}): Promise<Map<string, Asset>> {
6566
let runtimes = await config.getRuntimes();

‎packages/core/core/src/requests/BundleGraphRequest.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
Bundle as InternalBundle,
1111
Config,
1212
DevDepRequest,
13+
DevDepRequestRef,
1314
ParcelOptions,
1415
} from '../types';
1516
import type {ConfigAndCachePath} from './ParcelConfigRequest';
@@ -173,7 +174,7 @@ class BundlerRunner {
173174
pluginOptions: PluginOptions;
174175
api: RunAPI<BundleGraphResult>;
175176
previousDevDeps: Map<string, string>;
176-
devDepRequests: Map<string, DevDepRequest>;
177+
devDepRequests: Map<string, DevDepRequest | DevDepRequestRef>;
177178
configs: Map<string, Config>;
178179
cacheKey: string;
179180

@@ -236,7 +237,7 @@ class BundlerRunner {
236237
this.configs.set(plugin.name, config);
237238
}
238239

239-
async runDevDepRequest(devDepRequest: DevDepRequest) {
240+
async runDevDepRequest(devDepRequest: DevDepRequest | DevDepRequestRef) {
240241
let {specifier, resolveFrom} = devDepRequest;
241242
let key = `${specifier}:${fromProjectPathRelative(resolveFrom)}`;
242243
this.devDepRequests.set(key, devDepRequest);

‎packages/core/core/src/requests/DevDepRequest.js

+37-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
import type ParcelConfig from '../ParcelConfig';
88
import type {
99
DevDepRequest,
10+
DevDepRequestRef,
1011
ParcelOptions,
1112
InternalDevDepOptions,
1213
} from '../types';
@@ -34,7 +35,7 @@ export async function createDevDependency(
3435
opts: InternalDevDepOptions,
3536
requestDevDeps: Map<string, string>,
3637
options: ParcelOptions,
37-
): Promise<DevDepRequest> {
38+
): Promise<DevDepRequest | DevDepRequestRef> {
3839
let {specifier, resolveFrom, additionalInvalidations} = opts;
3940
let key = `${specifier}:${fromProjectPathRelative(resolveFrom)}`;
4041

@@ -44,6 +45,7 @@ export async function createDevDependency(
4445
let hash = requestDevDeps.get(key);
4546
if (hash != null) {
4647
return {
48+
type: 'ref',
4749
specifier,
4850
resolveFrom,
4951
hash,
@@ -189,12 +191,17 @@ export type DevDepRequestResult = {|
189191

190192
export async function runDevDepRequest<TResult: RequestResult>(
191193
api: RunAPI<TResult>,
192-
devDepRequest: DevDepRequest,
194+
devDepRequestRef: DevDepRequest | DevDepRequestRef,
193195
) {
194196
await api.runRequest<null, DevDepRequestResult | void>({
195-
id: 'dev_dep_request:' + devDepRequest.specifier + ':' + devDepRequest.hash,
197+
id:
198+
'dev_dep_request:' +
199+
devDepRequestRef.specifier +
200+
':' +
201+
devDepRequestRef.hash,
196202
type: requestTypes.dev_dep_request,
197203
run: ({api}) => {
204+
let devDepRequest = resolveDevDepRequestRef(devDepRequestRef);
198205
for (let filePath of nullthrows(
199206
devDepRequest.invalidateOnFileChange,
200207
'DevDepRequest missing invalidateOnFileChange',
@@ -225,19 +232,43 @@ export async function runDevDepRequest<TResult: RequestResult>(
225232
});
226233
}
227234

235+
const devDepRequests: Map<string, DevDepRequest> = createBuildCache();
236+
export function resolveDevDepRequestRef(
237+
devDepRequestRef: DevDepRequest | DevDepRequestRef,
238+
): DevDepRequest {
239+
const devDepRequest =
240+
devDepRequestRef.type === 'ref'
241+
? devDepRequests.get(devDepRequestRef.hash)
242+
: devDepRequestRef;
243+
if (devDepRequest == null) {
244+
throw new Error(
245+
`Worker send back a reference to a missing dev dep request.
246+
This might happen due to internal in-memory build caches not being cleared
247+
between builds or due a race condition.
248+
This is a bug in Parcel.`,
249+
);
250+
}
251+
252+
if (devDepRequestRef.type !== 'ref') {
253+
devDepRequests.set(devDepRequest.hash, devDepRequest);
254+
}
255+
256+
return devDepRequest;
257+
}
258+
228259
// A cache of plugin dependency hashes that we've already sent to the main thread.
229260
// Automatically cleared before each build.
230261
const pluginCache = createBuildCache();
231262

232263
export function getWorkerDevDepRequests(
233-
devDepRequests: Array<DevDepRequest>,
234-
): Array<DevDepRequest> {
264+
devDepRequests: Array<DevDepRequest | DevDepRequestRef>,
265+
): Array<DevDepRequest | DevDepRequestRef> {
235266
return devDepRequests.map(devDepRequest => {
236267
// If we've already sent a matching transformer + hash to the main thread during this build,
237268
// there's no need to repeat ourselves.
238269
let {specifier, resolveFrom, hash} = devDepRequest;
239270
if (hash === pluginCache.get(specifier)) {
240-
return {specifier, resolveFrom, hash};
271+
return {type: 'ref', specifier, resolveFrom, hash};
241272
} else {
242273
pluginCache.set(specifier, hash);
243274
return devDepRequest;

‎packages/core/core/src/requests/PathRequest.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
Config,
1313
Dependency,
1414
DevDepRequest,
15+
DevDepRequestRef,
1516
ParcelOptions,
1617
} from '../types';
1718
import type {ConfigAndCachePath} from './ParcelConfigRequest';
@@ -163,7 +164,7 @@ export class ResolverRunner {
163164
options: ParcelOptions;
164165
pluginOptions: PluginOptions;
165166
previousDevDeps: Map<string, string>;
166-
devDepRequests: Map<string, DevDepRequest>;
167+
devDepRequests: Map<string, DevDepRequest | DevDepRequestRef>;
167168
configs: Map<string, Config>;
168169

169170
constructor({config, options, previousDevDeps}: ResolverRunnerOpts) {
@@ -237,7 +238,7 @@ export class ResolverRunner {
237238
}
238239
}
239240

240-
runDevDepRequest(devDepRequest: DevDepRequest) {
241+
runDevDepRequest(devDepRequest: DevDepRequest | DevDepRequestRef) {
241242
let {specifier, resolveFrom} = devDepRequest;
242243
let key = `${specifier}:${fromProjectPathRelative(resolveFrom)}`;
243244
this.devDepRequests.set(key, devDepRequest);

‎packages/core/core/src/types.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -258,16 +258,23 @@ export type DevDepRequest = {|
258258
specifier: DependencySpecifier,
259259
resolveFrom: ProjectPath,
260260
hash: string,
261-
invalidateOnFileCreate?: Array<InternalFileCreateInvalidation>,
262-
invalidateOnFileChange?: Set<ProjectPath>,
263-
invalidateOnStartup?: boolean,
261+
invalidateOnFileCreate: Array<InternalFileCreateInvalidation>,
262+
invalidateOnFileChange: Set<ProjectPath>,
263+
invalidateOnStartup: boolean,
264264
additionalInvalidations?: Array<{|
265265
specifier: DependencySpecifier,
266266
resolveFrom: ProjectPath,
267267
range?: ?SemverRange,
268268
|}>,
269269
|};
270270

271+
export type DevDepRequestRef = {|
272+
type: 'ref',
273+
specifier: DependencySpecifier,
274+
resolveFrom: ProjectPath,
275+
hash: string,
276+
|};
277+
271278
declare type GlobPattern = string;
272279

273280
export type ParcelOptions = {|
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// @flow strict-local
2+
3+
// eslint-disable-next-line @parcel/no-self-package-imports
4+
import {clearBuildCaches} from '@parcel/core/src/buildCache';
5+
import {resolveDevDepRequestRef} from '../../src/requests/DevDepRequest';
6+
import type {DevDepRequest, DevDepRequestRef} from '../../src/types';
7+
import {toProjectPath} from '../../src/projectPath';
8+
import assert from 'assert';
9+
10+
describe('DevDepRequest', () => {
11+
beforeEach(() => {
12+
clearBuildCaches();
13+
});
14+
15+
describe('resolveDevDepRequestRef', () => {
16+
it('will return requests as is', () => {
17+
const request: DevDepRequest = {
18+
specifier: 'test',
19+
hash: 'hash',
20+
invalidateOnFileChange: new Set(),
21+
invalidateOnFileCreate: [],
22+
invalidateOnStartup: false,
23+
resolveFrom: toProjectPath('', 'path.js'),
24+
};
25+
const result = resolveDevDepRequestRef(request);
26+
assert.equal(result, request);
27+
});
28+
29+
it('will return cached requests for refs', () => {
30+
const request: DevDepRequest = {
31+
specifier: 'test',
32+
hash: 'hash',
33+
invalidateOnFileChange: new Set(),
34+
invalidateOnFileCreate: [],
35+
invalidateOnStartup: false,
36+
resolveFrom: toProjectPath('', 'path.js'),
37+
};
38+
resolveDevDepRequestRef(request);
39+
40+
const devDepRequestRef: DevDepRequestRef = {
41+
type: 'ref',
42+
specifier: 'test',
43+
hash: 'hash',
44+
resolveFrom: toProjectPath('', 'path.js'),
45+
};
46+
const result = resolveDevDepRequestRef(devDepRequestRef);
47+
assert.equal(result, request);
48+
});
49+
50+
it('will throw for uncached refs', () => {
51+
const devDepRequestRef: DevDepRequestRef = {
52+
type: 'ref',
53+
specifier: 'test',
54+
hash: 'hash',
55+
resolveFrom: toProjectPath('', 'path.js'),
56+
};
57+
assert.throws(() => {
58+
resolveDevDepRequestRef(devDepRequestRef);
59+
});
60+
});
61+
});
62+
});

0 commit comments

Comments
 (0)
Please sign in to comment.