diff --git a/.github/workflows/browsersupport.yml b/.github/workflows/browsersupport.yml new file mode 100644 index 00000000..61bfec19 --- /dev/null +++ b/.github/workflows/browsersupport.yml @@ -0,0 +1,35 @@ +name: Browser Support Tests +env: + BS_USERNAME: ${{ secrets.BS_USERNAME }} + BS_PASSWORD: ${{ secrets.BS_PASSWORD }} +on: + pull_request: + branches: [ main ] + push: + branches: [ main ] +jobs: + build: + runs-on: [ubuntu-latest] + + strategy: + matrix: + node-version: [14.x] + + steps: + - uses: actions/checkout@v2 + with: + submodules: true + fetch-depth: 100 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + registry-url: 'https://registry.npmjs.org' + - uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - run: npm ci + - run: npm run browserstack \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index f1317e6b..15e8707a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed +- Fixed Safari 13.1 crash when booting Excalibur because of they odd MediaQuery API in older Safari +- Fixed issue where pointers did not work because of missing types - Fixed issue with `ArcadeSolver` where stacked/overlapped tiles would double solve the position of the collider for the same overlap - Fixed issue where changing the `ex.Sprite.width` or `ex.Sprite.height` did not resize the graphic. - Fixed issue where initial Actor anchors set in the constructor were not being set in the graphics component diff --git a/karma.conf.browsers.js b/karma.conf.browsers.js new file mode 100644 index 00000000..8c2bcdcf --- /dev/null +++ b/karma.conf.browsers.js @@ -0,0 +1,201 @@ +// Karma configuration +const process = require('process'); +const path = require('path'); +const webpack = require('webpack'); +process.env.CHROME_BIN = require('puppeteer').executablePath(); + +module.exports = (config) => { + config.set({ + // global config of your BrowserStack account + browserStack: { + project: 'Excalibur', + username: process.env.BS_USERNAME, + accessKey: process.env.BS_PASSWORD + }, + singleRun: true, + frameworks: ['jasmine'], + client: { + // Excalibur logs / console logs suppressed when captureConsole = false; + captureConsole: false, + jasmine: { + timeoutInterval: 30000 + } + }, + proxies: { + // smooths over loading files because karma prepends '/base/' to everything + '/src/' : '/base/src/' + }, + files: [ + 'src/browsersupport/BrowserSupportSpec.ts', + ], + mime: { 'text/x-typescript': ['ts', 'tsx'] }, + preprocessors: { + './src/browsersupport/BrowserSupportSpec.ts': ['webpack'] + }, + webpack: { + mode: 'none', + devtool: 'source-map', + resolve: { + extensions: ['.ts', '.js'], + alias: { + "@excalibur": path.resolve(__dirname, './src/engine/') + } + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env.__EX_VERSION': '\'test-runner\'' + }), + ], + module: { + rules: [ + { + test: /\.ts$/, + loader: 'ts-loader', + options: { + projectReferences: true, + configFile: 'tsconfig.json' + } + }, + { + test: /\.css$/, + use: ['css-loader'] + }, + { + test: /\.(png|jpg|gif|mp3)$/i, + use: [ + { + loader: 'url-loader', + options: { + limit: 8192 + } + } + ] + }, + { + test: /\.glsl$/, + use: ['raw-loader'] + }, + { + test: /\.ts$/, + enforce: 'post', + include: path.resolve('src/engine/'), + use: { + loader: 'istanbul-instrumenter-loader', + options: { esModules: true } + } + } + ] + } + }, + webpackMiddleware: { + // webpack-dev-middleware configuration + // i. e. + stats: 'normal' + }, + reporters: ['progress', 'summary'], + summaryReporter: { + // 'failed', 'skipped' or 'all' + show: 'all', + // Limit the spec label to this length + specLength: 50, + // Show an 'all' column as a summary + overviewColumn: true, + // Show a list of test clients, 'always', 'never' or 'ifneeded' + browserList: 'always' + }, + browserNoActivityTimeout: 60000, // appveyor is slow :( + // define browsers + customLaunchers: { + bs_latest_chrome_win10: { + base: 'BrowserStack', + browser: 'Chrome', + browser_version: 'latest', + os: 'Windows', + os_version: '10' + }, + bs_latest_minus_1_chrome_win10: { + base: 'BrowserStack', + browser: 'Chrome', + browser_version: 'latest-1', + os: 'Windows', + os_version: '10' + }, + bs_latest_firefox_win10: { + base: 'BrowserStack', + browser: 'Firefox', + browser_version: 'latest', + os: 'Windows', + os_version: '10' + }, + bs_latest_minus_1_firefox_win10: { + base: 'BrowserStack', + browser: 'Firefox', + browser_version: 'latest-1', + os: 'Windows', + os_version: '10' + }, + bs_latest_opera_win10: { + base: 'BrowserStack', + browser: 'Opera', + browser_version: 'latest', + os: 'Windows', + os_version: '10' + }, + bs_latest_minus_1_opera_win10: { + base: 'BrowserStack', + browser: 'Opera', + browser_version: 'latest-1', + os: 'Windows', + os_version: '10' + }, + bs_safari_14_1: { + base: 'BrowserStack', + browser: 'safari', + browser_version: '14.1', + os: 'OS X', + os_version: 'Big Sur' + }, + bs_safari_13_1: { + base: 'BrowserStack', + browser: 'safari', + browser_version: '13.1', + os: 'OS X', + os_version: 'Catalina' + }, + bs_safari_12_1: { + base: 'BrowserStack', + browser: 'safari', + browser_version: '12.1', + os: 'OS X', + os_version: 'Mojave' + }, + }, + + browsers: [ + 'bs_latest_chrome_win10', + 'bs_latest_minus_1_chrome_win10', + 'bs_latest_firefox_win10', + 'bs_latest_minus_1_firefox_win10', + 'bs_latest_opera_win10', + 'bs_latest_minus_1_opera_win10', + 'bs_safari_14_1', + 'bs_safari_13_1', + 'bs_safari_12_1' + ] + // browsers: ['ChromeHeadless_with_audio'], + // customLaunchers: { + // ChromeHeadless_with_audio: { + // base: 'ChromeHeadless', + // flags: ['--autoplay-policy=no-user-gesture-required', '--mute-audio'] + // }, + // ChromeHeadless_with_debug: { + // base: 'ChromeHeadless', + // flags: ['--remote-debugging-port=9334', '--no-sandbox', '--disable-web-security'] + // }, + // Chrome_with_debug: { + // base: 'Chrome', + // flags: ['--remote-debugging-port=9334', '--no-sandbox'] + // } + // } + }); +}; diff --git a/package-lock.json b/package-lock.json index c1ef4a3a..cfcfb6b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9711,7 +9711,7 @@ }, "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, @@ -9796,7 +9796,7 @@ "dependencies": { "jsesc": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true }, @@ -10657,6 +10657,96 @@ } } }, + "browserstack": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.3.tgz", + "integrity": "sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + }, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "browserstack-local": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.8.tgz", + "integrity": "sha512-s+mc3gTOJwELdLWi4qFVKtGwMbb5JWsR+JxKlMaJkRJxoZ0gg3WREgPxAN0bm6iU5+S4Bi0sz0oxBRZT8BiNsQ==", + "dev": true, + "requires": { + "https-proxy-agent": "^4.0.0", + "is-running": "^2.1.0", + "ps-tree": "=1.2.0", + "temp-fs": "^0.9.9" + }, + "dependencies": { + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "dev": true + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "dev": true, + "requires": { + "agent-base": "5", + "debug": "4" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", @@ -12993,6 +13083,21 @@ "integrity": "sha512-n0XTVMGps+Deyr38jtqKPR5F5hb9owYeRQcKJW39eFvzUk/u/9Ww315werRzbiNMnHCUw/YHDPBphTlEnzdi+A==", "dev": true }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, "es6-shim": { "version": "0.35.6", "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.6.tgz", @@ -13526,6 +13631,21 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, "eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -14394,6 +14514,12 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -15597,7 +15723,7 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { @@ -15707,7 +15833,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { @@ -15898,6 +16024,12 @@ "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", "dev": true }, + "is-running": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-running/-/is-running-2.1.0.tgz", + "integrity": "sha1-MKc/9cw4VOT8JUkICen1q/jeCeA=", + "dev": true + }, "is-set": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", @@ -16087,7 +16219,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -16542,7 +16674,7 @@ }, "json5": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, @@ -16644,6 +16776,17 @@ } } }, + "karma-browserstack-launcher": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.6.0.tgz", + "integrity": "sha512-Y/UWPdHZkHIVH2To4GWHCTzmrsB6H7PBWy6pw+TWz5sr4HW2mcE+Uj6qWgoVNxvQU1Pfn5LQQzI6EQ65p8QbiQ==", + "dev": true, + "requires": { + "browserstack": "~1.5.1", + "browserstack-local": "^1.3.7", + "q": "~1.5.0" + } + }, "karma-chrome-launcher": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", @@ -16755,6 +16898,66 @@ "jasmine-core": "^3.6.0" } }, + "karma-summary-reporter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/karma-summary-reporter/-/karma-summary-reporter-3.0.0.tgz", + "integrity": "sha512-E8O18XzS1UZ+j5fd/MPKFhg+IvzxenHudfAXocrz3zVS/yfVmurHZvmCI/hHeNo4q6ItIA3yAUThh1ZIM7AkKw==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "karma-webpack": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-5.0.0.tgz", @@ -17071,6 +17274,12 @@ "integrity": "sha1-beJlMXSt+12e3DPGnT6Sobdvrwg=", "dev": true }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -17165,7 +17374,7 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, @@ -18232,7 +18441,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, @@ -18266,6 +18475,15 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "~2.3" + } + }, "pbkdf2": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", @@ -18698,6 +18916,15 @@ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, + "ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "dev": true, + "requires": { + "event-stream": "=3.3.4" + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -18829,6 +19056,12 @@ } } }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, "qjobs": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", @@ -19412,7 +19645,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -20039,7 +20272,7 @@ }, "resolve": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true }, @@ -20146,7 +20379,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -21157,6 +21390,15 @@ "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", "dev": true }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2" + } + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -21266,6 +21508,15 @@ "readable-stream": "^2.0.2" } }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "~0.1.1" + } + }, "stream-each": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", @@ -21400,7 +21651,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { @@ -21409,7 +21660,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { @@ -21418,7 +21669,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, @@ -21714,6 +21965,26 @@ "memoizerific": "^1.11.3" } }, + "temp-fs": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/temp-fs/-/temp-fs-0.9.9.tgz", + "integrity": "sha1-gHFzBDeHByDpQxUy/igUNk+IA9c=", + "dev": true, + "requires": { + "rimraf": "~2.5.2" + }, + "dependencies": { + "rimraf": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + } + } + }, "term-size": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", diff --git a/package.json b/package.json index da71e03b..b43ad8f9 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "clean": "rimraf .tsbuildinfo ./build/dist ./build ./src/spec/*.js ./src/spec/*.map", "linux:ci": "npm run clean && npm run all && npm run coveralls && npm run apidocs", "appveyor": "npm run all && npm run nuget 0.0.1", + "browserstack": "karma start karma.conf.browsers.js", "nuget": ".\\src\\tools\\NuGet.exe pack Excalibur.nuspec -OutputDirectory .\\build\\dist -version", "start": "npm run core:watch", "build": "npm run core", @@ -87,15 +88,17 @@ "jasmine": "3.9.0", "jasmine-core": "3.9.0", "karma": "6.3.7", + "karma-browserstack-launcher": "1.6.0", "karma-chrome-launcher": "3.1.0", "karma-coverage": "2.0.3", "karma-coverage-istanbul-reporter": "3.0.3", "karma-jasmine": "4.0.1", + "karma-summary-reporter": "3.0.0", "karma-webpack": "5.0.0", "puppeteer": "10.4.0", - "replace-in-file": "6.3.2", "react": "17.0.2", "react-dom": "17.0.2", + "replace-in-file": "6.3.2", "rimraf": "3.0.2", "semver": "7.3.5", "serve": "12.0.1", diff --git a/sandbox/tests/pointer/index.html b/sandbox/tests/pointer/index.html index a74f438d..a9bc93d8 100644 --- a/sandbox/tests/pointer/index.html +++ b/sandbox/tests/pointer/index.html @@ -9,6 +9,6 @@

