Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better handling of web3 recursive requires #361

Merged
merged 1 commit into from
Sep 11, 2019
Merged
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
20 changes: 20 additions & 0 deletions packages/buidler-core/src/internal/util/lazy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,13 @@ function createLazyProxy<ActualT extends GuardT, GuardT extends object>(

// tslint:disable-next-line
const dummyTarget: ActualT = dummyTargetCreator() as any;
let isBeingCreated = false;

function getRealTarget(): ActualT {
if (realTarget === undefined) {
isBeingCreated = true;
const target = targetCreator();
isBeingCreated = false;

validator(target);

Expand Down Expand Up @@ -110,6 +113,23 @@ function createLazyProxy<ActualT extends GuardT, GuardT extends object>(
},

get(target, property, receiver) {
// We have this short-circuit logic here to avoid a cyclic require when
// loading Web3.js.
//
// If a lazy object is somehow accessed while its real target is being
// created, it would trigger an endless loop of recreation, which node
// detects and resolve to an empty object.
//
// This happens with Web3.js because we a lazyFunction that loads it,
// and expose it as `global.Web3`. This Web3.js file accesses
// `global.Web3` when it's being loaded, triggering the loop we mentioned
// before: https://github.com/ethereum/web3.js/blob/8574bd3bf11a2e9cf4bcf8850cab13e1db56653f/packages/web3-core-requestmanager/src/givenProvider.js#L41
//
// We just return `undefined` in that case, to not enter into the loop.
if (isBeingCreated) {
return undefined;
}

return Reflect.get(getRealTarget(), property, receiver);
},

Expand Down
21 changes: 0 additions & 21 deletions packages/buidler-web3/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,6 @@ ensurePluginLoadedWithUsePlugin();

export default function() {
extendEnvironment(env => {
try {
// We require this file bebause it is required when loading web3,
// and it messes with global.web3.
//
// As we use a lazy object in global.web3, that triggers a full load
// of web3 if someone touches it, and web3 touches it when loading,
// a recrusive load will be started, and node will resolve
// require("web3") to an empty object.
//
// If we load it before assigning the global.web3 object, then it
// will be cached by node and never mess with our lazy object.
//
// tslint:disable-next-line no-implicit-dependencies
require("web3-core-requestmanager/src/givenProvider.js");
} catch (e) {
// This file was removed in beta 38, which doesn't mess
// with global.web3 during module loading anymore.
// We have this empty catch to prevent this plugin from breaking
// if web3 is upadted and this isn't revisited.
}

env.Web3 = lazyFunction(() => require("web3"));
env.web3 = lazyObject(
() => new env.Web3(new Web3HTTPProviderAdapter(env.network.provider))
Expand Down