diff --git a/.eslintrc.json b/.eslintrc.json index 30de9b2a58a..01e9af6f13c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,7 +9,8 @@ "BUNDLE_CHAIN_FILENAME": "readonly", "BUNDLE_ANALYTICS_FILENAME": "readonly", "BUNDLE_LIBRARY_FILENAME": "readonly", - "BUNDLE_CONSOLE_CHILD_FILENAME": "readonly" + "BUNDLE_CONSOLE_CHILD_FILENAME": "readonly", + "WORKER_CODE_BASE64": "readonly" }, "extends": [ "plugin:react-hooks/recommended" diff --git a/packages/compile-solidity-tests/test/compilerSupplier/index.ts b/packages/compile-solidity-tests/test/compilerSupplier/index.ts index 76d7bb63615..47a7fbbc51f 100644 --- a/packages/compile-solidity-tests/test/compilerSupplier/index.ts +++ b/packages/compile-solidity-tests/test/compilerSupplier/index.ts @@ -64,7 +64,8 @@ let fakeReturn = { describe("CompilerSupplier", () => { beforeEach(function () { supplierOptions = { - events: config.events + events: config.events, + cache: "fileSystem" }; }); diff --git a/packages/compile-solidity-tests/test/compilerSupplier/loadingStrategies/VersionRange.ts b/packages/compile-solidity-tests/test/compilerSupplier/loadingStrategies/VersionRange.ts index d0e9800364c..c7af8b35943 100644 --- a/packages/compile-solidity-tests/test/compilerSupplier/loadingStrategies/VersionRange.ts +++ b/packages/compile-solidity-tests/test/compilerSupplier/loadingStrategies/VersionRange.ts @@ -8,10 +8,11 @@ import Config from "@truffle/config"; const config = Config.default(); let versionRangeOptions = { events: config.events, - solcConfig: config.compilers.solc + solcConfig: config.compilers.solc, + cache: "fileSystem" }; const instance = new LoadingStrategies.VersionRange(versionRangeOptions); -let fileName, expectedResult; +let fileName: string, expectedResult: any; const compilerFileNames = [ "soljson-v0.4.22+commit.124ca40d.js", "soljson-v0.4.23+commit.1534a40d.js", @@ -76,11 +77,13 @@ describe("VersionRange loading strategy", () => { sinon.stub(instance, "getCachedSolcByVersionRange"); sinon.stub(instance, "getSolcFromCacheOrUrl"); sinon.stub(instance, "versionIsCached").returns("compilerFilename.js"); + sinon.stub(instance, "compilerFromString"); }); afterEach(() => { unStub(instance, "getCachedSolcByVersionRange"); unStub(instance, "getSolcFromCacheOrUrl"); unStub(instance, "versionIsCached"); + unStub(instance, "compilerFromString"); }); it("calls getCachedSolcByVersionRange when single solc is specified", async () => { @@ -105,32 +108,32 @@ describe("VersionRange loading strategy", () => { describe("when a version constraint is specified", () => { beforeEach(() => { - sinon.stub(instance, "getAndCacheSolcByUrl"); - sinon.stub(instance.cache, "has").returns(false); + sinon.stub(instance, "getAndCacheSoljsonByUrl"); + sinon.stub(instance.cache!, "has").returns(false); }); afterEach(() => { - unStub(instance, "getAndCacheSolcByUrl"); - unStub(instance.cache, "has"); + unStub(instance, "getAndCacheSoljsonByUrl"); + unStub(instance.cache!, "has"); }); it("calls findNewstValidVersion to determine which version to fetch", async () => { await instance.getSolcFromCacheOrUrl("^0.5.0"); assert.isTrue( // @ts-ignore - instance.getAndCacheSolcByUrl.calledWith( + instance.getAndCacheSoljsonByUrl.calledWith( "soljson-v0.5.4+commit.9549d8ff.js" ), - "getAndCacheSolcByUrl not called with the compiler file name" + "getAndCacheSoljsonByUrl not called with the compiler file name" ); }); }); describe("when the version is cached", () => { beforeEach(() => { - sinon.stub(instance.cache, "has").returns(true); + sinon.stub(instance.cache!, "has").returns(true); }); afterEach(() => { - unStub(instance.cache, "has"); + unStub(instance.cache!, "has"); }); it("calls getCachedSolcByFileName", async () => { @@ -146,27 +149,23 @@ describe("VersionRange loading strategy", () => { describe("when the version is not cached", () => { beforeEach(() => { - sinon.stub(instance.cache, "has").returns(false); - sinon.stub(instance.cache, "add"); - sinon.stub(instance, "compilerFromString").returns("compiler"); + sinon.stub(instance.cache!, "has").returns(false); + sinon.stub(instance, "getAndCacheSoljsonByUrl"); }); afterEach(() => { - unStub(instance.cache, "has"); - unStub(instance.cache, "add"); - unStub(instance, "compilerFromString"); + unStub(instance.cache!, "has"); + unStub(instance, "getAndCacheSoljsonByUrl"); }); - it("eventually calls add and compilerFromString", async () => { + it("eventually calls .getAndCacheSoljsonByUrl", async () => { await instance.getSolcFromCacheOrUrl("0.5.1"); // @ts-ignore - assert.isTrue(instance.cache.add.called); - // @ts-ignore - assert.isTrue(instance.compilerFromString.called); + assert.isTrue(instance.getAndCacheSoljsonByUrl.called); }).timeout(60000); }); }); - describe(".getAndCacheSolcByUrl(fileName)", () => { + describe(".getAndCacheSoljsonByUrl(fileName)", () => { beforeEach(() => { fileName = "someSolcFile"; sinon @@ -175,24 +174,19 @@ describe("VersionRange loading strategy", () => { .returns(Promise.resolve({ data: "requestReturn" })); // @ts-ignore sinon.stub(instance.cache, "add").withArgs("requestReturn"); - sinon - .stub(instance, "compilerFromString") - .withArgs("requestReturn") - .returns("success"); }); afterEach(() => { unStub(axios, "get"); - unStub(instance.cache, "add"); - unStub(instance, "compilerFromString"); + unStub(instance.cache!, "add"); }); it("calls add with the response and the file name", async () => { - const result = await instance.getAndCacheSolcByUrl(fileName, 0); + const result = await instance.getAndCacheSoljsonByUrl(fileName, 0); assert.isTrue( // @ts-ignore instance.cache.add.calledWith("requestReturn", "someSolcFile") ); - assert.equal(result, "success"); + assert.equal(result, "requestReturn"); }); }); @@ -216,10 +210,10 @@ describe("VersionRange loading strategy", () => { describe("versionIsCached(version)", () => { beforeEach(() => { - sinon.stub(instance.cache, "list").returns(compilerFileNames); + sinon.stub(instance.cache!, "list").returns(compilerFileNames); }); afterEach(() => { - unStub(instance.cache, "list"); + unStub(instance.cache!, "list"); }); describe("when a cached version of the compiler is present", () => { @@ -246,11 +240,11 @@ describe("VersionRange loading strategy", () => { describe("getCachedSolcByVersionRange(version)", () => { beforeEach(() => { expectedResult = "soljson-v0.4.23+commit.1534a40d.js"; - sinon.stub(instance.cache, "list").returns(compilerFileNames); + sinon.stub(instance.cache!, "list").returns(compilerFileNames); sinon.stub(instance, "getCachedSolcByFileName"); }); afterEach(() => { - unStub(instance.cache, "list"); + unStub(instance.cache!, "list"); unStub(instance, "getCachedSolcByFileName"); }); diff --git a/packages/compile-solidity/.gitignore b/packages/compile-solidity/.gitignore index acb715d0010..039830bc56a 100644 --- a/packages/compile-solidity/.gitignore +++ b/packages/compile-solidity/.gitignore @@ -1,4 +1,5 @@ dist +src/compileInWebWorker/bundledWorker.js node_modules yarn.lock package-lock.json diff --git a/packages/compile-solidity/package.json b/packages/compile-solidity/package.json index 2c9e22e4e8b..f01e1be9781 100644 --- a/packages/compile-solidity/package.json +++ b/packages/compile-solidity/package.json @@ -46,13 +46,19 @@ "babel-preset-env": "^1.6.1", "chai": "^4.2.0", "glob": "^7.1.6", + "https-browserify": "^1.0.0", "mocha": "10.1.0", + "process": "^0.11.10", "sinon": "^9.0.2", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", "tmp": "^0.2.1", "ts-node": "10.7.0", "ttypescript": "1.5.13", "typescript": "^4.7.4", - "typescript-transform-paths": "3.3.1" + "typescript-transform-paths": "3.3.1", + "webpack": "^5.74.0", + "webpack-cli": "^4.10.0" }, "keywords": [ "compile", diff --git a/packages/compile-solidity/src/compileInWebWorker/index.ts b/packages/compile-solidity/src/compileInWebWorker/index.ts new file mode 100644 index 00000000000..4ec11cc2f71 --- /dev/null +++ b/packages/compile-solidity/src/compileInWebWorker/index.ts @@ -0,0 +1,25 @@ +/* eslint-env browser */ +export async function compileInWebWorker({ + soljson, + compilerInput +}): Promise { + // @ts-ignore + const dataUrl = `data:text/javascript;base64,${WORKER_CODE_BASE64}`; + const worker = new Worker(dataUrl); + return new Promise(resolve => { + worker.addEventListener( + "message", + function (e) { + const output = e.data; + resolve({ + compilerOutput: output, + // TODO: figure out where the version information is + solcVersion: "" + }); + }, + false + ); + + worker.postMessage({ soljson, compilerInput }); + }); +} diff --git a/packages/compile-solidity/src/compileInWebWorker/worker.ts b/packages/compile-solidity/src/compileInWebWorker/worker.ts new file mode 100644 index 00000000000..c570014f50c --- /dev/null +++ b/packages/compile-solidity/src/compileInWebWorker/worker.ts @@ -0,0 +1,13 @@ +/* eslint-env worker */ +import solcWrap from "solc/wrapper"; + +self.addEventListener( + "message", + e => { + const { soljson, compilerInput } = e.data; + const solc = solcWrap(eval(soljson + "; Module;")); + const output = JSON.parse(solc.compile(JSON.stringify(compilerInput))); + self.postMessage(output); + }, + false +); diff --git a/packages/compile-solidity/src/compilerSupplier/index.ts b/packages/compile-solidity/src/compilerSupplier/index.ts index f24f688087a..86228f086af 100644 --- a/packages/compile-solidity/src/compilerSupplier/index.ts +++ b/packages/compile-solidity/src/compilerSupplier/index.ts @@ -1,11 +1,23 @@ +/* eslint-env node, browser */ import path from "path"; import fs from "fs"; import semver from "semver"; import { StrategyOptions } from "./types"; import { Docker, Local, Native, VersionRange } from "./loadingStrategies"; - const defaultSolcVersion = "0.5.16"; +type CompilerSupplierConstructorArgs = { + events?: any; + solcConfig: { + version?: string; + docker?: boolean; + compilerRoots?: string[]; + dockerTagsUrl?: string; + spawn?: any; + }; + cache?: string; +}; + type CompilerSupplierStrategy = | Docker | Native @@ -15,10 +27,10 @@ type CompilerSupplierStrategy = export class CompilerSupplier { private version: string; - private docker: boolean; + private docker?: boolean; private strategyOptions: StrategyOptions; - constructor({ events, solcConfig }) { + constructor({ events, solcConfig, cache }: CompilerSupplierConstructorArgs) { const { version, docker, compilerRoots, dockerTagsUrl, spawn } = solcConfig; this.version = version ? version : defaultSolcVersion; this.docker = docker; @@ -28,17 +40,22 @@ export class CompilerSupplier { if (compilerRoots) this.strategyOptions.compilerRoots = compilerRoots; if (events) this.strategyOptions.events = events; if (spawn) this.strategyOptions.spawn = spawn; + if (cache) this.strategyOptions.cache = cache; } - async load() { + getStrategy() { const userSpecification = this.version; - let strategy: CompilerSupplierStrategy; const useDocker = this.docker; const useNative = userSpecification === "native"; - const useSpecifiedLocal = - userSpecification && - (fs.existsSync(userSpecification) || path.isAbsolute(userSpecification)); + let useSpecifiedLocal: boolean | string | undefined; + // don't attempt file system access in browser environment + if (typeof window === "undefined") { + useSpecifiedLocal = + userSpecification && + (fs.existsSync(userSpecification) || + path.isAbsolute(userSpecification)); + } const isValidVersionRange = semver.validRange(userSpecification); if (useDocker) { @@ -50,7 +67,24 @@ export class CompilerSupplier { } else if (isValidVersionRange) { strategy = new VersionRange(this.strategyOptions); } + return { + strategy, + userSpecification + }; + } + + async loadSoljson() { + const { strategy, userSpecification } = this.getStrategy(); + if (strategy) { + const soljson = await strategy.loadSoljson(userSpecification); + return { soljson }; + } else { + throw new BadInputError(userSpecification); + } + } + async load() { + const { strategy, userSpecification } = this.getStrategy(); if (strategy) { const solc = await strategy.load(userSpecification); return { solc }; diff --git a/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Docker.ts b/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Docker.ts index a7a0b61f05d..80775a6476f 100644 --- a/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Docker.ts +++ b/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Docker.ts @@ -26,6 +26,10 @@ export class Docker { this.cache = new Cache(); } + loadSoljson() { + throw new Error("Method loadSoljson not implemented for Docker strategy."); + } + async load() { // Set a sensible limit for maxBuffer // See https://github.com/nodejs/node/pull/23027 diff --git a/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Local.ts b/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Local.ts index 0de5810510d..7b286a450c2 100644 --- a/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Local.ts +++ b/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Local.ts @@ -4,6 +4,10 @@ import solcWrap from "solc/wrapper"; import { observeListeners } from "../observeListeners"; export class Local { + loadSoljson() { + throw new Error("Method loadSoljson not implemented for Local strategy."); + } + load(localPath: string) { const listeners = observeListeners(); try { diff --git a/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Native.ts b/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Native.ts index a6cc2e9b239..6a632f23bf4 100644 --- a/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Native.ts +++ b/packages/compile-solidity/src/compilerSupplier/loadingStrategies/Native.ts @@ -3,6 +3,10 @@ const { normalizeSolcVersion } = require("../normalizeSolcVersion"); const { NoVersionError } = require("../errors"); export class Native { + loadSoljson() { + throw new Error("Method loadSoljson not implemented for Native strategy."); + } + load() { const versionString = this.validateAndGetSolcVersion(); const command = "solc --standard-json"; diff --git a/packages/compile-solidity/src/compilerSupplier/loadingStrategies/VersionRange.ts b/packages/compile-solidity/src/compilerSupplier/loadingStrategies/VersionRange.ts index ccba5381081..1a35993b928 100644 --- a/packages/compile-solidity/src/compilerSupplier/loadingStrategies/VersionRange.ts +++ b/packages/compile-solidity/src/compilerSupplier/loadingStrategies/VersionRange.ts @@ -2,7 +2,7 @@ import debugModule from "debug"; const debug = debugModule("compile:compilerSupplier"); import requireFromString from "require-from-string"; -import originalRequire from "original-require"; +import fs from "fs"; // must polyfill AbortController to use axios >=0.20.0, <=0.27.2 on node <= v14.x import "../../polyfill"; @@ -24,7 +24,7 @@ type SolidityCompilersList = { export class VersionRange { public config: StrategyOptions; - public cache: Cache; + public cache: Cache | null; constructor(options: StrategyOptions) { const defaultConfig = { @@ -41,25 +41,43 @@ export class VersionRange { }; this.config = Object.assign({}, defaultConfig, options); - this.cache = new Cache(); + switch (options.cache) { + case "fileSystem": + this.cache = new Cache(); + break; + case "noCache": + this.cache = null; + break; + default: + this.cache = new Cache(); + } } - async load(versionRange: string) { + async loadSoljson(versionRange: string) { const rangeIsSingleVersion = semver.valid(versionRange); - if (rangeIsSingleVersion && this.versionIsCached(versionRange)) { + if ( + rangeIsSingleVersion && + this.cache && + this.versionIsCached(versionRange) + ) { return this.getCachedSolcByVersionRange(versionRange); } try { return await this.getSolcFromCacheOrUrl(versionRange); } catch (error) { - if (error.message.includes("Failed to complete request")) { + if (error.message.includes("Failed to complete request") && this.cache) { return this.getSatisfyingVersionFromCache(versionRange); } throw error; } } + async load(versionRange: string) { + const soljson = await this.loadSoljson(versionRange); + return await this.compilerFromString(soljson); + } + async list(index = 0) { if (index >= this.config.compilerRoots!.length) { throw new Error( @@ -96,7 +114,7 @@ export class VersionRange { }; } - compilerFromString(code: string) { + async compilerFromString(code: string) { const listeners = observeListeners(); try { const soljson = requireFromString(code); @@ -117,12 +135,15 @@ export class VersionRange { } getCachedSolcByFileName(fileName: string) { + if (!this.cache) { + this.throwNoCacheError(); + } const listeners = observeListeners(); try { const filePath = this.cache.resolve(fileName); - const soljson = originalRequire(filePath); + const soljson = fs.readFileSync(filePath).toString(); debug("soljson %o", soljson); - return solcWrap(soljson); + return soljson; } finally { listeners.cleanup(); } @@ -130,6 +151,9 @@ export class VersionRange { // Range can also be a single version specification like "0.5.0" getCachedSolcByVersionRange(version: string) { + if (!this.cache) { + this.throwNoCacheError(); + } const cachedCompilerFileNames = this.cache.list(); const validVersions = cachedCompilerFileNames.filter(fileName => { const match = fileName.match(/v\d+\.\d+\.\d+.*/); @@ -144,6 +168,9 @@ export class VersionRange { } getCachedSolcFileName(commit: string) { + if (!this.cache) { + this.throwNoCacheError(); + } const cachedCompilerFileNames = this.cache.list(); return cachedCompilerFileNames.find(fileName => { return fileName.includes(commit); @@ -168,7 +195,7 @@ export class VersionRange { throw new NoVersionError(versionRange); } - async getAndCacheSolcByUrl(fileName: string, index: number) { + async getAndCacheSoljsonByUrl(fileName: string, index: number) { const { events, compilerRoots } = this.config; const url = `${compilerRoots![index].replace(/\/+$/, "")}/${fileName}`; events.emit("downloadCompiler:start", { @@ -182,8 +209,10 @@ export class VersionRange { throw error; } events.emit("downloadCompiler:succeed"); - this.cache.add(response.data, fileName); - return this.compilerFromString(response.data); + if (this.cache) { + this.cache.add(response.data, fileName); + } + return response.data; } async getSolcFromCacheOrUrl(versionConstraint: string, index: number = 0) { @@ -219,11 +248,12 @@ export class VersionRange { ); if (!fileName) throw new NoVersionError(versionToUse); - if (this.cache.has(fileName)) { + if (this.cache?.has(fileName)) { return this.getCachedSolcByFileName(fileName); } - return await this.getAndCacheSolcByUrl(fileName, index); + return await this.getAndCacheSoljsonByUrl(fileName, index); } catch (error) { + debug("there was an error fetching soljson -- %o", error.message); const attemptNumber = index + 1; return await this.getSolcFromCacheOrUrl(versionConstraint, attemptNumber); } @@ -240,6 +270,10 @@ export class VersionRange { const url = `${urlRoot.replace(/\/+$/, "")}/list.json`; try { const response = await axios.get(url, { maxRedirects: 50 }); + debug( + `obtained the following version list from ${url} -- %o`, + response.data + ); return response.data; } catch (error) { events.emit("fetchSolcList:fail"); @@ -268,13 +302,21 @@ export class VersionRange { } const versionToUse = this.findNewestValidVersion(version, allVersions); - - if (versionToUse) return allVersions.releases[versionToUse]; + if (versionToUse) { + debug( + "the solc filename that we will use -- %o", + allVersions.releases[versionToUse] + ); + return allVersions.releases[versionToUse]; + } return null; } versionIsCached(version: string) { + if (!this.cache) { + return false; + } const cachedCompilerFileNames = this.cache.list(); const cachedVersions = cachedCompilerFileNames .map(fileName => { @@ -286,6 +328,13 @@ export class VersionRange { semver.satisfies(cachedVersion, version) ); } + + throwNoCacheError(): never { + throw new Error( + "You are trying to access the cache but your configuration specifies " + + "no cache." + ); + } } export class NoUrlError extends Error { diff --git a/packages/compile-solidity/src/compilerSupplier/types.ts b/packages/compile-solidity/src/compilerSupplier/types.ts index 43aaba32cd7..29e5fc1e23c 100644 --- a/packages/compile-solidity/src/compilerSupplier/types.ts +++ b/packages/compile-solidity/src/compilerSupplier/types.ts @@ -7,4 +7,5 @@ export type StrategyOptions = { spawn?: { maxBuffer: number; }; + cache?: string; }; diff --git a/packages/compile-solidity/src/run.ts b/packages/compile-solidity/src/run.ts index 186db4866c5..0140311af26 100644 --- a/packages/compile-solidity/src/run.ts +++ b/packages/compile-solidity/src/run.ts @@ -1,7 +1,8 @@ +/* eslint-env node, browser */ import { zeroLinkReferences, formatLinkReferences } from "./shims"; import debugModule from "debug"; const debug = debugModule("compile:run"); -import OS = require("os"); +import OS from "os"; import semver from "semver"; import { CompilerSupplier } from "./compilerSupplier"; import * as Common from "@truffle/compile-common"; @@ -22,6 +23,7 @@ import type { Targets } from "./types"; import type Config from "@truffle/config"; +import { compileInWebWorker } from "./compileInWebWorker"; // this function returns a Compilation - legacy/index.js and ./index.js // both check to make sure rawSources exist before calling this method @@ -243,9 +245,22 @@ async function invokeCompiler({ compilerInput, options, solc }): Promise<{ const supplierOptions = { parser: options.parser, events: options.events, - solcConfig: options.compilers.solc + solcConfig: options.compilers.solc, + cache: options.compilers.solc?.cache }; + // in the browser, compile in a worker and return the result + // @ts-ignore + if (typeof window !== "undefined") { + const supplier = new CompilerSupplier(supplierOptions); + const { soljson } = await supplier.loadSoljson(); + debug( + "about to compile in a web worker with the following compilerInput -- %o", + compilerInput + ); + return await compileInWebWorker({ soljson, compilerInput }); + } + if (!solc) { const supplier = new CompilerSupplier(supplierOptions); ({ solc } = await supplier.load()); diff --git a/packages/compile-solidity/tsconfig.json b/packages/compile-solidity/tsconfig.json index bc6572eb3dd..9522b2cbbf8 100644 --- a/packages/compile-solidity/tsconfig.json +++ b/packages/compile-solidity/tsconfig.json @@ -35,6 +35,7 @@ ], "exclude": [ "dist", - "node_modules" + "node_modules", + "src/compileInWebWorker/bundledWorker.js" ] } diff --git a/packages/compile-solidity/webpack.config.js b/packages/compile-solidity/webpack.config.js new file mode 100644 index 00000000000..fb04f8cdca3 --- /dev/null +++ b/packages/compile-solidity/webpack.config.js @@ -0,0 +1,35 @@ +const path = require("path"); +const webpack = require("webpack"); + +module.exports = { + entry: "./src/compileInWebWorker/worker.ts", + mode: "development", + devtool: "inline-source-map", + target: "webworker", + resolve: { + extensions: [".tsx", ".ts", ".js", ".json"], + fallback: { + http: require.resolve("stream-http"), + https: require.resolve("https-browserify"), + stream: require.resolve("stream-browserify") + } + }, + module: { + rules: [ + { + test: /\.tsx?$/, + use: "ts-loader", + exclude: /node_modules/ + } + ] + }, + output: { + filename: "bundledWorker.js", + path: path.resolve(__dirname, "dist", "compileInWebWorker") + }, + plugins: [ + new webpack.ProvidePlugin({ + process: "process/browser" + }) + ] +}; diff --git a/packages/config/src/configDefaults.ts b/packages/config/src/configDefaults.ts index 3c499284824..7dd5a49380c 100644 --- a/packages/config/src/configDefaults.ts +++ b/packages/config/src/configDefaults.ts @@ -62,6 +62,7 @@ export const getInitialConfig = ({ }, compilers: { solc: { + cache: "fileSystem", settings: { //Note: The default solc version is *not* set here! //It's set in compilerSupplier/index.js in compile-solidity diff --git a/packages/fetch-and-compile/.eslintrc.json b/packages/fetch-and-compile/.eslintrc.json index 00ea4852831..177b7d1f506 100644 --- a/packages/fetch-and-compile/.eslintrc.json +++ b/packages/fetch-and-compile/.eslintrc.json @@ -1,3 +1,6 @@ { - "extends": ["../../.eslintrc.package.json"] + "extends": ["../../.eslintrc.package.json"], + "env": { + "browser": "readonly" + } } diff --git a/packages/fetch-and-compile/.gitignore b/packages/fetch-and-compile/.gitignore index 7f7636d880c..fb628978c24 100644 --- a/packages/fetch-and-compile/.gitignore +++ b/packages/fetch-and-compile/.gitignore @@ -1,5 +1,6 @@ node_modules dist +browser-dist .vscode *.abi diff --git a/packages/fetch-and-compile/emptyShim.js b/packages/fetch-and-compile/emptyShim.js new file mode 100644 index 00000000000..f053ebf7976 --- /dev/null +++ b/packages/fetch-and-compile/emptyShim.js @@ -0,0 +1 @@ +module.exports = {}; diff --git a/packages/fetch-and-compile/lib/fetch.ts b/packages/fetch-and-compile/lib/fetch.ts index db508289408..31809162dc6 100644 --- a/packages/fetch-and-compile/lib/fetch.ts +++ b/packages/fetch-and-compile/lib/fetch.ts @@ -134,6 +134,12 @@ async function tryFetchAndCompileAddress( solc: options } }); + + // @ts-ignore + if (typeof window === "undefined") { + externalConfig.compilers.cache = "noCache"; + } + //if using docker, transform it (this does nothing if not using docker) externalConfig = transformIfUsingDocker( externalConfig, diff --git a/packages/fetch-and-compile/lib/index.ts b/packages/fetch-and-compile/lib/index.ts index 71690c7411b..e3b6da8550a 100644 --- a/packages/fetch-and-compile/lib/index.ts +++ b/packages/fetch-and-compile/lib/index.ts @@ -1,6 +1,6 @@ import debugModule from "debug"; const debug = debugModule("fetch-and-compile"); -import type Config from "@truffle/config"; +import Config from "@truffle/config"; import { SingleRecognizer } from "./recognizer"; import { MultipleRecognizer } from "./multiple"; import { DebugRecognizer } from "./debug"; diff --git a/packages/fetch-and-compile/package.json b/packages/fetch-and-compile/package.json index b877210d5b4..f304102644a 100644 --- a/packages/fetch-and-compile/package.json +++ b/packages/fetch-and-compile/package.json @@ -42,10 +42,23 @@ "@types/mocha": "^9.0.0", "@types/node": "~12.12.0", "@types/semver": "^7.3.9", + "assert": "^2.0.0", "chai": "^4.2.0", + "crypto-browserify": "^3.12.0", + "https-browserify": "^1.0.0", "mocha": "9.2.2", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "timers-browserify": "^2.0.12", + "ts-loader": "^9.4.1", "ts-node": "10.7.0", - "typescript": "^4.7.4" + "typescript": "^4.7.4", + "vm-browserify": "^1.1.2", + "webpack": "^5.74.0", + "webpack-cli": "^4.10.0" }, "keywords": [ "compile", diff --git a/packages/fetch-and-compile/webpack.config.js b/packages/fetch-and-compile/webpack.config.js new file mode 100644 index 00000000000..b3ee0827adc --- /dev/null +++ b/packages/fetch-and-compile/webpack.config.js @@ -0,0 +1,63 @@ +const path = require("path"); +const webpack = require("webpack"); +const fs = require("fs"); + +module.exports = { + entry: "./lib/index.ts", + mode: "development", + devtool: "inline-source-map", + module: { + rules: [ + { + test: /\.tsx?$/, + use: "ts-loader", + exclude: /node_modules/ + } + ] + }, + resolve: { + extensions: [".tsx", ".ts", ".js", ".json"], + alias: { + "conf": path.resolve(__dirname, "emptyShim"), + "fs-extra": path.resolve(__dirname, "emptyShim") + }, + fallback: { + crypto: require.resolve("crypto-browserify"), + assert: require.resolve("assert/"), + fs: require.resolve("./emptyShim"), + url: require.resolve("url/"), + http: require.resolve("stream-http"), + https: require.resolve("https-browserify"), + module: require.resolve("./emptyShim"), + constants: require.resolve("./emptyShim"), + child_process: require.resolve("./emptyShim"), + constants: require.resolve("./emptyShim"), + readline: require.resolve("./emptyShim"), + os: require.resolve("os-browserify/browser"), + path: require.resolve("path-browserify"), + stream: require.resolve("stream-browserify"), + timers: require.resolve("timers-browserify"), + vm: require.resolve("vm-browserify") + } + }, + output: { + filename: "bundle.js", + path: path.resolve(__dirname, "browser-dist") + }, + plugins: [ + new webpack.DefinePlugin({ + WORKER_CODE_BASE64: `"${Buffer.from( + fs.readFileSync( + "../compile-solidity/dist/compileInWebWorker/bundledWorker.js", + { encoding: "utf8" } + ) + ).toString("base64")}"` + }), + new webpack.ProvidePlugin({ + process: "process/browser" + }), + new webpack.ProvidePlugin({ + Buffer: ["buffer", "Buffer"] + }) + ] +}; diff --git a/packages/source-fetcher/lib/common.ts b/packages/source-fetcher/lib/common.ts index f1575ff180b..72cbf8fd8cd 100644 --- a/packages/source-fetcher/lib/common.ts +++ b/packages/source-fetcher/lib/common.ts @@ -1,6 +1,4 @@ //these imports aren't actually necessary, but why not :) -import util from "util"; -import { setTimeout } from "timers"; import type * as Types from "./types"; export function makeFilename(name: string, extension: string = ".sol"): string { @@ -14,8 +12,11 @@ export function makeFilename(name: string, extension: string = ".sol"): string { } } -export const makeTimer: (milliseconds: number) => Promise = - util.promisify(setTimeout); +export const makeTimer = (milliseconds: number): Promise => { + return new Promise(resolve => { + setTimeout(() => resolve(), milliseconds); + }); +}; export function removeLibraries( settings: Types.SolcSettings, diff --git a/yarn.lock b/yarn.lock index 68c48cd1b51..6a3070a7c6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22879,7 +22879,7 @@ setimmediate@1.0.4: resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= -setimmediate@^1.0.5: +setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= @@ -24145,6 +24145,13 @@ timed-out@^4.0.0, timed-out@^4.0.1: resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= +timers-browserify@^2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== + dependencies: + setimmediate "^1.0.4" + timers-ext@^0.1.5: version "0.1.7" resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" @@ -25582,9 +25589,9 @@ webpack@^5.73.0: webpack-sources "^3.2.3" webpack@^5.74.0: - version "5.74.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980" - integrity sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA== + version "5.75.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" + integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51"