From d37f9c31c1cc4cac6c19e072098327f97c346407 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 25 Aug 2015 13:17:31 +0200 Subject: [PATCH] Don't unbind onload/onerror callbacks after invoking them From "[WHATWG HTML Living Standard] (https://html.spec.whatwg.org/multipage/indices.html#event-load)", the definition of 'onload': > Fired at the Window when the document has finished loading; fired at an element containing a resource (e.g. img, embed) when its resource has finished loading To adhere to that specification both handlers should be called as many times as Image loads. From Google Chrome's Developer Tools: ```js > function handler(evt) { console.log('img handler: %s', evt.type); } < undefined > var img = document.createElement('img') < undefined > img.onload = handler < handler(evt) > img.onerror = handler < handler(evt) > img.src = 'https://www.google.com/images/errors/logo_sm_2.png'; true < true < img handler: load > img.src = 'https://www.google.com/images/errors/logo_sm_2.png'; true < true < img handler: load > img.src = 'https://example.com/404.png'; true < true < img handler: error > img.src = 'https://example.com/404.png'; true < true < img handler: error ``` --- src/Image.cc | 4 --- test/image.test.js | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index 6410e4e..ec8b7db 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -366,8 +366,6 @@ Image::loaded() { if (onload != NULL) { onload->Call(0, NULL); - delete onload; - onload = NULL; } } @@ -381,8 +379,6 @@ Image::error(Local err) { if (onerror != NULL) { Local argv[1] = { err }; onerror->Call(1, argv); - delete onerror; - onerror = NULL; } } diff --git a/test/image.test.js b/test/image.test.js index 0e27327..7abf896 100644 --- a/test/image.test.js +++ b/test/image.test.js @@ -7,6 +7,7 @@ var Canvas = require('../') , Image = Canvas.Image , assert = require('assert'); +var png_checkers = __dirname + '/fixtures/checkers.png'; var png = __dirname + '/fixtures/clock.png'; module.exports = { @@ -36,6 +37,36 @@ module.exports = { assert.equal(1, n); }, + 'test Image#onload multiple times': function() { + var img = new Image + , n = 0; + + img.onload = function() { + ++n; + }; + + img.src = png_checkers; + assert.equal(img.src, png_checkers); + assert.strictEqual(true, img.complete); + assert.strictEqual(2, img.width); + assert.strictEqual(2, img.height); + + img.src = png; + assert.equal(img.src, png); + assert.strictEqual(true, img.complete); + assert.strictEqual(320, img.width); + assert.strictEqual(320, img.height); + + assert.equal(n, 2); + + n = 0; + img.onload = function() { + ++n; + }; + img.src = png; + assert.equal(n, 1); + }, + 'test Image#onerror': function(){ var img = new Image , error @@ -66,6 +97,36 @@ module.exports = { assert.equal(1, n); }, + 'test Image#onerror multiple calls': function() { + var img = new Image + , n = 0; + + + img.onload = function() { + assert.fail('called onload'); + }; + + img.onerror = function() { + ++n; + }; + + img.src = png + 's1'; + assert.equal(img.src, png + 's1'); + + img.src = png + 's2'; + assert.equal(img.src, png + 's2'); + + assert.equal(n, 2); + + n = 0; + img.onerror = function() { + ++n; + }; + img.src = png + 's3'; + assert.equal(img.src, png + 's3'); + assert.equal(n, 1); + }, + 'test Image#{width,height}': function(){ var img = new Image , n = 0;