Giter Site home page Giter Site logo

fiddle-core's Introduction

@electron/fiddle-core

CircleCI NPM

Run fiddles from anywhere, on any Electron release

CLI

# fiddle-core run ver (gist | repo URL | folder)
# fiddle-core test ver (gist | repo URL | folder)
# fiddle-core bisect ver1 ver2 (gist | repo URL | folder)
#
# Examples:

$ fiddle-core run 12.0.0 /path/to/fiddle
$ fiddle-core test 12.0.0 642fa8daaebea6044c9079e3f8a46390
$ fiddle-core bisect 8.0.0 13.0.0 https://github.com/my/testcase.git


$ fiddle-core bisect 8.0.0 13.0.0 642fa8daaebea6044c9079e3f8a46390
...
๐Ÿ finished bisecting across 438 versions...
# 219 ๐ŸŸข passed 11.0.0-nightly.20200611 (test #1)
# 328 ๐ŸŸข passed 12.0.0-beta.12 (test #2)
# 342 ๐ŸŸข passed 12.0.0-beta.29 (test #5)
# 346 ๐ŸŸข passed 12.0.1 (test #7)
# 347 ๐Ÿ”ด failed 12.0.2 (test #9)
# 348 ๐Ÿ”ด failed 12.0.3 (test #8)
# 349 ๐Ÿ”ด failed 12.0.4 (test #6)
# 356 ๐Ÿ”ด failed 12.0.11 (test #4)
# 383 ๐Ÿ”ด failed 13.0.0-nightly.20210108 (test #3)

๐Ÿ Done bisecting
๐ŸŸข passed 12.0.1
๐Ÿ”ด failed 12.0.2
Commits between versions:
โ†” https://github.com/electron/electron/compare/v12.0.1...v12.0.2
Done in 28.19s.

API

Hello, World!

import { Runner } from '@electron/fiddle-core';

const runner = await Runner.create();
const { status } = await runner.run('13.1.7', '/path/to/fiddle');
console.log(status);

Running Fiddles

import { Runner } from '@electron/fiddle-core';

const runner = await Runner.create();

// use a specific Electron version to run code from a local folder
const result = await runner.run('13.1.7', '/path/to/fiddle');

// use a specific Electron version to run code from a github gist
const result = await runner.run('14.0.0-beta.17', '642fa8daaebea6044c9079e3f8a46390');

// use a specific Electron version to run code from a git repo
const result = await runner.run('15.0.0-alpha.1', 'https://github.com/my/repo.git');

// use a specific Electron version to run code from iterable filename/content pairs
const files = new Map<string, string>([['main.js', '"use strict";']]);
const result = await runner.run('15.0.0-alpha.1', files);

// bisect a regression test across a range of Electron versions
const result = await runner.bisect('10.0.0', '13.1.7', path_or_gist_or_git_repo);

// see also `Runner.spawn()` in Advanced Use

Managing Electron Installations

import { Installer, ProgressObject } from '@electron/fiddle-core';

const installer = new Installer();
installer.on('state-changed', ({version, state}) => {
  console.log(`Version "${version}" state changed: "${state}"`);
});

// download a version of electron
await installer.ensureDownloaded('12.0.15');
// expect(installer.state('12.0.5').toBe('downloaded');

// download a version with callback
const callback = (progress: ProgressObject) => {
  const percent = progress.percent * 100;
  console.log(`Current download progress %: ${percent.toFixed(2)}`);
};
await installer.ensureDownloaded('12.0.15', {
  progressCallback: callback,
});

// download a version with a specific mirror
const npmMirrors = {
  electronMirror: 'https://npmmirror.com/mirrors/electron/',
  electronNightlyMirror: 'https://npmmirror.com/mirrors/electron-nightly/',
},

await installer.ensureDownloaded('12.0.15', {
  mirror: npmMirrors,
});

// remove a download
await installer.remove('12.0.15');
// expect(installer.state('12.0.15').toBe('not-downloaded');

// install a specific version for the runner to use
const exec = await installer.install('11.4.10');

