├── .babelrc ├── .gitignore ├── README.md ├── build └── webpack.config.js ├── package.json ├── src ├── Audio.js ├── Canvas.js ├── Element.js ├── Event.js ├── EventIniter │ ├── TouchEvent.js │ └── index.js ├── EventTarget.js ├── FileReader.js ├── HTMLAudioElement.js ├── HTMLElement.js ├── HTMLMediaElement.js ├── Image.js ├── Node.js ├── URL.js ├── WebSocket.js ├── WindowProperties.js ├── XMLHttpRequest.js ├── constructor.js ├── document.js ├── index.js ├── localStorage.js ├── location.js ├── navigator.js ├── performance.js ├── util │ └── index.js └── window.js ├── test ├── EventTarget.test.js ├── HTMLElement.test.js ├── WebSocket.test.js ├── XMLHttpRequest.test.js ├── contructor.test.js ├── document.test.js ├── localStorage.test.js ├── mock │ ├── Audio_mock.js │ ├── Canvas_mock.js │ ├── Image_mock.js │ └── wx_mock.js ├── test.test.js ├── vm.js └── window.test.js └── weapp-phaser3-adapter.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *swo 2 | *swp 3 | npm-debug.log 4 | node_modules 5 | dist 6 | .idea 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 微信小游戏 phaser3 适配解决方案 2 | 3 | 注意:当前在真机环境未测试通过 4 | 5 | ## 使用方法 6 | 7 | 将文件`weapp-phaser3-adapter.js`拷贝至微信小程序目录,并在入口引用即可。 8 | 9 | ```javascript 10 | import './js/libs/weapp-phaser3-adapter' 11 | ``` 12 | 13 | ## 游戏配置 14 | 15 | 在初始化`phaser3`实例时,配置建议加上: 16 | 17 | ```javascript 18 | let config = {}; // your config 19 | 20 | if (window.canvas) { 21 | config.canvas = window.canvas; 22 | } 23 | ``` 24 | 25 | ## 资源的加载 26 | 27 | 在微信端使用时,注意文件的加载。如果资源在远端,则按如下方式指定远端地址: 28 | 29 | ```javascript 30 | this.load.setBaseURL("http://your.domain.name"); 31 | ``` 32 | 33 | @[taliove](http://www.taliove.com) 2018 34 | -------------------------------------------------------------------------------- /build/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | entry: path.join(__dirname, '../src/index'), 5 | output: { 6 | path: path.join(__dirname, '../dist'), 7 | filename: 'weapp-phaser3-adapter.js', 8 | }, 9 | module: { 10 | loaders: [ 11 | { 12 | test: /\.js$/, 13 | exclude: /node_modules/, 14 | loaders: [ 15 | 'babel', 16 | // 'eslint-loader' 17 | ] 18 | } 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weapp-phaser3-adapter", 3 | "version": "0.0.1", 4 | "description": "Phaser3 Adapter for WeChat Mini Program", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "dev": "webpack --config build/webpack.config.js --watch", 11 | "build": "webpack --hide-modules --config build/webpack.config.js", 12 | "test": "jest" 13 | }, 14 | "author": "linkqjlin", 15 | "license": "MIT", 16 | "devDependencies": { 17 | "babel-core": "^6.13.2", 18 | "babel-eslint": "^6.1.2", 19 | "babel-loader": "^6.2.4", 20 | "babel-preset-es2015": "^6.13.2", 21 | "babel-preset-stage-0": "^6.5.0", 22 | "eslint": "^3.4.0", 23 | "eslint-friendly-formatter": "^2.0.6", 24 | "eslint-loader": "^1.5.0", 25 | "eslint-plugin-jest": "^20.0.3", 26 | "eventemitter2": "^4.1.2", 27 | "jest": "^20.0.4", 28 | "path": "^0.12.7", 29 | "webpack": "^1.13.1", 30 | "webpack-dev-server": "^1.15.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Audio.js: -------------------------------------------------------------------------------- 1 | import HTMLAudioElement from './HTMLAudioElement' 2 | 3 | const HAVE_NOTHING = 0 4 | const HAVE_METADATA = 1 5 | const HAVE_CURRENT_DATA = 2 6 | const HAVE_FUTURE_DATA = 3 7 | const HAVE_ENOUGH_DATA = 4 8 | 9 | const _innerAudioContext = new WeakMap() 10 | const _src = new WeakMap() 11 | const _loop = new WeakMap() 12 | const _autoplay = new WeakMap() 13 | export default class Audio extends HTMLAudioElement { 14 | HAVE_NOTHING = HAVE_NOTHING 15 | HAVE_METADATA = HAVE_METADATA 16 | HAVE_CURRENT_DATA = HAVE_CURRENT_DATA 17 | HAVE_FUTURE_DATA = HAVE_FUTURE_DATA 18 | HAVE_ENOUGH_DATA = HAVE_ENOUGH_DATA 19 | readyState = HAVE_NOTHING 20 | 21 | constructor(url) { 22 | super() 23 | 24 | _src.set(this, '') 25 | // 针对phaser3加入 26 | this.dataset = {}; 27 | const innerAudioContext = wx.createInnerAudioContext() 28 | 29 | _innerAudioContext.set(this, innerAudioContext) 30 | 31 | innerAudioContext.onCanplay(() => { 32 | this.dispatchEvent({type: 'load'}) 33 | this.dispatchEvent({type: 'loadend'}) 34 | this.dispatchEvent({type: 'canplay'}) 35 | this.dispatchEvent({type: 'canplaythrough'}) 36 | this.dispatchEvent({type: 'loadedmetadata'}) 37 | this.readyState = HAVE_CURRENT_DATA 38 | }) 39 | innerAudioContext.onPlay(() => { 40 | this.dispatchEvent({type: 'play'}) 41 | }) 42 | innerAudioContext.onPause(() => { 43 | this.dispatchEvent({type: 'pause'}) 44 | }) 45 | innerAudioContext.onEnded(() => { 46 | this.dispatchEvent({type: 'ended'}) 47 | this.readyState = HAVE_ENOUGH_DATA 48 | }) 49 | innerAudioContext.onError(() => { 50 | this.dispatchEvent({type: 'error'}) 51 | }) 52 | 53 | if (url) { 54 | _innerAudioContext.get(this).src = url 55 | } 56 | } 57 | 58 | load() { 59 | console.warn('HTMLAudioElement.load() is not implemented.') 60 | } 61 | 62 | play() { 63 | _innerAudioContext.get(this).play() 64 | } 65 | 66 | pause() { 67 | _innerAudioContext.get(this).pause() 68 | } 69 | 70 | canPlayType(mediaType = '') { 71 | if (typeof mediaType !== 'string') { 72 | return '' 73 | } 74 | 75 | if (mediaType.indexOf('audio/mpeg') > -1 || mediaType.indexOf('audio/mp4')) { 76 | return 'probably' 77 | } 78 | return '' 79 | } 80 | 81 | get currentTime() { 82 | return _innerAudioContext.get(this).currentTime 83 | } 84 | 85 | set currentTime(value) { 86 | _innerAudioContext.get(this).seek(value) 87 | } 88 | 89 | get src() { 90 | return _src.get(this) 91 | } 92 | 93 | set src(value) { 94 | _src.set(this, value) 95 | _innerAudioContext.get(this).src = value 96 | } 97 | 98 | get loop() { 99 | return _innerAudioContext.get(this).loop 100 | } 101 | 102 | set loop(value) { 103 | _innerAudioContext.get(this).loop = value 104 | } 105 | 106 | get autoplay() { 107 | return _innerAudioContext.get(this).autoplay 108 | } 109 | 110 | set autoplay(value) { 111 | _innerAudioContext.get(this).autoplay = value 112 | } 113 | 114 | get paused() { 115 | return _innerAudioContext.get(this).paused 116 | } 117 | 118 | cloneNode() { 119 | const newAudio = new Audio() 120 | newAudio.loop = _innerAudioContext.get(this).loop 121 | newAudio.autoplay = _innerAudioContext.get(this).autoplay 122 | newAudio.src = this.src 123 | return newAudio 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/Canvas.js: -------------------------------------------------------------------------------- 1 | import { HTMLCanvasElement, CanvasRenderingContext2D, WebGLRenderingContext } from './constructor' 2 | import HTMLElement from './HTMLElement' 3 | import document from './document' 4 | 5 | let hasModifiedCanvasPrototype = false 6 | let hasInit2DContextConstructor = false 7 | let hasInitWebGLContextConstructor = false 8 | 9 | export default function Canvas() { 10 | const canvas = wx.createCanvas() 11 | 12 | canvas.type = 'canvas' 13 | 14 | canvas.__proto__.__proto__ = new HTMLElement('canvas') 15 | 16 | const _getContext = canvas.getContext 17 | 18 | canvas.getBoundingClientRect = () => { 19 | const ret = { 20 | top: 0, 21 | left: 0, 22 | width: window.innerWidth, 23 | height: window.innerHeight 24 | } 25 | return ret 26 | } 27 | 28 | return canvas 29 | } 30 | -------------------------------------------------------------------------------- /src/Element.js: -------------------------------------------------------------------------------- 1 | import Node from './Node' 2 | 3 | export default class ELement extends Node { 4 | className = '' 5 | children = [] 6 | 7 | constructor() { 8 | super() 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Event.js: -------------------------------------------------------------------------------- 1 | import {noop} from './util' 2 | 3 | export default class Event { 4 | cancelBubble = false 5 | cancelable = false 6 | target = null 7 | timestampe = Date.now() 8 | preventDefault = noop 9 | stopPropagation = noop 10 | 11 | constructor(type) { 12 | this.type = type 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/EventIniter/TouchEvent.js: -------------------------------------------------------------------------------- 1 | import * as window from '../window' 2 | import document from '../document' 3 | import { noop } from '../util/' 4 | 5 | class TouchEvent { 6 | target = window.canvas 7 | currentTarget = window.canvas 8 | touches = [] 9 | targetTouches = [] 10 | changedTouches = [] 11 | preventDefault = noop 12 | stopPropagation = noop 13 | constructor(type) { 14 | this.type = type 15 | } 16 | } 17 | 18 | function touchEventHandlerFactory(type) { 19 | return (event) => { 20 | const touchEvent = new TouchEvent(type) 21 | 22 | touchEvent.touches = event.touches 23 | touchEvent.targetTouches = Array.prototype.slice.call(event.touches) 24 | touchEvent.changedTouches = event.changedTouches 25 | touchEvent.timeStamp = event.timeStamp 26 | document.dispatchEvent(touchEvent) 27 | } 28 | } 29 | 30 | wx.onTouchStart(touchEventHandlerFactory('touchstart')) 31 | wx.onTouchMove(touchEventHandlerFactory('touchmove')) 32 | wx.onTouchEnd(touchEventHandlerFactory('touchend')) 33 | wx.onTouchCancel(touchEventHandlerFactory('touchcancel')) 34 | -------------------------------------------------------------------------------- /src/EventIniter/index.js: -------------------------------------------------------------------------------- 1 | import './TouchEvent' 2 | -------------------------------------------------------------------------------- /src/EventTarget.js: -------------------------------------------------------------------------------- 1 | const _events = new WeakMap() 2 | 3 | class EventTarget { 4 | constructor() { 5 | _events.set(this, {}) 6 | } 7 | 8 | addEventListener(type, listener, options = {}) { 9 | let events = _events.get(this) 10 | 11 | if (!events) { 12 | events = {} 13 | _events.set(this, events) 14 | } 15 | if (!events[type]) { 16 | events[type] = [] 17 | } 18 | events[type].push(listener) 19 | 20 | if (options.capture) { 21 | console.warn('EventTarget.addEventListener: options.capture is not implemented.') 22 | } 23 | if (options.once) { 24 | console.warn('EventTarget.addEventListener: options.once is not implemented.') 25 | } 26 | if (options.passive) { 27 | console.warn('EventTarget.addEventListener: options.passive is not implemented.') 28 | } 29 | } 30 | 31 | removeEventListener(type, listener) { 32 | const listeners = _events.get(this)[type] 33 | 34 | if (listeners && listeners.length > 0) { 35 | for (let i = listeners.length; i--; i > 0) { 36 | if (listeners[i] === listener) { 37 | listeners.splice(i, 1) 38 | break 39 | } 40 | } 41 | } 42 | } 43 | 44 | dispatchEvent(event = {}) { 45 | const listeners = _events.get(this)[event.type] 46 | 47 | if (listeners) { 48 | for (let i = 0; i < listeners.length; i++) { 49 | listeners[i](event) 50 | } 51 | } 52 | } 53 | } 54 | 55 | export default EventTarget 56 | -------------------------------------------------------------------------------- /src/FileReader.js: -------------------------------------------------------------------------------- 1 | /* 2 | * TODO 使用 wx.readFile 来封装 FileReader 3 | */ 4 | export default class FileReader { 5 | construct() { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/HTMLAudioElement.js: -------------------------------------------------------------------------------- 1 | import HTMLMediaElement from './HTMLMediaElement' 2 | 3 | export default class HTMLAudioElement extends HTMLMediaElement { 4 | constructor() { 5 | super('audio') 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/HTMLElement.js: -------------------------------------------------------------------------------- 1 | import Element from './Element' 2 | import { noop } from './util' 3 | import { innerWidth, innerHeight } from './WindowProperties' 4 | 5 | export default class HTMLElement extends Element { 6 | className = '' 7 | childern = [] 8 | style = { 9 | width: `${innerWidth}px`, 10 | height: `${innerHeight}px` 11 | } 12 | 13 | insertBefore = noop 14 | 15 | innerHTML = '' 16 | 17 | constructor(tagName = '') { 18 | super() 19 | this.tagName = tagName.toUpperCase() 20 | } 21 | 22 | setAttribute(name, value) { 23 | this[name] = value 24 | } 25 | 26 | getAttribute(name) { 27 | return this[name] 28 | } 29 | 30 | get clientWidth() { 31 | const ret = parseInt(this.style.fontSize, 10) * this.innerHTML.length 32 | 33 | return Number.isNaN(ret) ? 0 : ret 34 | } 35 | 36 | get clientHeight() { 37 | const ret = parseInt(this.style.fontSize, 10) 38 | 39 | return Number.isNaN(ret) ? 0 : ret 40 | } 41 | 42 | getBoundingClientRect() { 43 | return { 44 | top: 0, 45 | left: 0, 46 | width: innerWidth, 47 | height: innerHeight 48 | } 49 | } 50 | 51 | focus() { 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/HTMLMediaElement.js: -------------------------------------------------------------------------------- 1 | import HTMLElement from './HTMLElement' 2 | 3 | export default class HTMLMediaElement extends HTMLElement { 4 | constructor(type) { 5 | super(type) 6 | } 7 | 8 | addTextTrack() { 9 | } 10 | 11 | captureStream() { 12 | } 13 | 14 | fastSeek() { 15 | } 16 | 17 | load() { 18 | } 19 | 20 | pause() { 21 | } 22 | 23 | play() { 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Image.js: -------------------------------------------------------------------------------- 1 | export default function Image() { 2 | const image = wx.createImage() 3 | 4 | return image 5 | } 6 | -------------------------------------------------------------------------------- /src/Node.js: -------------------------------------------------------------------------------- 1 | import EventTarget from './EventTarget' 2 | 3 | export default class Node extends EventTarget { 4 | constructor() { 5 | super() 6 | } 7 | 8 | childNodes = [] 9 | 10 | appendChild(node) { 11 | if (node instanceof Node) { 12 | this.childNodes.push(node) 13 | } else { 14 | throw new TypeError('Failed to executed \'appendChild\' on \'Node\': parameter 1 is not of type \'Node\'.') 15 | } 16 | } 17 | 18 | cloneNode() { 19 | const copyNode = Object.create(this) 20 | 21 | Object.assign(copyNode, this) 22 | return copyNode 23 | } 24 | 25 | removeChild(node) { 26 | const index = this.childNodes.findIndex((child) => child === node) 27 | 28 | if (index > -1) { 29 | return this.childNodes.splice(index, 1) 30 | } 31 | return null 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/URL.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 将arrayBuffer转换为base64 3 | * @param arrayBuffer 4 | * @returns {string} 5 | */ 6 | function base64ArrayBuffer(arrayBuffer) { 7 | var base64 = '' 8 | var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' 9 | 10 | var bytes = new Uint8Array(arrayBuffer) 11 | var byteLength = bytes.byteLength 12 | var byteRemainder = byteLength % 3 13 | var mainLength = byteLength - byteRemainder 14 | 15 | var a, b, c, d 16 | var chunk 17 | 18 | // Main loop deals with bytes in chunks of 3 19 | for (var i = 0; i < mainLength; i = i + 3) { 20 | // Combine the three bytes into a single integer 21 | chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2] 22 | 23 | // Use bitmasks to extract 6-bit segments from the triplet 24 | a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18 25 | b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12 26 | c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6 27 | d = chunk & 63 // 63 = 2^6 - 1 28 | 29 | // Convert the raw binary segments to the appropriate ASCII encoding 30 | base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d] 31 | } 32 | 33 | // Deal with the remaining bytes and padding 34 | if (byteRemainder == 1) { 35 | chunk = bytes[mainLength] 36 | 37 | a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2 38 | 39 | // Set the 4 least significant bits to zero 40 | b = (chunk & 3) << 4 // 3 = 2^2 - 1 41 | 42 | base64 += encodings[a] + encodings[b] + '==' 43 | } else if (byteRemainder == 2) { 44 | chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1] 45 | 46 | a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10 47 | b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4 48 | 49 | // Set the 2 least significant bits to zero 50 | c = (chunk & 15) << 2 // 15 = 2^4 - 1 51 | 52 | base64 += encodings[a] + encodings[b] + encodings[c] + '=' 53 | } 54 | 55 | return base64 56 | } 57 | 58 | let URL = function () { 59 | }; 60 | URL.createObjectURL = function (buffer) { 61 | return "data:image/png;base64," + base64ArrayBuffer(buffer); 62 | }; 63 | URL.revokeObjectURL = function () { 64 | //nothing 65 | }; 66 | 67 | export default URL; -------------------------------------------------------------------------------- /src/WebSocket.js: -------------------------------------------------------------------------------- 1 | const _socketTask = new WeakMap() 2 | 3 | class WebSocket { 4 | static CONNECTING = 0 // The connection is not yet open. 5 | static OPEN = 1 // The connection is open and ready to communicate. 6 | static CLOSING = 2 // The connection is in the process of closing. 7 | static CLOSED = 3 // The connection is closed or couldn't be opened. 8 | 9 | binaryType = '' // TODO 更新 binaryType 10 | bufferedAmount = 0 // TODO 更新 bufferedAmount 11 | extensions = '' 12 | 13 | onclose = null 14 | onerror = null 15 | onmessage = null 16 | onopen = null 17 | 18 | protocol = '' // TODO 小程序内目前获取不到,实际上需要根据服务器选择的 sub-protocol 返回 19 | readyState = 3 20 | 21 | constructor(url, protocols = []) { 22 | if (typeof url !== 'string' || !(/(^ws:\/\/)|(^wss:\/\/)/).test(url)) { 23 | throw new TypeError(`Failed to construct 'WebSocket': The URL '${url}' is invalid`) 24 | } 25 | 26 | this.url = url 27 | this.readyState = WebSocket.CONNECTING 28 | 29 | const socketTask = wx.connectSocket({ 30 | url, 31 | protocols: Array.isArray(protocols) ? protocols : [protocols] 32 | }) 33 | 34 | _socketTask.set(this, socketTask) 35 | 36 | socketTask.onClose((res) => { 37 | this.readyState = WebSocket.CLOSED 38 | if (typeof this.onclose === 'function') { 39 | this.onclose(res) 40 | } 41 | }) 42 | 43 | socketTask.onMessage((res) => { 44 | if (typeof this.onmessage === 'function') { 45 | this.onmessage(res) 46 | } 47 | }) 48 | 49 | socketTask.onOpen(() => { 50 | this.readyState = WebSocket.OPEN 51 | if (typeof this.onopen === 'function') { 52 | this.onopen() 53 | } 54 | }) 55 | 56 | socketTask.onError((res) => { 57 | if (typeof this.onerror === 'function') { 58 | this.onerror(new Error(res.errMsg)) 59 | } 60 | }) 61 | 62 | return this 63 | } 64 | 65 | close(code, reason) { 66 | this.readyState = WebSocket.CLOSING 67 | const socketTask = _socketTask.get(this) 68 | 69 | socketTask.close({ 70 | code, 71 | reason 72 | }) 73 | } 74 | 75 | send(data) { 76 | if (typeof data !== 'string' && !(data instanceof ArrayBuffer)) { 77 | throw new TypeError(`Failed to send message: The data ${data} is invalid`) 78 | } 79 | 80 | const socketTask = _socketTask.get(this) 81 | 82 | socketTask.send({ 83 | data 84 | }) 85 | } 86 | } 87 | 88 | export default WebSocket 89 | -------------------------------------------------------------------------------- /src/WindowProperties.js: -------------------------------------------------------------------------------- 1 | const { screenWidth, screenHeight, devicePixelRatio } = wx.getSystemInfoSync() 2 | 3 | export const innerWidth = screenWidth 4 | export const innerHeight = screenHeight 5 | export { devicePixelRatio } 6 | export const screen = { 7 | availWidth: innerWidth, 8 | availHeight: innerHeight 9 | } 10 | export const ontouchstart = null 11 | export const ontouchmove = null 12 | export const ontouchend = null 13 | 14 | export performance from './performance' 15 | -------------------------------------------------------------------------------- /src/XMLHttpRequest.js: -------------------------------------------------------------------------------- 1 | const _url = new WeakMap() 2 | const _method = new WeakMap() 3 | const _requestHeader = new WeakMap() 4 | const _responseHeader = new WeakMap() 5 | const _requestTask = new WeakMap() 6 | 7 | function _triggerEvent(type, ...args) { 8 | if (typeof this[`on${type}`] === 'function') { 9 | args[0] = {target: {status: 200}}; 10 | this[`on${type}`].apply(this, args) 11 | } 12 | } 13 | 14 | function _changeReadyState(readyState) { 15 | this.readyState = readyState 16 | _triggerEvent.call(this, 'readystatechange') 17 | } 18 | 19 | export default class XMLHttpRequest { 20 | // TODO 没法模拟 HEADERS_RECEIVED 和 LOADING 两个状态 21 | static UNSEND = 0 22 | static OPENED = 1 23 | static HEADERS_RECEIVED = 2 24 | static LOADING = 3 25 | static DONE = 4 26 | 27 | /* 28 | * TODO 这一批事件应该是在 XMLHttpRequestEventTarget.prototype 上面的 29 | */ 30 | onabort = null 31 | onerror = null 32 | onload = null 33 | onloadstart = null 34 | onprogress = null 35 | ontimeout = null 36 | onloadend = null 37 | 38 | onreadystatechange = null 39 | readyState = 0 40 | response = null 41 | responseText = null 42 | responseType = '' 43 | responseXML = null 44 | status = 0 45 | statusText = '' 46 | upload = {} 47 | withCredentials = false 48 | 49 | constructor() { 50 | _requestHeader.set(this, { 51 | 'content-type': 'application/x-www-form-urlencoded' 52 | }) 53 | _responseHeader.set(this, {}) 54 | } 55 | 56 | abort() { 57 | const myRequestTask = _requestTask.get(this) 58 | 59 | if (myRequestTask) { 60 | myRequestTask.abort() 61 | } 62 | } 63 | 64 | getAllResponseHeaders() { 65 | const responseHeader = _responseHeader.get(this) 66 | 67 | return Object.keys(responseHeader).map((header) => { 68 | return `${header}: ${responseHeader[header]}` 69 | }).join('\n') 70 | } 71 | 72 | getResponseHeader(header) { 73 | return _responseHeader.get(this)[header] 74 | } 75 | 76 | open(method, url/* async, user, password 这几个参数在小程序内不支持*/) { 77 | _method.set(this, method) 78 | _url.set(this, url) 79 | _changeReadyState.call(this, XMLHttpRequest.OPENED) 80 | } 81 | 82 | overrideMimeType() { 83 | } 84 | 85 | send(data = '') { 86 | if (this.readyState !== XMLHttpRequest.OPENED) { 87 | throw new Error("Failed to execute 'send' on 'XMLHttpRequest': The object's state must be OPENED.") 88 | } else { 89 | // 对于phaser3使用blob类型,微信并不支持,所以使用微信支付的arraybuffer作为传输类型 90 | // 之后在其它地方将其处理成对应的内容 91 | if (this.responseType === "blob") { 92 | this.responseType = "arraybuffer"; 93 | } 94 | wx.request({ 95 | data, 96 | url: _url.get(this), 97 | method: _method.get(this), 98 | header: _requestHeader.get(this), 99 | responseType: this.responseType, 100 | success: ({data, statusCode, header}) => { 101 | if (typeof data !== 'string' && !(data instanceof ArrayBuffer)) { 102 | try { 103 | data = JSON.stringify(data) 104 | } catch (e) { 105 | data = data 106 | } 107 | } 108 | 109 | this.status = statusCode 110 | _responseHeader.set(this, header) 111 | _triggerEvent.call(this, 'loadstart') 112 | _changeReadyState.call(this, XMLHttpRequest.HEADERS_RECEIVED) 113 | _changeReadyState.call(this, XMLHttpRequest.LOADING) 114 | 115 | this.response = data 116 | 117 | if (data instanceof ArrayBuffer) { 118 | this.responseText = '' 119 | const bytes = new Uint8Array(data) 120 | const len = bytes.byteLength 121 | 122 | for (let i = 0; i < len; i++) { 123 | this.responseText += String.fromCharCode(bytes[i]) 124 | } 125 | } else { 126 | this.responseText = data 127 | } 128 | _changeReadyState.call(this, XMLHttpRequest.DONE) 129 | _triggerEvent.call(this, 'load') 130 | _triggerEvent.call(this, 'loadend') 131 | }, 132 | fail: ({errMsg}) => { 133 | // TODO 规范错误 134 | if (errMsg.indexOf('abort') !== -1) { 135 | _triggerEvent.call(this, 'abort') 136 | } else { 137 | _triggerEvent.call(this, 'error', errMsg) 138 | } 139 | _triggerEvent.call(this, 'loadend') 140 | } 141 | }) 142 | } 143 | } 144 | 145 | setRequestHeader(header, value) { 146 | const myHeader = _requestHeader.get(this) 147 | 148 | myHeader[header] = value 149 | _requestHeader.set(this, myHeader) 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/constructor.js: -------------------------------------------------------------------------------- 1 | import HTMLElement from './HTMLElement' 2 | 3 | export class HTMLImageElement extends HTMLElement { 4 | constructor() { 5 | super('img') 6 | } 7 | } 8 | 9 | export class HTMLCanvasElement extends HTMLElement { 10 | constructor() { 11 | super('canvas') 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/document.js: -------------------------------------------------------------------------------- 1 | import * as window from './window' 2 | import HTMLElement from './HTMLElement' 3 | import Image from './Image' 4 | import Audio from './Audio' 5 | import Canvas from './Canvas' 6 | import './EventIniter/' 7 | 8 | const events = {} 9 | 10 | const document = { 11 | readyState: 'complete', 12 | visibilityState: 'visible', 13 | documentElement: window, 14 | hidden: false, 15 | style: {}, 16 | location: window.location, 17 | ontouchstart: null, 18 | ontouchmove: null, 19 | ontouchend: null, 20 | 21 | head: new HTMLElement('head'), 22 | body: new HTMLElement('body'), 23 | 24 | createElement(tagName) { 25 | if (tagName === 'canvas') { 26 | return new Canvas() 27 | } else if (tagName === 'audio') { 28 | return new Audio() 29 | } else if (tagName === 'img') { 30 | return new Image() 31 | } 32 | 33 | return new HTMLElement(tagName) 34 | }, 35 | 36 | getElementById(id) { 37 | if (id === window.canvas.id) { 38 | return window.canvas 39 | } 40 | return null 41 | }, 42 | 43 | getElementsByTagName(tagName) { 44 | if (tagName === 'head') { 45 | return [document.head] 46 | } else if (tagName === 'body') { 47 | return [document.body] 48 | } else if (tagName === 'canvas') { 49 | return [window.canvas] 50 | } 51 | return [] 52 | }, 53 | 54 | getElementsByName(tagName) { 55 | if (tagName === 'head') { 56 | return [document.head] 57 | } else if (tagName === 'body') { 58 | return [document.body] 59 | } else if (tagName === 'canvas') { 60 | return [window.canvas] 61 | } 62 | return [] 63 | }, 64 | 65 | querySelector(query) { 66 | if (query === 'head') { 67 | return document.head 68 | } else if (query === 'body') { 69 | return document.body 70 | } else if (query === 'canvas') { 71 | return window.canvas 72 | } else if (query === `#${window.canvas.id}`) { 73 | return window.canvas 74 | } 75 | return null 76 | }, 77 | 78 | querySelectorAll(query) { 79 | if (query === 'head') { 80 | return [document.head] 81 | } else if (query === 'body') { 82 | return [document.body] 83 | } else if (query === 'canvas') { 84 | return [window.canvas] 85 | } 86 | return [] 87 | }, 88 | 89 | addEventListener(type, listener) { 90 | if (!events[type]) { 91 | events[type] = [] 92 | } 93 | events[type].push(listener) 94 | }, 95 | 96 | removeEventListener(type, listener) { 97 | const listeners = events[type] 98 | 99 | if (listeners && listeners.length > 0) { 100 | for (let i = listeners.length; i--; i > 0) { 101 | if (listeners[i] === listener) { 102 | listeners.splice(i, 1) 103 | break 104 | } 105 | } 106 | } 107 | }, 108 | 109 | dispatchEvent(event) { 110 | const listeners = events[event.type] 111 | 112 | if (listeners) { 113 | for (let i = 0; i < listeners.length; i++) { 114 | listeners[i](event) 115 | } 116 | } 117 | } 118 | } 119 | 120 | export default document 121 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import * as _window from './window' 2 | import HTMLElement from './HTMLElement' 3 | 4 | const global = GameGlobal 5 | 6 | function inject () { 7 | _window.addEventListener = (type, listener) => { 8 | _window.document.addEventListener(type, listener) 9 | } 10 | _window.removeEventListener = (type, listener) => { 11 | _window.document.removeEventListener(type, listener) 12 | } 13 | 14 | if (_window.canvas) { 15 | _window.canvas.addEventListener = _window.addEventListener 16 | _window.canvas.removeEventListener = _window.removeEventListener 17 | } 18 | 19 | const { platform } = wx.getSystemInfoSync() 20 | 21 | // 开发者工具无法重定义 window 22 | if (platform === 'devtools') { 23 | for (const key in _window) { 24 | const descriptor = Object.getOwnPropertyDescriptor(global, key) 25 | 26 | if (!descriptor || descriptor.configurable === true) { 27 | Object.defineProperty(window, key, { 28 | value: _window[key] 29 | }) 30 | } 31 | } 32 | 33 | for (const key in _window.document) { 34 | const descriptor = Object.getOwnPropertyDescriptor(global.document, key) 35 | 36 | if (!descriptor || descriptor.configurable === true) { 37 | Object.defineProperty(global.document, key, { 38 | value: _window.document[key] 39 | }) 40 | } 41 | } 42 | window.parent = window 43 | } else { 44 | for (const key in _window) { 45 | global[key] = _window[key] 46 | } 47 | global.window = _window 48 | window = global 49 | window.top = window.parent = window 50 | } 51 | } 52 | 53 | if (!GameGlobal.__isAdapterInjected) { 54 | GameGlobal.__isAdapterInjected = true 55 | inject() 56 | } 57 | -------------------------------------------------------------------------------- /src/localStorage.js: -------------------------------------------------------------------------------- 1 | const localStorage = { 2 | get length() { 3 | const { keys } = wx.getStorageInfoSync() 4 | 5 | return keys.length 6 | }, 7 | 8 | key(n) { 9 | const { keys } = wx.getStorageInfoSync() 10 | 11 | return keys[n] 12 | }, 13 | 14 | getItem(key) { 15 | return wx.getStorageSync(key) 16 | }, 17 | 18 | setItem(key, value) { 19 | return wx.setStorageSync(key, value) 20 | }, 21 | 22 | removeItem(key) { 23 | wx.removeStorageSync(key) 24 | }, 25 | 26 | clear() { 27 | wx.clearStorageSync() 28 | } 29 | } 30 | 31 | export default localStorage 32 | -------------------------------------------------------------------------------- /src/location.js: -------------------------------------------------------------------------------- 1 | const location = { 2 | href: 'game.js', 3 | reload() { 4 | } 5 | } 6 | 7 | export default location 8 | -------------------------------------------------------------------------------- /src/navigator.js: -------------------------------------------------------------------------------- 1 | import { noop } from './util' 2 | 3 | // TODO 需要 wx.getSystemInfo 获取更详细信息 4 | const { platform } = wx.getSystemInfoSync() 5 | const navigator = { 6 | platform, 7 | language: 'zh-cn', 8 | appVersion: '5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1', 9 | userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E8301 MicroMessenger/6.6.0 MiniGame NetType/WIFI Language/zh_CN', 10 | onLine: true, // TODO 用 wx.getNetworkStateChange 和 wx.onNetworkStateChange 来返回真实的状态 11 | 12 | // TODO 用 wx.getLocation 来封装 geolocation 13 | geolocation: { 14 | getCurrentPosition: noop, 15 | watchPosition: noop, 16 | clearWatch: noop 17 | } 18 | } 19 | 20 | export default navigator 21 | -------------------------------------------------------------------------------- /src/performance.js: -------------------------------------------------------------------------------- 1 | let performance 2 | 3 | if (wx.getPerformance) { 4 | const { platform } = wx.getSystemInfoSync() 5 | const wxPerf = wx.getPerformance() 6 | const initTime = wxPerf.now() 7 | 8 | const clientPerfAdapter = Object.assign({}, wxPerf, { 9 | now: function() { 10 | return (wxPerf.now() - initTime) / 1000 11 | } 12 | }) 13 | 14 | performance = platform === 'devtools' ? wxPerf : clientPerfAdapter 15 | } 16 | 17 | export default performance 18 | -------------------------------------------------------------------------------- /src/util/index.js: -------------------------------------------------------------------------------- 1 | export function noop() {} 2 | -------------------------------------------------------------------------------- /src/window.js: -------------------------------------------------------------------------------- 1 | import Canvas from './Canvas' 2 | 3 | export document from './document' 4 | export navigator from './navigator' 5 | export XMLHttpRequest from './XMLHttpRequest' 6 | export WebSocket from './WebSocket' 7 | export Image from './Image' 8 | export Audio from './Audio' 9 | export FileReader from './FileReader' 10 | export HTMLElement from './HTMLElement' 11 | export localStorage from './localStorage' 12 | export location from './location' 13 | export * from './WindowProperties' 14 | export * from './constructor' 15 | export URL from './URL' 16 | 17 | // 暴露全局的 canvas 18 | const canvas = new Canvas() 19 | 20 | export {canvas} 21 | export {setTimeout} 22 | export {setInterval} 23 | export {clearTimeout} 24 | export {clearInterval} 25 | export {requestAnimationFrame} 26 | export {cancelAnimationFrame} 27 | -------------------------------------------------------------------------------- /test/EventTarget.test.js: -------------------------------------------------------------------------------- 1 | import EventTarget from '../src/EventTarget' 2 | 3 | describe('EventTarget', () => { 4 | it('addEventListener', () => { 5 | const target = new EventTarget() 6 | 7 | const listener = jest.fn() 8 | target.addEventListener('foo', listener) 9 | target.dispatchEvent({ type: 'foo' }) 10 | expect(listener).toHaveBeenCalledTimes(1) 11 | }) 12 | 13 | it('removeEventListener', () => { 14 | const target = new EventTarget() 15 | 16 | const listener = jest.fn() 17 | target.addEventListener('foo', listener) 18 | target.removeEventListener('foo', listener) 19 | target.dispatchEvent({ type: 'foo' }) 20 | expect(listener).toHaveBeenCalledTimes(0) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /test/HTMLElement.test.js: -------------------------------------------------------------------------------- 1 | import { loadEnv } from './vm' 2 | import HTMLElement from '../src/HTMLElement' 3 | 4 | describe('HTMLElement', () => { 5 | it('return clientHeight', () => { 6 | const div = new HTMLElement('div') 7 | div.style.fontSize = '14px' 8 | expect(div.clientHeight).toEqual(14) 9 | }) 10 | 11 | it('return clientWidth', () => { 12 | const div = new HTMLElement('div') 13 | div.style.fontSize = '14px' 14 | expect(div.clientWidth).toEqual(0) 15 | 16 | div.innerHTML = 'hello' 17 | expect(div.clientWidth).toEqual(70) 18 | }) 19 | }) 20 | -------------------------------------------------------------------------------- /test/WebSocket.test.js: -------------------------------------------------------------------------------- 1 | import WebSocket from '../src/WebSocket' 2 | 3 | let connectSocket, onOpen, onClose, onMessage, onError 4 | 5 | beforeEach(() => { 6 | onOpen = jest.fn() 7 | onClose = jest.fn() 8 | onMessage = jest.fn() 9 | onError = jest.fn() 10 | connectSocket = jest.fn(() => { 11 | return { 12 | onOpen, 13 | onClose, 14 | onMessage, 15 | onError 16 | } 17 | }) 18 | 19 | global.wx = { 20 | connectSocket 21 | } 22 | }) 23 | 24 | describe('WebSocket', () => { 25 | it('constructor check invalid url', () => { 26 | expect(() => { 27 | const ws = new WebSocket() 28 | }).toThrow() 29 | 30 | expect(() => { 31 | const ws = new WebSocket('http://foo.bar') 32 | }).toThrow() 33 | }) 34 | 35 | it('contructor basic', () => { 36 | const url = 'wss://foo.bar' 37 | const ws = new WebSocket(url) 38 | 39 | expect(onOpen).toHaveBeenCalledTimes(1) 40 | expect(onClose).toHaveBeenCalledTimes(1) 41 | expect(onMessage).toHaveBeenCalledTimes(1) 42 | expect(onClose).toHaveBeenCalledTimes(1) 43 | expect(connectSocket).toBeCalledWith({ 44 | url, 45 | protocols: [] 46 | }) 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /test/XMLHttpRequest.test.js: -------------------------------------------------------------------------------- 1 | import XMLHttpRequest from '../src/XMLHttpRequest' 2 | 3 | let request 4 | const testURL = 'http://qq.com' 5 | const testMethod = 'GET' 6 | const defaultRequsetArguments = { 7 | data: expect.any(String), 8 | header: expect.any(Object), 9 | method: expect.any(String), 10 | url: expect.any(String), 11 | success: expect.any(Function), 12 | fail: expect.any(Function), 13 | responseType: expect.any(String) 14 | } 15 | 16 | beforeEach(() => { 17 | request = jest.fn() 18 | 19 | global.wx = { 20 | request 21 | } 22 | }) 23 | 24 | 25 | describe('XMLHttpRequest', () => { 26 | it('constructor return default properties', () => { 27 | const xhr = new XMLHttpRequest() 28 | expect(xhr.onreadystatechange).toBeNull() 29 | expect(xhr.readyState).toEqual(0) 30 | expect(xhr.response).toBeNull() 31 | expect(xhr.responseType).toEqual('') 32 | expect(xhr.responseXML).toBeNull() 33 | expect(xhr.status).toEqual(0) 34 | expect(xhr.statusText).toEqual('') 35 | expect(xhr.upload).toEqual(expect.any(Object)) 36 | expect(xhr.withCredentials).toEqual(false) 37 | expect(request).toHaveBeenCalledTimes(0) 38 | }) 39 | 40 | it('open() set "method" and "url"', () => { 41 | const xhr = new XMLHttpRequest() 42 | xhr.open(testMethod, testURL) 43 | xhr.send() 44 | expect(request).toHaveBeenCalledWith(Object.assign({}, defaultRequsetArguments, { 45 | method: testMethod, 46 | url: testURL 47 | })) 48 | }) 49 | 50 | it('setRequestHeader() set header', () => { 51 | const xhr = new XMLHttpRequest() 52 | xhr.setRequestHeader('foo', 'bar') 53 | xhr.open(testMethod, testURL) 54 | xhr.send() 55 | expect(request).toHaveBeenCalledWith(Object.assign({}, defaultRequsetArguments, { 56 | header: { 57 | 'content-type': 'application/x-www-form-urlencoded', // 默认加上的 header 58 | foo: 'bar' 59 | } 60 | })) 61 | }) 62 | 63 | it('send() with POST data', () => { 64 | const xhr = new XMLHttpRequest() 65 | xhr.open('POST', testURL) 66 | xhr.send('hello, world') 67 | expect(request).toHaveBeenCalledWith(Object.assign({}, defaultRequsetArguments, { 68 | method: 'POST', 69 | data: 'hello, world' 70 | })) 71 | }) 72 | 73 | it('getResponseHeader() and getAllResponseHeaders()', (done) => { 74 | wx.request = jest.fn((args) => { 75 | args.success({ 76 | header: { 77 | header1: 'value1', 78 | header2: 'value2' 79 | } 80 | }) 81 | }) 82 | 83 | const xhr = new XMLHttpRequest() 84 | xhr.onreadystatechange = () => { 85 | if (xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED) { 86 | expect(xhr.getAllResponseHeaders()).toEqual('header1: value1\nheader2: value2') 87 | expect(xhr.getResponseHeader('header1')).toEqual('value1') 88 | expect(xhr.getResponseHeader('header2')).toEqual('value2') 89 | done() 90 | } 91 | } 92 | xhr.open(testMethod, testURL) 93 | xhr.send() 94 | }) 95 | 96 | it('get response', (done) => { 97 | wx.request = jest.fn((args) => { 98 | args.success({ 99 | data: 'hello, world', 100 | statusCode: 200 101 | }) 102 | }) 103 | 104 | const xhr = new XMLHttpRequest() 105 | xhr.onreadystatechange = () => { 106 | if (xhr.readyState === XMLHttpRequest.DONE) { 107 | expect(xhr.status).toEqual(200) 108 | expect(xhr.response).toEqual('hello, world') 109 | expect(xhr.responseText).toEqual('hello, world') 110 | done() 111 | } 112 | } 113 | xhr.open(testMethod, testURL) 114 | xhr.send() 115 | }) 116 | 117 | }) 118 | -------------------------------------------------------------------------------- /test/contructor.test.js: -------------------------------------------------------------------------------- 1 | import { loadEnv } from './vm' 2 | import * as window from '../src/window' 3 | 4 | describe('contructor', () => { 5 | it() 6 | //it('img instanceof of HTMLImageElement', () => { 7 | //const img = window.document.createElement('img') 8 | //expect(img instanceof window.HTMLElement).toEqual(true) 9 | //expect(img instanceof window.HTMLImageElement).toEqual(true) 10 | //}) 11 | 12 | //it('canvas instance of HTMLCanvasElement', () => { 13 | //const canvas = window.document.createElement('canvas') 14 | //expect(canvas instanceof window.HTMLElement).toEqual(true) 15 | //expect(canvas instanceof window.HTMLCanvasElement).toEqual(true) 16 | //}) 17 | 18 | //it('audio instance of HTMLAudioElement', () => { 19 | //const audio = window.document.createElement('audio') 20 | //expect(audio instanceof window.HTMLElement).toEqual(true) 21 | //expect(audio instanceof window.HTMLAudioElement).toEqual(true) 22 | //}) 23 | 24 | //it('ctx instance of CanvasRenderingContext2D', () => { 25 | //const canvas = window.document.createElement('canvas') 26 | //const ctx = canvas.getContext('2d') 27 | //expect(ctx instanceof window.CanvasRenderingContext2D).toEqual(true) 28 | //}) 29 | 30 | //it('ctx instance of WebGLRenderingContext', () => { 31 | //const canvas = window.document.createElement('canvas') 32 | //const ctx = canvas.getContext('webgl') 33 | //expect(ctx instanceof window.WebGLRenderingContext).toEqual(true) 34 | //}) 35 | }) 36 | -------------------------------------------------------------------------------- /test/document.test.js: -------------------------------------------------------------------------------- 1 | import { loadEnv } from './vm' 2 | import document from '../src/document' 3 | 4 | describe('document', () => { 5 | it('document prperties', () => { 6 | expect(document).toMatchObject({ 7 | readyState: expect.any(String), 8 | visibilityState: expect.any(String), 9 | hidden: expect.any(Boolean), 10 | documentElement: expect.any(Object), 11 | location: expect.any(Object) 12 | }) 13 | }) 14 | 15 | it('addEventListener', () => { 16 | document.addEventListener('touchstart', () => { 17 | }) 18 | }) 19 | }) 20 | -------------------------------------------------------------------------------- /test/localStorage.test.js: -------------------------------------------------------------------------------- 1 | import localStorage from '../src/localStorage' 2 | 3 | let getStorageSync, setStorageSync, removeStorageSync, getStorageInfoSync, clearStorageSync 4 | 5 | beforeEach(() => { 6 | getStorageSync = setStorageSync = removeStorageSync = getStorageInfoSync = clearStorageSync = jest.fn() 7 | 8 | global.wx = { 9 | getStorageSync, 10 | setStorageSync, 11 | removeStorageSync, 12 | getStorageInfoSync, 13 | clearStorageSync 14 | } 15 | }) 16 | 17 | describe('localStorage', () => { 18 | it('call getStorageInfoSync() with length', () => { 19 | wx.getStorageInfoSync = jest.fn(() => { 20 | return { 21 | keys: ['key0', 'key1', 'key2', 'key3', 'key4'] 22 | } 23 | }) 24 | 25 | expect(localStorage.length).toEqual(5) 26 | expect(wx.getStorageInfoSync).toHaveBeenCalledTimes(1) 27 | }) 28 | 29 | it('call getStorageInfoSync() with key()', () => { 30 | wx.getStorageInfoSync = jest.fn(() => { 31 | return { 32 | keys: ['key0', 'key1', 'key2', 'key3', 'key4'] 33 | } 34 | }) 35 | expect(localStorage.key(0)).toEqual('key0') 36 | expect(localStorage.key(3)).toEqual('key3') 37 | expect(wx.getStorageInfoSync).toHaveBeenCalledTimes(2) 38 | }) 39 | 40 | it('call wx.getStorageSync() with getItem()', () => { 41 | localStorage.getItem('key') 42 | expect(getStorageSync).toHaveBeenCalledTimes(1) 43 | expect(getStorageSync).toHaveBeenCalledWith('key') 44 | }) 45 | 46 | it('call setStorageSync() with setItem()', () => { 47 | localStorage.setItem('key', 'value') 48 | expect(setStorageSync).toHaveBeenCalledWith('key', 'value') 49 | }) 50 | 51 | it('call removeStorageSync() with removeItem()', () => { 52 | localStorage.removeItem('key') 53 | expect(removeStorageSync).toHaveBeenCalledWith('key') 54 | }) 55 | 56 | it('call clearStorageInfoSync() with clear()', () => { 57 | localStorage.clear() 58 | expect(clearStorageSync).toHaveBeenCalledTimes(1) 59 | }) 60 | 61 | }) 62 | -------------------------------------------------------------------------------- /test/mock/Audio_mock.js: -------------------------------------------------------------------------------- 1 | export default class Audio { 2 | } 3 | -------------------------------------------------------------------------------- /test/mock/Canvas_mock.js: -------------------------------------------------------------------------------- 1 | export default class Canvas { 2 | getContext(type) { 3 | return {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/mock/Image_mock.js: -------------------------------------------------------------------------------- 1 | export default class Image { 2 | } 3 | -------------------------------------------------------------------------------- /test/mock/wx_mock.js: -------------------------------------------------------------------------------- 1 | import Audio from './Audio_mock' 2 | import Image from './Image_mock' 3 | import Canvas from './Canvas_mock' 4 | 5 | const wx = { 6 | getSystemInfoSync() { 7 | return { 8 | screenWidth: 300, 9 | screenHeight: 600, 10 | devicePixelRatio: 2 11 | } 12 | }, 13 | createCanvas() { 14 | return new Canvas() 15 | }, 16 | createImage() { 17 | return new Image() 18 | }, 19 | createAudio() { 20 | return new Audio() 21 | }, 22 | createInnerAudioContext() { 23 | return new Audio() 24 | }, 25 | onTouchStart(callback) { 26 | }, 27 | offTouchStart() { 28 | }, 29 | onTouchMove(callback) { 30 | }, 31 | offTouchMove() { 32 | }, 33 | onTouchEnd(callback) { 34 | }, 35 | offTouchEnd() { 36 | }, 37 | onTouchCancel(callback) { 38 | }, 39 | offTouchCancel() { 40 | }, 41 | getStorageInfoSync() { 42 | return { 43 | keys: [] 44 | } 45 | }, 46 | getPerformance() { 47 | return { 48 | } 49 | } 50 | } 51 | 52 | module.exports = wx 53 | -------------------------------------------------------------------------------- /test/test.test.js: -------------------------------------------------------------------------------- 1 | describe('test', () => { 2 | it('instance of', () => { 3 | class Person { 4 | } 5 | class Student extends Person { 6 | } 7 | class Something { 8 | } 9 | Something.prototype = new Student() 10 | const s = new Something() 11 | 12 | Student.prototype = s.__proto__ 13 | 14 | expect(s instanceof Student).toEqual(true) 15 | expect(s instanceof Person).toEqual(true) 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /test/vm.js: -------------------------------------------------------------------------------- 1 | function loadEnv() { 2 | Object.assign(global, { 3 | requestAnimationFrame: jest.fn(), 4 | cancelAnimationFrame: jest.fn(), 5 | XMLHttpRequest: jest.fn(), // TODO 待替换成小程序封装的 XMLHttpRequest 后移除此全局变量 6 | WebSocket: jest.fn(), // TODO 待替换成小程序封装的 WebSocket 后移除此全局变量 7 | wx: require('./mock/wx_mock') 8 | }) 9 | jest.resetModules() 10 | } 11 | 12 | loadEnv() 13 | 14 | export { 15 | loadEnv 16 | } 17 | -------------------------------------------------------------------------------- /test/window.test.js: -------------------------------------------------------------------------------- 1 | import { loadEnv } from './vm' 2 | import * as window from '../src/window' 3 | 4 | describe('window', () => { 5 | it('window properties', () => { 6 | expect(window).toMatchObject({ 7 | WebSocket: expect.any(Function), 8 | document: expect.any(Object), 9 | devicePixelRatio: expect.any(Number), 10 | innerWidth: expect.any(Number), 11 | innerHeight: expect.any(Number), 12 | navigator: expect.any(Object), 13 | Image: expect.any(Function), 14 | Audio: expect.any(Function), 15 | //XMLHttpRequest: expect.any(Function), 16 | localStorage: expect.any(Object), 17 | location: expect.any(Object) 18 | }) 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /weapp-phaser3-adapter.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) 10 | /******/ return installedModules[moduleId].exports; 11 | 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ exports: {}, 15 | /******/ id: moduleId, 16 | /******/ loaded: false 17 | /******/ }; 18 | 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | 22 | /******/ // Flag the module as loaded 23 | /******/ module.loaded = true; 24 | 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | 29 | 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | 36 | /******/ // __webpack_public_path__ 37 | /******/ __webpack_require__.p = ""; 38 | 39 | /******/ // Load entry module and return exports 40 | /******/ return __webpack_require__(0); 41 | /******/ }) 42 | /************************************************************************/ 43 | /******/ ([ 44 | /* 0 */ 45 | /***/ (function(module, exports, __webpack_require__) { 46 | 47 | 'use strict'; 48 | 49 | var _window2 = __webpack_require__(1); 50 | 51 | var _window = _interopRequireWildcard(_window2); 52 | 53 | var _HTMLElement = __webpack_require__(5); 54 | 55 | var _HTMLElement2 = _interopRequireDefault(_HTMLElement); 56 | 57 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 58 | 59 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 60 | 61 | var global = GameGlobal; 62 | 63 | function inject() { 64 | _window.addEventListener = function (type, listener) { 65 | _window.document.addEventListener(type, listener); 66 | }; 67 | _window.removeEventListener = function (type, listener) { 68 | _window.document.removeEventListener(type, listener); 69 | }; 70 | 71 | if (_window.canvas) { 72 | _window.canvas.addEventListener = _window.addEventListener; 73 | _window.canvas.removeEventListener = _window.removeEventListener; 74 | } 75 | 76 | var _wx$getSystemInfoSync = wx.getSystemInfoSync(), 77 | platform = _wx$getSystemInfoSync.platform; 78 | 79 | // 开发者工具无法重定义 window 80 | 81 | 82 | if (platform === 'devtools') { 83 | for (var key in _window) { 84 | var descriptor = Object.getOwnPropertyDescriptor(global, key); 85 | 86 | if (!descriptor || descriptor.configurable === true) { 87 | Object.defineProperty(window, key, { 88 | value: _window[key] 89 | }); 90 | } 91 | } 92 | 93 | for (var _key in _window.document) { 94 | var _descriptor = Object.getOwnPropertyDescriptor(global.document, _key); 95 | 96 | if (!_descriptor || _descriptor.configurable === true) { 97 | Object.defineProperty(global.document, _key, { 98 | value: _window.document[_key] 99 | }); 100 | } 101 | } 102 | window.parent = window; 103 | } else { 104 | for (var _key2 in _window) { 105 | global[_key2] = _window[_key2]; 106 | } 107 | global.window = _window; 108 | window = global; 109 | window.top = window.parent = window; 110 | } 111 | } 112 | 113 | if (!GameGlobal.__isAdapterInjected) { 114 | GameGlobal.__isAdapterInjected = true; 115 | inject(); 116 | } 117 | 118 | /***/ }), 119 | /* 1 */ 120 | /***/ (function(module, exports, __webpack_require__) { 121 | 122 | 'use strict'; 123 | 124 | Object.defineProperty(exports, "__esModule", { 125 | value: true 126 | }); 127 | exports.cancelAnimationFrame = exports.requestAnimationFrame = exports.clearInterval = exports.clearTimeout = exports.setInterval = exports.setTimeout = exports.canvas = exports.URL = exports.location = exports.localStorage = exports.HTMLElement = exports.FileReader = exports.Audio = exports.Image = exports.WebSocket = exports.XMLHttpRequest = exports.navigator = exports.document = undefined; 128 | 129 | var _WindowProperties = __webpack_require__(2); 130 | 131 | Object.keys(_WindowProperties).forEach(function (key) { 132 | if (key === "default" || key === "__esModule") return; 133 | Object.defineProperty(exports, key, { 134 | enumerable: true, 135 | get: function get() { 136 | return _WindowProperties[key]; 137 | } 138 | }); 139 | }); 140 | 141 | var _constructor = __webpack_require__(4); 142 | 143 | Object.keys(_constructor).forEach(function (key) { 144 | if (key === "default" || key === "__esModule") return; 145 | Object.defineProperty(exports, key, { 146 | enumerable: true, 147 | get: function get() { 148 | return _constructor[key]; 149 | } 150 | }); 151 | }); 152 | 153 | var _Canvas = __webpack_require__(10); 154 | 155 | var _Canvas2 = _interopRequireDefault(_Canvas); 156 | 157 | var _document2 = __webpack_require__(11); 158 | 159 | var _document3 = _interopRequireDefault(_document2); 160 | 161 | var _navigator2 = __webpack_require__(18); 162 | 163 | var _navigator3 = _interopRequireDefault(_navigator2); 164 | 165 | var _XMLHttpRequest2 = __webpack_require__(19); 166 | 167 | var _XMLHttpRequest3 = _interopRequireDefault(_XMLHttpRequest2); 168 | 169 | var _WebSocket2 = __webpack_require__(20); 170 | 171 | var _WebSocket3 = _interopRequireDefault(_WebSocket2); 172 | 173 | var _Image2 = __webpack_require__(12); 174 | 175 | var _Image3 = _interopRequireDefault(_Image2); 176 | 177 | var _Audio2 = __webpack_require__(13); 178 | 179 | var _Audio3 = _interopRequireDefault(_Audio2); 180 | 181 | var _FileReader2 = __webpack_require__(21); 182 | 183 | var _FileReader3 = _interopRequireDefault(_FileReader2); 184 | 185 | var _HTMLElement2 = __webpack_require__(5); 186 | 187 | var _HTMLElement3 = _interopRequireDefault(_HTMLElement2); 188 | 189 | var _localStorage2 = __webpack_require__(22); 190 | 191 | var _localStorage3 = _interopRequireDefault(_localStorage2); 192 | 193 | var _location2 = __webpack_require__(23); 194 | 195 | var _location3 = _interopRequireDefault(_location2); 196 | 197 | var _URL2 = __webpack_require__(24); 198 | 199 | var _URL3 = _interopRequireDefault(_URL2); 200 | 201 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 202 | 203 | exports.document = _document3.default; 204 | exports.navigator = _navigator3.default; 205 | exports.XMLHttpRequest = _XMLHttpRequest3.default; 206 | exports.WebSocket = _WebSocket3.default; 207 | exports.Image = _Image3.default; 208 | exports.Audio = _Audio3.default; 209 | exports.FileReader = _FileReader3.default; 210 | exports.HTMLElement = _HTMLElement3.default; 211 | exports.localStorage = _localStorage3.default; 212 | exports.location = _location3.default; 213 | exports.URL = _URL3.default; 214 | 215 | // 暴露全局的 canvas 216 | 217 | var canvas = new _Canvas2.default(); 218 | 219 | exports.canvas = canvas; 220 | exports.setTimeout = setTimeout; 221 | exports.setInterval = setInterval; 222 | exports.clearTimeout = clearTimeout; 223 | exports.clearInterval = clearInterval; 224 | exports.requestAnimationFrame = requestAnimationFrame; 225 | exports.cancelAnimationFrame = cancelAnimationFrame; 226 | 227 | /***/ }), 228 | /* 2 */ 229 | /***/ (function(module, exports, __webpack_require__) { 230 | 231 | 'use strict'; 232 | 233 | Object.defineProperty(exports, "__esModule", { 234 | value: true 235 | }); 236 | exports.performance = exports.ontouchend = exports.ontouchmove = exports.ontouchstart = exports.screen = exports.devicePixelRatio = exports.innerHeight = exports.innerWidth = undefined; 237 | 238 | var _performance2 = __webpack_require__(3); 239 | 240 | var _performance3 = _interopRequireDefault(_performance2); 241 | 242 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 243 | 244 | var _wx$getSystemInfoSync = wx.getSystemInfoSync(), 245 | screenWidth = _wx$getSystemInfoSync.screenWidth, 246 | screenHeight = _wx$getSystemInfoSync.screenHeight, 247 | devicePixelRatio = _wx$getSystemInfoSync.devicePixelRatio; 248 | 249 | var innerWidth = exports.innerWidth = screenWidth; 250 | var innerHeight = exports.innerHeight = screenHeight; 251 | exports.devicePixelRatio = devicePixelRatio; 252 | var screen = exports.screen = { 253 | availWidth: innerWidth, 254 | availHeight: innerHeight 255 | }; 256 | var ontouchstart = exports.ontouchstart = null; 257 | var ontouchmove = exports.ontouchmove = null; 258 | var ontouchend = exports.ontouchend = null; 259 | 260 | exports.performance = _performance3.default; 261 | 262 | /***/ }), 263 | /* 3 */ 264 | /***/ (function(module, exports) { 265 | 266 | 'use strict'; 267 | 268 | Object.defineProperty(exports, "__esModule", { 269 | value: true 270 | }); 271 | var performance = void 0; 272 | 273 | if (wx.getPerformance) { 274 | var _wx$getSystemInfoSync = wx.getSystemInfoSync(), 275 | platform = _wx$getSystemInfoSync.platform; 276 | 277 | var wxPerf = wx.getPerformance(); 278 | var initTime = wxPerf.now(); 279 | 280 | var clientPerfAdapter = Object.assign({}, wxPerf, { 281 | now: function now() { 282 | return (wxPerf.now() - initTime) / 1000; 283 | } 284 | }); 285 | 286 | performance = platform === 'devtools' ? wxPerf : clientPerfAdapter; 287 | } 288 | 289 | exports.default = performance; 290 | 291 | /***/ }), 292 | /* 4 */ 293 | /***/ (function(module, exports, __webpack_require__) { 294 | 295 | 'use strict'; 296 | 297 | Object.defineProperty(exports, "__esModule", { 298 | value: true 299 | }); 300 | exports.HTMLCanvasElement = exports.HTMLImageElement = undefined; 301 | 302 | var _HTMLElement3 = __webpack_require__(5); 303 | 304 | var _HTMLElement4 = _interopRequireDefault(_HTMLElement3); 305 | 306 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 307 | 308 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 309 | 310 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 311 | 312 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 313 | 314 | var HTMLImageElement = exports.HTMLImageElement = function (_HTMLElement) { 315 | _inherits(HTMLImageElement, _HTMLElement); 316 | 317 | function HTMLImageElement() { 318 | _classCallCheck(this, HTMLImageElement); 319 | 320 | return _possibleConstructorReturn(this, (HTMLImageElement.__proto__ || Object.getPrototypeOf(HTMLImageElement)).call(this, 'img')); 321 | } 322 | 323 | return HTMLImageElement; 324 | }(_HTMLElement4.default); 325 | 326 | var HTMLCanvasElement = exports.HTMLCanvasElement = function (_HTMLElement2) { 327 | _inherits(HTMLCanvasElement, _HTMLElement2); 328 | 329 | function HTMLCanvasElement() { 330 | _classCallCheck(this, HTMLCanvasElement); 331 | 332 | return _possibleConstructorReturn(this, (HTMLCanvasElement.__proto__ || Object.getPrototypeOf(HTMLCanvasElement)).call(this, 'canvas')); 333 | } 334 | 335 | return HTMLCanvasElement; 336 | }(_HTMLElement4.default); 337 | 338 | /***/ }), 339 | /* 5 */ 340 | /***/ (function(module, exports, __webpack_require__) { 341 | 342 | 'use strict'; 343 | 344 | Object.defineProperty(exports, "__esModule", { 345 | value: true 346 | }); 347 | 348 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 349 | 350 | var _Element2 = __webpack_require__(6); 351 | 352 | var _Element3 = _interopRequireDefault(_Element2); 353 | 354 | var _util = __webpack_require__(9); 355 | 356 | var _WindowProperties = __webpack_require__(2); 357 | 358 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 359 | 360 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 361 | 362 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 363 | 364 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 365 | 366 | var HTMLElement = function (_Element) { 367 | _inherits(HTMLElement, _Element); 368 | 369 | function HTMLElement() { 370 | var tagName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; 371 | 372 | _classCallCheck(this, HTMLElement); 373 | 374 | var _this = _possibleConstructorReturn(this, (HTMLElement.__proto__ || Object.getPrototypeOf(HTMLElement)).call(this)); 375 | 376 | _this.className = ''; 377 | _this.childern = []; 378 | _this.style = { 379 | width: _WindowProperties.innerWidth + 'px', 380 | height: _WindowProperties.innerHeight + 'px' 381 | }; 382 | _this.insertBefore = _util.noop; 383 | _this.innerHTML = ''; 384 | 385 | _this.tagName = tagName.toUpperCase(); 386 | return _this; 387 | } 388 | 389 | _createClass(HTMLElement, [{ 390 | key: 'setAttribute', 391 | value: function setAttribute(name, value) { 392 | this[name] = value; 393 | } 394 | }, { 395 | key: 'getAttribute', 396 | value: function getAttribute(name) { 397 | return this[name]; 398 | } 399 | }, { 400 | key: 'getBoundingClientRect', 401 | value: function getBoundingClientRect() { 402 | return { 403 | top: 0, 404 | left: 0, 405 | width: _WindowProperties.innerWidth, 406 | height: _WindowProperties.innerHeight 407 | }; 408 | } 409 | }, { 410 | key: 'focus', 411 | value: function focus() {} 412 | }, { 413 | key: 'clientWidth', 414 | get: function get() { 415 | var ret = parseInt(this.style.fontSize, 10) * this.innerHTML.length; 416 | 417 | return Number.isNaN(ret) ? 0 : ret; 418 | } 419 | }, { 420 | key: 'clientHeight', 421 | get: function get() { 422 | var ret = parseInt(this.style.fontSize, 10); 423 | 424 | return Number.isNaN(ret) ? 0 : ret; 425 | } 426 | }]); 427 | 428 | return HTMLElement; 429 | }(_Element3.default); 430 | 431 | exports.default = HTMLElement; 432 | 433 | /***/ }), 434 | /* 6 */ 435 | /***/ (function(module, exports, __webpack_require__) { 436 | 437 | 'use strict'; 438 | 439 | Object.defineProperty(exports, "__esModule", { 440 | value: true 441 | }); 442 | 443 | var _Node2 = __webpack_require__(7); 444 | 445 | var _Node3 = _interopRequireDefault(_Node2); 446 | 447 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 448 | 449 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 450 | 451 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 452 | 453 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 454 | 455 | var ELement = function (_Node) { 456 | _inherits(ELement, _Node); 457 | 458 | function ELement() { 459 | _classCallCheck(this, ELement); 460 | 461 | var _this = _possibleConstructorReturn(this, (ELement.__proto__ || Object.getPrototypeOf(ELement)).call(this)); 462 | 463 | _this.className = ''; 464 | _this.children = []; 465 | return _this; 466 | } 467 | 468 | return ELement; 469 | }(_Node3.default); 470 | 471 | exports.default = ELement; 472 | 473 | /***/ }), 474 | /* 7 */ 475 | /***/ (function(module, exports, __webpack_require__) { 476 | 477 | 'use strict'; 478 | 479 | Object.defineProperty(exports, "__esModule", { 480 | value: true 481 | }); 482 | 483 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 484 | 485 | var _EventTarget2 = __webpack_require__(8); 486 | 487 | var _EventTarget3 = _interopRequireDefault(_EventTarget2); 488 | 489 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 490 | 491 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 492 | 493 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 494 | 495 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 496 | 497 | var Node = function (_EventTarget) { 498 | _inherits(Node, _EventTarget); 499 | 500 | function Node() { 501 | _classCallCheck(this, Node); 502 | 503 | var _this = _possibleConstructorReturn(this, (Node.__proto__ || Object.getPrototypeOf(Node)).call(this)); 504 | 505 | _this.childNodes = []; 506 | return _this; 507 | } 508 | 509 | _createClass(Node, [{ 510 | key: 'appendChild', 511 | value: function appendChild(node) { 512 | if (node instanceof Node) { 513 | this.childNodes.push(node); 514 | } else { 515 | throw new TypeError('Failed to executed \'appendChild\' on \'Node\': parameter 1 is not of type \'Node\'.'); 516 | } 517 | } 518 | }, { 519 | key: 'cloneNode', 520 | value: function cloneNode() { 521 | var copyNode = Object.create(this); 522 | 523 | Object.assign(copyNode, this); 524 | return copyNode; 525 | } 526 | }, { 527 | key: 'removeChild', 528 | value: function removeChild(node) { 529 | var index = this.childNodes.findIndex(function (child) { 530 | return child === node; 531 | }); 532 | 533 | if (index > -1) { 534 | return this.childNodes.splice(index, 1); 535 | } 536 | return null; 537 | } 538 | }]); 539 | 540 | return Node; 541 | }(_EventTarget3.default); 542 | 543 | exports.default = Node; 544 | 545 | /***/ }), 546 | /* 8 */ 547 | /***/ (function(module, exports) { 548 | 549 | 'use strict'; 550 | 551 | Object.defineProperty(exports, "__esModule", { 552 | value: true 553 | }); 554 | 555 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 556 | 557 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 558 | 559 | var _events = new WeakMap(); 560 | 561 | var EventTarget = function () { 562 | function EventTarget() { 563 | _classCallCheck(this, EventTarget); 564 | 565 | _events.set(this, {}); 566 | } 567 | 568 | _createClass(EventTarget, [{ 569 | key: 'addEventListener', 570 | value: function addEventListener(type, listener) { 571 | var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; 572 | 573 | var events = _events.get(this); 574 | 575 | if (!events) { 576 | events = {}; 577 | _events.set(this, events); 578 | } 579 | if (!events[type]) { 580 | events[type] = []; 581 | } 582 | events[type].push(listener); 583 | 584 | if (options.capture) { 585 | console.warn('EventTarget.addEventListener: options.capture is not implemented.'); 586 | } 587 | if (options.once) { 588 | console.warn('EventTarget.addEventListener: options.once is not implemented.'); 589 | } 590 | if (options.passive) { 591 | console.warn('EventTarget.addEventListener: options.passive is not implemented.'); 592 | } 593 | } 594 | }, { 595 | key: 'removeEventListener', 596 | value: function removeEventListener(type, listener) { 597 | var listeners = _events.get(this)[type]; 598 | 599 | if (listeners && listeners.length > 0) { 600 | for (var i = listeners.length; i--; i > 0) { 601 | if (listeners[i] === listener) { 602 | listeners.splice(i, 1); 603 | break; 604 | } 605 | } 606 | } 607 | } 608 | }, { 609 | key: 'dispatchEvent', 610 | value: function dispatchEvent() { 611 | var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 612 | 613 | var listeners = _events.get(this)[event.type]; 614 | 615 | if (listeners) { 616 | for (var i = 0; i < listeners.length; i++) { 617 | listeners[i](event); 618 | } 619 | } 620 | } 621 | }]); 622 | 623 | return EventTarget; 624 | }(); 625 | 626 | exports.default = EventTarget; 627 | 628 | /***/ }), 629 | /* 9 */ 630 | /***/ (function(module, exports) { 631 | 632 | "use strict"; 633 | 634 | Object.defineProperty(exports, "__esModule", { 635 | value: true 636 | }); 637 | exports.noop = noop; 638 | function noop() {} 639 | 640 | /***/ }), 641 | /* 10 */ 642 | /***/ (function(module, exports, __webpack_require__) { 643 | 644 | 'use strict'; 645 | 646 | Object.defineProperty(exports, "__esModule", { 647 | value: true 648 | }); 649 | exports.default = Canvas; 650 | 651 | var _constructor = __webpack_require__(4); 652 | 653 | var _HTMLElement = __webpack_require__(5); 654 | 655 | var _HTMLElement2 = _interopRequireDefault(_HTMLElement); 656 | 657 | var _document = __webpack_require__(11); 658 | 659 | var _document2 = _interopRequireDefault(_document); 660 | 661 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 662 | 663 | var hasModifiedCanvasPrototype = false; 664 | var hasInit2DContextConstructor = false; 665 | var hasInitWebGLContextConstructor = false; 666 | 667 | function Canvas() { 668 | var canvas = wx.createCanvas(); 669 | 670 | canvas.type = 'canvas'; 671 | 672 | canvas.__proto__.__proto__ = new _HTMLElement2.default('canvas'); 673 | 674 | var _getContext = canvas.getContext; 675 | 676 | canvas.getBoundingClientRect = function () { 677 | var ret = { 678 | top: 0, 679 | left: 0, 680 | width: window.innerWidth, 681 | height: window.innerHeight 682 | }; 683 | return ret; 684 | }; 685 | 686 | return canvas; 687 | } 688 | 689 | /***/ }), 690 | /* 11 */ 691 | /***/ (function(module, exports, __webpack_require__) { 692 | 693 | 'use strict'; 694 | 695 | Object.defineProperty(exports, "__esModule", { 696 | value: true 697 | }); 698 | 699 | var _window = __webpack_require__(1); 700 | 701 | var window = _interopRequireWildcard(_window); 702 | 703 | var _HTMLElement = __webpack_require__(5); 704 | 705 | var _HTMLElement2 = _interopRequireDefault(_HTMLElement); 706 | 707 | var _Image = __webpack_require__(12); 708 | 709 | var _Image2 = _interopRequireDefault(_Image); 710 | 711 | var _Audio = __webpack_require__(13); 712 | 713 | var _Audio2 = _interopRequireDefault(_Audio); 714 | 715 | var _Canvas = __webpack_require__(10); 716 | 717 | var _Canvas2 = _interopRequireDefault(_Canvas); 718 | 719 | __webpack_require__(16); 720 | 721 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 722 | 723 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 724 | 725 | var events = {}; 726 | 727 | var document = { 728 | readyState: 'complete', 729 | visibilityState: 'visible', 730 | documentElement: window, 731 | hidden: false, 732 | style: {}, 733 | location: window.location, 734 | ontouchstart: null, 735 | ontouchmove: null, 736 | ontouchend: null, 737 | 738 | head: new _HTMLElement2.default('head'), 739 | body: new _HTMLElement2.default('body'), 740 | 741 | createElement: function createElement(tagName) { 742 | if (tagName === 'canvas') { 743 | return new _Canvas2.default(); 744 | } else if (tagName === 'audio') { 745 | return new _Audio2.default(); 746 | } else if (tagName === 'img') { 747 | return new _Image2.default(); 748 | } 749 | 750 | return new _HTMLElement2.default(tagName); 751 | }, 752 | getElementById: function getElementById(id) { 753 | if (id === window.canvas.id) { 754 | return window.canvas; 755 | } 756 | return null; 757 | }, 758 | getElementsByTagName: function getElementsByTagName(tagName) { 759 | if (tagName === 'head') { 760 | return [document.head]; 761 | } else if (tagName === 'body') { 762 | return [document.body]; 763 | } else if (tagName === 'canvas') { 764 | return [window.canvas]; 765 | } 766 | return []; 767 | }, 768 | getElementsByName: function getElementsByName(tagName) { 769 | if (tagName === 'head') { 770 | return [document.head]; 771 | } else if (tagName === 'body') { 772 | return [document.body]; 773 | } else if (tagName === 'canvas') { 774 | return [window.canvas]; 775 | } 776 | return []; 777 | }, 778 | querySelector: function querySelector(query) { 779 | if (query === 'head') { 780 | return document.head; 781 | } else if (query === 'body') { 782 | return document.body; 783 | } else if (query === 'canvas') { 784 | return window.canvas; 785 | } else if (query === '#' + window.canvas.id) { 786 | return window.canvas; 787 | } 788 | return null; 789 | }, 790 | querySelectorAll: function querySelectorAll(query) { 791 | if (query === 'head') { 792 | return [document.head]; 793 | } else if (query === 'body') { 794 | return [document.body]; 795 | } else if (query === 'canvas') { 796 | return [window.canvas]; 797 | } 798 | return []; 799 | }, 800 | addEventListener: function addEventListener(type, listener) { 801 | if (!events[type]) { 802 | events[type] = []; 803 | } 804 | events[type].push(listener); 805 | }, 806 | removeEventListener: function removeEventListener(type, listener) { 807 | var listeners = events[type]; 808 | 809 | if (listeners && listeners.length > 0) { 810 | for (var i = listeners.length; i--; i > 0) { 811 | if (listeners[i] === listener) { 812 | listeners.splice(i, 1); 813 | break; 814 | } 815 | } 816 | } 817 | }, 818 | dispatchEvent: function dispatchEvent(event) { 819 | var listeners = events[event.type]; 820 | 821 | if (listeners) { 822 | for (var i = 0; i < listeners.length; i++) { 823 | listeners[i](event); 824 | } 825 | } 826 | } 827 | }; 828 | 829 | exports.default = document; 830 | 831 | /***/ }), 832 | /* 12 */ 833 | /***/ (function(module, exports) { 834 | 835 | "use strict"; 836 | 837 | Object.defineProperty(exports, "__esModule", { 838 | value: true 839 | }); 840 | exports.default = Image; 841 | function Image() { 842 | var image = wx.createImage(); 843 | 844 | return image; 845 | } 846 | 847 | /***/ }), 848 | /* 13 */ 849 | /***/ (function(module, exports, __webpack_require__) { 850 | 851 | 'use strict'; 852 | 853 | Object.defineProperty(exports, "__esModule", { 854 | value: true 855 | }); 856 | 857 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 858 | 859 | var _HTMLAudioElement2 = __webpack_require__(14); 860 | 861 | var _HTMLAudioElement3 = _interopRequireDefault(_HTMLAudioElement2); 862 | 863 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 864 | 865 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 866 | 867 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 868 | 869 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 870 | 871 | var HAVE_NOTHING = 0; 872 | var HAVE_METADATA = 1; 873 | var HAVE_CURRENT_DATA = 2; 874 | var HAVE_FUTURE_DATA = 3; 875 | var HAVE_ENOUGH_DATA = 4; 876 | 877 | var _innerAudioContext = new WeakMap(); 878 | var _src = new WeakMap(); 879 | var _loop = new WeakMap(); 880 | var _autoplay = new WeakMap(); 881 | 882 | var Audio = function (_HTMLAudioElement) { 883 | _inherits(Audio, _HTMLAudioElement); 884 | 885 | function Audio(url) { 886 | _classCallCheck(this, Audio); 887 | 888 | var _this = _possibleConstructorReturn(this, (Audio.__proto__ || Object.getPrototypeOf(Audio)).call(this)); 889 | 890 | _this.HAVE_NOTHING = HAVE_NOTHING; 891 | _this.HAVE_METADATA = HAVE_METADATA; 892 | _this.HAVE_CURRENT_DATA = HAVE_CURRENT_DATA; 893 | _this.HAVE_FUTURE_DATA = HAVE_FUTURE_DATA; 894 | _this.HAVE_ENOUGH_DATA = HAVE_ENOUGH_DATA; 895 | _this.readyState = HAVE_NOTHING; 896 | 897 | 898 | _src.set(_this, ''); 899 | // 针对phaser3加入 900 | _this.dataset = {}; 901 | var innerAudioContext = wx.createInnerAudioContext(); 902 | 903 | _innerAudioContext.set(_this, innerAudioContext); 904 | 905 | innerAudioContext.onCanplay(function () { 906 | _this.dispatchEvent({ type: 'load' }); 907 | _this.dispatchEvent({ type: 'loadend' }); 908 | _this.dispatchEvent({ type: 'canplay' }); 909 | _this.dispatchEvent({ type: 'canplaythrough' }); 910 | _this.dispatchEvent({ type: 'loadedmetadata' }); 911 | _this.readyState = HAVE_CURRENT_DATA; 912 | }); 913 | innerAudioContext.onPlay(function () { 914 | _this.dispatchEvent({ type: 'play' }); 915 | }); 916 | innerAudioContext.onPause(function () { 917 | _this.dispatchEvent({ type: 'pause' }); 918 | }); 919 | innerAudioContext.onEnded(function () { 920 | _this.dispatchEvent({ type: 'ended' }); 921 | _this.readyState = HAVE_ENOUGH_DATA; 922 | }); 923 | innerAudioContext.onError(function () { 924 | _this.dispatchEvent({ type: 'error' }); 925 | }); 926 | 927 | if (url) { 928 | _innerAudioContext.get(_this).src = url; 929 | } 930 | return _this; 931 | } 932 | 933 | _createClass(Audio, [{ 934 | key: 'load', 935 | value: function load() { 936 | console.warn('HTMLAudioElement.load() is not implemented.'); 937 | } 938 | }, { 939 | key: 'play', 940 | value: function play() { 941 | _innerAudioContext.get(this).play(); 942 | } 943 | }, { 944 | key: 'pause', 945 | value: function pause() { 946 | _innerAudioContext.get(this).pause(); 947 | } 948 | }, { 949 | key: 'canPlayType', 950 | value: function canPlayType() { 951 | var mediaType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; 952 | 953 | if (typeof mediaType !== 'string') { 954 | return ''; 955 | } 956 | 957 | if (mediaType.indexOf('audio/mpeg') > -1 || mediaType.indexOf('audio/mp4')) { 958 | return 'probably'; 959 | } 960 | return ''; 961 | } 962 | }, { 963 | key: 'cloneNode', 964 | value: function cloneNode() { 965 | var newAudio = new Audio(); 966 | newAudio.loop = _innerAudioContext.get(this).loop; 967 | newAudio.autoplay = _innerAudioContext.get(this).autoplay; 968 | newAudio.src = this.src; 969 | return newAudio; 970 | } 971 | }, { 972 | key: 'currentTime', 973 | get: function get() { 974 | return _innerAudioContext.get(this).currentTime; 975 | }, 976 | set: function set(value) { 977 | _innerAudioContext.get(this).seek(value); 978 | } 979 | }, { 980 | key: 'src', 981 | get: function get() { 982 | return _src.get(this); 983 | }, 984 | set: function set(value) { 985 | _src.set(this, value); 986 | _innerAudioContext.get(this).src = value; 987 | } 988 | }, { 989 | key: 'loop', 990 | get: function get() { 991 | return _innerAudioContext.get(this).loop; 992 | }, 993 | set: function set(value) { 994 | _innerAudioContext.get(this).loop = value; 995 | } 996 | }, { 997 | key: 'autoplay', 998 | get: function get() { 999 | return _innerAudioContext.get(this).autoplay; 1000 | }, 1001 | set: function set(value) { 1002 | _innerAudioContext.get(this).autoplay = value; 1003 | } 1004 | }, { 1005 | key: 'paused', 1006 | get: function get() { 1007 | return _innerAudioContext.get(this).paused; 1008 | } 1009 | }]); 1010 | 1011 | return Audio; 1012 | }(_HTMLAudioElement3.default); 1013 | 1014 | exports.default = Audio; 1015 | 1016 | /***/ }), 1017 | /* 14 */ 1018 | /***/ (function(module, exports, __webpack_require__) { 1019 | 1020 | 'use strict'; 1021 | 1022 | Object.defineProperty(exports, "__esModule", { 1023 | value: true 1024 | }); 1025 | 1026 | var _HTMLMediaElement2 = __webpack_require__(15); 1027 | 1028 | var _HTMLMediaElement3 = _interopRequireDefault(_HTMLMediaElement2); 1029 | 1030 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1031 | 1032 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1033 | 1034 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 1035 | 1036 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 1037 | 1038 | var HTMLAudioElement = function (_HTMLMediaElement) { 1039 | _inherits(HTMLAudioElement, _HTMLMediaElement); 1040 | 1041 | function HTMLAudioElement() { 1042 | _classCallCheck(this, HTMLAudioElement); 1043 | 1044 | return _possibleConstructorReturn(this, (HTMLAudioElement.__proto__ || Object.getPrototypeOf(HTMLAudioElement)).call(this, 'audio')); 1045 | } 1046 | 1047 | return HTMLAudioElement; 1048 | }(_HTMLMediaElement3.default); 1049 | 1050 | exports.default = HTMLAudioElement; 1051 | 1052 | /***/ }), 1053 | /* 15 */ 1054 | /***/ (function(module, exports, __webpack_require__) { 1055 | 1056 | 'use strict'; 1057 | 1058 | Object.defineProperty(exports, "__esModule", { 1059 | value: true 1060 | }); 1061 | 1062 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1063 | 1064 | var _HTMLElement2 = __webpack_require__(5); 1065 | 1066 | var _HTMLElement3 = _interopRequireDefault(_HTMLElement2); 1067 | 1068 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1069 | 1070 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1071 | 1072 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 1073 | 1074 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 1075 | 1076 | var HTMLMediaElement = function (_HTMLElement) { 1077 | _inherits(HTMLMediaElement, _HTMLElement); 1078 | 1079 | function HTMLMediaElement(type) { 1080 | _classCallCheck(this, HTMLMediaElement); 1081 | 1082 | return _possibleConstructorReturn(this, (HTMLMediaElement.__proto__ || Object.getPrototypeOf(HTMLMediaElement)).call(this, type)); 1083 | } 1084 | 1085 | _createClass(HTMLMediaElement, [{ 1086 | key: 'addTextTrack', 1087 | value: function addTextTrack() {} 1088 | }, { 1089 | key: 'captureStream', 1090 | value: function captureStream() {} 1091 | }, { 1092 | key: 'fastSeek', 1093 | value: function fastSeek() {} 1094 | }, { 1095 | key: 'load', 1096 | value: function load() {} 1097 | }, { 1098 | key: 'pause', 1099 | value: function pause() {} 1100 | }, { 1101 | key: 'play', 1102 | value: function play() {} 1103 | }]); 1104 | 1105 | return HTMLMediaElement; 1106 | }(_HTMLElement3.default); 1107 | 1108 | exports.default = HTMLMediaElement; 1109 | 1110 | /***/ }), 1111 | /* 16 */ 1112 | /***/ (function(module, exports, __webpack_require__) { 1113 | 1114 | 'use strict'; 1115 | 1116 | __webpack_require__(17); 1117 | 1118 | /***/ }), 1119 | /* 17 */ 1120 | /***/ (function(module, exports, __webpack_require__) { 1121 | 1122 | 'use strict'; 1123 | 1124 | var _window = __webpack_require__(1); 1125 | 1126 | var window = _interopRequireWildcard(_window); 1127 | 1128 | var _document = __webpack_require__(11); 1129 | 1130 | var _document2 = _interopRequireDefault(_document); 1131 | 1132 | var _util = __webpack_require__(9); 1133 | 1134 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1135 | 1136 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 1137 | 1138 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1139 | 1140 | var TouchEvent = function TouchEvent(type) { 1141 | _classCallCheck(this, TouchEvent); 1142 | 1143 | this.target = window.canvas; 1144 | this.currentTarget = window.canvas; 1145 | this.touches = []; 1146 | this.targetTouches = []; 1147 | this.changedTouches = []; 1148 | this.preventDefault = _util.noop; 1149 | this.stopPropagation = _util.noop; 1150 | 1151 | this.type = type; 1152 | }; 1153 | 1154 | function touchEventHandlerFactory(type) { 1155 | return function (event) { 1156 | var touchEvent = new TouchEvent(type); 1157 | 1158 | touchEvent.touches = event.touches; 1159 | touchEvent.targetTouches = Array.prototype.slice.call(event.touches); 1160 | touchEvent.changedTouches = event.changedTouches; 1161 | touchEvent.timeStamp = event.timeStamp; 1162 | _document2.default.dispatchEvent(touchEvent); 1163 | }; 1164 | } 1165 | 1166 | wx.onTouchStart(touchEventHandlerFactory('touchstart')); 1167 | wx.onTouchMove(touchEventHandlerFactory('touchmove')); 1168 | wx.onTouchEnd(touchEventHandlerFactory('touchend')); 1169 | wx.onTouchCancel(touchEventHandlerFactory('touchcancel')); 1170 | 1171 | /***/ }), 1172 | /* 18 */ 1173 | /***/ (function(module, exports, __webpack_require__) { 1174 | 1175 | 'use strict'; 1176 | 1177 | Object.defineProperty(exports, "__esModule", { 1178 | value: true 1179 | }); 1180 | 1181 | var _util = __webpack_require__(9); 1182 | 1183 | // TODO 需要 wx.getSystemInfo 获取更详细信息 1184 | var _wx$getSystemInfoSync = wx.getSystemInfoSync(), 1185 | platform = _wx$getSystemInfoSync.platform; 1186 | 1187 | var navigator = { 1188 | platform: platform, 1189 | language: 'zh-cn', 1190 | appVersion: '5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1', 1191 | userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E8301 MicroMessenger/6.6.0 MiniGame NetType/WIFI Language/zh_CN', 1192 | onLine: true, // TODO 用 wx.getNetworkStateChange 和 wx.onNetworkStateChange 来返回真实的状态 1193 | 1194 | // TODO 用 wx.getLocation 来封装 geolocation 1195 | geolocation: { 1196 | getCurrentPosition: _util.noop, 1197 | watchPosition: _util.noop, 1198 | clearWatch: _util.noop 1199 | } 1200 | }; 1201 | 1202 | exports.default = navigator; 1203 | 1204 | /***/ }), 1205 | /* 19 */ 1206 | /***/ (function(module, exports) { 1207 | 1208 | 'use strict'; 1209 | 1210 | Object.defineProperty(exports, "__esModule", { 1211 | value: true 1212 | }); 1213 | 1214 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1215 | 1216 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1217 | 1218 | var _url = new WeakMap(); 1219 | var _method = new WeakMap(); 1220 | var _requestHeader = new WeakMap(); 1221 | var _responseHeader = new WeakMap(); 1222 | var _requestTask = new WeakMap(); 1223 | 1224 | function _triggerEvent(type) { 1225 | if (typeof this['on' + type] === 'function') { 1226 | for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 1227 | args[_key - 1] = arguments[_key]; 1228 | } 1229 | 1230 | args[0] = { target: { status: 200 } }; 1231 | this['on' + type].apply(this, args); 1232 | } 1233 | } 1234 | 1235 | function _changeReadyState(readyState) { 1236 | this.readyState = readyState; 1237 | _triggerEvent.call(this, 'readystatechange'); 1238 | } 1239 | 1240 | var XMLHttpRequest = function () { 1241 | // TODO 没法模拟 HEADERS_RECEIVED 和 LOADING 两个状态 1242 | function XMLHttpRequest() { 1243 | _classCallCheck(this, XMLHttpRequest); 1244 | 1245 | this.onabort = null; 1246 | this.onerror = null; 1247 | this.onload = null; 1248 | this.onloadstart = null; 1249 | this.onprogress = null; 1250 | this.ontimeout = null; 1251 | this.onloadend = null; 1252 | this.onreadystatechange = null; 1253 | this.readyState = 0; 1254 | this.response = null; 1255 | this.responseText = null; 1256 | this.responseType = ''; 1257 | this.responseXML = null; 1258 | this.status = 0; 1259 | this.statusText = ''; 1260 | this.upload = {}; 1261 | this.withCredentials = false; 1262 | 1263 | _requestHeader.set(this, { 1264 | 'content-type': 'application/x-www-form-urlencoded' 1265 | }); 1266 | _responseHeader.set(this, {}); 1267 | } 1268 | 1269 | /* 1270 | * TODO 这一批事件应该是在 XMLHttpRequestEventTarget.prototype 上面的 1271 | */ 1272 | 1273 | 1274 | _createClass(XMLHttpRequest, [{ 1275 | key: 'abort', 1276 | value: function abort() { 1277 | var myRequestTask = _requestTask.get(this); 1278 | 1279 | if (myRequestTask) { 1280 | myRequestTask.abort(); 1281 | } 1282 | } 1283 | }, { 1284 | key: 'getAllResponseHeaders', 1285 | value: function getAllResponseHeaders() { 1286 | var responseHeader = _responseHeader.get(this); 1287 | 1288 | return Object.keys(responseHeader).map(function (header) { 1289 | return header + ': ' + responseHeader[header]; 1290 | }).join('\n'); 1291 | } 1292 | }, { 1293 | key: 'getResponseHeader', 1294 | value: function getResponseHeader(header) { 1295 | return _responseHeader.get(this)[header]; 1296 | } 1297 | }, { 1298 | key: 'open', 1299 | value: function open(method, url /* async, user, password 这几个参数在小程序内不支持*/) { 1300 | _method.set(this, method); 1301 | _url.set(this, url); 1302 | _changeReadyState.call(this, XMLHttpRequest.OPENED); 1303 | } 1304 | }, { 1305 | key: 'overrideMimeType', 1306 | value: function overrideMimeType() {} 1307 | }, { 1308 | key: 'send', 1309 | value: function send() { 1310 | var _this = this; 1311 | 1312 | var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; 1313 | 1314 | if (this.readyState !== XMLHttpRequest.OPENED) { 1315 | throw new Error("Failed to execute 'send' on 'XMLHttpRequest': The object's state must be OPENED."); 1316 | } else { 1317 | // 对于phaser3使用blob类型,微信并不支持,所以使用微信支付的arraybuffer作为传输类型 1318 | // 之后在其它地方将其处理成对应的内容 1319 | if (this.responseType === "blob") { 1320 | this.responseType = "arraybuffer"; 1321 | } 1322 | wx.request({ 1323 | data: data, 1324 | url: _url.get(this), 1325 | method: _method.get(this), 1326 | header: _requestHeader.get(this), 1327 | responseType: this.responseType, 1328 | success: function success(_ref) { 1329 | var data = _ref.data, 1330 | statusCode = _ref.statusCode, 1331 | header = _ref.header; 1332 | 1333 | if (typeof data !== 'string' && !(data instanceof ArrayBuffer)) { 1334 | try { 1335 | data = JSON.stringify(data); 1336 | } catch (e) { 1337 | data = data; 1338 | } 1339 | } 1340 | 1341 | _this.status = statusCode; 1342 | _responseHeader.set(_this, header); 1343 | _triggerEvent.call(_this, 'loadstart'); 1344 | _changeReadyState.call(_this, XMLHttpRequest.HEADERS_RECEIVED); 1345 | _changeReadyState.call(_this, XMLHttpRequest.LOADING); 1346 | 1347 | _this.response = data; 1348 | 1349 | if (data instanceof ArrayBuffer) { 1350 | _this.responseText = ''; 1351 | var bytes = new Uint8Array(data); 1352 | var len = bytes.byteLength; 1353 | 1354 | for (var i = 0; i < len; i++) { 1355 | _this.responseText += String.fromCharCode(bytes[i]); 1356 | } 1357 | } else { 1358 | _this.responseText = data; 1359 | } 1360 | _changeReadyState.call(_this, XMLHttpRequest.DONE); 1361 | _triggerEvent.call(_this, 'load'); 1362 | _triggerEvent.call(_this, 'loadend'); 1363 | }, 1364 | fail: function fail(_ref2) { 1365 | var errMsg = _ref2.errMsg; 1366 | 1367 | // TODO 规范错误 1368 | if (errMsg.indexOf('abort') !== -1) { 1369 | _triggerEvent.call(_this, 'abort'); 1370 | } else { 1371 | _triggerEvent.call(_this, 'error', errMsg); 1372 | } 1373 | _triggerEvent.call(_this, 'loadend'); 1374 | } 1375 | }); 1376 | } 1377 | } 1378 | }, { 1379 | key: 'setRequestHeader', 1380 | value: function setRequestHeader(header, value) { 1381 | var myHeader = _requestHeader.get(this); 1382 | 1383 | myHeader[header] = value; 1384 | _requestHeader.set(this, myHeader); 1385 | } 1386 | }]); 1387 | 1388 | return XMLHttpRequest; 1389 | }(); 1390 | 1391 | XMLHttpRequest.UNSEND = 0; 1392 | XMLHttpRequest.OPENED = 1; 1393 | XMLHttpRequest.HEADERS_RECEIVED = 2; 1394 | XMLHttpRequest.LOADING = 3; 1395 | XMLHttpRequest.DONE = 4; 1396 | exports.default = XMLHttpRequest; 1397 | 1398 | /***/ }), 1399 | /* 20 */ 1400 | /***/ (function(module, exports) { 1401 | 1402 | 'use strict'; 1403 | 1404 | Object.defineProperty(exports, "__esModule", { 1405 | value: true 1406 | }); 1407 | 1408 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1409 | 1410 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1411 | 1412 | var _socketTask = new WeakMap(); 1413 | 1414 | var WebSocket = function () { 1415 | // TODO 更新 binaryType 1416 | // The connection is in the process of closing. 1417 | // The connection is not yet open. 1418 | function WebSocket(url) { 1419 | var _this = this; 1420 | 1421 | var protocols = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; 1422 | 1423 | _classCallCheck(this, WebSocket); 1424 | 1425 | this.binaryType = ''; 1426 | this.bufferedAmount = 0; 1427 | this.extensions = ''; 1428 | this.onclose = null; 1429 | this.onerror = null; 1430 | this.onmessage = null; 1431 | this.onopen = null; 1432 | this.protocol = ''; 1433 | this.readyState = 3; 1434 | 1435 | if (typeof url !== 'string' || !/(^ws:\/\/)|(^wss:\/\/)/.test(url)) { 1436 | throw new TypeError('Failed to construct \'WebSocket\': The URL \'' + url + '\' is invalid'); 1437 | } 1438 | 1439 | this.url = url; 1440 | this.readyState = WebSocket.CONNECTING; 1441 | 1442 | var socketTask = wx.connectSocket({ 1443 | url: url, 1444 | protocols: Array.isArray(protocols) ? protocols : [protocols] 1445 | }); 1446 | 1447 | _socketTask.set(this, socketTask); 1448 | 1449 | socketTask.onClose(function (res) { 1450 | _this.readyState = WebSocket.CLOSED; 1451 | if (typeof _this.onclose === 'function') { 1452 | _this.onclose(res); 1453 | } 1454 | }); 1455 | 1456 | socketTask.onMessage(function (res) { 1457 | if (typeof _this.onmessage === 'function') { 1458 | _this.onmessage(res); 1459 | } 1460 | }); 1461 | 1462 | socketTask.onOpen(function () { 1463 | _this.readyState = WebSocket.OPEN; 1464 | if (typeof _this.onopen === 'function') { 1465 | _this.onopen(); 1466 | } 1467 | }); 1468 | 1469 | socketTask.onError(function (res) { 1470 | if (typeof _this.onerror === 'function') { 1471 | _this.onerror(new Error(res.errMsg)); 1472 | } 1473 | }); 1474 | 1475 | return this; 1476 | } // TODO 小程序内目前获取不到,实际上需要根据服务器选择的 sub-protocol 返回 1477 | // TODO 更新 bufferedAmount 1478 | // The connection is closed or couldn't be opened. 1479 | 1480 | // The connection is open and ready to communicate. 1481 | 1482 | 1483 | _createClass(WebSocket, [{ 1484 | key: 'close', 1485 | value: function close(code, reason) { 1486 | this.readyState = WebSocket.CLOSING; 1487 | var socketTask = _socketTask.get(this); 1488 | 1489 | socketTask.close({ 1490 | code: code, 1491 | reason: reason 1492 | }); 1493 | } 1494 | }, { 1495 | key: 'send', 1496 | value: function send(data) { 1497 | if (typeof data !== 'string' && !(data instanceof ArrayBuffer)) { 1498 | throw new TypeError('Failed to send message: The data ' + data + ' is invalid'); 1499 | } 1500 | 1501 | var socketTask = _socketTask.get(this); 1502 | 1503 | socketTask.send({ 1504 | data: data 1505 | }); 1506 | } 1507 | }]); 1508 | 1509 | return WebSocket; 1510 | }(); 1511 | 1512 | WebSocket.CONNECTING = 0; 1513 | WebSocket.OPEN = 1; 1514 | WebSocket.CLOSING = 2; 1515 | WebSocket.CLOSED = 3; 1516 | exports.default = WebSocket; 1517 | 1518 | /***/ }), 1519 | /* 21 */ 1520 | /***/ (function(module, exports) { 1521 | 1522 | "use strict"; 1523 | 1524 | Object.defineProperty(exports, "__esModule", { 1525 | value: true 1526 | }); 1527 | 1528 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1529 | 1530 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1531 | 1532 | /* 1533 | * TODO 使用 wx.readFile 来封装 FileReader 1534 | */ 1535 | var FileReader = function () { 1536 | function FileReader() { 1537 | _classCallCheck(this, FileReader); 1538 | } 1539 | 1540 | _createClass(FileReader, [{ 1541 | key: "construct", 1542 | value: function construct() {} 1543 | }]); 1544 | 1545 | return FileReader; 1546 | }(); 1547 | 1548 | exports.default = FileReader; 1549 | 1550 | /***/ }), 1551 | /* 22 */ 1552 | /***/ (function(module, exports) { 1553 | 1554 | "use strict"; 1555 | 1556 | Object.defineProperty(exports, "__esModule", { 1557 | value: true 1558 | }); 1559 | var localStorage = { 1560 | get length() { 1561 | var _wx$getStorageInfoSyn = wx.getStorageInfoSync(), 1562 | keys = _wx$getStorageInfoSyn.keys; 1563 | 1564 | return keys.length; 1565 | }, 1566 | 1567 | key: function key(n) { 1568 | var _wx$getStorageInfoSyn2 = wx.getStorageInfoSync(), 1569 | keys = _wx$getStorageInfoSyn2.keys; 1570 | 1571 | return keys[n]; 1572 | }, 1573 | getItem: function getItem(key) { 1574 | return wx.getStorageSync(key); 1575 | }, 1576 | setItem: function setItem(key, value) { 1577 | return wx.setStorageSync(key, value); 1578 | }, 1579 | removeItem: function removeItem(key) { 1580 | wx.removeStorageSync(key); 1581 | }, 1582 | clear: function clear() { 1583 | wx.clearStorageSync(); 1584 | } 1585 | }; 1586 | 1587 | exports.default = localStorage; 1588 | 1589 | /***/ }), 1590 | /* 23 */ 1591 | /***/ (function(module, exports) { 1592 | 1593 | 'use strict'; 1594 | 1595 | Object.defineProperty(exports, "__esModule", { 1596 | value: true 1597 | }); 1598 | var location = { 1599 | href: 'game.js', 1600 | reload: function reload() {} 1601 | }; 1602 | 1603 | exports.default = location; 1604 | 1605 | /***/ }), 1606 | /* 24 */ 1607 | /***/ (function(module, exports) { 1608 | 1609 | 'use strict'; 1610 | 1611 | Object.defineProperty(exports, "__esModule", { 1612 | value: true 1613 | }); 1614 | /** 1615 | * 将arrayBuffer转换为base64 1616 | * @param arrayBuffer 1617 | * @returns {string} 1618 | */ 1619 | function base64ArrayBuffer(arrayBuffer) { 1620 | var base64 = ''; 1621 | var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; 1622 | 1623 | var bytes = new Uint8Array(arrayBuffer); 1624 | var byteLength = bytes.byteLength; 1625 | var byteRemainder = byteLength % 3; 1626 | var mainLength = byteLength - byteRemainder; 1627 | 1628 | var a, b, c, d; 1629 | var chunk; 1630 | 1631 | // Main loop deals with bytes in chunks of 3 1632 | for (var i = 0; i < mainLength; i = i + 3) { 1633 | // Combine the three bytes into a single integer 1634 | chunk = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2]; 1635 | 1636 | // Use bitmasks to extract 6-bit segments from the triplet 1637 | a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18 1638 | b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12 1639 | c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6 1640 | d = chunk & 63; // 63 = 2^6 - 1 1641 | 1642 | // Convert the raw binary segments to the appropriate ASCII encoding 1643 | base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]; 1644 | } 1645 | 1646 | // Deal with the remaining bytes and padding 1647 | if (byteRemainder == 1) { 1648 | chunk = bytes[mainLength]; 1649 | 1650 | a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2 1651 | 1652 | // Set the 4 least significant bits to zero 1653 | b = (chunk & 3) << 4; // 3 = 2^2 - 1 1654 | 1655 | base64 += encodings[a] + encodings[b] + '=='; 1656 | } else if (byteRemainder == 2) { 1657 | chunk = bytes[mainLength] << 8 | bytes[mainLength + 1]; 1658 | 1659 | a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10 1660 | b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4 1661 | 1662 | // Set the 2 least significant bits to zero 1663 | c = (chunk & 15) << 2; // 15 = 2^4 - 1 1664 | 1665 | base64 += encodings[a] + encodings[b] + encodings[c] + '='; 1666 | } 1667 | 1668 | return base64; 1669 | } 1670 | 1671 | var URL = function URL() {}; 1672 | URL.createObjectURL = function (buffer) { 1673 | return "data:image/png;base64," + base64ArrayBuffer(buffer); 1674 | }; 1675 | URL.revokeObjectURL = function () { 1676 | //nothing 1677 | }; 1678 | 1679 | exports.default = URL; 1680 | 1681 | /***/ }) 1682 | /******/ ]); --------------------------------------------------------------------------------