lessons-worker-helper.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Copyright 2019, Gregg Tavares.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above
  12. * copyright notice, this list of conditions and the following disclaimer
  13. * in the documentation and/or other materials provided with the
  14. * distribution.
  15. * * Neither the name of Gregg Tavares. nor the names of his
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. /* global */
  32. 'use strict'; // eslint-disable-line
  33. (function() {
  34. const lessonSettings = self.lessonSettings || {};
  35. function isInEditor() {
  36. return self.location.href.substring(0, 4) === 'blob';
  37. }
  38. function sendMessage(data) {
  39. self.postMessage({
  40. type: '__editor__',
  41. data,
  42. });
  43. }
  44. const origConsole = {};
  45. function setupConsole() {
  46. function wrapFunc(obj, logType) {
  47. const origFunc = obj[logType].bind(obj);
  48. origConsole[logType] = origFunc;
  49. return function(...args) {
  50. origFunc(...args);
  51. sendMessage({
  52. type: 'log',
  53. logType,
  54. msg: [...args].join(' '),
  55. });
  56. };
  57. }
  58. self.console.log = wrapFunc(self.console, 'log');
  59. self.console.warn = wrapFunc(self.console, 'warn');
  60. self.console.error = wrapFunc(self.console, 'error');
  61. }
  62. /**
  63. * Gets a WebGL context.
  64. * makes its backing store the size it is displayed.
  65. * @param {OffscreenCanvas} canvas a canvas element.
  66. * @memberOf module:webgl-utils
  67. */
  68. let setupLesson = function(canvas) {
  69. // only once
  70. setupLesson = function() {};
  71. if (canvas) {
  72. canvas.addEventListener('webglcontextlost', function() {
  73. // the default is to do nothing. Preventing the default
  74. // means allowing context to be restored
  75. // e.preventDefault(); // can't do this because firefox bug - https://bugzilla.mozilla.org/show_bug.cgi?id=1633280
  76. sendMessage({
  77. type: 'lostContext',
  78. });
  79. });
  80. }
  81. };
  82. function captureJSErrors() {
  83. // capture JavaScript Errors
  84. self.addEventListener('error', function(e) {
  85. const msg = e.message || e.error;
  86. const url = e.filename;
  87. const lineNo = e.lineno || 1;
  88. const colNo = e.colno || 1;
  89. sendMessage({
  90. type: 'jsError',
  91. lineNo,
  92. colNo,
  93. url,
  94. msg,
  95. });
  96. });
  97. }
  98. const isWebGLRE = /^(webgl|webgl2|experimental-webgl)$/i;
  99. function installWebGLLessonSetup() {
  100. OffscreenCanvas.prototype.getContext = (function(oldFn) {
  101. return function() {
  102. const type = arguments[0];
  103. const isWebGL = isWebGLRE.test(type);
  104. if (isWebGL) {
  105. setupLesson(this);
  106. }
  107. const args = [].slice.apply(arguments);
  108. args[1] = {
  109. powerPreference: 'low-power',
  110. ...args[1],
  111. };
  112. return oldFn.apply(this, args);
  113. };
  114. }(OffscreenCanvas.prototype.getContext));
  115. }
  116. function installWebGLDebugContextCreator() {
  117. if (!self.webglDebugHelper) {
  118. return;
  119. }
  120. const {
  121. makeDebugContext,
  122. glFunctionArgToString,
  123. glEnumToString,
  124. } = self.webglDebugHelper;
  125. // capture GL errors
  126. OffscreenCanvas.prototype.getContext = (function(oldFn) {
  127. return function() {
  128. let ctx = oldFn.apply(this, arguments);
  129. // Using bindTexture to see if it's WebGL. Could check for instanceof WebGLRenderingContext
  130. // but that might fail if wrapped by debugging extension
  131. if (ctx && ctx.bindTexture) {
  132. ctx = makeDebugContext(ctx, {
  133. maxDrawCalls: 100,
  134. errorFunc: function(err, funcName, args) {
  135. const numArgs = args.length;
  136. const enumedArgs = [].map.call(args, function(arg, ndx) {
  137. let str = glFunctionArgToString(funcName, numArgs, ndx, arg);
  138. // shorten because of long arrays
  139. if (str.length > 200) {
  140. str = str.substring(0, 200) + '...';
  141. }
  142. return str;
  143. });
  144. {
  145. const error = new Error();
  146. sendMessage({
  147. type: 'jsErrorWithStack',
  148. stack: error.stack,
  149. msg: `${glEnumToString(err)} in ${funcName}(${enumedArgs.join(', ')})`,
  150. });
  151. }
  152. },
  153. });
  154. }
  155. return ctx;
  156. };
  157. }(OffscreenCanvas.prototype.getContext));
  158. }
  159. installWebGLLessonSetup();
  160. if (isInEditor()) {
  161. setupConsole();
  162. captureJSErrors();
  163. if (lessonSettings.glDebug !== false) {
  164. installWebGLDebugContextCreator();
  165. }
  166. }
  167. }());