Skip to content
This repository was archived by the owner on Mar 6, 2023. It is now read-only.

Commit e092746

Browse files
committed
Removed jsonCopy and added deepCopy instead (ethers-io#261).
1 parent 388b658 commit e092746

File tree

5 files changed

+56
-32
lines changed

5 files changed

+56
-32
lines changed

src.ts/contracts/contract.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { getAddress, getContractAddress } from '../utils/address';
77
import { BigNumber, bigNumberify } from '../utils/bignumber';
88
import { hexDataLength, hexDataSlice, isHexString } from '../utils/bytes';
99
import { Zero } from '../utils/constants';
10-
import { defineReadOnly, jsonCopy, shallowCopy } from '../utils/properties';
10+
import { defineReadOnly, deepCopy, shallowCopy } from '../utils/properties';
1111
import { poll } from '../utils/web';
1212

1313
import * as errors from '../utils/errors';
@@ -536,7 +536,7 @@ export class Contract {
536536
let wrappedListener = (log: Log) => {
537537
let decoded = Array.prototype.slice.call(eventFilter.decode(log));
538538

539-
let event = jsonCopy(log);
539+
let event = deepCopy(log);
540540
event.args = decoded;
541541
event.decode = eventFilter.event.decode;
542542
event.event = eventFilter.event.name;

src.ts/contracts/interface.ts

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { BigNumber, bigNumberify } from '../utils/bignumber';
88
import { arrayify, concat, hexlify, hexZeroPad, isHexString } from '../utils/bytes';
99
import { id } from '../utils/hash';
1010
import { keccak256 } from '../utils/keccak256';
11-
import { defineReadOnly, defineFrozen, isType, setType } from '../utils/properties';
11+
import { deepCopy, defineReadOnly, isType, setType } from '../utils/properties';
1212

1313
import * as errors from '../utils/errors';
1414

@@ -83,18 +83,11 @@ class _Indexed implements Indexed {
8383

8484
class Description {
8585
constructor(info: any) {
86+
setType(this, 'Description');
8687
for (var key in info) {
87-
let value = info[key];
88-
if (value != null && typeof(value) === 'object') {
89-
if (BigNumber.isBigNumber(value)) {
90-
defineReadOnly(this, key, value);
91-
} else {
92-
defineFrozen(this, key, value);
93-
}
94-
} else {
95-
defineReadOnly(this, key, value);
96-
}
88+
defineReadOnly(this, key, deepCopy(info[key], true));
9789
}
90+
Object.freeze(this);
9891
}
9992
}
10093

@@ -256,7 +249,7 @@ class _EventDescription extends Description implements EventDescription {
256249
arrayify(data)
257250
);
258251

259-
var result = new Result({});
252+
var result: any = {};
260253
var nonIndexedIndex = 0, indexedIndex = 0;
261254
this.inputs.forEach(function(input, index) {
262255
if (input.indexed) {
@@ -277,7 +270,7 @@ class _EventDescription extends Description implements EventDescription {
277270

278271
result.length = this.inputs.length;
279272

280-
return result;
273+
return new Result(result);
281274
}
282275
}
283276

@@ -416,7 +409,7 @@ export class Interface {
416409
_abi.push(<EventFragment | FunctionFragment>fragment);
417410
});
418411

419-
defineFrozen(this, 'abi', _abi);
412+
defineReadOnly(this, 'abi', deepCopy(_abi, true));
420413

421414
_abi.forEach(addMethod, this);
422415

src.ts/utils/abi-coder.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { BigNumber, bigNumberify } from './bignumber';
77
import { arrayify, concat, hexlify, padZeros } from './bytes';
88
import { NegativeOne, Zero, One, MaxUint256 } from '../utils/constants';
99
import { toUtf8Bytes, toUtf8String } from './utf8';
10-
import { defineReadOnly, jsonCopy } from './properties';
10+
import { deepCopy, defineReadOnly, shallowCopy } from './properties';
1111

1212
import * as errors from './errors';
1313

@@ -986,8 +986,9 @@ function getParamCoder(coerceFunc: CoerceFunc, param: ParamType): Coder {
986986
var match = param.type.match(paramTypeArray);
987987
if (match) {
988988
let size = parseInt(match[2] || "-1");
989-
param = jsonCopy(param);
989+
param = shallowCopy(param);
990990
param.type = match[1];
991+
param = deepCopy(param);
991992
return new CoderArray(coerceFunc, getParamCoder(coerceFunc, param), size, param.name);
992993
}
993994

@@ -1056,7 +1057,7 @@ export class AbiCoder {
10561057
if (typeof(type) === 'string') {
10571058
typeObject = parseParam(type);
10581059
} else {
1059-
typeObject = jsonCopy(type);
1060+
typeObject = deepCopy(type);
10601061
}
10611062

10621063
coders.push(getParamCoder(this.coerceFunc, typeObject));

src.ts/utils/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ import { sha256 } from './sha2';
1212
import { keccak256 as solidityKeccak256, pack as solidityPack, sha256 as soliditySha256 } from './solidity';
1313
import { randomBytes } from './random-bytes';
1414
import { getNetwork } from './networks';
15-
import { defineFrozen, defineReadOnly, resolveProperties, shallowCopy } from './properties';
15+
import { deepCopy, defineReadOnly, resolveProperties, shallowCopy } from './properties';
1616
import * as RLP from './rlp';
1717
import { computePublicKey, verifyMessage } from './secp256k1';
1818
import { parse as parseTransaction, serialize as serializeTransaction } from './transaction';
19-
import { toUtf8Bytes, toUtf8String } from './utf8';
19+
import { formatBytes32String, parseBytes32String, toUtf8Bytes, toUtf8String } from './utf8';
2020
import { formatEther, parseEther, formatUnits, parseUnits } from './units';
2121
import { fetchJson } from './web';
2222

@@ -32,8 +32,8 @@ export {
3232
fetchJson,
3333
getNetwork,
3434

35+
deepCopy,
3536
defineReadOnly,
36-
defineFrozen,
3737
resolveProperties,
3838
shallowCopy,
3939

@@ -56,6 +56,9 @@ export {
5656
toUtf8Bytes,
5757
toUtf8String,
5858

59+
formatBytes32String,
60+
parseBytes32String,
61+
5962
hashMessage,
6063
namehash,
6164
id,

src.ts/utils/properties.ts

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@ export function defineReadOnly(object: any, name: string, value: any): void {
88
});
99
}
1010

11-
export function defineFrozen(object: any, name: string, value: any): void {
12-
var frozen = JSON.stringify(value);
13-
Object.defineProperty(object, name, {
14-
enumerable: true,
15-
get: function() { return JSON.parse(frozen); }
16-
});
17-
}
18-
1911
// There are some issues with instanceof with npm link, so we use this
2012
// to ensure types are what we expect.
2113

@@ -56,8 +48,43 @@ export function shallowCopy(object: any): any {
5648
return result;
5749
}
5850

59-
export function jsonCopy(object: any): any {
60-
return JSON.parse(JSON.stringify(object));
51+
let opaque: { [key: string]: boolean } = { boolean: true, number: true, string: true };
52+
53+
export function deepCopy(object: any, frozen?: boolean): any {
54+
55+
if (object === undefined || object === null || opaque[typeof(object)]) { return object; }
56+
57+
if (Array.isArray(object)) {
58+
let result: Array<any> = [];
59+
object.forEach((item) => {
60+
result.push(deepCopy(item, frozen));
61+
});
62+
63+
if (frozen) { Object.freeze(result); }
64+
65+
return result
66+
}
67+
68+
if (typeof(object) === 'object') {
69+
70+
// Some internal objects, which are already immutable
71+
if (isType(object, 'BigNumber')) { return object; }
72+
if (isType(object, 'Description')) { return object; }
73+
if (isType(object, 'Indexed')) { return object; }
74+
75+
let result: { [ key: string ]: any } = {};
76+
for (var key in object) {
77+
let value = object[key];
78+
if (value === undefined) { continue; }
79+
defineReadOnly(result, key, deepCopy(value, frozen));
80+
}
81+
82+
if (frozen) { Object.freeze(result); }
83+
84+
return result;
85+
}
86+
87+
throw new Error('Cannot deepCopy ' + typeof(object));
6188
}
6289

6390
// See: https://github.com/isaacs/inherits/blob/master/inherits_browser.js

0 commit comments

Comments
 (0)