Click on the squares to see events propagate in z order in the console. The black square cancels the event preventing propagation.

- + \ No newline at end of file diff --git a/sandbox/tests/screen/index.html b/sandbox/tests/screen/index.html index 32e4f555..de2c86fb 100644 --- a/sandbox/tests/screen/index.html +++ b/sandbox/tests/screen/index.html @@ -33,6 +33,6 @@ - + \ No newline at end of file diff --git a/src/browsersupport/BrowserSupportSpec.ts b/src/browsersupport/BrowserSupportSpec.ts new file mode 100644 index 00000000..eff7ab2a --- /dev/null +++ b/src/browsersupport/BrowserSupportSpec.ts @@ -0,0 +1,43 @@ +import * as ex from '@excalibur'; + +describe('Browser integration test', () => { + it('should boot on browser', (done) => { + const boot = () => { + const game = new ex.Engine({ + width: 800, + height: 800 + }); + game.start().then(() => { + done() + }); + } + + expect(boot).not.toThrow(); + }); + + it('should allow pointers', (done) => { + const downSpy = jasmine.createSpy("down"); + class Game2 extends ex.Engine { + initialize() { + const player1 = new ex.Actor({x: 0, y: 0, width: 100, height: 100, color: ex.Color.Red}); + this.add(player1); + player1.z = 10; + player1.on("pointerdown", downSpy); + + return this.start(); + } + } + + const pointer = () => { + var game2 = new Game2({width: 600, height: 400}); + + game2.initialize().then(() => { + game2.input.pointers.triggerEvent("down", ex.vec(0, 0)); + expect(downSpy).toHaveBeenCalledTimes(1); + done(); + }); + } + + expect(pointer).not.toThrow(); + }); +}); \ No newline at end of file diff --git a/src/browsersupport/tsconfig.json b/src/browsersupport/tsconfig.json new file mode 100644 index 00000000..38c81e00 --- /dev/null +++ b/src/browsersupport/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "types": ["@types/jasmine", "@types/webpack-env"], + "moduleResolution": "node", + "sourceMap": true, + "experimentalDecorators": true, + "target": "es2015", + "module": "es2015", + "noImplicitAny": false, + "noUnusedLocals": false, + "downlevelIteration": true, + "lib": [ + "dom", + "es5", + "es2015.collection", + "es2015.iterable", + "es2015.promise", + "es2015.proxy", + "es2018.promise", + "es2016", + "es2017.object" + ], + "baseUrl": ".", + "rootDir": "../", + "paths": { + "@excalibur": ["../engine/"] + } + }, + "include": ["./**/*Spec.ts"], + "files": ["../engine/files.d.ts", "../engine/globals.d.ts"] +} diff --git a/src/engine/Input/PointerEventReceiver.ts b/src/engine/Input/PointerEventReceiver.ts index e14ea562..3cd5e4d3 100644 --- a/src/engine/Input/PointerEventReceiver.ts +++ b/src/engine/Input/PointerEventReceiver.ts @@ -19,6 +19,16 @@ export type NativeMouseEvent = globalThis.MouseEvent; export type NativeTouchEvent = globalThis.TouchEvent; export type NativeWheelEvent = globalThis.WheelEvent; +function isTouchEvent(value: any): value is NativeTouchEvent { + // Gaurd for Safari <= 13.1 + return globalThis.TouchEvent && value instanceof globalThis.TouchEvent; +} + +function isPointerEvent(value: any): value is NativePointerEvent { + // Gaurd for Safari <= 13.1 + return globalThis.PointerEvent && value instanceof globalThis.PointerEvent; +} + /** * The PointerEventProcessor is responsible for collecting all the events from the canvas and transforming them into GlobalCoordinates */ @@ -296,7 +306,7 @@ export class PointerEventReceiver extends Class { const eventCoords = new Map(); let button: PointerButton; let pointerType: PointerType; - if (ev instanceof TouchEvent) { + if (isTouchEvent(ev)) { button = PointerButton.Unknown; pointerType = PointerType.Touch; // https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent @@ -313,7 +323,7 @@ export class PointerEventReceiver extends Class { pointerType = PointerType.Mouse; const coordinates = GlobalCoordinates.fromPagePosition(ev.pageX, ev.pageY, this.engine); let nativePointerId = 1; - if (ev instanceof window.PointerEvent) { + if (isPointerEvent(ev)) { nativePointerId = ev.pointerId; pointerType = this._stringToPointerType(ev.pointerType); } @@ -396,11 +406,19 @@ export class PointerEventReceiver extends Class { public triggerEvent(type: 'down' | 'up' | 'move' | 'cancel', pos: Vector) { const page = this.engine.screen.worldToPageCoordinates(pos); // Send an event to the event receiver - this._handle(new window.PointerEvent('pointer' + type, { - pointerId: 0, - clientX: page.x, - clientY: page.y - })); + if (window.PointerEvent) { + this._handle(new window.PointerEvent('pointer' + type, { + pointerId: 0, + clientX: page.x, + clientY: page.y + })); + } else { + // Safari hack + this._handle(new window.MouseEvent('mouse' + type, { + clientX: page.x, + clientY: page.y + })); + } // Force update pointer system const pointerSystem = this.engine.currentScene.world.systemManager.get(PointerSystem); diff --git a/src/engine/Screen.ts b/src/engine/Screen.ts index d5ae83a9..190e430b 100644 --- a/src/engine/Screen.ts +++ b/src/engine/Screen.ts @@ -214,7 +214,13 @@ export class Screen { this._applyDisplayMode(); this._mediaQueryList = this._browser.window.nativeComponent.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`); - this._mediaQueryList.addEventListener('change', this._pixelRatioChangeHandler); + + // Safari <=13.1 workaround + if (this._mediaQueryList.addEventListener) { + this._mediaQueryList.addEventListener('change', this._pixelRatioChangeHandler); + } else { + this._mediaQueryList.addListener(this._pixelRatioChangeHandler); + } this._canvas.addEventListener('fullscreenchange', this._fullscreenChangeHandler); this.applyResolutionAndViewport(); @@ -229,7 +235,12 @@ export class Screen { this._resizeObserver.disconnect(); } this.parent.removeEventListener('resize', this._resizeHandler); - this._mediaQueryList.removeEventListener('change', this._pixelRatioChangeHandler); + // Safari <=13.1 workaround + if (this._mediaQueryList.removeEventListener) { + this._mediaQueryList.removeEventListener('change', this._pixelRatioChangeHandler); + } else { + this._mediaQueryList.removeListener(this._pixelRatioChangeHandler); + } this._canvas.removeEventListener('fullscreenchange', this._fullscreenChangeHandler); } }