Skip to content

Commit

Permalink
Fix the crash when hashing an async function (#90)
Browse files Browse the repository at this point in the history
Co-authored-by: Anna Henningsen <anna@addaleax.net>
  • Loading branch information
whatisaphone and addaleax authored Feb 10, 2020
1 parent 9b84910 commit e090f7e
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 6 deletions.
3 changes: 3 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ gulp.task('dist', function(){
.pipe(uglify())
.pipe(gulp.dest('./dist')),
gulp.src([paths.tests])
// Hack: browserify seems to not support async-await.
// It's probably better to replace gulp-browserify altogether instead.
.pipe(replace(/async function/g, 'function'))
.pipe(browserify())
.pipe(rename('object_hash_test.js'))
.pipe(gulp.dest('./dist'))
Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ function typeHasher(options, writeTo, context){
return write(object);
}

if(objType !== 'object' && objType !== 'function') {
if(objType !== 'object' && objType !== 'function' && objType !== 'asyncfunction') {
if(this['_' + objType]) {
this['_' + objType](object);
} else if (options.ignoreUnknown) {
Expand Down
22 changes: 22 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,28 @@ describe('hash', function() {
assert.notEqual(c,d, 'changing a property in the prototype changes the hash');
});

it('distinguishes async functions based on their properties', function() {
var a, b;

var Foo;

try {
Foo = eval('async function Foo() {}; Foo');
} catch (err) {
if (err.name === 'SyntaxError')
return this.skip('Not available on Node 6');
else
throw err;
}

a = hash(Foo);

Foo.foo = 22;
b = hash(Foo);

assert.notEqual(a,b, 'adding a property changes the hash');
});

it('Distinguish objects based on their type', function() {

function Foo() {}
Expand Down
18 changes: 13 additions & 5 deletions test/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@ var validSha1 = /^[0-9a-f]{40}$/i;
describe('hash()ing different types', function() {
it('hashes non-object types', function() {
var func = function(a){ return a + 1; };
var asyncFunc;
try {
asyncFunc = eval('async function(a) { return a + 1; }');
} catch (err) {
if (err.name === 'SyntaxError') asyncFunc = func;
else throw err;
}
assert.ok(validSha1.test(hash('Shazbot!')), 'hash string');
assert.ok(validSha1.test(hash(42)), 'hash number');
assert.ok(validSha1.test(hash(NaN)), 'hash bool');
assert.ok(validSha1.test(hash(true)), 'hash bool');
assert.ok(validSha1.test(hash(func)), 'hash function');
assert.ok(validSha1.test(hash(asyncFunc)), 'hash async function');
});

it('hashes special object types', function() {
Expand All @@ -34,7 +42,7 @@ describe('hash()ing different types', function() {
if (typeof process !== 'undefined') {
assert.ok(validSha1.test(hash(process)), 'hash process');
}

var timer = setTimeout(function() {}, 0);
assert.ok(validSha1.test(hash(timer)), 'hash timer');
});
Expand All @@ -53,7 +61,7 @@ describe('hash()ing different types', function() {

if (typeof Uint8Array !== 'undefined') {
it("Typed arrays can be hashed", function() {

assert.ok(validSha1.test(hash(new Uint8Array([1,2,3,4]))), 'hashes Uint8Array');
assert.ok(validSha1.test(hash(new Int8Array([1,2,3,4]))), 'hashes Int8Array');
assert.ok(validSha1.test(hash(new Uint16Array([1,2,3,4]))), 'hashes Uint16Array');
Expand Down Expand Up @@ -130,7 +138,7 @@ describe('hash()ing different types', function() {
// Self check; did we really hash all the types?
assert.equal(no, types.length);
});

it("Builtin types might result in identical hashes with respectFunctionNames = false", function() {
var hashcount = {};
var types = [Object, Date, Number, String, Function, RegExp,
Expand Down Expand Up @@ -159,14 +167,14 @@ describe('hash()ing different types', function() {
// Self check; did we really hash all the types?
assert.equal(no, types.length);
});

it("Functions with identical bodies and different names result in identical hashes with respectFunctionNames = false", function() {
var fn1 = function a() {};
var fn2 = function b() {};
var toStringDummy = function() { return '...'; };
fn1.toString = toStringDummy;
fn2.toString = toStringDummy;

var h1 = hash(fn1, { respectFunctionNames: false });
var h2 = hash(fn2, { respectFunctionNames: false });
assert.strictEqual(h1, h2);
Expand Down

0 comments on commit e090f7e

Please sign in to comment.