Skip to content

Commit

Permalink
Enable installing specific engine versions alongside the auto-updated…
Browse files Browse the repository at this point in the history
… binaries (#60)

Closes #16.
  • Loading branch information
mathiasbynens authored Mar 8, 2019
1 parent d58b578 commit 853836d
Show file tree
Hide file tree
Showing 47 changed files with 427 additions and 170 deletions.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,36 @@ jsvu --os=mac64 --engines=chakra,javascriptcore,spidermonkey,v8,xs

Note that `--engines=all` does not install the `v8-debug` binaries.

## Installing specific versions

jsvu also supports installing specific versions alongside the main engine binaries (which it keeps up to date). Here’s an example:

```sh
jsvu v8@7.2.502
```

Binaries installed using this method are named `${BINARY}-${VERSION}`, so that the above example installs a binary named `v8-7.2.502`. This way, there’s never any conflict with the main `v8` binary, which jsvu can keep up to date.

This feature works for all the supported engines:

```sh
jsvu chakra@1.11.6
jsvu javascriptcore@242640
jsvu spidermonkey@66.0b13
jsvu v8@7.2.502
jsvu v8-debug@v7.1.302
jsvu xs@8.7.0
```

If you pass in an invalid version number, or if the JavaScript engine creators don’t provide a precompiled binary for that specific version, jsvu shows an error.

As a shorthand, for `v8` and `v8-debug` builds, jsvu can even figure out the last known good revision within a [milestone](https://v8.dev/docs/version-numbers). To install the latest available V8 v7.2.x for example, run:

```sh
jsvu v8@7.2
# jsvu figures out that this means v7.2.502, and then installs that version.
```

## Security considerations

_jsvu_ avoids the need for `sudo` privileges by installing everything in `~/.jsvu` rather than, say, `/usr/bin`.
Expand Down
51 changes: 48 additions & 3 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,58 @@ const promptEngines = () => {
// Warn if an update is available.
updateNotifier({ pkg }).notify();

// Read the user configuration, and prompt for any missing info.
// Read the user configuration + CLI arguments, and prompt for any
// missing info.
const status = getStatus();

const args = process.argv.slice(2);
for (const arg of args) {
if (arg.startsWith('--os=')) {
const os = arg.split('=')[1];
status.os = os;
}
else if (arg.startsWith('--engines=')) {
const enginesArg = arg.split('=')[1];
const engines = enginesArg === 'all' ?
['chakra', 'javascriptcore', 'spidermonkey', 'v8', 'xs'] :
enginesArg.split(',');
status.engines = engines;
}
else if (arg.includes('@')) {
const [engine, version] = arg.split('@');
status.engine = engine;
status.version = version;
}
}

if (status.os === undefined) {
status.os = (await promptOs()).step;
setStatus(status);
// Don't store one-off CLI args in the persistent configuration.
const statusCopy = { ...status };
delete statusCopy.engine;
delete statusCopy.version;
setStatus(statusCopy);
} else {
log.success(`Read OS from config: ${status.os}`);
}

// The user provided a specific engine + version, e.g. `jsvu v8@7.2`.
if (status.engine && status.version) {
const { engine, version } = status;
log.success(`Read engine + version from CLI argument: ${engine} v${
version}`);
const installSpecificEngineVersion =
require('./shared/install-specific-version.js');
await installSpecificEngineVersion({
...require(`./engines/${engine}/index.js`),
os: status.os,
version: version,
});
return;
}

// The user wants to install or update engines, but we don’t know
// which ones.
if (status.engines === undefined || status.engines.length === 0) {
status.engines = (await promptEngines()).step;
if (status.engines.length === 0) {
Expand All @@ -136,8 +180,9 @@ const promptEngines = () => {
}

// Install the desired JavaScript engines.
const updateEngine = require('./shared/engine.js');
for (const engine of status.engines) {
await require(`./engines/${engine}/index.js`);
await updateEngine(require(`./engines/${engine}/index.js`));
}

})();
22 changes: 11 additions & 11 deletions engines/chakra/extract.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 Google Inc.
// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
Expand All @@ -20,7 +20,7 @@ const tar = require('tar');
const { Installer } = require('../../shared/installer.js');
const unzip = require('../../shared/unzip.js');

const extract = ({ filePath, engine, os }) => {
const extract = ({ filePath, binary, alias, os }) => {
return new Promise(async (resolve, reject) => {
const tmpPath = path.dirname(filePath);
if (os.startsWith('win')) {
Expand All @@ -39,36 +39,36 @@ const extract = ({ filePath, engine, os }) => {
case 'linux32':
case 'linux64': {
const installer = new Installer({
engine,
engine: binary,
path: `${tmpPath}/ChakraCoreFiles`,
});
installer.installLibraryGlob('lib/*');
installer.installBinary({ 'bin/ch': 'chakra' });
installer.installBinarySymlink({ 'chakra': 'ch' });
installer.installLicense({ 'LICENSE': 'LICENSE-chakra' });
installer.installBinary({ 'bin/ch': binary });
installer.installBinarySymlink({ [binary]: alias });
installer.installLicense({ 'LICENSE': `LICENSE-${binary}` });
break;
}
case 'win32':
case 'win64': {
const installer = new Installer({
engine,
engine: binary,
path: `${tmpPath}/${os === 'win32' ?
'x86_release' : 'x64_release'}`,
});
installer.installLibraryGlob('*.pdb');
installer.installLibraryGlob('*.dll');
installer.installBinary(
{ 'ch.exe': 'chakra.exe' },
{ 'ch.exe': `${binary}.exe` },
{ symlink: false }
);
installer.installScript({
name: 'chakra.cmd',
alias: 'ch.cmd',
name: `${binary}.cmd`,
alias: `${alias}.cmd`,
symlink: false,
generateScript: (targetPath) => {
return `
@echo off
"${targetPath}\\chakra.exe" %*
"${targetPath}\\${binary}.exe" %*
`;
}
});
Expand Down
2 changes: 1 addition & 1 deletion engines/chakra/get-latest-version.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 Google Inc.
// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
Expand Down
22 changes: 22 additions & 0 deletions engines/chakra/get-specific-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// <https://apache.org/licenses/LICENSE-2.0>.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

const getSpecificVersion = (version) => {
// If we ever want to add logic that maps e.g. `'1.11'` to the latest
// available version in that range (e.g. `'1.11.6'`), it can go here.
return version;
};

module.exports = getSpecificVersion;
9 changes: 4 additions & 5 deletions engines/chakra/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 Google Inc.
// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
Expand All @@ -13,9 +13,8 @@

'use strict';

const updateEngine = require('../../shared/engine.js');

module.exports = updateEngine({
module.exports = {
name: 'Chakra',
id: 'chakra',
});
alias: 'ch',
};
2 changes: 1 addition & 1 deletion engines/chakra/predict-url.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 Google Inc.
// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
Expand Down
8 changes: 4 additions & 4 deletions engines/chakra/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 Google Inc.
// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
Expand All @@ -21,14 +21,14 @@ const tempy = require('tempy');
const config = require('../../shared/config.js');
const jsvuPath = config.path;

const test = async () => {
const test = async ({ binary, alias }) => {
const path = tempy.file();
fs.writeFileSync(path, `print('Hi!');\n`);
console.assert(
(await execa(`${jsvuPath}/chakra`, [path])).stdout === 'Hi!'
(await execa(`${jsvuPath}/${binary}`, [path])).stdout === 'Hi!'
);
console.assert(
(await execa(`${jsvuPath}/ch`, [path])).stdout === 'Hi!'
(await execa(`${jsvuPath}/${alias}`, [path])).stdout === 'Hi!'
);
};

Expand Down
30 changes: 15 additions & 15 deletions engines/javascriptcore/extract.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 Google Inc.
// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
Expand All @@ -20,7 +20,7 @@ const execa = require('execa');
const { Installer } = require('../../shared/installer.js');
const unzip = require('../../shared/unzip.js');

const extract = ({ filePath, engine, os }) => {
const extract = ({ filePath, binary, alias, os }) => {
return new Promise(async (resolve, reject) => {
const tmpPath = path.dirname(filePath);
await unzip({
Expand All @@ -30,18 +30,18 @@ const extract = ({ filePath, engine, os }) => {
switch (os) {
case 'mac64': {
const installer = new Installer({
engine,
engine: binary,
path: `${tmpPath}/Release`,
});
installer.installLibraryGlob('JavaScriptCore.framework/*');
installer.installBinary({ 'jsc': 'javascriptcore' }, { symlink: false });
installer.installBinary({ 'jsc': binary }, { symlink: false });
installer.installScript({
name: 'javascriptcore',
alias: 'jsc',
name: binary,
alias: alias,
generateScript: (targetPath) => {
return `
#!/usr/bin/env bash
DYLD_FRAMEWORK_PATH="${targetPath}" DYLD_LIBRARY_PATH="${targetPath}" "${targetPath}/javascriptcore" "$@"
DYLD_FRAMEWORK_PATH="${targetPath}" DYLD_LIBRARY_PATH="${targetPath}" "${targetPath}/${binary}" "$@"
`;
}
});
Expand All @@ -50,19 +50,19 @@ const extract = ({ filePath, engine, os }) => {
case 'linux32':
case 'linux64': {
const installer = new Installer({
engine,
engine: binary,
path: tmpPath,
});
installer.installLibraryGlob('lib/*');
installer.installBinary({ 'bin/jsc': 'javascriptcore' }, { symlink: false });
installer.installBinary({ 'bin/jsc': binary }, { symlink: false });
installer.installScript({
name: 'javascriptcore',
alias: 'jsc',
name: binary,
alias: alias,
generateScript: (targetPath) => {
return `
#!/usr/bin/env bash
LD_LIBRARY_PATH="${targetPath}/lib" exec "${targetPath}/lib/ld-linux${
os === 'linux64' ? '-x86-64' : '' }.so.2" "${targetPath}/javascriptcore" "$@"
os === 'linux64' ? '-x86-64' : '' }.so.2" "${targetPath}/${binary}" "$@"
`;
}
});
Expand All @@ -71,7 +71,7 @@ const extract = ({ filePath, engine, os }) => {
case 'win32':
case 'win64': {
const installer = new Installer({
engine,
engine: binary,
path: `${tmpPath}/bin${os === 'win64' ? '64' : '32'}`,
});
installer.installLibraryGlob('JavaScriptCore.resources/*');
Expand All @@ -82,8 +82,8 @@ const extract = ({ filePath, engine, os }) => {
// to `javascriptcore.exe` on Windows.
installer.installBinary('jsc.exe', { symlink: false });
installer.installScript({
name: 'javascriptcore.cmd',
alias: 'jsc.cmd',
name: `${binary}.cmd`,
alias: `${alias}.cmd`,
symlink: false,
generateScript: (targetPath) => {
return `
Expand Down
2 changes: 1 addition & 1 deletion engines/javascriptcore/get-latest-version.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 Google Inc.
// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
Expand Down
22 changes: 22 additions & 0 deletions engines/javascriptcore/get-specific-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// <https://apache.org/licenses/LICENSE-2.0>.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

const getSpecificVersion = (version) => {
// If we ever want to add logic that maps a given revision number
// to some other number, it can go here.
return version;
};

module.exports = getSpecificVersion;
9 changes: 4 additions & 5 deletions engines/javascriptcore/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 Google Inc.
// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
Expand All @@ -13,9 +13,8 @@

'use strict';

const updateEngine = require('../../shared/engine.js');

module.exports = updateEngine({
module.exports = {
name: 'JavaScriptCore',
id: 'javascriptcore',
});
alias: 'jsc',
};
2 changes: 1 addition & 1 deletion engines/javascriptcore/predict-url.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017 Google Inc.
// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
Expand Down
Loading

0 comments on commit 853836d

Please sign in to comment.