Skip to content

Commit

Permalink
Merge pull request #1149 from embroider-build/externals-race
Browse files Browse the repository at this point in the history
Update externals stubs atomically
  • Loading branch information
ef4 authored Mar 4, 2022
2 parents be9de27 + 041d3f9 commit 5b923af
Showing 1 changed file with 23 additions and 4 deletions.
27 changes: 23 additions & 4 deletions packages/core/src/babel-plugin-adjust-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import type { NodePath } from '@babel/traverse';
import type * as Babel from '@babel/core';
import type { types as t } from '@babel/core';
import { PackageCache, Package, V2Package, explicitRelative } from '@embroider/shared-internals';
import { outputFileSync } from 'fs-extra';
import { Memoize } from 'typescript-memoize';
import { compile } from './js-handlebars';
import { handleImportDeclaration } from './mini-modules-polyfill';
import { ImportUtil } from 'babel-import-util';
import { randomBytes } from 'crypto';
import { outputFileSync, pathExistsSync, renameSync } from 'fs-extra';

interface State {
adjustFile: AdjustFile;
Expand Down Expand Up @@ -332,8 +333,8 @@ function handleExternal(specifier: string, sourceFile: AdjustFile, opts: Options
}

function makeMissingModule(specifier: string, sourceFile: AdjustFile, opts: Options): string {
let target = join(opts.externalsDir, specifier + '.js');
outputFileSync(
let target = join(opts.externalsDir, 'missing', specifier + '.js');
atomicWrite(
target,
dynamicMissingModule({
moduleName: specifier,
Expand All @@ -344,7 +345,7 @@ function makeMissingModule(specifier: string, sourceFile: AdjustFile, opts: Opti

function makeExternal(specifier: string, sourceFile: AdjustFile, opts: Options): string {
let target = join(opts.externalsDir, specifier + '.js');
outputFileSync(
atomicWrite(
target,
externalTemplate({
runtimeName: specifier,
Expand All @@ -353,6 +354,24 @@ function makeExternal(specifier: string, sourceFile: AdjustFile, opts: Options):
return explicitRelative(dirname(sourceFile.name), target.slice(0, -3));
}

function atomicWrite(path: string, content: string) {
if (pathExistsSync(path)) {
return;
}
let suffix = randomBytes(8).toString('hex');
outputFileSync(path + suffix, content);
try {
renameSync(path + suffix, path);
} catch (err: any) {
// windows throws EPERM for concurrent access. For us it's not an error
// condition because the other thread is writing the exact same value we
// would have.
if (err.code !== 'EPERM') {
throw err;
}
}
}

export default function main(babel: typeof Babel) {
let t = babel.types;
return {
Expand Down

0 comments on commit 5b923af

Please sign in to comment.