Skip to content

Commit

Permalink
Improved error messages and fixed asset loading in tests
Browse files Browse the repository at this point in the history
  • Loading branch information
robertlong committed Feb 15, 2020
1 parent 3ed1d7c commit 051aa71
Show file tree
Hide file tree
Showing 41 changed files with 802 additions and 652 deletions.
3 changes: 3 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ jobs:
rm google-chrome.deb
echo 'export CHROME_PATH=/opt/google/chrome/google-chrome' >> $BASH_ENV
source $BASH_ENV
- run:
name: Add hubs.local to /etc/hosts
command: echo "127.0.0.1 hubs.local" >> /etc/hosts
- run: yarn
- run: yarn test
- persist_to_workspace:
Expand Down
2 changes: 1 addition & 1 deletion .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ RETICULUM_SERVER="dev.reticulum.io"
FARSPARK_SERVER="farspark-dev.reticulum.io"
NON_CORS_PROXY_DOMAINS="hubs.local,localhost"
CORS_PROXY_SERVER="hubs-proxy.com"
HOST_PORT="9091"
HOST_PORT="9090"
IS_MOZ="false"
25 changes: 12 additions & 13 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,21 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach",
"port": 9229
},
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/bin/spoke",
"env": {
"NODE_ENV": "development"
},
"args": [
"${workspaceFolder}/example"
"name": "Debug AVA test file (Start test-server first)",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/ava",
"runtimeArgs": [
"debug",
"--break",
"--serial",
"${file}"
],
"port": 9229,
"outputCapture": "std",
"skipFiles": [
"<node_internals>/**/*.js"
]
}
]
Expand Down
18 changes: 10 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,29 @@
"lint:css": "stylelint './src/**/*.js'",
"pretest": "yarn lint",
"test": "concurrently --success \"first\" --kill-others \"yarn test-all\" \"yarn test-server\"",
"test-server": "cross-env NODE_ENV=test webpack-dev-server --mode development --port 9091 --content-base ./test/fixtures",
"test-all": "ava",
"test-server": "cross-env NODE_ENV=test webpack-dev-server --mode development --content-base ./test/fixtures",
"test-all": "ava --verbose",
"unit-tests": "ava ./test/unit/**/*.test.js",
"integration-tests": "concurrently --success \"first\" --kill-others \"ava ./test/integration\" \"yarn test-server\"",
"update-test-snapshots": "concurrently --success \"first\" --kill-others \"ava -u\" \"yarn test-server\"",
"storybook": "start-storybook",
"deploy-storybook": "storybook-to-ghpages"
},
"esm": {
"mode": "auto",
"cjs": true
},
"ava": {
"files": [
"./test/unit/**/*.test.js",
"./test/integration/**/*.test.js"
],
"sources": [
"src/**/*.js"
],
"require": [
"@babel/register",
"esm",
"@babel/register",
"./test/entry.js"
]
],
"timeout": "60s"
},
"lint-staged": {
"*.js": [
Expand Down Expand Up @@ -121,7 +123,7 @@
"@storybook/source-loader": "^5.2.0",
"@storybook/storybook-deployer": "^2.8.1",
"@storybook/theming": "^5.2.0",
"ava": "2.3.0",
"ava": "^3.3.0",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.0",
"babel-plugin-styled-components": "^1.10.6",
Expand Down
72 changes: 46 additions & 26 deletions src/api/Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import ProgressDialog from "../ui/dialogs/ProgressDialog";
import jwtDecode from "jwt-decode";
import { buildAbsoluteURL } from "url-toolkit";
import PublishedSceneDialog from "./PublishedSceneDialog";
import { RethrownError } from "../editor/utils/errors";

// Media related functions should be kept up to date with Hubs media-utils:
// https://github.com/mozilla/hubs/blob/master/src/utils/media-utils.js
Expand Down Expand Up @@ -239,12 +240,12 @@ export default class Project extends EventEmitter {
});

if (!response.ok) {
const message = `Error resolving url "${url}":`;
const message = `Error resolving url "${url}":\n `;
try {
const body = await response.text();
throw new Error(message + " " + body);
throw new Error(message + body.replace(/\n/g, "\n "));
} catch (e) {
throw new Error(message + " " + response.statusText);
throw new Error(message + response.statusText.replace(/\n/g, "\n "));
}
}

Expand Down Expand Up @@ -276,22 +277,32 @@ export default class Project extends EventEmitter {
return { accessibleUrl: absoluteUrl };
}

const result = await this.resolveUrl(absoluteUrl);
const canonicalUrl = result.origin;
const accessibleUrl = proxiedUrlFor(canonicalUrl, index);
let contentType, canonicalUrl, accessibleUrl;

const contentType =
(result.meta && result.meta.expected_content_type) ||
guessContentType(canonicalUrl) ||
(await this.fetchContentType(accessibleUrl));
try {
const result = await this.resolveUrl(absoluteUrl);
canonicalUrl = result.origin;
accessibleUrl = proxiedUrlFor(canonicalUrl, index);

contentType =
(result.meta && result.meta.expected_content_type) ||
guessContentType(canonicalUrl) ||
(await this.fetchContentType(accessibleUrl));
} catch (error) {
throw new RethrownError(`Error resolving media "${absoluteUrl}"`, error);
}

if (contentType === "model/gltf+zip") {
// TODO: Sketchfab object urls should be revoked after they are loaded by the glTF loader.
const { getFilesFromSketchfabZip } = await import(
/* webpackChunkName: "SketchfabZipLoader", webpackPrefetch: true */ "./SketchfabZipLoader"
);
const files = await getFilesFromSketchfabZip(accessibleUrl);
return { canonicalUrl, accessibleUrl: files["scene.gtlf"], contentType, files };
try {
if (contentType === "model/gltf+zip") {
// TODO: Sketchfab object urls should be revoked after they are loaded by the glTF loader.
const { getFilesFromSketchfabZip } = await import(
/* webpackChunkName: "SketchfabZipLoader", webpackPrefetch: true */ "./SketchfabZipLoader"
);
const files = await getFilesFromSketchfabZip(accessibleUrl);
return { canonicalUrl, accessibleUrl: files["scene.gtlf"], contentType, files };
}
} catch (error) {
throw new RethrownError(`Error loading Sketchfab model "${accessibleUrl}"`, error);
}

return { canonicalUrl, accessibleUrl, contentType };
Expand Down Expand Up @@ -934,11 +945,11 @@ export default class Project extends EventEmitter {
}
});