// Installing with callback and custom mirrors
await installer.install('11.4.10', {
  progressCallback: callback,
  mirror: npmMirrors,
});
// expect(installer.state('11.4.10').toBe('installed');
// expect(fs.accessSync(exec, fs.constants.X_OK)).toBe(true);

Versions

import { ElectronVersions } from '@electron/fiddle-core';

// - querying specific versions
const elves = await ElectronVersions.create();
// expect(elves.isVersion('12.0.0')).toBe(true);
// expect(elves.isVersion('12.99.99')).toBe(false);
const { versions } = elves;
// expect(versions).find((ver) => ver.version === '12.0.0').not.toBeNull();
// expect(versions[versions.length - 1]).toStrictEqual(elves.latest);

// - supported major versions
const { supportedMajors } = elves;
// expect(supportedMajors.length).toBe(4);

// - querying prerelease branches
const { supportedMajors, prereleaseMajors } = elves;
const newestSupported = Math.max(...supportedMajors);
const oldestPrerelease = Math.min(...prereleaseMajors);
// expect(newestSupported + 1).toBe(oldestPrerelease);

// - get all releases in a range
let range = releases.inRange('12.0.0', '12.0.15');
// expect(range.length).toBe(16);
// expect(range.shift().version).toBe('12.0.0');
// expect(range.pop().version).toBe('12.0.15');

// - get all 10-x-y releases
range = releases.inMajor(10);
// expect(range.length).toBe(101);
// expect(range.shift().version).toBe('10.0.0-nightly.20200209');
// expect(range.pop().version).toBe('10.4.7');

Advanced Use

child_process.Spawn

import { Runner } from '@electron/fiddle-core';

// third argument is same as node.spawn()'s opts
const child = await runner.spawn('12.0.1', fiddle, nodeSpawnOpts);

// see also `Runner.run()` and `Runner.bisect()` above

Using Local Builds

import { Runner } from '@electron/fiddle-core';

const runner = await Runner.create();
const result = await runner.run('/path/to/electron/build', fiddle);

Using Custom Paths

import { Paths, Runner } from '@electron/fiddle-core';

const paths: Paths = {
  // where to store zipfiles of downloaded electron versions
  electronDownloads: '/tmp/my/electron-downloads',

  // where to install an electron version to be used by the Runner
  electronInstall: '/tmp/my/electron-install',

  // where to save temporary copies of fiddles
  fiddles: '/tmp/my/fiddles',

  // where to save releases fetched from online
  versionsCache: '/tmp/my/releases.json',
});

const runner = await Runner.create({ paths });

Manually Creating Fiddle Objects

Runner will do this work for you; but if you want finer-grained control over the lifecycle of your Fiddle objects, you can instantiate them yourself:

import { FiddleFactory } from '@electron/fiddle-core';

const factory = new FiddleFactory();

// load a fiddle from a local directory
const fiddle = await factory.from('/path/to/fiddle'));

// ...or from a gist
const fiddle = await factory.from('642fa8daaebea6044c9079e3f8a46390'));

// ...or from a git repo
const fiddle = await factory.from('https://github.com/my/testcase.git'));

// ...or from an iterable of key / value entries
const fiddle = await factory.from([
  ['main.js', '"use strict";'],
]);

fiddle-core's People

Contributors

akgupta0777 avatar aryanshridhar avatar ckerr avatar codebytere avatar dependabot[bot] avatar dsanders11 avatar electron-roller[bot] avatar erickzhao avatar marshallofsound avatar vertedinde avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fiddle-core's Issues

Run from ASAR Support

In support of electron/fiddle#1551.

Would be nice if we could use @electron/asar to run a fiddle from an ASAR so we can exercise more code branches within Electron.

I think roughly this is what would need to be done in this repo:

  • Extend FiddleFactory constructor to take a new option, e.g. packAsAsar
  • Update FiddleFactory to use @electron/asar to package the fiddle into an ASAR when that option is used
  • Update tests to cover this case

Can't Load Gist

