Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion build/gulpfile.vscode.js
Original file line number Diff line number Diff line change
Expand Up @@ -355,14 +355,21 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
api,
// --- Start Positron ---
positronApi,
getQuartoBinaries(),
moduleSources,
// --- End Positron ---
telemetry,
sources,
deps
);

/// --- Start Positron ---
// The Quarto binaries are not available for Windows ARM builds, but are
// for all other platforms/architectures
if (!(platform === 'win32' && arch === 'arm64')) {
all = es.merge(all, getQuartoBinaries());
}
// --- End Positron ---

if (platform === 'win32') {
all = es.merge(all, gulp.src([
'resources/win32/bower.ico',
Expand Down
117 changes: 99 additions & 18 deletions build/lib/extensions.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

135 changes: 114 additions & 21 deletions build/lib/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ function fromLocal(extensionPath: string, forWeb: boolean, disableMangle: boolea
return input;
}


function fromLocalWebpack(extensionPath: string, webpackConfigFileName: string, disableMangle: boolean): Stream {
const vsce = require('@vscode/vsce') as typeof import('@vscode/vsce');
const webpack = require('webpack');
Expand Down Expand Up @@ -140,15 +139,6 @@ function fromLocalWebpack(extensionPath: string, webpackConfigFileName: string,
// --- Start PWB: from Positron ---
// Replace vsce.listFiles with listExtensionFiles to queue the work
listExtensionFiles({ cwd: extensionPath, packageManager: packageManger, packagedDependencies }).then(fileNames => {
const files = fileNames
.map(fileName => path.join(extensionPath, fileName))
.map(filePath => new File({
path: filePath,
stat: fs.statSync(filePath),
base: extensionPath,
contents: fs.createReadStream(filePath) as any
}));

// check for a webpack configuration files, then invoke webpack
// and merge its output with the files stream.
const webpackConfigLocations = (<string[]>glob.sync(
Expand Down Expand Up @@ -215,7 +205,9 @@ function fromLocalWebpack(extensionPath: string, webpackConfigFileName: string,
});
});

es.merge(...webpackStreams, es.readArray(files))
const localFilesStream = createSequentialFileStream(extensionPath, fileNames);

es.merge(...webpackStreams, localFilesStream)
// .pipe(es.through(function (data) {
// // debug
// console.log('out', data.path, data.contents.length);
Expand All @@ -241,16 +233,7 @@ function fromLocalNormal(extensionPath: string): Stream {
// Replace vsce.listFiles with listExtensionFiles to queue the work
listExtensionFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Npm })
.then(fileNames => {
const files = fileNames
.map(fileName => path.join(extensionPath, fileName))
.map(filePath => new File({
path: filePath,
stat: fs.statSync(filePath),
base: extensionPath,
contents: fs.createReadStream(filePath) as any
}));

es.readArray(files).pipe(result);
createSequentialFileStream(extensionPath, fileNames).pipe(result);
})
.catch(err => result.emit('error', err));
// --- End PWB: from Positron ---
Expand All @@ -266,6 +249,7 @@ const baseHeaders = {
};

// --- Start Positron ---

function getPlatformDownloads(bootstrap: boolean): string[] {
// return both architectures for mac universal installer
if (bootstrap && process.platform === 'darwin' && !process.env['VSCODE_DEV']) {
Expand Down Expand Up @@ -858,6 +842,115 @@ export async function buildExtensionMedia(isWatch: boolean, outputRoot?: string)

// --- Start PWB: from Positron ---

/**
* Create a stream that emits files in the order of `fileNames`, one at a time,
* reading each file from disk before emitting it.
*
* This is used to serialize file reads when packaging extensions, to avoid
* running out of file descriptors (EMFILE) when building.
*
* @param extensionPath The root path of the extension
* @param fileNames The list of file names to emit, relative to `extensionPath`
* @returns A stream that emits the files in order
*/
function createSequentialFileStream(extensionPath: string, fileNames: string[]): Stream {
const stream = es.through();
const queue = [...fileNames];
let ended = false;

const finish = () => {
if (!ended) {
ended = true;
stream.emit('end');
}
};

stream.on('close', () => {
ended = true;
queue.length = 0;
});

stream.on('error', () => {
ended = true;
queue.length = 0;
});

const pump = () => {
if (ended) {
return;
}
if (queue.length === 0) {
finish();
return;
}

const relativePath = queue.shift()!;
const absolutePath = path.join(extensionPath, relativePath);
let stats: fs.Stats;
try {
stats = fs.statSync(absolutePath);
} catch (error) {
ended = true;
queue.length = 0;
stream.emit('error', error);
return;
}

let fileStream: fs.ReadStream;
try {
fileStream = fs.createReadStream(absolutePath);
} catch (error) {
ended = true;
queue.length = 0;
stream.emit('error', error);
return;
}

let settled = false;
const cleanup = () => {
if (settled) {
return;
}
settled = true;
fileStream.removeListener('end', cleanup);
fileStream.removeListener('close', cleanup);
fileStream.removeListener('error', onError);
setImmediate(pump);
};

const onError = (err: Error) => {
if (settled) {
return;
}
settled = true;
fileStream.removeListener('end', cleanup);
fileStream.removeListener('close', cleanup);
fileStream.removeListener('error', onError);
ended = true;
queue.length = 0;
stream.emit('error', err);
};

fileStream.on('end', cleanup);
fileStream.on('close', cleanup);
fileStream.on('error', onError);

const file = new File({
path: absolutePath,
stat: stats,
base: extensionPath,
contents: fileStream as any
});

stream.emit('data', file);
};

setImmediate(pump);

return stream;
}


// Node 20 consistently crashes when there are too many `vsce.listFiles`
// operations in flight at once; these operations are expensive as they recurse
// back into `yarn`. The code below serializes these operations when building
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ async function main() {
// On macOS, we need both the x64 and arm64 versions of the language
// server. By default npm just installs the one for the current CPU
// architecture.
if (platform() === 'darwin') {
//
// We also need to force the platform on windows since there is no arm64
// build of the copilot language server yet.
if (platform() === 'darwin' || platform() === 'win32') {
console.log(`Installing ${packageName} (${targetArch})...`);

// Use --force to prevent npm from blocking the installation due to
Expand Down
2 changes: 1 addition & 1 deletion extensions/positron-r/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@
},
"positron": {
"binaryDependencies": {
"ark": "0.1.213"
"ark": "0.1.214"
},
"minimumRVersion": "4.2.0",
"minimumRenvVersion": "1.0.9"
Expand Down
Loading