request.addEventListener("error", e => {
request.addEventListener("error", error => {
if (signal) {
signal.removeEventListener("abort", onAbort);
}
reject(new Error(`Upload failed ${e}`));
reject(new RethrownError("Upload failed", error));
});

request.addEventListener("load", () => {
Expand Down Expand Up @@ -1128,14 +1139,23 @@ export default class Project extends EventEmitter {
}

async fetch(url, options) {
const res = await fetch(url, options);
try {
const res = await fetch(url, options);

if (res.ok) {
return res;
}
if (res.ok) {
return res;
}

const err = new Error("Network Error: " + res.statusText);
err.response = res;
throw err;
const err = new Error(
`Network Error: ${res.status || "Unknown Status."} ${res.statusText || "Unknown Error. Possibly a CORS error."}`
);
err.response = res;
throw err;
} catch (error) {
if (error.message === "Failed to fetch") {
error.message += " (Possibly a CORS error)";
}
throw new RethrownError(`Failed to fetch "${url}"`, error);
}
}
}
14 changes: 9 additions & 5 deletions src/editor/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import TextureCache from "./caches/TextureCache";
import getDetachedObjectsRoots from "./utils/getDetachedObjectsRoots";
import { loadEnvironmentMap } from "./utils/EnvironmentMap";
import makeUniqueName from "./utils/makeUniqueName";
import eventToMessage from "./utils/eventToMessage";
import { RethrownError, MultiError } from "./utils/errors";
import cloneObject3D from "./utils/cloneObject3D";
import isEmptyObject from "./utils/isEmptyObject";
import getIntersectingNode from "./utils/getIntersectingNode";
Expand Down Expand Up @@ -179,7 +179,7 @@ export default class Editor extends EventEmitter {

async installAssetSource(manifestUrl) {
const proxiedUrl = this.api.proxyUrl(new URL(manifestUrl, window.location).href);
const res = await fetch(proxiedUrl);
const res = await this.api.fetch(proxiedUrl);
const json = await res.json();
this.sources.push(new AssetManifestSource(this, json.name, manifestUrl));
this.emit("settingsChanged");
Expand Down Expand Up @@ -284,7 +284,7 @@ export default class Editor extends EventEmitter {
this.sceneLoading = true;
this.disableUpdate = true;

const scene = await SceneNode.loadProject(this, projectFile);
const [scene, errors] = await SceneNode.loadProject(this, projectFile);

this.sceneLoading = false;
this.disableUpdate = false;
Expand Down Expand Up @@ -313,6 +313,10 @@ export default class Editor extends EventEmitter {
}
});

if (errors.length > 0) {
this.emit("error", new MultiError("Errors loading project", errors));
}

this.emit("projectLoaded");
this.emit("sceneGraphChanged");

Expand Down Expand Up @@ -393,7 +397,7 @@ export default class Editor extends EventEmitter {
try {
chunks = await exporter.exportChunks(clonedScene);
} catch (error) {
throw new Error(`Error exporting scene. ${eventToMessage(error)}`);
throw new RethrownError(`Error exporting scene`, error);
}

const json = chunks.json;
Expand Down Expand Up @@ -481,7 +485,7 @@ export default class Editor extends EventEmitter {
const glbBlob = await exporter.exportGLBBlob(chunks);
return glbBlob;
} catch (error) {
throw new Error(`Error creating glb blob. ${eventToMessage(error)}`);
throw new RethrownError("Error creating glb blob", error);
}
}

Expand Down
11 changes: 2 additions & 9 deletions src/editor/caches/TextureCache.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TextureLoader } from "three";
import Cache from "./Cache";
import eventToMessage from "../utils/eventToMessage";
import loadTexture from "../utils/loadTexture";

export default class TextureCache extends Cache {
constructor() {
Expand All @@ -11,14 +11,7 @@ export default class TextureCache extends Cache {
get(url) {
const absoluteURL = new URL(url, window.location).href;
if (!this._cache.has(absoluteURL)) {
this._cache.set(
absoluteURL,
new Promise((resolve, reject) => {
this.textureLoader.load(absoluteURL, resolve, null, e => {
reject(new Error(`Error loading texture with url: ${absoluteURL}. ${eventToMessage(e)}`));
});
})
);
this._cache.set(absoluteURL, loadTexture(absoluteURL, this.textureLoader));
}
return this._cache.get(absoluteURL);
}
Expand Down
33 changes: 22 additions & 11 deletions src/editor/gltf/GLTFLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
* @author Don McCurdy / https://www.donmccurdy.com
*/

import { RethrownError } from "../utils/errors";
import loadTexture from "../utils/loadTexture";

import {
AnimationClip,
Bone,
Expand Down Expand Up @@ -344,7 +347,11 @@ class GLTFLoader {
let glbBuffer, json;

try {
const data = await new Promise((resolve, reject) => fileLoader.load(this.url, resolve, undefined, reject));
const data = await new Promise((resolve, reject) =>
fileLoader.load(this.url, resolve, undefined, event => {
reject(event);
})
);

let content;

Expand Down Expand Up @@ -419,7 +426,7 @@ class GLTFLoader {
} catch (error) {
this.manager.itemError(this.url);
this.manager.itemEnd(this.url);
throw error;
throw new RethrownError(`Error loading glTF root`, error);
}

return { json, glbBuffer };
Expand Down Expand Up @@ -566,12 +573,16 @@ class GLTFLoader {
}

async loadGLTF() {
const { json } = await this.getDependency("root");
const sceneIndex = json.scene || 0;
const scene = await this.getDependency("scene", sceneIndex);
const sceneAnimations = await this.getDependency("sceneAnimations", sceneIndex);
scene.animations = sceneAnimations || [];
return { scene, json };
try {
const { json } = await this.getDependency("root");
const sceneIndex = json.scene || 0;
const scene = await this.getDependency("scene", sceneIndex);
const sceneAnimations = await this.getDependency("sceneAnimations", sceneIndex);
scene.animations = sceneAnimations || [];
return { scene, json };
} catch (error) {
throw new RethrownError(`Error loading glTF "${this.url}"`, error);
}
}

/**
Expand Down Expand Up @@ -1595,9 +1606,9 @@ class GLTFLoader {
loader = textureLoader;
}

const texture = await new Promise((resolve, reject) => {
loader.load(this.resolveURL(sourceURI, options.path), resolve, undefined, reject);
});
const textureUrl = this.resolveURL(sourceURI, options.path);

const texture = await loadTexture(textureUrl, this.textureLoader);

// Clean up resources and configure Texture.

Expand Down
Loading

0 comments on commit 051aa71

Please sign in to comment.