Skip to content

Commit

Permalink
implement setImmediate and remove its polyfill
Browse files Browse the repository at this point in the history
  • Loading branch information
Muhammad-Altabba committed Nov 27, 2023
1 parent db22dbd commit 2b915f9
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 9 deletions.
1 change: 0 additions & 1 deletion packages/web3-eth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
"web3-providers-http": "^4.1.0"
},
"dependencies": {
"setimmediate": "^1.0.5",
"web3-core": "^4.3.0",
"web3-errors": "^1.1.3",
"web3-eth-abi": "^4.1.4",
Expand Down
5 changes: 0 additions & 5 deletions packages/web3-eth/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,6 @@ along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*
* With `web3-eth` you can also subscribe (if supported by provider) to events in the Ethereum Blockchain, using the `subscribe` function. See more at the {@link Web3Eth.subscribe} function.
*/
/**
*
*/
import 'setimmediate';

import { Web3Eth } from './web3_eth.js';

export * from './web3_eth.js';
Expand Down
2 changes: 1 addition & 1 deletion packages/web3-eth/src/rpc_method_wrappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import {
Eip712TypedData,
} from 'web3-types';
import { Web3Context, Web3PromiEvent } from 'web3-core';
import { format, hexToBytes, bytesToUint8Array, numberToHex } from 'web3-utils';
import { format, hexToBytes, bytesToUint8Array, numberToHex, setImmediate } from 'web3-utils';
import { TransactionFactory } from 'web3-eth-accounts';
import { isBlockTag, isBytes, isNullish, isString } from 'web3-validator';
import { SignatureError } from 'web3-errors';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/
import { Bytes, Numbers, BlockHeaderOutput, TransactionReceipt } from 'web3-types';
import { format } from 'web3-utils';
import { format, setImmediate } from 'web3-utils';

import { DataFormat } from 'web3-types';
import { NewHeadsSubscription } from '../web3_subscriptions.js';
Expand Down
2 changes: 1 addition & 1 deletion packages/web3-eth/src/web3_eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {
} from 'web3-types';
import { isSupportedProvider, Web3Context, Web3ContextInitOptions } from 'web3-core';
import { TransactionNotFound } from 'web3-errors';
import { toChecksumAddress, isNullish } from 'web3-utils';
import { toChecksumAddress, isNullish, setImmediate } from 'web3-utils';
import { ethRpcMethods } from 'web3-rpc-methods';

import * as rpcMethodsWrappers from './rpc_method_wrappers.js';
Expand Down
1 change: 1 addition & 0 deletions packages/web3-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ export * from './web3_deferred_promise.js';
export * from './chunk_response_parser.js';
export * from './uuid.js';
export * from './web3_eip1193_provider.js';
export { setImmediate, clearImmediate } from './setImmediate.js';

Check warning on line 33 in packages/web3-utils/src/index.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/index.ts#L33

Added line #L33 was not covered by tests
export * from './socket_provider.js';
export * from './uint8array.js';
216 changes: 216 additions & 0 deletions packages/web3-utils/src/setImmediate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/* eslint-disable */

/*
This file is part of web3.js.
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Copyright (c) 2023 Web3
Copyright (c) 2012-2016 Barnesandnoble.com, llc, Donavon West, and Domenic Denicola
*/

interface Task {
callback: Function;
args: any[];
}

interface TasksByHandle {
[handle: number]: Task;
}

const tasksByHandle: TasksByHandle = {};
let registerImmediate: (handle: number) => void;
let nextHandle = 1; // Spec says greater than zero

interface SelfGlobalThis {
setImmediate: (callback: Function, ...args: any[]) => number;
clearImmediate: (handle: number) => void;
}

const selfGlobalThis: any =
typeof self === 'undefined' ? (typeof global === 'undefined' ? this : global) : self;

export const setImmediate =
(selfGlobalThis as SelfGlobalThis)?.setImmediate ||
function (callback: Function, ...args: any[]): number {

Check warning on line 49 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L49

Added line #L49 was not covered by tests
// Callback can either be a function or a string
if (typeof callback !== 'function') {
callback = new Function(`${callback}`);

Check warning on line 52 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L51-L52

Added lines #L51 - L52 were not covered by tests
}
// Store and register the task
const task: Task = { callback, args };
tasksByHandle[nextHandle] = task;
registerImmediate(nextHandle);
return nextHandle++;

Check warning on line 58 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L55-L58

Added lines #L55 - L58 were not covered by tests
};

export const clearImmediate =
(selfGlobalThis as SelfGlobalThis)?.clearImmediate ||
function (handle: number): void {
if (selfGlobalThis.clearImmediate) {
return selfGlobalThis.clearImmediate(handle);

Check warning on line 65 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L63-L65

Added lines #L63 - L65 were not covered by tests
}
delete tasksByHandle[handle];

Check warning on line 67 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L67

Added line #L67 was not covered by tests
};

(function (global: any) {
if (global.setImmediate) {
return;
}

let currentlyRunningATask = false;
const doc: Document = global.document;

Check warning on line 76 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L75-L76

Added lines #L75 - L76 were not covered by tests

function run(task: Task): void {
const { callback } = task;
const { args } = task;
switch (args.length) {
case 0:
callback();
break;
case 1:
callback(args[0]);
break;
case 2:
callback(args[0], args[1]);
break;
case 3:
callback(args[0], args[1], args[2]);
break;
default:
callback.apply(undefined, args);
break;

Check warning on line 96 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L78-L96

Added lines #L78 - L96 were not covered by tests
}
}

function runIfPresent(handle: number): void {

Check warning on line 100 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L100

Added line #L100 was not covered by tests
// From the spec: "Wait until any invocations of this algorithm started before this one have completed."
// So if we're currently running a task, we'll need to delay this invocation.
if (currentlyRunningATask) {

Check warning on line 103 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L103

Added line #L103 was not covered by tests
// Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
// "too much recursion" error.
setTimeout(runIfPresent, 0, handle);
} else {
const task: Task = tasksByHandle[handle];
if (task) {
currentlyRunningATask = true;
try {
run(task);

Check warning on line 112 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L106-L112

Added lines #L106 - L112 were not covered by tests
} finally {
clearImmediate(handle);
currentlyRunningATask = false;

Check warning on line 115 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L114-L115

Added lines #L114 - L115 were not covered by tests
}
}
}
}

function canUsePostMessage(): boolean | void {

Check warning on line 121 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L121

Added line #L121 was not covered by tests
// The test against `importScripts` prevents this implementation from being installed inside a web worker,
// where `global.postMessage` means something completely different and can't be used for this purpose.
if (global.postMessage && !global.importScripts) {
let postMessageIsAsynchronous = true;
const oldOnMessage: Function = global.onmessage;
global.onmessage = function (): void {
postMessageIsAsynchronous = false;

Check warning on line 128 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L124-L128

Added lines #L124 - L128 were not covered by tests
};
global.postMessage('', '*');
global.onmessage = oldOnMessage;
return postMessageIsAsynchronous;

Check warning on line 132 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L130-L132

Added lines #L130 - L132 were not covered by tests
}
}

function installPostMessageImplementation(): void {

Check warning on line 136 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L136

Added line #L136 was not covered by tests
// Installs an event handler on `global` for the `message` event: see
// * https://developer.mozilla.org/en/DOM/window.postMessage
// * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages

const messagePrefix = `setImmediate$${Math.random()}$`;
const onGlobalMessage: (event: MessageEvent) => void = function (
event: MessageEvent,

Check warning on line 143 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L141-L143

Added lines #L141 - L143 were not covered by tests
): void {
if (
event.source === global &&
typeof event.data === 'string' &&
event.data.startsWith(messagePrefix)

Check warning on line 148 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L145-L148

Added lines #L145 - L148 were not covered by tests
) {
runIfPresent(+event.data.slice(messagePrefix.length));

Check warning on line 150 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L150

Added line #L150 was not covered by tests
}
};

if (global.addEventListener) {
global.addEventListener('message', onGlobalMessage, false);
} else {
global.attachEvent('onmessage', onGlobalMessage);

Check warning on line 157 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L154-L157

Added lines #L154 - L157 were not covered by tests
}

registerImmediate = function (handle: number): void {
global.postMessage(messagePrefix + handle, '*');

Check warning on line 161 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L160-L161

Added lines #L160 - L161 were not covered by tests
};
}

function installMessageChannelImplementation(): void {
const channel: MessageChannel = new MessageChannel();
channel.port1.onmessage = function (event: MessageEvent): void {
const handle: number = event.data;
runIfPresent(handle);

Check warning on line 169 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L165-L169

Added lines #L165 - L169 were not covered by tests
};

registerImmediate = function (handle: number): void {
channel.port2.postMessage(handle);

Check warning on line 173 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L172-L173

Added lines #L172 - L173 were not covered by tests
};
}

function installReadyStateChangeImplementation(): void {
const html: HTMLElement = doc.documentElement;
registerImmediate = function (handle: number): void {

Check warning on line 179 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L177-L179

Added lines #L177 - L179 were not covered by tests
// Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
// into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
let script: HTMLScriptElement | null = doc.createElement('script');
(script as any).onreadystatechange = function (): void {
runIfPresent(handle);
(script as any).onreadystatechange = null;
html.removeChild(script as HTMLScriptElement);
script = null;

Check warning on line 187 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L182-L187

Added lines #L182 - L187 were not covered by tests
};
html.appendChild(script);

Check warning on line 189 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L189

Added line #L189 was not covered by tests
};
}

function installSetTimeoutImplementation(): void {
registerImmediate = function (handle: number): void {
setTimeout(runIfPresent, 0, handle);

Check warning on line 195 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L193-L195

Added lines #L193 - L195 were not covered by tests
};
}

// If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
let attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
attachTo = attachTo && attachTo.setTimeout ? attachTo : global;

Check warning on line 201 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L200-L201

Added lines #L200 - L201 were not covered by tests

if (canUsePostMessage()) {

Check warning on line 203 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L203

Added line #L203 was not covered by tests
// For non-IE10 modern browsers
installPostMessageImplementation();
} else if (global.MessageChannel) {

Check warning on line 206 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L205-L206

Added lines #L205 - L206 were not covered by tests
// For web workers, where supported
installMessageChannelImplementation();
} else if (doc && 'onreadystatechange' in doc.createElement('script')) {

Check warning on line 209 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L208-L209

Added lines #L208 - L209 were not covered by tests
// For IE 6–8
installReadyStateChangeImplementation();
} else {

Check warning on line 212 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L211-L212

Added lines #L211 - L212 were not covered by tests
// For older browsers
installSetTimeoutImplementation();

Check warning on line 214 in packages/web3-utils/src/setImmediate.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-utils/src/setImmediate.ts#L214

Added line #L214 was not covered by tests
}
})(selfGlobalThis);
1 change: 1 addition & 0 deletions packages/web3-utils/src/socket_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
RequestAlreadySentError,
Web3WSProviderError,
} from 'web3-errors';
import { setImmediate } from './setImmediate.js';
import { Eip1193Provider } from './web3_eip1193_provider.js';
import { ChunkResponseParser } from './chunk_response_parser.js';
import { isNullish } from './validation.js';
Expand Down

0 comments on commit 2b915f9

Please sign in to comment.