GitHub switched the default branch for gists to main a while ago, but fiddle-core's built in gist loading will try to check out master.

Simple solution would be to use main when cloning the gist, but old gists will still be using master. Most robust solution is probably to port the code in Fiddle's src/renderer/remote-loader.ts and use Octokit to grab the gist instead of just git.

Download Progress Bar Goes Straight to 100%

When displaying download progress, it goes straight to "๐Ÿ downloading 23.0.0-beta.3 - 100%"

Doing some logging, it looks like the progress percentages it receives are 0, 1, 0, and then actual fractional values. When 1 is received it sets progress to 100% and considers it done and doesn't display the real progress updates.

Issue is upstream either in @electron/get or got.

Stale Cache + Fetch Failure = No Versions

In ElectronVersions.create, if the cache is determined to be stale, it doesn't load any versions and tries to fetch fresh. If that fetch fails, like you're offline, then you will end up with no versions, instead of the stale cache.

Stale versions are better than no versions, so refactor this logic and write a test to ensure versions still exist even with a stale cache and offline.

fiddle-core/src/versions.ts

Lines 218 to 243 in 1ee2d27

public static async create(
paths: Partial<Paths> = {},
): Promise<ElectronVersions> {
const d = debug('fiddle-core:ElectronVersions:create');
const { versionsCache } = { ...DefaultPaths, ...paths };
let versions: unknown;
const now = Date.now();
try {
const st = await fs.stat(versionsCache);
if (ElectronVersions.isCacheFresh(st.mtimeMs, now))
versions = (await fs.readJson(versionsCache)) as unknown;
} catch (err) {
d('cache file missing or cannot be read', err);
}
if (!versions) {
try {
versions = await ElectronVersions.fetchVersions(versionsCache);
} catch (err) {
d('error fetching versions', err);
}
}
return new ElectronVersions(versionsCache, now, versions);
}

Add Support For Flipping Fuses

Would be nice if @electron/fiddle-core could flip fuses before running a fiddle. This would help make it easier to create repro cases for issues which involve fuses for use in Fiddle, and would also make it easier for users to play with fuses with a friendly UX in Fiddle.

I think this would dovetail with the suggested solution in #87 of extracting Electron to a temp directory for each run, so that we can flip fuses without causing side effects between runs.

Allow Multiple Installed Versions

Currently fiddle-core continually swaps the installed version (via Installer) into Paths.electronInstall as needed. Fiddle can have multiple windows, each with a different version of Electron selected. These two paradigms are at odds with each other since running two different fiddles with different Electron versions will cause the second run to try to replace the files of the first one.

The current approach has the distinct advantage that there's only ever one installed version extracted on disk, so even if no cleanup is performed, at worse the files for a single version remain extracted. The limitation on multiple installed versions is somewhat problematic, though. A better default behavior may be to use temp directories and have Runner remove them as clean up. This would be a breaking change.

Expose Release Info From Versions

Extend BaseVersions with a getReleaseInfo(version: SemOrStr) method to expose release info from releases.json. BaseVersions.setVersions should handle an array of objects with the full release info, or just the version like it currently does, for convenience.

This would be used by electron/fiddle to get the Node.js version for typings and help close the loop on electron/fiddle#1222. All the info is already in electron/fiddle-core, so let's expose it from the releases cache so we don't have to fetch releases.json separately for that use case.

Example return value:

{
  "version": "24.0.0-nightly.20230203",
  "date": "2023-02-03",
  "node": "18.13.0",
  "v8": "11.1.269-electron.0",
  "uv": "1.44.2",
  "zlib": "1.2.13",
  "openssl": "1.1.1",
  "modules": "114",
  "chrome": "111.0.5560.0",
  "files": [
    "darwin-x64",
    "darwin-x64-symbols",
    "linux-ia32",
    "linux-ia32-symbols",
    "linux-x64",
    "linux-x64-symbols",
    "win32-ia32",
    "win32-ia32-symbols",
    "win32-x64",
    "win32-x64-symbols"
  ]
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.