Skip to content

Commit 853836d

Browse files
Enable installing specific engine versions alongside the auto-updated binaries (#60)
Closes #16.
1 parent d58b578 commit 853836d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+427
-170
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,36 @@ jsvu --os=mac64 --engines=chakra,javascriptcore,spidermonkey,v8,xs
111111

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

114+
## Installing specific versions
115+
116+
jsvu also supports installing specific versions alongside the main engine binaries (which it keeps up to date). Here’s an example:
117+
118+
```sh
119+
jsvu v8@7.2.502
120+
```
121+
122+
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.
123+
124+
This feature works for all the supported engines:
125+
126+
```sh
127+
jsvu chakra@1.11.6
128+
jsvu javascriptcore@242640
129+
jsvu spidermonkey@66.0b13
130+
jsvu v8@7.2.502
131+
jsvu v8-debug@v7.1.302
132+
jsvu xs@8.7.0
133+
```
134+
135+
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.
136+
137+
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:
138+
139+
```sh
140+
jsvu v8@7.2
141+
# jsvu figures out that this means v7.2.502, and then installs that version.
142+
```
143+
114144
## Security considerations
115145

116146
_jsvu_ avoids the need for `sudo` privileges by installing everything in `~/.jsvu` rather than, say, `/usr/bin`.

cli.js

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,58 @@ const promptEngines = () => {
117117
// Warn if an update is available.
118118
updateNotifier({ pkg }).notify();
119119

120-
// Read the user configuration, and prompt for any missing info.
120+
// Read the user configuration + CLI arguments, and prompt for any
121+
// missing info.
121122
const status = getStatus();
123+
124+
const args = process.argv.slice(2);
125+
for (const arg of args) {
126+
if (arg.startsWith('--os=')) {
127+
const os = arg.split('=')[1];
128+
status.os = os;
129+
}
130+
else if (arg.startsWith('--engines=')) {
131+
const enginesArg = arg.split('=')[1];
132+
const engines = enginesArg === 'all' ?
133+
['chakra', 'javascriptcore', 'spidermonkey', 'v8', 'xs'] :
134+
enginesArg.split(',');
135+
status.engines = engines;
136+
}
137+
else if (arg.includes('@')) {
138+
const [engine, version] = arg.split('@');
139+
status.engine = engine;
140+
status.version = version;
141+
}
142+
}
143+
122144
if (status.os === undefined) {
123145
status.os = (await promptOs()).step;
124-
setStatus(status);
146+
// Don't store one-off CLI args in the persistent configuration.
147+
const statusCopy = { ...status };
148+
delete statusCopy.engine;
149+
delete statusCopy.version;
150+
setStatus(statusCopy);
125151
} else {
126152
log.success(`Read OS from config: ${status.os}`);
127153
}
154+
155+
// The user provided a specific engine + version, e.g. `jsvu v8@7.2`.
156+
if (status.engine && status.version) {
157+
const { engine, version } = status;
158+
log.success(`Read engine + version from CLI argument: ${engine} v${
159+
version}`);
160+
const installSpecificEngineVersion =
161+
require('./shared/install-specific-version.js');
162+
await installSpecificEngineVersion({
163+
...require(`./engines/${engine}/index.js`),
164+
os: status.os,
165+
version: version,
166+
});
167+
return;
168+
}
169+
170+
// The user wants to install or update engines, but we don’t know
171+
// which ones.
128172
if (status.engines === undefined || status.engines.length === 0) {
129173
status.engines = (await promptEngines()).step;
130174
if (status.engines.length === 0) {
@@ -136,8 +180,9 @@ const promptEngines = () => {
136180
}
137181

138182
// Install the desired JavaScript engines.
183+
const updateEngine = require('./shared/engine.js');
139184
for (const engine of status.engines) {
140-
await require(`./engines/${engine}/index.js`);
185+
await updateEngine(require(`./engines/${engine}/index.js`));
141186
}
142187

143188
})();

engines/chakra/extract.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2017 Google Inc.
1+
// Copyright 2019 Google Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the “License”);
44
// you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ const tar = require('tar');
2020
const { Installer } = require('../../shared/installer.js');
2121
const unzip = require('../../shared/unzip.js');
2222

23-
const extract = ({ filePath, engine, os }) => {
23+
const extract = ({ filePath, binary, alias, os }) => {
2424
return new Promise(async (resolve, reject) => {
2525
const tmpPath = path.dirname(filePath);
2626
if (os.startsWith('win')) {
@@ -39,36 +39,36 @@ const extract = ({ filePath, engine, os }) => {
3939
case 'linux32':
4040
case 'linux64': {
4141
const installer = new Installer({
42-
engine,
42+
engine: binary,
4343
path: `${tmpPath}/ChakraCoreFiles`,
4444
});
4545
installer.installLibraryGlob('lib/*');
46-
installer.installBinary({ 'bin/ch': 'chakra' });
47-
installer.installBinarySymlink({ 'chakra': 'ch' });
48-
installer.installLicense({ 'LICENSE': 'LICENSE-chakra' });
46+
installer.installBinary({ 'bin/ch': binary });
47+
installer.installBinarySymlink({ [binary]: alias });
48+
installer.installLicense({ 'LICENSE': `LICENSE-${binary}` });
4949
break;
5050
}
5151
case 'win32':
5252
case 'win64': {
5353
const installer = new Installer({
54-
engine,
54+
engine: binary,
5555
path: `${tmpPath}/${os === 'win32' ?
5656
'x86_release' : 'x64_release'}`,
5757
});
5858
installer.installLibraryGlob('*.pdb');
5959
installer.installLibraryGlob('*.dll');
6060
installer.installBinary(
61-
{ 'ch.exe': 'chakra.exe' },
61+
{ 'ch.exe': `${binary}.exe` },
6262
{ symlink: false }
6363
);
6464
installer.installScript({
65-
name: 'chakra.cmd',
66-
alias: 'ch.cmd',
65+
name: `${binary}.cmd`,
66+
alias: `${alias}.cmd`,
6767
symlink: false,
6868
generateScript: (targetPath) => {
6969
return `
7070
@echo off
71-
"${targetPath}\\chakra.exe" %*
71+
"${targetPath}\\${binary}.exe" %*
7272
`;
7373
}
7474
});

engines/chakra/get-latest-version.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2017 Google Inc.
1+
// Copyright 2019 Google Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the “License”);
44
// you may not use this file except in compliance with the License.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2019 Google Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the “License”);
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
// <https://apache.org/licenses/LICENSE-2.0>.
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an “AS IS” BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
'use strict';
15+
16+
const getSpecificVersion = (version) => {
17+
// If we ever want to add logic that maps e.g. `'1.11'` to the latest
18+
// available version in that range (e.g. `'1.11.6'`), it can go here.
19+
return version;
20+
};
21+
22+
module.exports = getSpecificVersion;

engines/chakra/index.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2017 Google Inc.
1+
// Copyright 2019 Google Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the “License”);
44
// you may not use this file except in compliance with the License.
@@ -13,9 +13,8 @@
1313

1414
'use strict';
1515

16-
const updateEngine = require('../../shared/engine.js');
17-
18-
module.exports = updateEngine({
16+
module.exports = {
1917
name: 'Chakra',
2018
id: 'chakra',
21-
});
19+
alias: 'ch',
20+
};

engines/chakra/predict-url.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2017 Google Inc.
1+
// Copyright 2019 Google Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the “License”);
44
// you may not use this file except in compliance with the License.

engines/chakra/test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2017 Google Inc.
1+
// Copyright 2019 Google Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the “License”);
44
// you may not use this file except in compliance with the License.
@@ -21,14 +21,14 @@ const tempy = require('tempy');
2121
const config = require('../../shared/config.js');
2222
const jsvuPath = config.path;
2323

24-
const test = async () => {
24+
const test = async ({ binary, alias }) => {
2525
const path = tempy.file();
2626
fs.writeFileSync(path, `print('Hi!');\n`);
2727
console.assert(
28-
(await execa(`${jsvuPath}/chakra`, [path])).stdout === 'Hi!'
28+
(await execa(`${jsvuPath}/${binary}`, [path])).stdout === 'Hi!'
2929
);
3030
console.assert(
31-
(await execa(`${jsvuPath}/ch`, [path])).stdout === 'Hi!'
31+
(await execa(`${jsvuPath}/${alias}`, [path])).stdout === 'Hi!'
3232
);
3333
};
3434

engines/javascriptcore/extract.js

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2017 Google Inc.
1+
// Copyright 2019 Google Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the “License”);
44
// you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ const execa = require('execa');
2020
const { Installer } = require('../../shared/installer.js');
2121
const unzip = require('../../shared/unzip.js');
2222

23-
const extract = ({ filePath, engine, os }) => {
23+
const extract = ({ filePath, binary, alias, os }) => {
2424
return new Promise(async (resolve, reject) => {
2525
const tmpPath = path.dirname(filePath);
2626
await unzip({
@@ -30,18 +30,18 @@ const extract = ({ filePath, engine, os }) => {
3030
switch (os) {
3131
case 'mac64': {
3232
const installer = new Installer({
33-
engine,
33+
engine: binary,
3434
path: `${tmpPath}/Release`,
3535
});
3636
installer.installLibraryGlob('JavaScriptCore.framework/*');
37-
installer.installBinary({ 'jsc': 'javascriptcore' }, { symlink: false });
37+
installer.installBinary({ 'jsc': binary }, { symlink: false });
3838
installer.installScript({
39-
name: 'javascriptcore',
40-
alias: 'jsc',
39+
name: binary,
40+
alias: alias,
4141
generateScript: (targetPath) => {
4242
return `
4343
#!/usr/bin/env bash
44-
DYLD_FRAMEWORK_PATH="${targetPath}" DYLD_LIBRARY_PATH="${targetPath}" "${targetPath}/javascriptcore" "$@"
44+
DYLD_FRAMEWORK_PATH="${targetPath}" DYLD_LIBRARY_PATH="${targetPath}" "${targetPath}/${binary}" "$@"
4545
`;
4646
}
4747
});
@@ -50,19 +50,19 @@ const extract = ({ filePath, engine, os }) => {
5050
case 'linux32':
5151
case 'linux64': {
5252
const installer = new Installer({
53-
engine,
53+
engine: binary,
5454
path: tmpPath,
5555
});
5656
installer.installLibraryGlob('lib/*');
57-
installer.installBinary({ 'bin/jsc': 'javascriptcore' }, { symlink: false });
57+
installer.installBinary({ 'bin/jsc': binary }, { symlink: false });
5858
installer.installScript({
59-
name: 'javascriptcore',
60-
alias: 'jsc',
59+
name: binary,
60+
alias: alias,
6161
generateScript: (targetPath) => {
6262
return `
6363
#!/usr/bin/env bash
6464
LD_LIBRARY_PATH="${targetPath}/lib" exec "${targetPath}/lib/ld-linux${
65-
os === 'linux64' ? '-x86-64' : '' }.so.2" "${targetPath}/javascriptcore" "$@"
65+
os === 'linux64' ? '-x86-64' : '' }.so.2" "${targetPath}/${binary}" "$@"
6666
`;
6767
}
6868
});
@@ -71,7 +71,7 @@ const extract = ({ filePath, engine, os }) => {
7171
case 'win32':
7272
case 'win64': {
7373
const installer = new Installer({
74-
engine,
74+
engine: binary,
7575
path: `${tmpPath}/bin${os === 'win64' ? '64' : '32'}`,
7676
});
7777
installer.installLibraryGlob('JavaScriptCore.resources/*');
@@ -82,8 +82,8 @@ const extract = ({ filePath, engine, os }) => {
8282
// to `javascriptcore.exe` on Windows.
8383
installer.installBinary('jsc.exe', { symlink: false });
8484
installer.installScript({
85-
name: 'javascriptcore.cmd',
86-
alias: 'jsc.cmd',
85+
name: `${binary}.cmd`,
86+
alias: `${alias}.cmd`,
8787
symlink: false,
8888
generateScript: (targetPath) => {
8989
return `

engines/javascriptcore/get-latest-version.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2017 Google Inc.
1+
// Copyright 2019 Google Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the “License”);
44
// you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)