Skip to content

Commit 1bddf85

Browse files
committed
Return null from loadTexture when image fails to load intead of wrongly creating a VideoTexture
1 parent 4c9b4a4 commit 1bddf85

3 files changed

Lines changed: 51 additions & 18 deletions

File tree

src/systems/material.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,14 @@ export var System = registerSystem('material', {
3030
*
3131
* @param {string|Element} src - URL or element
3232
* @param {object} data - Relevant texture properties
33-
* @param {function} cb - Callback to pass texture to
33+
* @param {function} cb - Callback that receives the texture, or null if loading failed
3434
*/
3535
loadTexture: function (src, data, cb) {
3636
this.loadTextureSource(src, function sourceLoaded (source) {
37+
if (source === null) {
38+
cb(null);
39+
return;
40+
}
3741
var texture = createCompatibleTexture(source);
3842
setTextureProperties(texture, data);
3943
cb(texture);
@@ -44,15 +48,15 @@ export var System = registerSystem('material', {
4448
* Determine whether `src` is an image or video. Then try to load the asset, then call back.
4549
*
4650
* @param {string|Element} src - URL or element.
47-
* @param {function} cb - Callback to pass texture source to.
51+
* @param {function} cb - Callback that receives the texture source, or null if loading failed.
4852
*/
4953
loadTextureSource: function (src, cb) {
5054
var self = this;
5155
var sourceCache = this.sourceCache;
5256

5357
var hash = this.hash(src);
5458
if (sourceCache[hash]) {
55-
sourceCache[hash].then(cb);
59+
sourceCache[hash].then(cb, function () { cb(null); });
5660
return;
5761
}
5862

@@ -64,14 +68,15 @@ export var System = registerSystem('material', {
6468

6569
sourceLoaded(new Promise(doSourceLoad));
6670
function doSourceLoad (resolve, reject) {
67-
utils.srcLoader.validateSrc(src, loadImageCb, loadVideoCb);
71+
utils.srcLoader.validateSrc(src, loadImageCb, loadVideoCb, notFoundCb);
6872
function loadImageCb (src) { self.loadImage(src, resolve); }
6973
function loadVideoCb (src) { self.loadVideo(src, resolve); }
74+
function notFoundCb () { reject(new Error('Resource not found: ' + src)); }
7075
}
7176

7277
function sourceLoaded (sourcePromise) {
7378
sourceCache[hash] = Promise.resolve(sourcePromise);
74-
sourceCache[hash].then(cb);
79+
sourceCache[hash].then(cb, function () { cb(null); });
7580
}
7681
},
7782

@@ -199,8 +204,9 @@ function loadImageUrl (src) {
199204
resolveSource,
200205
function () { /* no-op */ },
201206
function (xhr) {
202-
error('`$s` could not be fetched (Error code: %s; Response: %s)', xhr.status,
207+
error('`%s` could not be fetched (Error code: %s; Response: %s)', src, xhr.status,
203208
xhr.statusText);
209+
reject(new Error('Failed to load image: ' + src));
204210
}
205211
);
206212

src/utils/src-loader.js

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,17 @@ var warn = debug('utils:src-loader:warn');
1313
* @param {string|Element} src - URL or media element.
1414
* @param {function} isImageCb - callback if texture is an image.
1515
* @param {function} isVideoCb - callback if texture is a video.
16+
* @param {function} isNotFoundCb - optional callback if texture is not found.
1617
*/
17-
export function validateSrc (src, isImageCb, isVideoCb) {
18-
checkIsImage(src, function isAnImageUrl (isImage) {
19-
if (isImage) {
18+
export function validateSrc (src, isImageCb, isVideoCb, isNotFoundCb) {
19+
checkIsImage(src, function isAnImageUrl (result) {
20+
if (result === true) {
2021
isImageCb(src);
21-
return;
22+
} else if (result === false) {
23+
isVideoCb(src);
24+
} else if (isNotFoundCb) {
25+
isNotFoundCb(src);
2226
}
23-
isVideoCb(src);
2427
});
2528
}
2629

@@ -120,7 +123,7 @@ export function parseUrl (src) {
120123
* Call back whether `src` is an image.
121124
*
122125
* @param {string|Element} src - URL or element that will be tested.
123-
* @param {function} onResult - Callback with whether `src` is an image.
126+
* @param {function} onResult - Callback with true (image), false (video), or null (not found).
124127
*/
125128
function checkIsImage (src, onResult) {
126129
var request;
@@ -139,18 +142,21 @@ function checkIsImage (src, onResult) {
139142
contentType = request.getResponseHeader('Content-Type');
140143
if (contentType == null) {
141144
checkIsImageFallback(src, onResult);
145+
} else if (contentType.startsWith('image')) {
146+
onResult(true);
142147
} else {
143-
if (contentType.startsWith('image')) {
144-
onResult(true);
145-
} else {
146-
onResult(false);
147-
}
148+
onResult(false);
148149
}
149150
} else {
150-
checkIsImageFallback(src, onResult);
151+
// Non-success status (404, etc.) - resource not found.
152+
onResult(null);
151153
}
152154
request.abort();
153155
});
156+
request.addEventListener('error', function () {
157+
// Network error - resource not found.
158+
onResult(null);
159+
});
154160
request.send();
155161
}
156162

tests/systems/material.test.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { entityFactory } from '../helpers.js';
33

44
var IMAGE1 = 'base/tests/assets/test.png';
55
var IMAGE2 = 'base/tests/assets/test2.png';
6+
var IMAGE_FAIL = 'base/tests/assets/nonexistent.png';
67
var VIDEO1 = 'base/tests/assets/test.mp4';
78
var VIDEO2 = 'base/tests/assets/test2.mp4';
89

@@ -122,6 +123,26 @@ suite('material system', function () {
122123
done();
123124
});
124125
});
126+
127+
test('returns null when image fails to load', function (done) {
128+
var system = this.system;
129+
130+
system.loadTextureSource(IMAGE_FAIL, function (source) {
131+
assert.equal(source, null);
132+
done();
133+
});
134+
});
135+
});
136+
137+
suite('loadTexture', function () {
138+
test('returns null when image fails to load', function (done) {
139+
var system = this.system;
140+
141+
system.loadTexture(IMAGE_FAIL, {}, function (texture) {
142+
assert.equal(texture, null);
143+
done();
144+
});
145+
});
125146
});
126147

127148
suite('loadVideo', function () {

0 commit comments

Comments
 (0)