diff --git a/packages/driver-worker/CHANGELOG.md b/packages/driver-worker/CHANGELOG.md deleted file mode 100644 index 1f9cb21164..0000000000 --- a/packages/driver-worker/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# Changelog - -## v0.7.11 - -- Chore: add `@babel/runtime` as dependency diff --git a/packages/driver-worker/README.md b/packages/driver-worker/README.md deleted file mode 100644 index b2485bc568..0000000000 --- a/packages/driver-worker/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# driver-worker - -> Worker driver for Rax. - -## Install - -```bash -$ npm install --save driver-worker -``` - -## Usage - -`worker.js` -```js -import createDriver from 'driver-worker'; -import { render } from 'rax'; -import App from './App'; - -render( - - null, - { - driver: createDriver({ postMessage, addEventListener }) - } -); -``` - -`index.js` -```js -import domRenderer from 'driver-worker/lib/renderer'; -import spawnWorker from 'worker-loader?inline!./worker.js'; - -const worker = spawnWorker(); -domRenderer({ worker }); -``` diff --git a/packages/driver-worker/package.json b/packages/driver-worker/package.json deleted file mode 100644 index e676c7b347..0000000000 --- a/packages/driver-worker/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "driver-worker", - "version": "0.7.11", - "description": "Worker driver for Rax", - "license": "BSD-3-Clause", - "main": "dist/driver-worker.min.js", - "repository": { - "type": "git", - "url": "git+https://github.com/alibaba/rax.git" - }, - "bugs": { - "url": "https://github.com/alibaba/rax/issues" - }, - "homepage": "https://github.com/alibaba/rax#readme", - "dependencies": { - "style-unit": "^3.0.0", - "@babel/runtime": "^7.14.6" - }, - "devDependencies": { - "rax": "^0.6.7" - } -} diff --git a/packages/driver-worker/src/Driver.js b/packages/driver-worker/src/Driver.js deleted file mode 100644 index e36e4df429..0000000000 --- a/packages/driver-worker/src/Driver.js +++ /dev/null @@ -1,208 +0,0 @@ -import { convertUnit, setDecimalPixelTransformer, setRpx } from 'style-unit'; - -const CLASS_NAME = 'className'; -const CLASS = 'class'; -const STYLE = 'style'; -const CHILDREN = 'children'; -const EVENT_PREFIX_REGEXP = /^on[A-Z]/; -const ADD_EVENT = 'addEvent'; -const REMOVE_EVENT = 'removeEvent'; -const EMPTY_CONTENT = ''; - -/** - * Implement rax driver interface for worker driver - */ -export default class Driver { - deviceWidth = null; - viewportWidth = 750; - eventRegistry = {}; - - constructor(document) { - this.document = document; - } - - getDeviceWidth() { - return this.deviceWidth || this.document.documentElement.clientWidth; - } - - setDeviceWidth(width) { - this.deviceWidth = width; - } - - getViewportWidth() { - return this.viewportWidth; - } - - setViewportWidth(width) { - this.viewportWidth = width; - } - - getElementById(id) { - return this.document.getElementById(id); - } - - createBody() { - const { document } = this; - return document.body; - } - - createComment(content) { - const { document } = this; - return document.createComment(content); - } - - createEmpty() { - return this.createComment(EMPTY_CONTENT); - } - - createText(text) { - return this.document.createTextNode(text); - } - - updateText(node, text) { - node.textContent = text; - } - - createElement(component) { - let node = this.document.createElement(component.type); - let props = component.props; - - this.setNativeProps(node, props); - - return node; - } - - appendChild(node, parent) { - return parent.appendChild(node); - } - - removeChild(node, parent) { - parent = parent || node.parentNode; - // Maybe has been removed when remove child - if (parent) { - parent.removeChild(node); - } - } - - replaceChild(newChild, oldChild, parent) { - parent = parent || oldChild.parentNode; - if (parent) parent.replaceChild(newChild, oldChild); - } - - insertAfter(node, after, parent) { - parent = parent || after.parentNode; - const nextSibling = after.nextSibling; - if (nextSibling) { - parent.insertBefore(node, nextSibling); - } else { - parent.appendChild(node); - } - } - - insertBefore(node, before, parent) { - parent = parent || before.parentNode; - parent.insertBefore(node, before); - } - - addEventListener(node, eventName, eventHandler, props) { - if (this.eventRegistry[eventName]) { - return this.eventRegistry[eventName]( - ADD_EVENT, - node, - eventName, - eventHandler, - props - ); - } else { - return node.addEventListener(eventName, eventHandler); - } - } - - removeEventListener(node, eventName, eventHandler, props) { - if (this.eventRegistry[eventName]) { - return this.eventRegistry[eventName]( - REMOVE_EVENT, - node, - eventName, - eventHandler, - props - ); - } else { - return node.removeEventListener(eventName, eventHandler); - } - } - - removeAllEventListeners(node) { - node._eventListeners = {}; - } - - removeAttribute(node, propKey) { - if (propKey === CLASS_NAME) { - propKey = CLASS; - } - - if (propKey in node) { - try { - // Some node property is readonly when in strict mode - node[propKey] = null; - } catch (e) { } - } - - node.removeAttribute(propKey); - } - - setAttribute(node, propKey, propValue) { - if (propKey === CLASS_NAME) { - propKey = CLASS; - } - - if (propKey in node) { - try { - // Some node property is readonly when in strict mode - node[propKey] = propValue; - } catch (e) { - node.setAttribute(propKey, propValue); - } - } else { - node.setAttribute(propKey, propValue); - } - } - - setStyles(node, styles) { - let newStyles = node.style; - - for (let prop in styles) { - let val = styles[prop]; - newStyles[prop] = convertUnit(val, prop); - } - // Assign to style for trigger style update - node.style = newStyles; - } - - beforeRender() { - // Init rem unit - const rpxRadio = this.getDeviceWidth() / this.getViewportWidth(); - setRpx(rpxRadio); - setDecimalPixelTransformer((rpx) => Math.floor(parseFloat(rpx) * rpxRadio) + 'px'); - } - - setNativeProps(node, props) { - for (let prop in props) { - let value = props[prop]; - if (prop === CHILDREN) { - continue; - } - - if (value != null) { - if (prop === STYLE) { - this.setStyles(node, value); - } else if (EVENT_PREFIX_REGEXP.test(prop)) { - let eventName = prop.slice(2).toLowerCase(); - this.addEventListener(node, eventName, value); - } else { - this.setAttribute(node, prop, value); - } - } - } - } -} diff --git a/packages/driver-worker/src/WorkerDriver.js b/packages/driver-worker/src/WorkerDriver.js deleted file mode 100644 index 87b88d5cee..0000000000 --- a/packages/driver-worker/src/WorkerDriver.js +++ /dev/null @@ -1,203 +0,0 @@ -import createWorkerGlobalScope from './worker/createWorkerGlobalScope'; -import Evaluator from './worker/Evaluator'; -import Event from './worker/Event'; -import Driver from './Driver'; -import memorized from './shared/memorized'; - -const ELEMENT_NODE = 1; -const TEXT_NODE = 3; -const COMMENT_NODE = 8; -const BODY = 'BODY'; -const IS_TOUCH_EVENTS = /^touch/; -const TO_SANITIZE = [ - 'target', - 'addedNodes', - 'removedNodes', - 'nextSibling', - 'previousSibling', -]; -const isTouchEvent = memorized((type) => IS_TOUCH_EVENTS.test(type)); - -export default class WorkerDriver extends Driver { - constructor(options = {}) { - const { postMessage, addEventListener } = options; - const workerGlobalScope = createWorkerGlobalScope(); - super(workerGlobalScope.document); - - this.evaluator = new Evaluator(postMessage); - this.nodesMap = new Map(); - this.nodeCounter = 0; - - let mutationObserver = this.createMutationObserver(postMessage); - mutationObserver.observe(this.document, { subtree: true }); - - addEventListener('message', this.handleMessage); - } - - createMutationObserver(callback) { - const MutationObserver = this.document.defaultView.MutationObserver; - return new MutationObserver(mutations => { - for (let i = mutations.length; i--;) { - let mutation = mutations[i]; - for (let j = TO_SANITIZE.length; j--;) { - let prop = TO_SANITIZE[j]; - const value = this.sanitize(mutation[prop], prop); - if (value) mutation[prop] = value; - } - } - - callback({ - type: 'MutationRecord', - mutations: this.optimizeMutations(mutations), - }); - }); - } - - /** - * Reduce size of mutations, exclude empty operation. - */ - optimizeMutations(mutations) { - const ret = []; - for (let i = 0, l = mutations.length; i < l; i++) { - const mutation = mutations[i]; - - if (mutation.type === 'childList') { - if (mutation.hasOwnProperty('addedNodes') - && mutation.addedNodes.length === 0) { - continue; - } - - if (mutation.hasOwnProperty('removedNodes') - && mutation.removedNodes.length === 0) { - continue; - } - } - - ret.push(mutation); - } - return ret; - } - - /** - * Event `message' listener. - */ - handleMessage = ({ data }) => { - const document = this.document; - switch (data.type) { - case 'init': - document.URL = data.url; - document.documentElement.clientWidth = data.width; - break; - case 'event': - this.handleEvent(data.event); - break; - case 'return': - this.handleReturn(data.return); - break; - } - }; - - /** - * Serialize instruction. - */ - sanitize(node, prop) { - if (!node || typeof node !== 'object') { - return node; - } - - if (Array.isArray(node)) { - let ret = []; - for (let i = 0, l = node.length; i < l; i ++) { - const sanitized = this.sanitize(node[i], prop); - if (sanitized !== null) ret.push(sanitized); - } - return ret; - } - - if (!node.$$id) { - node.$$id = String(++this.nodeCounter); - this.nodesMap.set(node.$$id, node); - } - - const result = { - $$id: node.$$id, - }; - - if (node.nodeName === BODY) { - result.nodeName = BODY; - } else if (prop === 'addedNodes') { - const nodeType = node.nodeType; - result.nodeType = nodeType; - - switch (nodeType) { - case ELEMENT_NODE: - result.nodeName = node.nodeName; - - const events = node._getEvents(); - if (events.length > 0) result.events = events; - if (node.attributes && node.attributes.length > 0) result.attributes = node.attributes; - if (Object.keys(node.style).length > 0) result.style = node.style; - break; - - case TEXT_NODE: - case COMMENT_NODE: - result.data = node.data; - break; - } - } - - return result; - } - - getNode(node) { - let id; - if (node && typeof node === 'object') id = node.$$id; - if (typeof node === 'string') id = node; - if (!id) return null; - if (node.nodeName === BODY) return this.document.body; - return this.nodesMap.get(id); - } - - handleEvent(rawEventObject) { - const target = this.getNode(rawEventObject.target); - - if (target) { - const { type } = rawEventObject; - const event = new Event(type, rawEventObject); - - if (isTouchEvent(type)) { - this.convertTouchTarget(event); - } - - target.dispatchEvent(event); - } - } - - handleReturn(data) { - this.evaluator.apply(data); - } - - /** - * Convert TouchEvent#$$id to targetNode - */ - extractTouchListTarget(touchList) { - for (let i = 0, l = touchList.length; i < l; i++) { - if ('$$id' in touchList[i]) { - touchList[i].target = this.getNode(touchList[i].$$id); - delete touchList[i].$$id; - } - } - } - - /** - * Extract touches and currentTouches - */ - convertTouchTarget(event) { - if (event.touches) { - this.extractTouchListTarget(event.touches); - } - if (event.changedTouches) { - this.extractTouchListTarget(event.changedTouches); - } - } -} diff --git a/packages/driver-worker/src/__tests__/__snapshots__/driver.js.snap b/packages/driver-worker/src/__tests__/__snapshots__/driver.js.snap deleted file mode 100644 index 7967786dd4..0000000000 --- a/packages/driver-worker/src/__tests__/__snapshots__/driver.js.snap +++ /dev/null @@ -1,251 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`driver-worker convertTouchTarget 1`] = ` -Event { - "bubbles": false, - "cancelable": false, - "changedTouches": Array [ - Object { - "target": "FOO", - }, - ], - "defaultPrevented": false, - "touches": Array [ - Object { - "target": "FOO", - }, - ], - "type": "touchstart", -} -`; - -exports[`driver-worker sanitize 1`] = ` -Object { - "$$id": "1", - "attributes": Array [ - Object { - "name": "foo", - "value": "bar", - }, - ], - "nodeName": "FOO", - "nodeType": 1, - "style": Object { - "color": "red", - }, -} -`; - -exports[`driver-worker sanitize 2`] = ` -Array [ - Object { - "$$id": "1", - "attributes": Array [ - Object { - "name": "foo", - "value": "bar", - }, - ], - "nodeName": "FOO", - "nodeType": 1, - "style": Object { - "color": "red", - }, - }, - Object { - "$$id": "1", - "attributes": Array [ - Object { - "name": "foo", - "value": "bar", - }, - ], - "nodeName": "FOO", - "nodeType": 1, - "style": Object { - "color": "red", - }, - }, -] -`; - -exports[`driver-worker should be drived by rax 1`] = ` -Object { - "mutations": Array [ - Object { - "addedNodes": Array [ - Object { - "$$id": "1", - "nodeName": "VIEW", - "nodeType": 1, - }, - ], - "target": Object { - "$$id": "2", - "nodeName": "BODY", - }, - "type": "childList", - }, - ], - "type": "MutationRecord", -} -`; - -exports[`driver-worker should work with setNativeProps 1`] = ` -Object { - "mutations": Array [ - Object { - "addedNodes": Array [ - Object { - "$$id": "1", - "attributes": Array [ - Object { - "name": "foo", - "value": "bar", - }, - Object { - "name": "number", - "value": 0, - }, - ], - "events": Array [ - "click", - ], - "nodeName": "VIEW", - "nodeType": 1, - }, - ], - "target": Object { - "$$id": "2", - "nodeName": "BODY", - }, - "type": "childList", - }, - ], - "type": "MutationRecord", -} -`; - -exports[`driver-worker should works with dom operation 1`] = ` -Object { - "mutations": Array [ - Object { - "addedNodes": Array [ - Object { - "$$id": "6", - "attributes": Array [ - Object { - "name": "count", - "value": 0, - }, - ], - "nodeName": "VIEW", - "nodeType": 1, - }, - ], - "target": Object { - "$$id": "3", - "nodeName": "BODY", - }, - "type": "childList", - }, - Object { - "addedNodes": Array [ - Object { - "$$id": "1", - "data": "empty", - "nodeType": 8, - }, - ], - "target": Object { - "$$id": "6", - }, - "type": "childList", - }, - Object { - "addedNodes": Array [ - Object { - "$$id": "5", - "nodeName": "BE-REMOVE", - "nodeType": 1, - }, - ], - "target": Object { - "$$id": "3", - "nodeName": "BODY", - }, - "type": "childList", - }, - Object { - "removedNodes": Array [ - Object { - "$$id": "5", - }, - ], - "target": Object { - "$$id": "3", - "nodeName": "BODY", - }, - "type": "childList", - }, - Object { - "removedNodes": Array [ - Object { - "$$id": "5", - }, - ], - "target": Object { - "$$id": "3", - "nodeName": "BODY", - }, - "type": "childList", - }, - Object { - "addedNodes": Array [ - Object { - "$$id": "5", - "nodeName": "BE-REMOVE", - "nodeType": 1, - }, - ], - "target": Object { - "$$id": "3", - "nodeName": "BODY", - }, - "type": "childList", - }, - Object { - "addedNodes": Array [ - Object { - "$$id": "4", - "nodeName": "BE-INSERT-AFTER", - "nodeType": 1, - }, - ], - "target": Object { - "$$id": "3", - "nodeName": "BODY", - }, - "type": "childList", - }, - Object { - "addedNodes": Array [ - Object { - "$$id": "2", - "nodeName": "BE-INSERT-BEFORE", - "nodeType": 1, - }, - ], - "nextSibling": Object { - "$$id": "1", - }, - "target": Object { - "$$id": "3", - "nodeName": "BODY", - }, - "type": "childList", - }, - ], - "type": "MutationRecord", -} -`; diff --git a/packages/driver-worker/src/__tests__/driver.js b/packages/driver-worker/src/__tests__/driver.js deleted file mode 100644 index 8ed6f90eaa..0000000000 --- a/packages/driver-worker/src/__tests__/driver.js +++ /dev/null @@ -1,230 +0,0 @@ -import { render, createElement } from 'rax'; -import Event from '../worker/Event'; -import createDriver from '../index'; - -describe('driver-worker', () => { - it('should be drived by rax', (done) => { - const addEventListener = () => {}; - const postMessage = (message) => { - expect(message).toMatchSnapshot(); - done(); - }; - const driver = createDriver({ addEventListener, postMessage }); - render(createElement('view'), null, { driver }); - }); - - it('should works with dom operation', (done) => { - const addEventListener = (eventName, handler) => { - // console.log('addEventListener', eventName, handler); - }; - const postMessage = (message) => { - expect(message).toMatchSnapshot(); - done(); - }; - const driver = createDriver({ addEventListener, postMessage }); - - // Create body - const body = driver.createBody(); - // Create element - const container = driver.createElement({ type: 'view', props: { count: 0 } }); - // Append child - body.appendChild(container); - // Create comment - const comment = driver.createComment('empty'); - driver.appendChild(comment, container); - - // removeChild - const toBeRemoved = driver.createElement({ type: 'be-remove' }); - body.appendChild(toBeRemoved); - driver.removeChild(toBeRemoved, body); - - // replaceChild - const toBeReplaced = driver.createElement({ type: 'be-replace' }); - const toReplace = driver.createElement({ type: 'replaced' }); - body.appendChild(toBeRemoved); - driver.replaceChild(toReplace, toBeReplaced, body); - - // insertAfter - const toBeInsertAfter = driver.createElement({ type: 'be-insert-after' }); - driver.insertAfter(toBeInsertAfter, comment, body); - - // insertBefore - const toBeInsertBefore = driver.createElement({ type: 'be-insert-before' }); - driver.insertBefore(toBeInsertBefore, comment, body); - }); - - it('should works with device width and viewport width', () => { - let sendMessageToWorker; - const addEventListener = (event, handler) => { - sendMessageToWorker = handler; - }; - const postMessage = (message) => {}; - const driver = createDriver({ addEventListener, postMessage }); - - // Default device width be undefined - expect(driver.getDeviceWidth()).toBeUndefined(); - - // Mock init event. - sendMessageToWorker({ - data: { - type: 'init', - width: 100, - }, - }); - expect(driver.getDeviceWidth()).toEqual(100); - - // Set device width - driver.setDeviceWidth(200); - expect(driver.getDeviceWidth()).toEqual(200); - - // Set viewport width - driver.setViewportWidth(100); - expect(driver.getViewportWidth()).toEqual(100); - }); - - - it('shuold work with event listener API', (done) => { - const addEventListener = (event, handler) => { }; - const postMessage = (message) => {}; - const driver = createDriver({ addEventListener, postMessage }); - - const body = driver.createBody(); - const onMove = (event) => { - throw new Error('should not fire move event.'); - }; - const el = driver.createElement({ - type: 'view', - props: { - onMove, - onClick: (event) => done(), - }, - }); - body.appendChild(el); - - driver.removeEventListener(el, 'move', onMove); - el.dispatchEvent({ - type: 'move', - target: el, - }); - - el.dispatchEvent({ - type: 'click', - target: el, - }); - }); - - it('shuold work with remove all event listeners', (done) => { - const addEventListener = (event, handler) => { }; - const postMessage = (message) => {}; - const driver = createDriver({ addEventListener, postMessage }); - - const body = driver.createBody(); - const toThrow = (event) => { - throw new Error('should not fire move event.'); - }; - const el = driver.createElement({ - type: 'view', - props: { - onMove: toThrow, - onClick: toThrow, - }, - }); - body.appendChild(el); - - // Remove all event listeners will not fire anymore. - driver.removeAllEventListeners(el); - el.dispatchEvent({ - type: 'move', - target: el, - }); - el.dispatchEvent({ - type: 'click', - target: el, - }); - done(); - }); - - it('should work with attributes', () => { - const addEventListener = (event, handler) => { }; - const postMessage = (message) => {}; - const driver = createDriver({ addEventListener, postMessage }); - - const body = driver.createBody(); - const el = driver.createElement({ - type: 'view', - }); - body.appendChild(el); - - driver.setAttribute(el, 'key', 'value'); - expect(el.getAttribute('key')).toEqual('value'); - }); - - it('should work with setNativeProps', (done) => { - const addEventListener = (event, handler) => { }; - const postMessage = (message) => { - expect(message).toMatchSnapshot(); - done(); - }; - const driver = createDriver({ addEventListener, postMessage }); - - const body = driver.createBody(); - const el = driver.createElement({ - type: 'view', - }); - driver.setNativeProps(el, { - onClick: () => {}, - foo: 'bar', - number: 0, - }); - body.appendChild(el); - }); - - it('sanitize', () => { - const addEventListener = (event, handler) => { }; - const postMessage = (message) => {}; - const driver = createDriver({ addEventListener, postMessage }); - const el = driver.createElement({ type: 'foo' }); - el.setAttribute('foo', 'bar'); - el.style = { color: 'red' }; - - expect(driver.sanitize(el, 'addedNodes')).toMatchSnapshot(); - expect(driver.sanitize([el, el], 'addedNodes')).toMatchSnapshot(); - }); - - it('convertTouchTarget', () => { - const addEventListener = (event, handler) => { }; - const postMessage = (message) => {}; - const driver = createDriver({ addEventListener, postMessage }); - const event = new Event('touchstart'); - driver.nodesMap.set('0', 'FOO'); - const touch = { - $$id: '0', - }; - event.touches = [touch]; - event.changedTouches = [touch]; - driver.convertTouchTarget(event); - - expect(event).toMatchSnapshot(); - }); - - it('appendChild', () => { - const addEventListener = (event, handler) => { }; - const postMessage = (message) => {}; - const driver = createDriver({ addEventListener, postMessage }); - const parent = driver.createElement({ type: 'parent' }); - const son = driver.createElement({ type: 'son' }); - driver.appendChild(son, parent); - expect(son.parentNode).toEqual(parent); - }); - - it('removeChild', () => { - const addEventListener = (event, handler) => { }; - const postMessage = (message) => {}; - const driver = createDriver({ addEventListener, postMessage }); - const parent = driver.createElement({ type: 'parent' }); - const son = driver.createElement({ type: 'son' }); - parent.appendChild(son); - driver.removeChild(son, parent); - expect(parent.childNodes.length).toEqual(0); - }); -}); diff --git a/packages/driver-worker/src/index.js b/packages/driver-worker/src/index.js deleted file mode 100644 index 594fdbd1f9..0000000000 --- a/packages/driver-worker/src/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import WorkerDriver from './WorkerDriver'; - -/** - * Instantiate a worker driver. - * @param options.postMessage {Function} Tunnel for send message to renderer. - * @param options.addEventListener {Function} Tunnel for driver to receive message. - * @return {WorkerDriver} - */ -export default function createDriver(options) { - return new WorkerDriver(options); -}; diff --git a/packages/driver-worker/src/shared/__tests__/camelCase.js b/packages/driver-worker/src/shared/__tests__/camelCase.js deleted file mode 100644 index c440a12cf6..0000000000 --- a/packages/driver-worker/src/shared/__tests__/camelCase.js +++ /dev/null @@ -1,19 +0,0 @@ -import camelCase from '../camelCase'; - -describe('camel case', () => { - it('should transform -foo-bar', () => { - expect(camelCase('-foo-bar')).toBe('FooBar'); - }); - - it('should transform foo-bar', () => { - expect(camelCase('foo-bar')).toBe('fooBar'); - }); - - it('should not transform foobar', () => { - expect(camelCase('foobar')).toBe('foobar'); - }); - - it('should not transform fooBar', () => { - expect(camelCase('fooBar')).toBe('fooBar'); - }); -}); diff --git a/packages/driver-worker/src/shared/__tests__/kebabCase.js b/packages/driver-worker/src/shared/__tests__/kebabCase.js deleted file mode 100644 index 9c2a100ee8..0000000000 --- a/packages/driver-worker/src/shared/__tests__/kebabCase.js +++ /dev/null @@ -1,20 +0,0 @@ -import kebabCase from '../kebabCase'; - -describe('kebab case', () => { - it('should transform fooBar', () => { - expect(kebabCase('fooBar')).toBe('foo-bar'); - }); - - it('should transform FooBar', () => { - expect(kebabCase('FooBar')).toBe('-foo-bar'); - }); - - it('should not transform foo-bar', () => { - expect(kebabCase('foo-bar')).toBe('foo-bar'); - }); - - it('should not transform foobar', () => { - expect(kebabCase('foobar')).toBe('foobar'); - }); -}); - diff --git a/packages/driver-worker/src/shared/__tests__/memorized.js b/packages/driver-worker/src/shared/__tests__/memorized.js deleted file mode 100644 index 5d4a66e358..0000000000 --- a/packages/driver-worker/src/shared/__tests__/memorized.js +++ /dev/null @@ -1,16 +0,0 @@ -import memorized from '../memorized'; - -describe('memorized', () => { - it('should memory a pure function', () => { - let count = 0; - const fn = memorized((str) => count++); - - expect(fn('key')).toEqual(0); - // Memorized by 'key'. - expect(fn('key')).toEqual(0); - // A new argument. - expect(fn('foo')).toEqual(1); - // Arguments length effects. - expect(fn('foo', true)).toEqual(2); - }); -}); diff --git a/packages/driver-worker/src/shared/__tests__/setImmediate.js b/packages/driver-worker/src/shared/__tests__/setImmediate.js deleted file mode 100644 index 2894dc5a6a..0000000000 --- a/packages/driver-worker/src/shared/__tests__/setImmediate.js +++ /dev/null @@ -1,15 +0,0 @@ -describe('setImmediate', () => { - beforeAll(() => { - global._setImmediate = global.setImmediate; - global.setImmediate = null; - }); - afterAll(() => { - global.setImmediate = global._setImmediate; - delete global._setImmediate; - }); - - it('setImmediate', (done) => { - const setImmediate = require('../setImmediate').default; - setImmediate(done); - }); -}); diff --git a/packages/driver-worker/src/shared/camelCase.js b/packages/driver-worker/src/shared/camelCase.js deleted file mode 100644 index 5977405582..0000000000 --- a/packages/driver-worker/src/shared/camelCase.js +++ /dev/null @@ -1,11 +0,0 @@ -const CAMELCASE_REG = /-[a-z]/g; -const CamelCaseCache = {}; - -export default function camelCase(str) { - return ( - CamelCaseCache[str] || - (CamelCaseCache[str] = str.replace(CAMELCASE_REG, $1 => - $1.slice(1).toUpperCase() - )) - ); -} diff --git a/packages/driver-worker/src/shared/findWhere.js b/packages/driver-worker/src/shared/findWhere.js deleted file mode 100644 index 3a13aa6925..0000000000 --- a/packages/driver-worker/src/shared/findWhere.js +++ /dev/null @@ -1,7 +0,0 @@ -export default function findWhere(arr, fn, returnIndex, byValueOnly) { - let i = arr.length; - while (i--) - if (typeof fn === 'function' && !byValueOnly ? fn(arr[i]) : arr[i] === fn) - break; - return returnIndex ? i : arr[i]; -} diff --git a/packages/driver-worker/src/shared/global.js b/packages/driver-worker/src/shared/global.js deleted file mode 100644 index 0120b437e4..0000000000 --- a/packages/driver-worker/src/shared/global.js +++ /dev/null @@ -1,5 +0,0 @@ -const global = typeof global !== 'undefined' - ? global : typeof self !== 'undefined' - ? self : new Function('return this')(); - -export default global; diff --git a/packages/driver-worker/src/shared/kebabCase.js b/packages/driver-worker/src/shared/kebabCase.js deleted file mode 100644 index 6503d8e132..0000000000 --- a/packages/driver-worker/src/shared/kebabCase.js +++ /dev/null @@ -1,20 +0,0 @@ -const KebabCache = {}; - -export default function kebabCase(string) { - if (KebabCache[string]) { - return KebabCache[string]; - } - - let kebab = ''; - for (let i = 0, l = string.length; i < l; i++) { - if (/[a-z]/.test(string[i])) { - kebab += string[i]; - } else if (/[A-Z]/.test(string[i])) { - kebab += '-' + string[i].toLowerCase(); - } else if (string[i] === '-') { - kebab += '-'; - } - } - - return KebabCache[string] = kebab; -} diff --git a/packages/driver-worker/src/shared/memorized.js b/packages/driver-worker/src/shared/memorized.js deleted file mode 100644 index 926a622977..0000000000 --- a/packages/driver-worker/src/shared/memorized.js +++ /dev/null @@ -1,15 +0,0 @@ -const hasOwnProperty = Object.prototype.hasOwnProperty; -/** - * Create a memorized version of pure function. - * @note arguments must be stringify, object or function is not acceptable. - * @param fn {Function} - */ -export default function memorized(fn) { - const cache = Object.create(null); - return function cachedFn(...args) { - const cacheKey = args.join('|'); - return hasOwnProperty.call(cache, cacheKey) - ? cache[cacheKey] - : cache[cacheKey] = fn.apply(this, args); - }; -} diff --git a/packages/driver-worker/src/shared/requestAnimationFrame.js b/packages/driver-worker/src/shared/requestAnimationFrame.js deleted file mode 100644 index f49076cee7..0000000000 --- a/packages/driver-worker/src/shared/requestAnimationFrame.js +++ /dev/null @@ -1,7 +0,0 @@ -import global from './global'; - -const requestAnimationFrame = global.requestAnimationFrame || function(cb) { - return setTimeout(cb, 16); -}; - -export default requestAnimationFrame; diff --git a/packages/driver-worker/src/shared/setImmediate.js b/packages/driver-worker/src/shared/setImmediate.js deleted file mode 100644 index c38629accd..0000000000 --- a/packages/driver-worker/src/shared/setImmediate.js +++ /dev/null @@ -1,7 +0,0 @@ -import global from './global'; - -const setImmediate = global.setImmediate || function(cb) { - return setTimeout(cb, 0); -}; - -export default setImmediate; diff --git a/packages/driver-worker/src/shared/splice.js b/packages/driver-worker/src/shared/splice.js deleted file mode 100644 index f72330b0e5..0000000000 --- a/packages/driver-worker/src/shared/splice.js +++ /dev/null @@ -1,7 +0,0 @@ -import findWhere from './findWhere'; - -export default function splice(arr, item, add, byValueOnly) { - let i = arr ? findWhere(arr, item, true, byValueOnly) : -1; - if (~i) add ? arr.splice(i, 0, add) : arr.splice(i, 1); - return i; -} diff --git a/packages/driver-worker/src/worker/Animation.js b/packages/driver-worker/src/worker/Animation.js deleted file mode 100644 index 529e0189e7..0000000000 --- a/packages/driver-worker/src/worker/Animation.js +++ /dev/null @@ -1,140 +0,0 @@ -const patchTransform = {}; - -export function dispatchAnimationToStyle(node, animationGroup) { - // properties aren't belonged to transform - const notBelongedToTransform = [ - 'opacity', - 'backgroundColor', - 'width', - 'height', - 'top', - 'left', - 'bottom', - 'right' - ]; - let nextProperties = {}; - let nextTranfrom = ''; - let transformActions = []; - - // actions about transform - animationGroup.animation.map(prop => { - let [name, value] = prop; - - if (notBelongedToTransform.indexOf(name) > -1) { - let unit = ''; - /** - * Tip: - * Currently, we are not supprt custom unit - */ - if (['opacity', 'backgroundColor'].indexOf(name) < 0) { - unit = 'px'; - } else if (name === 'backgroundColor') { - name = 'background-color'; - } - - nextProperties[name] = value + unit; - } else { - transformActions.push({ - name, - value - }); - } - }); - - // match actions and update patchTransform - transformActions.forEach(({ name, value }) => { - let defaultVal = 0; - let unit = ''; - - if (/rotate[XYZ]?$/.test(name)) { - unit = 'deg'; - } - - if (/translate/.test(name)) { - unit = 'px'; - } - // scale's defaultVal is 1 - if (/scale/.test(name)) { - defaultVal = 1; - } - - if (['rotate', 'scale', 'translate', 'skew'].indexOf(name) > -1) { - // if the rotate only has one param, it equals to rotateZ - if (name === 'rotate' && value.length === 1) { - patchTransform[`${name}Z`] = (value[0] || defaultVal) + unit; - return; - } - - if (value.length === 3) { - patchTransform[`${name}Z`] = (value[2] || defaultVal) + unit; - } - - patchTransform[`${name}X`] = (value[0] || defaultVal) + unit; - patchTransform[`${name}Y`] = (value[1] || defaultVal) + unit; - } else if (['scale3d', 'translate3d'].indexOf(name) > -1) { - // three args - patchTransform[name] = value - .map(i => `${i || defaultVal}${unit}`) - .join(','); - } else if ('rotate3d' === name) { - patchTransform[name] = - value.map(i => `${i || defaultVal}${unit}`).join(',') + 'deg'; - } else if (['matrix', 'matrix3d'].indexOf(name) > -1) { - nextTranfrom += ` ${name}(${value.join(',')})`; - } else { - // key = val - patchTransform[name] = value[0] + unit; - } - }); - - // stitching patchTransform into a string - Object.keys(patchTransform).forEach(name => { - nextTranfrom += ` ${name}(${patchTransform[name]})`; - }); - - /** - * Merge onto style cssText - * before every animationGroup setTimeout 16ms - * - * it shouldn't just assignment cssText - * but parse cssText - */ - - requestAnimationFrame(() => { - const { - duration, - timeFunction, - delay, - transformOrigin - } = animationGroup.config; - let properties = {}; - - if (node.style) { - const propList = Object.keys(node.style); - const style = {}; - const transformProperties = [ - 'transition', - 'transform', - 'transform-origin' - ]; - // traverse all properties that aren't about transform - propList.forEach((prop) => { - if ( - prop && - transformProperties.indexOf(prop) < 0 - ) { - style[prop] = node.style[prop]; - } - }); - // merge nextProperties into style - properties = Object.assign(style, nextProperties); - } - - node.style = Object.assign(node.style, { - transition: `all ${duration}ms ${timeFunction} ${delay}ms`, - transformOrigin: transformOrigin, - transform: `${nextTranfrom}`, - ...properties - }); - }); -} diff --git a/packages/driver-worker/src/worker/CanvasElement.js b/packages/driver-worker/src/worker/CanvasElement.js deleted file mode 100644 index a67fcfa97c..0000000000 --- a/packages/driver-worker/src/worker/CanvasElement.js +++ /dev/null @@ -1,12 +0,0 @@ -import Element from './Element'; -import CanvasRenderingContext2D from './CanvasRenderingContext2D'; - -export default class CanvasElement extends Element { - getContext(contextType) { - if (contextType === '2d') { - return new CanvasRenderingContext2D(this); - } else { - return null; - } - } -} diff --git a/packages/driver-worker/src/worker/CanvasRenderingContext2D.js b/packages/driver-worker/src/worker/CanvasRenderingContext2D.js deleted file mode 100644 index e97f303d9f..0000000000 --- a/packages/driver-worker/src/worker/CanvasRenderingContext2D.js +++ /dev/null @@ -1,122 +0,0 @@ -import { mutate } from './MutationObserver'; - -const CanvasContext2DMethods = [ - 'arc', - 'arcTo', - 'addHitRegion', - 'beginPath', - 'bezierCurveTo', - 'clearHitRegions', - 'clearRect', - 'clip', - 'closePath', - 'createImageData', - 'createLinearGradient', - 'createPattern', - 'createRadialGradient', - 'drawFocusIfNeeded', - 'drawImage', - 'drawWidgetAsOnScreen', - 'drawWindow', - 'ellipse', - 'fill', - 'fillRect', - 'fillText', - 'getImageData', - 'getLineDash', - 'isPointInPath', - 'isPointInStroke', - 'lineTo', - 'measureText', - 'moveTo', - 'putImageData', - 'quadraticCurveTo', - 'rect', - 'removeHitRegion', - 'resetTransform', - 'restore', - 'rotate', - 'save', - 'scale', - 'scrollPathIntoView', - 'setLineDash', - 'setTransform', - 'stroke', - 'strokeRect', - 'strokeText', - 'transform', - 'translate' -]; - -export default class CanvasRenderingContext2D { - constructor(vnode) { - this.canvas = vnode; - - let propertyValues = { - fillStyle: '#000000', - filter: 'none', - font: '10px sans-serif', - globalAlpha: 1, - globalCompositeOperation: 'source-over', - imageSmoothingEnabled: true, - imageSmoothingQuality: 'low', - lineCap: 'butt', - lineDashOffset: 0, - lineJoin: 'miter', - lineWidth: 1, - miterLimit: 10, - shadowBlur: 0, - shadowColor: 'rgba(0, 0, 0, 0)', - shadowOffsetX: 0, - shadowOffsetY: 0, - strokeStyle: '#000000', - textAlign: 'start', - textBaseline: 'alphabetic' - }; - - // context properties - const properties = [ - 'direction', - 'fillStyle', - 'filter', - 'font', - 'globalAlpha', - 'globalCompositeOperation', - 'imageSmoothingEnabled', - 'imageSmoothingQuality', - 'lineCap', - 'lineDashOffset', - 'lineJoin', - 'lineWidth', - 'miterLimit', - 'shadowBlur', - 'shadowColor', - 'shadowOffsetX', - 'shadowOffsetY', - 'strokeStyle', - 'textAlign', - 'textBaseline' - ]; - - properties.forEach(property => { - Object.defineProperty(this, property, { - get: function() { - return propertyValues[property]; - }, - set: function(value) { - propertyValues[property] = value; - } - }); - }); - - CanvasContext2DMethods.forEach(method => { - this[method] = (...args) => { - mutate(vnode, 'canvasRenderingContext2D', { - method: method, - args: args, - properties: Object.assign({}, propertyValues) - }); - }; - }); - } -} diff --git a/packages/driver-worker/src/worker/Comment.js b/packages/driver-worker/src/worker/Comment.js deleted file mode 100644 index 90c7b030dd..0000000000 --- a/packages/driver-worker/src/worker/Comment.js +++ /dev/null @@ -1,9 +0,0 @@ -import Node from './Node'; -import { COMMENT_NODE } from './NodeTypes'; - -export default class Comment extends Node { - constructor(text) { - super(COMMENT_NODE, '#comment'); - this.data = text; - } -} diff --git a/packages/driver-worker/src/worker/Document.js b/packages/driver-worker/src/worker/Document.js deleted file mode 100644 index 8dcf413c44..0000000000 --- a/packages/driver-worker/src/worker/Document.js +++ /dev/null @@ -1,57 +0,0 @@ -import { DOCUMENT_NODE } from './NodeTypes'; -import MutationObserver from './MutationObserver'; -import Node from './Node'; -import Element, { createElement, createElementNS, registerElement } from './Element'; -import CanvasElement from './CanvasElement'; -import Text from './Text'; -import Event from './Event'; -import Comment from './Comment'; - -registerElement('canvas', CanvasElement); - -export function createDocument() { - const document = new Document(); - document.appendChild(document.documentElement = createElement('html')); - document.documentElement.appendChild(document.head = document.createElement('head')); - document.documentElement.appendChild(document.body = document.createElement('body')); - return document; -} - -export default class Document extends Element { - constructor() { - super(DOCUMENT_NODE, '#DOCUMENT', null); - - this.defaultView = { - document: this, - MutationObserver, - Document, - Node, - Text, - Element, - SVGElement: Element, - Event, - Comment, - }; - } - - createElement(tagName) { - return createElement(tagName); - } - - createElementNS(namespaceURI, tagName) { - return createElementNS(namespaceURI, tagName); - } - - createComment(content) { - return new Comment(content); - } - - createTextNode(text) { - return new Text(text); - } - - getElementById(id) { - // TODO - } -} - diff --git a/packages/driver-worker/src/worker/Element.js b/packages/driver-worker/src/worker/Element.js deleted file mode 100644 index 31df5f42f1..0000000000 --- a/packages/driver-worker/src/worker/Element.js +++ /dev/null @@ -1,141 +0,0 @@ -import Node from './Node'; -import { ELEMENT_NODE } from './NodeTypes'; -import { dispatchAnimationToStyle } from './Animation'; -import { mutate } from './MutationObserver'; -import camelCase from '../shared/camelCase'; -import findWhere from '../shared/findWhere'; -import splice from '../shared/splice'; -import memorized from '../shared/memorized'; - -const IS_DATASET_REG = /^data-/; -const elementConstructors = {}; - -export function registerElement(nodeName, elementConstructor) { - elementConstructors[nodeName] = elementConstructor; -} - -export function createElement(nodeName) { - return createElementNS(null, nodeName); -} - -export function createElementNS(namespaceURI, nodeName) { - return new (elementConstructors[nodeName] || Element)(ELEMENT_NODE, nodeName, namespaceURI); -} - -export function isElement(node) { - return node && node.nodeType === ELEMENT_NODE; -} - -const isDataset = memorized(function(attrName) { - return IS_DATASET_REG.test(attrName); -}); - -const createAttributeFilter = memorized(function(ns, name) { - return o => o.ns === ns && String(o.name).toLowerCase() === String(name).toLowerCase(); -}); - -export default class Element extends Node { - attributes = []; - _style = {}; - - constructor(nodeType, nodeName, namespaceURI) { - super(nodeType || ELEMENT_NODE, nodeName.toUpperCase()); - this._namespace = namespaceURI; - } - - set className(val) { - this.setAttribute('class', val); - } - - get className() { - return this.getAttribute('class'); - } - - set id(val) { - this.setAttribute('id', val); - } - - get id() { - return this.getAttribute('id'); - } - - set animation(queues) { - this.setAttribute('animation', queues); - if (Array.isArray(queues) && queues.length > 0) { - const handleAnimationQueue = () => { - if (queues.length > 0) { - dispatchAnimationToStyle(this, queues.shift()); - } else { - this.removeEventListener('transitionend', handleAnimationQueue); - } - }; - if (queues.length > 0) { - dispatchAnimationToStyle(this, queues.shift()); - this.addEventListener('transitionend', handleAnimationQueue); - } - } - } - get animation() { - return this.getAttribute('animation'); - } - - get children() { - return this.childNodes.filter(isElement); - } - - get dataset() { - const dataset = {}; - for (let i = 0, l = this.attributes.length; i < l; i++) { - const attr = this.attributes[i]; - if (isDataset(attr.name)) { - // Remove `data-` - dataset[camelCase(attr.name.slice(5))] = attr.value; - } - } - return dataset; - } - - get style() { - return this._style; - } - - set style(styleObject) { - this._style = styleObject; - mutate(this, 'attributes', { style: styleObject }); - } - - setAttribute(key, value) { - if (value !== this.getAttribute(key)) { - let attr = findWhere(this.attributes, createAttributeFilter(undefined, key)); - if (!attr) this.attributes.push(attr = { name: key }); - attr.value = value; - mutate(this, 'attributes', { attributeName: key, newValue: value }); - } - } - - getAttribute(key) { - return this.getAttributeNS(undefined, key); - } - - removeAttribute(key) { - this.removeAttributeNS(undefined, key); - } - - setAttributeNS(ns, name, value) { - let attr = findWhere(this.attributes, createAttributeFilter(ns, name)); - if (!attr) this.attributes.push(attr = { ns, name }); - - attr.value = value; - mutate(this, 'attributes', { attributeName: name, newValue: value }); - } - - getAttributeNS(ns, name) { - let attr = findWhere(this.attributes, createAttributeFilter(ns, name)); - return attr && attr.value; - } - - removeAttributeNS(ns, name) { - splice(this.attributes, createAttributeFilter(ns, name)); - mutate(this, 'attributes', { attributeName: name }); - } -} diff --git a/packages/driver-worker/src/worker/Evaluator.js b/packages/driver-worker/src/worker/Evaluator.js deleted file mode 100644 index 7602824edc..0000000000 --- a/packages/driver-worker/src/worker/Evaluator.js +++ /dev/null @@ -1,81 +0,0 @@ -export default class Evaluator { - _taskPending = {}; - _id = 0; - - constructor(sender) { - this.sender = sender; - } - - apply(data) { - const task = this._taskPending[data.id]; - // Task only can be resolved once. - if (task) { - const { resolve, reject } = task; - if (data.type === 'success') { - resolve(data.success); - } else if (data.type === 'error') { - reject(data.error); - } - - this._taskPending[data.id] = null; - } - } - - _send(data) { - this.sender({ - type: 'EvaluationRecord', - data, - }); - } - - /** - * Query a variable's value. - * get('location.href') - */ - get(expression) { - return this._eval({ code: expression }); - } - - /** - * Assign value to an variable. - * set('location.href', value) - */ - set(expression, value) { - return this._eval({ code: `${expression}=${value}` }); - } - - /** - * Delete an variable. - * delete('location.href') - */ - delete(expression) { - return this._eval({ code: `delete ${expression}` }); - } - - /** - * Call a specfic method with params. - * call('location.replace', '') - */ - call(method) { - var params = []; - for (var l = arguments.length, i = 1; i < l; i++) { - params[i - 1] = JSON.stringify(arguments[i]); - } - return this._eval({ code: `${method}(${params.toString()})` }); - } - - _eval({ code }) { - const id = this._generateId(); - return new Promise((resolve, reject) => { - this._taskPending[id] = { resolve, reject }; - this._send({ type: 'eval', id, code }); - }); - } - - /** - * Generate a unique procedure id. - */ - _generateId() { - return this._id++; - } -} diff --git a/packages/driver-worker/src/worker/Event.js b/packages/driver-worker/src/worker/Event.js deleted file mode 100644 index 7827feb19d..0000000000 --- a/packages/driver-worker/src/worker/Event.js +++ /dev/null @@ -1,25 +0,0 @@ -export default class Event { - constructor(type, options = {}) { - Object.assign(this, options); // extend event. - - this.defaultPrevented = false; - this.bubbles = !!options.bubbles; - this.cancelable = !!options.cancelable; - this.type = type.toLowerCase(); - } - stopPropagation() { - this.bubbles = false; - } - stopImmediatePropagation() { - this.bubbles = false; - this._end = true; - } - preventDefault() { - if (this.cancelable) { - this.defaultPrevented = true; - } else { - // Calling preventDefault in uncancelable event should produce errors, - // but in chrome and safari, which not throw or console errors, follow behaviors here. - } - } -} diff --git a/packages/driver-worker/src/worker/EventTarget.js b/packages/driver-worker/src/worker/EventTarget.js deleted file mode 100644 index c31eefb692..0000000000 --- a/packages/driver-worker/src/worker/EventTarget.js +++ /dev/null @@ -1,65 +0,0 @@ -import { mutate } from './MutationObserver'; -import splice from '../shared/splice'; - -export default class EventTarget { - _eventListeners = {}; - - _getEvents() { - const eventKeys = Object.keys(this._eventListeners); - // Must have at least one handler. - return eventKeys.filter((eventName) => { - return this._eventListeners[eventName].length > 0; - }); - } - - /** - * Add event listener. - * @param type {String} Event name. - * @param handler {EventHandler} Event handler. - */ - addEventListener(type, handler) { - type = String(type).toLowerCase(); - ( - this._eventListeners[type] || - (this._eventListeners[type] = []) - ).push(handler); - mutate(this, 'addEvent', { eventName: type }); - } - - /** - * Remove event listener. - * @param type {String} Event name. - * @param handler {EventHandler} Event handler. - */ - removeEventListener(type, handler) { - type = String(type).toLowerCase(); - splice(this._eventListeners[type], handler, 0, true); - mutate(this, 'removeEvent', { eventName: type }); - } - - /** - * Dispatch an event to target. - * @param event {Event} event. - * @return {boolean} - */ - dispatchEvent(event) { - let type = event.type; - let target = event.target = event.currentTarget = this; - - let listeners; - let i; - do { - listeners = target._eventListeners && target._eventListeners[type]; - if (listeners) { - for (i = listeners.length; i--;) { - const handlerResult = listeners[i].call(target, event); - if (handlerResult === false || event._end) break; - } - } - } while ( - event.bubbles && !event.defaultPrevented && - (event.currentTarget = target = target.parentNode) - ); - return !event.defaultPrevented; - } -} diff --git a/packages/driver-worker/src/worker/MutationObserver.js b/packages/driver-worker/src/worker/MutationObserver.js deleted file mode 100644 index 1b5cb4144f..0000000000 --- a/packages/driver-worker/src/worker/MutationObserver.js +++ /dev/null @@ -1,59 +0,0 @@ -import splice from '../shared/splice'; -import setImmediate from '../shared/setImmediate'; - -let observers = []; -let pendingMutations = false; - -export function mutate(target, type, record) { - record.target = target; - record.type = type; - - for (let i = observers.length; i--;) { - let _target = target; - let ob = observers[i], - match = _target === ob._target; - if (!match && ob._options.subtree) { - do { - if (match = _target === ob._target) break; - } while (_target = _target.parentNode); - } - - if (match) { - ob._records.push(record); - if (!pendingMutations) { - pendingMutations = true; - setImmediate(flushMutations, 0); - } - } - } -} - -export function flushMutations() { - pendingMutations = false; - for (let i = observers.length; i--;) { - let ob = observers[i]; - if (ob._records.length) { - ob.callback(ob.takeRecords()); - } - } -} - -export default class MutationObserver { - constructor(callback) { - this.callback = callback; - this._records = []; - } - observe(target, options) { - this.disconnect(); - this._target = target; - this._options = options || {}; - observers.push(this); - } - disconnect() { - this._target = null; - splice(observers, this); - } - takeRecords() { - return this._records.splice(0, this._records.length); - } -} diff --git a/packages/driver-worker/src/worker/Node.js b/packages/driver-worker/src/worker/Node.js deleted file mode 100644 index fcda523bdc..0000000000 --- a/packages/driver-worker/src/worker/Node.js +++ /dev/null @@ -1,71 +0,0 @@ -import EventTarget from './EventTarget'; -import { mutate } from './MutationObserver'; -import findWhere from '../shared/findWhere'; -import splice from '../shared/splice'; - -function mutateChildNodes(node) { - if (node && node.childNodes) { - for (let i = 0, len = node.childNodes.length; i < len; i++) { - const child = node.childNodes[i]; - mutate(node, 'childList', { addedNodes: [child] }); - mutateChildNodes(child); - } - } -} - -export default class Node extends EventTarget { - constructor(nodeType, nodeName) { - super(); - this.nodeType = nodeType; - this.nodeName = nodeName; - this.childNodes = []; - } - get nextSibling() { - let p = this.parentNode; - if (p) return p.childNodes[findWhere(p.childNodes, this, true) + 1]; - } - get previousSibling() { - let p = this.parentNode; - if (p) return p.childNodes[findWhere(p.childNodes, this, true) - 1]; - } - get firstChild() { - return this.childNodes[0]; - } - get lastChild() { - return this.childNodes[this.childNodes.length - 1]; - } - appendChild(child) { - this.insertBefore(child); - return child; - } - insertBefore(child, ref) { - child.remove(); - child.parentNode = this; - - if (ref) { - splice(this.childNodes, ref, child); - mutate(this, 'childList', { addedNodes: [child], nextSibling: ref }); - } else { - this.childNodes.push(child); - mutate(this, 'childList', { addedNodes: [child] }); - } - - mutateChildNodes(child); - return child; - } - replaceChild(child, ref) { - if (ref.parentNode === this) { - this.insertBefore(child, ref); - ref.remove(); - return ref; - } - } - removeChild(child) { - splice(this.childNodes, child); - mutate(this, 'childList', { removedNodes: [child] }); - return child; - } - remove() { - if (this.parentNode) this.parentNode.removeChild(this); - } -} diff --git a/packages/driver-worker/src/worker/NodeTypes.js b/packages/driver-worker/src/worker/NodeTypes.js deleted file mode 100644 index 2844473d0f..0000000000 --- a/packages/driver-worker/src/worker/NodeTypes.js +++ /dev/null @@ -1,4 +0,0 @@ -export const ELEMENT_NODE = 1; -export const TEXT_NODE = 3; -export const COMMENT_NODE = 8; -export const DOCUMENT_NODE = 9; diff --git a/packages/driver-worker/src/worker/Text.js b/packages/driver-worker/src/worker/Text.js deleted file mode 100644 index 274a73c19a..0000000000 --- a/packages/driver-worker/src/worker/Text.js +++ /dev/null @@ -1,17 +0,0 @@ -import Node from './Node'; -import { TEXT_NODE } from './NodeTypes'; -import { mutate } from './MutationObserver'; - -export default class Text extends Node { - constructor(text) { - super(TEXT_NODE, '#text'); // TEXT_NODE - this.data = text; - } - set textContent(text) { - mutate(this, 'characterData', { newValue: text }); - this.data = text; - } - get textContent() { - return this.data; - } -} diff --git a/packages/driver-worker/src/worker/__tests__/__snapshots__/animation.js.snap b/packages/driver-worker/src/worker/__tests__/__snapshots__/animation.js.snap deleted file mode 100644 index 56a3b15ff7..0000000000 --- a/packages/driver-worker/src/worker/__tests__/__snapshots__/animation.js.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Animation merge style 1`] = ` -Object { - "transform": "rotate(30deg)", -} -`; diff --git a/packages/driver-worker/src/worker/__tests__/__snapshots__/evaluator.js.snap b/packages/driver-worker/src/worker/__tests__/__snapshots__/evaluator.js.snap deleted file mode 100644 index 9bcec1d030..0000000000 --- a/packages/driver-worker/src/worker/__tests__/__snapshots__/evaluator.js.snap +++ /dev/null @@ -1,56 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Evaluator call with error 1`] = ` -Object { - "data": Object { - "code": "foo.bar(123,\\"hello\\")", - "id": 0, - "type": "eval", - }, - "type": "EvaluationRecord", -} -`; - -exports[`Evaluator call with success 1`] = ` -Object { - "data": Object { - "code": "foo.bar(123,\\"hello\\")", - "id": 0, - "type": "eval", - }, - "type": "EvaluationRecord", -} -`; - -exports[`Evaluator delete 1`] = ` -Object { - "data": Object { - "code": "delete foo.bar", - "id": 0, - "type": "eval", - }, - "type": "EvaluationRecord", -} -`; - -exports[`Evaluator get 1`] = ` -Object { - "data": Object { - "code": "document.body.clientWidth", - "id": 0, - "type": "eval", - }, - "type": "EvaluationRecord", -} -`; - -exports[`Evaluator set 1`] = ` -Object { - "data": Object { - "code": "document.body.innerHTML=\\"hello world\\"", - "id": 0, - "type": "eval", - }, - "type": "EvaluationRecord", -} -`; diff --git a/packages/driver-worker/src/worker/__tests__/animation.js b/packages/driver-worker/src/worker/__tests__/animation.js deleted file mode 100644 index df94743e23..0000000000 --- a/packages/driver-worker/src/worker/__tests__/animation.js +++ /dev/null @@ -1,68 +0,0 @@ -import { createElement } from '../Element'; - -describe('Animation', () => { - function animate(animation) { - return [{ - config: { - transformOrigin: 'top right', - duration: 3000, - timeFunction: 'ease-in-out', - delay: 100 - }, - animation, - }]; - } - - it('merge style', () => { - const animationConfig = animate([['translate', [35]]]); - const el = createElement('foo'); - el.style = { - transform: 'rotate(30deg)' - }; - el.animation = animationConfig; - expect(el.animation).toEqual(animationConfig); - expect(el.style).toMatchSnapshot(); - }); - - it('translate', () => { - const animationConfig = animate([['translate', [35]]]); - const el = createElement('foo'); - el.animation = animationConfig; - expect(el.animation).toEqual(animationConfig); - }); - - it('translate3d', () => { - const animationConfig = animate([['translate3d', [35, 40, 0]]]); - const el = createElement('foo'); - el.animation = animationConfig; - expect(el.animation).toEqual(animationConfig); - }); - - it('scale', () => { - const animationConfig = animate([['scale', [1.5]]]); - const el = createElement('foo'); - el.animation = animationConfig; - expect(el.animation).toEqual(animationConfig); - }); - - it('scale3d', () => { - const animationConfig = animate([['scale3d', [1.5, 1.2, 1.0]]]); - const el = createElement('foo'); - el.animation = animationConfig; - expect(el.animation).toEqual(animationConfig); - }); - - it('rotateX', () => { - const animationConfig = animate([['rotateX', [30]]]); - const el = createElement('foo'); - el.animation = animationConfig; - expect(el.animation).toEqual(animationConfig); - }); - - it('rotate3d', () => { - const animationConfig = animate([['rotate3d', [30, 40, 50]]]); - const el = createElement('foo'); - el.animation = animationConfig; - expect(el.animation).toEqual(animationConfig); - }); -}); diff --git a/packages/driver-worker/src/worker/__tests__/canvas.js b/packages/driver-worker/src/worker/__tests__/canvas.js deleted file mode 100644 index f2db2ac7c5..0000000000 --- a/packages/driver-worker/src/worker/__tests__/canvas.js +++ /dev/null @@ -1,38 +0,0 @@ -import { registerElement, createElement } from '../Element'; -import CanvasElement from '../CanvasElement'; -import CanvasRenderingContext2D from '../CanvasRenderingContext2D'; - -describe('Canvas', () => { - registerElement('canvas', CanvasElement); - - it('create canvas element', () => { - const canvas = createElement('canvas'); - expect(typeof canvas.getContext).toEqual('function'); - }); - - it('getContext', () => { - const canvas = createElement('canvas'); - const context2d = canvas.getContext('2d'); - expect(context2d).toBeInstanceOf(CanvasRenderingContext2D); - - const contextOther = canvas.getContext('webgl'); - expect(contextOther).toBeNull(); - }); - - describe('context2d', () => { - it('property', () => { - const canvas = createElement('canvas'); - const context2d = canvas.getContext('2d'); - - expect(context2d.globalAlpha).toEqual(1); - context2d.fillStyle = '#ff5000'; - expect(context2d.fillStyle).toEqual('#ff5000'); - }); - - it('method', () => { - const canvas = createElement('canvas'); - const context2d = canvas.getContext('2d'); - context2d.fill('with', 'args'); - }); - }); -}); diff --git a/packages/driver-worker/src/worker/__tests__/element.js b/packages/driver-worker/src/worker/__tests__/element.js deleted file mode 100644 index 5796f5a721..0000000000 --- a/packages/driver-worker/src/worker/__tests__/element.js +++ /dev/null @@ -1,95 +0,0 @@ -import Element, { - registerElement, - createElement, - createElementNS, - isElement -} from '../Element'; -import Text from '../Text'; -import { ELEMENT_NODE, TEXT_NODE } from '../NodeTypes'; - -describe('workerDOM element', () => { - /** - * - * - * "text" - * - * @type {Element} - */ - const view = new Element(ELEMENT_NODE, 'view'); - view.setAttribute('data-foo', 'foo'); - view.setAttribute('data-foo-bar', 1); - view.setAttribute('data-object-val', { key: 'value' }); - view.setAttribute('id', 'ID'); - view.className = 'foo bar'; - - const text = new Element(ELEMENT_NODE, 'text'); - view.appendChild(text); - const textNode = new Element(TEXT_NODE, 'text'); - view.appendChild(textNode); - - it('should get className', () => { - expect(view.className).toBe('foo bar'); - expect(view.getAttribute('class')).toBe('foo bar'); - }); - - it('should get id', () => { - expect(view.id).toBe('ID'); - expect(view.getAttribute('id')).toBe('ID'); - }); - - it('should get dataset', () => { - expect(Object.keys(view.dataset)).toEqual(['foo', 'fooBar', 'objectVal']); - expect(view.dataset.foo).toBe('foo'); - expect(view.dataset.fooBar).toEqual(1); - expect(view.dataset.objectVal).toEqual({ key: 'value' }); - }); - - it('should have right length of children', () => { - expect(view.children.length).toBe(1); - }); - - it('setAttribute & getAttribute & removeAttribute', () => { - const v = new Element(ELEMENT_NODE, 'view'); - v.setAttribute('key', 'val'); - expect(v.getAttribute('key')).toEqual('val'); - - v.removeAttribute('key'); - expect(v.getAttribute('key')).toEqual(undefined); - }); - - it('children', () => { - const parent = createElement('view'); - const child1 = createElement('view'); - const child2 = createElement('view'); - const child3 = new Text('hello'); - parent.appendChild(child1); - parent.appendChild(child2); - parent.appendChild(child3); - - expect(parent.children).toEqual([child1, child2]); - }); - - it('registerElement', (done) => { - registerElement('foo', class Foo { - constructor() { - done(); - } - }); - createElement('foo'); - }); - - it('createElement', () => { - const el = createElement('view'); - expect(el).toBeInstanceOf(Element); - }); - - it('createElementNS', () => { - const el = createElementNS('namespaceURI', 'view'); - expect(el).toBeInstanceOf(Element); - }); - - it('isElement', () => { - const el = createElement('view'); - expect(isElement(el)).toEqual(true); - }); -}); diff --git a/packages/driver-worker/src/worker/__tests__/evaluator.js b/packages/driver-worker/src/worker/__tests__/evaluator.js deleted file mode 100644 index d8625157b0..0000000000 --- a/packages/driver-worker/src/worker/__tests__/evaluator.js +++ /dev/null @@ -1,81 +0,0 @@ -import Evaluator from '../Evaluator'; - -describe('Evaluator', () => { - it('send', (done) => { - const data = { hello: 'world' }; - const sender = (message) => { - expect(message).toEqual({ - type: 'EvaluationRecord', - data, - }); - done(); - }; - const evaluator = new Evaluator(sender); - evaluator._send(data); - }); - - it('get', (done) => { - const sender = (message) => { - expect(message).toMatchSnapshot(); - done(); - }; - const evaluator = new Evaluator(sender); - evaluator.get('document.body.clientWidth'); - }); - - it('set', (done) => { - const sender = (message) => { - expect(message).toMatchSnapshot(); - done(); - }; - const evaluator = new Evaluator(sender); - evaluator.set('document.body.innerHTML', JSON.stringify('hello world')); - }); - - it('delete', (done) => { - const sender = (message) => { - expect(message).toMatchSnapshot(); - done(); - }; - const evaluator = new Evaluator(sender); - evaluator.delete('foo.bar'); - }); - - it('call with success', (done) => { - const evaluator = new Evaluator((message) => { - expect(message).toMatchSnapshot(); - - setTimeout(() => { - evaluator.apply({ - id: message.data.id, - type: 'success', - success: 'YES', - }); - }, 300); - }); - evaluator.call('foo.bar', 123, 'hello') - .then((val) => { - expect(val).toEqual('YES'); - done(); - }); - }); - - it('call with error', (done) => { - const evaluator = new Evaluator((message) => { - expect(message).toMatchSnapshot(); - - setTimeout(() => { - evaluator.apply({ - id: message.data.id, - type: 'error', - error: 'NO', - }); - }, 300); - }); - evaluator.call('foo.bar', 123, 'hello') - .catch((error) => { - expect(error).toEqual('NO'); - done(); - }); - }); -}); diff --git a/packages/driver-worker/src/worker/__tests__/event.js b/packages/driver-worker/src/worker/__tests__/event.js deleted file mode 100644 index d3a75096e4..0000000000 --- a/packages/driver-worker/src/worker/__tests__/event.js +++ /dev/null @@ -1,36 +0,0 @@ -import Event from '../Event'; - -describe('Event', () => { - it('contructor', () => { - const event = new Event('input', { - bubbles: true, - cancelable: true, - }); - expect(event.type).toEqual('input'); - expect(event.bubbles).toEqual(true); - expect(event.cancelable).toEqual(true); - }); - - it('stopPropagation', () => { - const event = new Event('input'); - event.stopPropagation(); - expect(event.bubbles).toEqual(false); - }); - - it('stopImmediatePropagation', () => { - const event = new Event('input'); - event.stopImmediatePropagation(); - expect(event.bubbles).toEqual(false); - expect(event._end).toEqual(true); - }); - - it('preventDefault', () => { - const cancelableEvent = new Event('input', { cancelable: true }); - cancelableEvent.preventDefault(); - expect(cancelableEvent.defaultPrevented).toEqual(true); - - const uncancelableEvent = new Event('input', { cancelable: false }); - uncancelableEvent.preventDefault(); - expect(uncancelableEvent.defaultPrevented).toEqual(false); - }); -}); diff --git a/packages/driver-worker/src/worker/__tests__/eventTarget.js b/packages/driver-worker/src/worker/__tests__/eventTarget.js deleted file mode 100644 index fea9640c00..0000000000 --- a/packages/driver-worker/src/worker/__tests__/eventTarget.js +++ /dev/null @@ -1,65 +0,0 @@ -import EventTarget from '../EventTarget'; -import Event from '../Event'; - -describe('EventTarget', () => { - it('addEventListener', () => { - const eventTarget = new EventTarget(); - const handler = () => {}; - eventTarget.addEventListener('foo', handler); - expect(eventTarget._eventListeners.foo).toEqual([handler]); - }); - - it('removeEventListener', () => { - const eventTarget = new EventTarget(); - const handler = () => {}; - eventTarget.addEventListener('foo', handler); - eventTarget.removeEventListener('foo', handler); - expect(eventTarget._eventListeners.foo).toEqual([]); - }); - - it('dispatchEvent', (done) => { - const eventTarget = new EventTarget(); - const handler = () => { - done(); - }; - eventTarget.addEventListener('foo', handler); - eventTarget.dispatchEvent(new Event('foo')); - }); - - it('getEvents', () => { - const eventTarget = new EventTarget(); - const handler = () => {}; - eventTarget.addEventListener('foo', handler); - eventTarget.removeEventListener('foo', handler); - expect(eventTarget._getEvents()).toEqual([]); - }); - - - it('bubbles', (done) => { - const eventTarget1 = new EventTarget(); - const eventTarget2 = new EventTarget(); - eventTarget2.parentNode = eventTarget1; - - eventTarget1.addEventListener('foo', (evt) => { - done(); - }); - eventTarget2.dispatchEvent(new Event('foo', { bubbles: true, cancelable: true })); - }); - - it('stopPropagation', (done) => { - const eventTarget1 = new EventTarget(); - const eventTarget2 = new EventTarget(); - eventTarget2.parentNode = eventTarget1; - - eventTarget1.addEventListener('foo', (evt) => { - expect(evt.bubbles).toEqual(false); - throw new Error('Should not bubble event.'); - }); - eventTarget2.addEventListener('foo', (evt) => { - expect(evt.bubbles).toEqual(true); - evt.stopPropagation(); - setTimeout(done); - }); - eventTarget2.dispatchEvent(new Event('foo', { bubbles: true })); - }); -}); diff --git a/packages/driver-worker/src/worker/__tests__/node.js b/packages/driver-worker/src/worker/__tests__/node.js deleted file mode 100644 index 6b2917e1d1..0000000000 --- a/packages/driver-worker/src/worker/__tests__/node.js +++ /dev/null @@ -1,67 +0,0 @@ -import Node from '../Node'; -import { ELEMENT_NODE} from '../NodeTypes'; - -describe('Node', () => { - it('node type', () => { - const node = new Node(ELEMENT_NODE, 'view'); - expect(node.nodeType).toEqual(ELEMENT_NODE); - expect(node.nodeName).toEqual('view'); - }); - - it('node structures', () => { - const parent = new Node(ELEMENT_NODE, 'view'); - const child1 = new Node(ELEMENT_NODE, 'view'); - const child2 = new Node(ELEMENT_NODE, 'view'); - const child3 = new Node(ELEMENT_NODE, 'view'); - parent.appendChild(child1); - parent.appendChild(child2); - parent.appendChild(child3); - - expect(parent.childNodes).toMatchObject([child1, child2, child3]); - expect(child1.parentNode).toEqual(parent); - expect(child1.nextSibling).toEqual(child2); - expect(child2.previousSibling).toEqual(child1); - expect(parent.firstChild).toEqual(child1); - expect(parent.lastChild).toEqual(child3); - }); - - it('replace child', () => { - const parent = new Node(ELEMENT_NODE, 'view'); - const child1 = new Node(ELEMENT_NODE, 'view'); - const child2 = new Node(ELEMENT_NODE, 'view'); - const child3 = new Node(ELEMENT_NODE, 'view'); - const child4 = new Node(ELEMENT_NODE, 'view'); - parent.appendChild(child1); - parent.appendChild(child2); - parent.appendChild(child3); - - parent.replaceChild(child4, child2); - expect(parent.childNodes[1] === child4).toEqual(true); - }); - - it('remove child', () => { - const parent = new Node(ELEMENT_NODE, 'view'); - const child1 = new Node(ELEMENT_NODE, 'view'); - const child2 = new Node(ELEMENT_NODE, 'view'); - const child3 = new Node(ELEMENT_NODE, 'view'); - parent.appendChild(child1); - parent.appendChild(child2); - parent.appendChild(child3); - - parent.removeChild(child2); - expect(parent.childNodes).toEqual([child1, child3]); - }); - - it('mutate child nodes', () => { - const parent = new Node(ELEMENT_NODE, 'view'); - const child1 = new Node(ELEMENT_NODE, 'view'); - const child2 = new Node(ELEMENT_NODE, 'view'); - const child3 = new Node(ELEMENT_NODE, 'view'); - parent.appendChild(child1); - parent.appendChild(child2); - parent.appendChild(child3); - - const root = new Node(ELEMENT_NODE, 'view'); - root.appendChild(parent); - }); -}); diff --git a/packages/driver-worker/src/worker/__tests__/text.js b/packages/driver-worker/src/worker/__tests__/text.js deleted file mode 100644 index 70e6f38f8b..0000000000 --- a/packages/driver-worker/src/worker/__tests__/text.js +++ /dev/null @@ -1,18 +0,0 @@ -import Text from '../Text'; -import { TEXT_NODE } from '../NodeTypes'; - -describe('Text', () => { - it('type', () => { - const text = new Text('hello'); - expect(text.nodeType).toEqual(TEXT_NODE); - }); - - it('textContent', () => { - const text = new Text('hello'); - expect(text.data).toEqual('hello'); - expect(text.textContent).toEqual('hello'); - - text.textContent = 'world'; - expect(text.data).toEqual('world'); - }); -}); diff --git a/packages/driver-worker/src/worker/createWorkerGlobalScope.js b/packages/driver-worker/src/worker/createWorkerGlobalScope.js deleted file mode 100644 index 6168255e92..0000000000 --- a/packages/driver-worker/src/worker/createWorkerGlobalScope.js +++ /dev/null @@ -1,7 +0,0 @@ -import { createDocument } from './Document'; - -export default function createWorkerGlobalScope() { - return { - document: createDocument() - }; -} diff --git a/packages/rax-miniapp-renderer/README.md b/packages/rax-miniapp-renderer/README.md deleted file mode 100644 index 7c4b9cf264..0000000000 --- a/packages/rax-miniapp-renderer/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# rax-miniapp-renderer - -> Rax renderer for miniapp. - -## Install - -```bash -$ npm install --save rax-miniapp-renderer -``` - -## Usage - -`render.js` -```js -import domRender from 'rax-miniapp-renderer'; -import spawnWorker from 'worker-loader?inline!./worker.js'; - -const worker = spawnWorker(); -domRender({ worker }); -``` diff --git a/packages/rax-miniapp-renderer/package.json b/packages/rax-miniapp-renderer/package.json deleted file mode 100644 index 63fe04fcb5..0000000000 --- a/packages/rax-miniapp-renderer/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "rax-miniapp-renderer", - "version": "0.1.1", - "description": "Rax renderer for miniapp.", - "license": "BSD-3-Clause", - "main": "dist/rax-miniapp-renderer.min.js", - "repository": { - "type": "git", - "url": "git+https://github.com/alibaba/rax.git" - }, - "bugs": { - "url": "https://github.com/alibaba/rax/issues" - }, - "homepage": "https://github.com/alibaba/rax#readme", - "dependencies": { - "driver-worker": "^0.7.9" - } -} diff --git a/packages/rax-miniapp-renderer/src/EvaluationHandler.js b/packages/rax-miniapp-renderer/src/EvaluationHandler.js deleted file mode 100644 index bb24e26c83..0000000000 --- a/packages/rax-miniapp-renderer/src/EvaluationHandler.js +++ /dev/null @@ -1,45 +0,0 @@ -export default class EvaluationHandler { - constructor(sender) { - this.sender = sender; - } - - apply({ data }) { - const { type } = data; - this[type](data); - } - - returnSuccess(id, success) { - if (typeof success === 'object') { - try { - success = JSON.parse(JSON.stringify(success)); - } catch (e) { - success = success.toString(); - } - } - - if (typeof success === 'function') { - success = success.toString(); - } - - this.send({ type: 'success', id, success }); - } - - returnError(id, { name, message }) { - this.send({ type: 'error', id, error: { name, message } }); - } - - send(data) { - this.sender({ - type: 'return', - return: data, - }); - } - - eval({ id, code }) { - try { - this.returnSuccess(id, window.eval(code)); - } catch (error) { - this.returnError(id, error); - } - } -} diff --git a/packages/rax-miniapp-renderer/src/EventHandler.js b/packages/rax-miniapp-renderer/src/EventHandler.js deleted file mode 100644 index 3439f868dd..0000000000 --- a/packages/rax-miniapp-renderer/src/EventHandler.js +++ /dev/null @@ -1,196 +0,0 @@ -import { passive as supportsPassive } from './supports'; - -const EVENT_OPTIONS = supportsPassive ? { capture: true, passive: true } : true; -const NO_BUBBLES_EVENTS = { - // Resource Events and Progress Events - load: true, - error: true, - unload: true, - abort: true, - loadstart: true, - progress: true, - loadend: true, - // Focus Events - blur: true, - focus: true, - // View Events - scroll: true, // Not bubles on elements - appear: true, - disappear: true, - // Uncategorized events - invalid: true -}; -const TOUCH_EVENTS = ['touchstart', 'touchmove', 'touchend', 'touchcancel']; -const EVENT_LISTENERS = '__event_listeners__'; - -export default class EventHandler { - constructor(handler, options = {}) { - this.postMessage = handler; - this.registeredEventCounts = {}; - this.nobubbleEventNodes = []; - this.mountNode = options.mountNode || document; - this.touch = null; - } - - addEvent(node, name) { - if (NO_BUBBLES_EVENTS[name]) { - this.addNoBubblesEventListener(node, name); - } else { - const registeredCount = this.registeredEventCounts[name]; - if (!registeredCount) { - this.registeredEventCounts[name] = 1; - // Top-level register - this.mountNode.addEventListener(name, this.eventProxyHandler, EVENT_OPTIONS); - } else { - this.registeredEventCounts[name]++; - } - } - } - - removeAllEvents() { - // Remove no-bubbles events. - let noBubblesEventNode; - while (noBubblesEventNode = this.nobubbleEventNodes.pop()) { - if (noBubblesEventNode[EVENT_LISTENERS]) { - const eventNames = Object.keys(noBubblesEventNode[EVENT_LISTENERS]); - for (let i = 0, l = eventNames.length; i < l; i++) { - this.removeNoBubblesEventListener(noBubblesEventNode, eventNames[i]); - } - } - } - - // Remove regular events. - const events = Object.keys(this.registeredEventCounts); - for (let i = 0, l = events.length; i < l; i++) { - const name = events[i]; - this.mountNode.removeEventListener(name, this.eventProxyHandler, EVENT_OPTIONS); - delete this.registeredEventCounts[name]; - } - } - - removeEvent(node, name) { - if (NO_BUBBLES_EVENTS[name]) { - this.removeNoBubblesEventListener(node, name); - } else { - this.registeredEventCounts[name]--; - if (this.registeredEventCounts[name] === 0) { - this.mountNode.removeEventListener(name, this.eventProxyHandler, EVENT_OPTIONS); - } - } - } - - addNoBubblesEventListener(node, name) { - const listener = (evt) => { - const target = { $$id: node.$$id }; - - if (node === document.body) { - target.nodeName = 'BODY'; - } - - this.postMessage({ - type: 'event', - event: { - type: name, - target, - currentTarget: target, - detail: evt.detail - } - }); - }; - const listeners = node[EVENT_LISTENERS] = node[EVENT_LISTENERS] || {}; - listeners[name] = listeners[name] || []; - listeners[name].push(listener); - if (this.nobubbleEventNodes.indexOf(node) !== -1) this.nobubbleEventNodes.push(node); - node.addEventListener(name, listener, EVENT_OPTIONS); - } - - removeNoBubblesEventListener(node, name) { - if (node[EVENT_LISTENERS] && node[EVENT_LISTENERS][name]) { - for (let i = 0, l = node[EVENT_LISTENERS][name].length; i < l; i++) { - node.removeEventListener(name, node[EVENT_LISTENERS][name][i], EVENT_OPTIONS); - } - delete node[EVENT_LISTENERS][name]; - } - this.nobubbleEventNodes.splice(this.nobubbleEventNodes.indexOf(node), 1); - } - - eventProxyHandler = (e) => { - if (e.type === 'click' && this.touch) return false; - - let event = { type: e.type }; - if (e.target) event.target = e.target.$$id; - if (e.type === 'scroll' && e.target === document) { - event.target = document.body.$$id; - // page scroll container's top - // safari is document.body.scrollTop - // chrome is document.documentElement.scrollTop - event.scrollTop = document.documentElement.scrollTop || document.body.scrollTop; - } - // CustomEvent detail - if (e.detail) event.detail = e.detail; - for (let i in e) { - let v = e[i]; - if ( - typeof v !== 'object' && - typeof v !== 'function' && - i !== i.toUpperCase() && - !event.hasOwnProperty(i) - ) { - event[i] = v; - } - } - - if (TOUCH_EVENTS.indexOf(e.type) !== -1) { - event.touches = serializeTouchList(e.touches); - event.changedTouches = serializeTouchList(e.changedTouches); - } - - this.postMessage({ - type: 'event', - event - }); - - if (e.type === 'touchstart') { - this.touch = getTouch(e); - } else if (e.type === 'touchend' && this.touch) { - let t = getTouch(e); - if (t) { - let delta = Math.sqrt( - Math.pow(t.pageX - this.touch.pageX, 2) + - Math.pow(t.pageY - this.touch.pageY, 2) - ); - if (delta < 10) { - event.type = 'click'; - this.postMessage({ type: 'event', event }); - } - } - } - } -} - -function getTouch(e) { - let t = e.changedTouches && e.changedTouches[0] || - e.touches && e.touches[0] || e; - return t && { pageX: t.pageX, pageY: t.pageY }; -} - -function serializeTouchList(touchList) { - const touches = []; - for (let i = 0, l = touchList.length; i < l; i++) { - const { - clientX, clientY, - pageX, pageY, - identifier, target - } = touchList[i]; - - touches.push({ - clientX, clientY, - pageX, pageY, - identifier, - // instance id of changed target - $$id: target.$$id, - }); - } - return touches; -} - diff --git a/packages/rax-miniapp-renderer/src/LocationHandler.js b/packages/rax-miniapp-renderer/src/LocationHandler.js deleted file mode 100644 index 89a2bd5054..0000000000 --- a/packages/rax-miniapp-renderer/src/LocationHandler.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Deperated location handler. - */ -export default class LocationHandler { - constructor(sender) { - this.sender = sender; - } - - apply(data) { - const { data: payload } = data; - const { type, prop } = payload; - - if (type === 'call' && prop === 'replace') { - location.replace(payload.args[0]); - } - } -} diff --git a/packages/rax-miniapp-renderer/src/MutationHandler.js b/packages/rax-miniapp-renderer/src/MutationHandler.js deleted file mode 100644 index f5fed9c3fd..0000000000 --- a/packages/rax-miniapp-renderer/src/MutationHandler.js +++ /dev/null @@ -1,171 +0,0 @@ -import NodeMap from './NodeMap'; -import EventHandler from './EventHandler'; -import { createNode, getTagName } from './nodes'; -import { setAttribute } from './attrs'; -import { setStyle } from './styles'; - -const STYLE_ELEMENT = 'STYLE'; -const TEXT_CONTENT = 'textContent'; -const TEXT_CONTENT_ATTR = TEXT_CONTENT in document ? TEXT_CONTENT : 'nodeValue'; - -/** - * Returns "attributes" if it was an attribute mutation. - * "characterData" if it was a mutation to a CharacterData node. - * And "childList" if it was a mutation to the tree of nodes. - */ -export default class MutationHandler { - constructor(sender, mountNode) { - this.eventHandler = new EventHandler(sender, { - mountNode - }); - this.mountNode = mountNode || document.body; - - this.sharedNodeMap = new NodeMap(); - this.sharedNodeMap._setMountNode(this.mountNode); - } - - apply(data) { - let mutations = data.mutations; - for (let i = 0; i < mutations.length; i++) { - // apply mutation - let mutation = mutations[i]; - this[mutation.type](mutation); - } - } - - childList({ target, removedNodes, addedNodes, nextSibling }) { - let sharedNodeMap = this.sharedNodeMap; - let vnode = target; - - if (vnode && vnode.nodeName === 'BODY' && vnode.$$id) { - this.mountNode.$$id = vnode.$$id; - } - - let parent = sharedNodeMap.get(vnode); - if (removedNodes) { - for (let i = removedNodes.length; i--;) { - let node = sharedNodeMap.get(removedNodes[i]); - /** - * @NOTE For performance: - * do not remove style element or textContent of style element. - */ - if ( - parent - && parent.nodeName !== STYLE_ELEMENT - && node - && node.nodeName !== STYLE_ELEMENT - ) { - sharedNodeMap.delete(node); - parent.removeChild(node); - } - } - } - - if (addedNodes) { - for (let i = 0; i < addedNodes.length; i++) { - let newNode = sharedNodeMap.get(addedNodes[i]); - if (!newNode) { - newNode = this.createNode(addedNodes[i]); - } - - if (parent) { - let siblingElement = nextSibling && sharedNodeMap.get(nextSibling) || null; - parent.insertBefore(newNode, siblingElement); - } - } - } - } - - createNode(vnode) { - let node = createNode(vnode); - - if (vnode.nodeType === 1 && getTagName(vnode.nodeName)) { - if (vnode.className) { - node.className = vnode.className; - } - - if (vnode.style) { - setStyle(node, vnode.style); - } - - if (vnode.attributes) { - for (let i = 0; i < vnode.attributes.length; i++) { - let { name, value } = vnode.attributes[i]; - setAttribute(node, name, value); - } - } - - if (vnode.childNodes) { - for (let i = 0; i < vnode.childNodes.length; i++) { - node.appendChild(this.createNode(vnode.childNodes[i])); - } - } - - if (vnode.events) { - for (let i = 0; i < vnode.events.length; i++) { - this.eventHandler.addEvent(node, vnode.events[i]); - } - } - } - - this.sharedNodeMap.set(vnode, node); - - return node; - } - - attributes({ target, attributeName, newValue, style }) { - let node = this.sharedNodeMap.get(target); - // Node maybe null when node is removed and there is a setInterval change the node that will cause error - if (!node) return; - - if (style) { - setAttribute(node, 'style', style); - } - if (attributeName) { - setAttribute(node, attributeName, newValue); - } - } - - characterData({ target, newValue }) { - let node = this.sharedNodeMap.get(target); - node[TEXT_CONTENT_ATTR] = newValue; - } - - addEvent({ target, eventName }) { - let node = this.sharedNodeMap.get(target); - if (!node) return; - this.eventHandler.addEvent(node, eventName); - } - - removeEvent({ target, eventName }) { - let node = this.sharedNodeMap.get(target); - if (!node) return; - - this.eventHandler.removeEvent(node, eventName); - } - - canvasRenderingContext2D({ target, method, args, properties }) { - let canvas = this.sharedNodeMap.get(target); - if (!canvas) return; - - let context = canvas.getContext('2d'); - - if (properties) { - for (let key in properties) { - if (properties.hasOwnProperty(key)) { - context[key] = properties[key]; - } - } - } - - if (method) { - context[method].apply(context, args); - } - } - - destroy() { - this.eventHandler.removeAllEvents(); - this.sharedNodeMap = null; - this.mountNode.parentElement.removeChild(this.mountNode); - } -} diff --git a/packages/rax-miniapp-renderer/src/NodeMap.js b/packages/rax-miniapp-renderer/src/NodeMap.js deleted file mode 100644 index 33ff3d6aa8..0000000000 --- a/packages/rax-miniapp-renderer/src/NodeMap.js +++ /dev/null @@ -1,40 +0,0 @@ - -export default class NodeMap { - _map = new Map(); - - _setMountNode(mountNode) { - this.mountNode = mountNode; - } - - get(vnode) { - if (!vnode) return null; - if (vnode.nodeName === 'BODY') return this.mountNode; - return this._map.get(vnode.$$id); - } - - set(vnode, node) { - node.$$id = vnode.$$id; - return this._map.set(vnode.$$id, node); - } - - delete(vnode) { - if (!vnode) return null; - const node = this._map.get(vnode.$$id); - if (node) traverseNodes(node, el => el.$$id && this._map.delete(el.$$id)); - } -} - -/** - * Traverse HTML Node in DFS (trailing call). - * @param node {Node} - * @param effect {Function} - */ -function traverseNodes(node, effect) { - if (node.childNodes.length > 0) { - for (let i = 0, l = node.childNodes.length; i < l; i++) { - traverseNodes(node.childNodes[i], effect); - effect(node.childNodes[i]); - } - } - effect(node); -} diff --git a/packages/rax-miniapp-renderer/src/attrs.js b/packages/rax-miniapp-renderer/src/attrs.js deleted file mode 100644 index c2fb9cdd14..0000000000 --- a/packages/rax-miniapp-renderer/src/attrs.js +++ /dev/null @@ -1,42 +0,0 @@ -import { setStyle } from './styles'; -import camelCase from './camelCase'; -import kebabCase from './kebabCase'; - -const STYLE = 'style'; -const INVALID_ATTRS_MAP = { - /** - * In web components, slot attribute has side effects to - * deliver child nodes. - */ - slot: true, -}; - -export function isInvalidAttr(attr) { - return INVALID_ATTRS_MAP.hasOwnProperty(attr); -} - -export function setAttribute(node, attrName, value) { - if (isInvalidAttr(attrName)) return; - - if (attrName === STYLE) { - setStyle(node, value); - return; - } - - if (typeof value === 'object' || typeof value === 'boolean') { - /** - * Transform kebab cased attribute name to camel cased property name. - * - * -> - * el.fooBar = true; - */ - node[camelCase(attrName)] = value; - } else { - attrName = kebabCase(attrName); - if (value == null) { - node.removeAttribute(attrName); - } else { - node.setAttribute(attrName, value); - } - } -} diff --git a/packages/rax-miniapp-renderer/src/camelCase.js b/packages/rax-miniapp-renderer/src/camelCase.js deleted file mode 100644 index 5977405582..0000000000 --- a/packages/rax-miniapp-renderer/src/camelCase.js +++ /dev/null @@ -1,11 +0,0 @@ -const CAMELCASE_REG = /-[a-z]/g; -const CamelCaseCache = {}; - -export default function camelCase(str) { - return ( - CamelCaseCache[str] || - (CamelCaseCache[str] = str.replace(CAMELCASE_REG, $1 => - $1.slice(1).toUpperCase() - )) - ); -} diff --git a/packages/rax-miniapp-renderer/src/index.js b/packages/rax-miniapp-renderer/src/index.js deleted file mode 100644 index a112a5af6c..0000000000 --- a/packages/rax-miniapp-renderer/src/index.js +++ /dev/null @@ -1,49 +0,0 @@ -/* global DEVICE_WIDTH */ -import MutationHandler from './MutationHandler'; -import EvaluationHandler from './EvaluationHandler'; -import LocationHandler from './LocationHandler'; - -export default ({ worker, mountNode }) => { - const postMessage = worker.postMessage.bind(worker); - - let handlers = { - MutationRecord: new MutationHandler(postMessage, mountNode), - EvaluationRecord: new EvaluationHandler(postMessage), - - // Deprecated handler. - Location: new LocationHandler(postMessage), - }; - - worker.onmessage = ({ data }) => { - let type = data.type; - if (handlers[type]) { - handlers[type].apply(data); - } else { - console.error('Can not handle with ' + type, data); - } - }; - - worker.postMessage({ - type: 'init', - url: location.href, - width: getDeviceWidth(), - }); - - return function unmount() { - handlers.MutationRecord.destroy(); - worker.onmessage = noop; - handlers = null; - }; -}; - -/** - * Get device base width - * @return {number} - */ -function getDeviceWidth() { - return typeof DEVICE_WIDTH !== 'undefined' - ? DEVICE_WIDTH - : document.documentElement.clientWidth; -} - -function noop() {} diff --git a/packages/rax-miniapp-renderer/src/kebabCase.js b/packages/rax-miniapp-renderer/src/kebabCase.js deleted file mode 100644 index 6503d8e132..0000000000 --- a/packages/rax-miniapp-renderer/src/kebabCase.js +++ /dev/null @@ -1,20 +0,0 @@ -const KebabCache = {}; - -export default function kebabCase(string) { - if (KebabCache[string]) { - return KebabCache[string]; - } - - let kebab = ''; - for (let i = 0, l = string.length; i < l; i++) { - if (/[a-z]/.test(string[i])) { - kebab += string[i]; - } else if (/[A-Z]/.test(string[i])) { - kebab += '-' + string[i].toLowerCase(); - } else if (string[i] === '-') { - kebab += '-'; - } - } - - return KebabCache[string] = kebab; -} diff --git a/packages/rax-miniapp-renderer/src/nodes.js b/packages/rax-miniapp-renderer/src/nodes.js deleted file mode 100644 index 203bdf46d5..0000000000 --- a/packages/rax-miniapp-renderer/src/nodes.js +++ /dev/null @@ -1,37 +0,0 @@ -const CUSTOM_TAG_PREFIX = 'a-'; - -/** - * Whitelist that declear w3c standard tag names. - */ -const w3cTags = { - style: true, -}; - -function isValidW3CTag(tagName) { - return w3cTags.hasOwnProperty(tagName); -} - -/** - * Format tag name. - */ -export function getTagName(nodeName) { - const tagName = String(nodeName).toLowerCase(); - if (isValidW3CTag(tagName)) { - return tagName; - } else { - return CUSTOM_TAG_PREFIX + tagName; - } -} - -export function createNode(vnode) { - let node, tagName; - if (vnode.nodeType === 3) { - node = document.createTextNode(vnode.data); - } else if (vnode.nodeType === 1 && (tagName = getTagName(vnode.nodeName))) { - node = document.createElement(tagName); - } else if (vnode.nodeType === 8) { - node = document.createComment(vnode.data); - } - - return node; -} diff --git a/packages/rax-miniapp-renderer/src/styles.js b/packages/rax-miniapp-renderer/src/styles.js deleted file mode 100644 index 5020af274e..0000000000 --- a/packages/rax-miniapp-renderer/src/styles.js +++ /dev/null @@ -1,107 +0,0 @@ -const PREFIX_PROPS = { - flex: true, - alignItems: true, - alignSelf: true, - flexDirection: true, - justifyContent: true, - flexWrap: true, - - lineClamp: true, - textSizeAdjust: true, - textDecorationLine: true, - textDecorationColor: true, - textDecorationStyle: true, - textDecorationSkip: true, - writingMode: true, - - animatin: true, - animationName: true, - animationDuration: true, - animationTimingFunction: true, - animationDelay: true, - animationIterationCount: true, - animationDirection: true, - animationFillMode: true, - animationPlayState: true, - - transform: true, - transformOrigin: true, - transformStyle: true, - perspective: true, - perspectiveOrigin: true, - backfaceVisibility: true, - appearance: true, - userSelect: true, - - columns: true, - columnWidth: true, - columnCount: true, - columnGap: true, - columnRule: true, - columnRuleWidth: true, - columnRuleStyle: true, - columnRuleColor: true, - columnSpan: true, - columnFill: true, - columnBreakBefore: true, - columnBreakAfter: true, - columnBreakInside: true, -}; - -const PREFIX_PROP_VALS = { - position: 'sticky', - display: 'flex', -}; - -const StylePrefixer = { - shouldPrefix(prop) { - return PREFIX_PROPS[prop] || PREFIX_PROP_VALS[prop]; - }, -}; - -Object.keys(PREFIX_PROPS).forEach((prop) => { - const vendorProp = 'webkit' + prop[0].toUpperCase() + prop.slice(1); - StylePrefixer[prop] = (value, style = {}) => { - style[vendorProp] = value; - style[prop] = value; - return style; - }; -}); - -Object.keys(PREFIX_PROP_VALS).forEach((prop) => { - const rule = PREFIX_PROP_VALS[prop]; - StylePrefixer[prop] = (value, style = {}) => { - if (value === rule) { - style[prop] = ['-webkit-' + rule, rule]; - } else { - style[prop] = value; - } - return style; - }; -}); - -export function setStyle(node, styleObject) { - let tranformedStyles = {}; - - for (let prop in styleObject) { - let val = styleObject[prop]; - if (StylePrefixer.shouldPrefix(prop)) { - StylePrefixer[prop](val, tranformedStyles); - } else { - tranformedStyles[prop] = val; - } - } - - for (let prop in tranformedStyles) { - const transformValue = tranformedStyles[prop]; - // if browser only accept -webkit-flex - // node.style.display = 'flex' will not work - if (Array.isArray(transformValue)) { - for (let i = 0; i < transformValue.length; i++) { - node.style[prop] = transformValue[i]; - } - } else { - node.style[prop] = transformValue; - } - } -} diff --git a/packages/rax-miniapp-renderer/src/supports.js b/packages/rax-miniapp-renderer/src/supports.js deleted file mode 100644 index f3aa6c2a24..0000000000 --- a/packages/rax-miniapp-renderer/src/supports.js +++ /dev/null @@ -1,11 +0,0 @@ -// feature-detect support for event listener options -let supportsPassive = false; -try { - addEventListener('test', null, { - get passive() { - supportsPassive = true; - } - }); -} catch (e) { } - -export let passive = supportsPassive; diff --git a/packages/runtime-shared/README.md b/packages/runtime-shared/README.md deleted file mode 100644 index 436c14387e..0000000000 --- a/packages/runtime-shared/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# runtime-shared - - -## Polyfills - - -ES6 - -* Object.{[assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign), [is](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)} -* Number.{[isNaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN), [isInteger](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger), [isFinite](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite), [EPSILON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON), [MIN_SAFE_INTEGER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER), [MAX_SAFE_INTEGER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)} -* String.prototype.{[startsWith](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith), [endsWith](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith), [repeat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat), [includes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes), [codePointAt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt)} -* Array.{[from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from), [to](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/to)} -* Array.prototype.{[find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find), [findIndex](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex)} - -ES7 - -* Array.prototype.{[includes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)} - -ES8 - -* String.prototype.{[padStart](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart), [padEnd](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd)} -* Object.{[entries](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries), [values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values)} diff --git a/packages/runtime-shared/package.json b/packages/runtime-shared/package.json deleted file mode 100644 index 2e793e7a8a..0000000000 --- a/packages/runtime-shared/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "runtime-shared", - "version": "0.6.6-1", - "description": "Shared Runtime.", - "license": "BSD-3-Clause", - "main": "lib/index.js", - "repository": { - "type": "git", - "url": "git+https://github.com/alibaba/rax.git" - }, - "bugs": { - "url": "https://github.com/alibaba/rax/issues" - }, - "homepage": "https://github.com/alibaba/rax#readme" -} diff --git a/packages/runtime-shared/src/__tests__/url.js b/packages/runtime-shared/src/__tests__/url.js deleted file mode 100644 index db49529fae..0000000000 --- a/packages/runtime-shared/src/__tests__/url.js +++ /dev/null @@ -1,9 +0,0 @@ -import URL from '../url'; - -describe('URL', () => { - it('accept url with proctal', () => { - var url = new URL('http://example.com/path/to?query=string'); - expect(url.search).toEqual('?query=string'); - expect(url.hostname).toEqual('example.com'); - }); -}); diff --git a/packages/runtime-shared/src/appear/IntersectionObserver.js b/packages/runtime-shared/src/appear/IntersectionObserver.js deleted file mode 100644 index 3ca807c701..0000000000 --- a/packages/runtime-shared/src/appear/IntersectionObserver.js +++ /dev/null @@ -1,652 +0,0 @@ -/** - * An IntersectionObserver registry. This registry exists to hold a strong - * reference to IntersectionObserver instances currently observing a target - * element. Without this registry, instances without another reference may be - * garbage collected. - */ -const registry = []; - - -/** - * Creates the global IntersectionObserverEntry constructor. - * https://w3c.github.io/IntersectionObserver/#intersection-observer-entry - * @param {Object} entry A dictionary of instance properties. - * @constructor - */ -export function IntersectionObserverEntry(entry) { - this.time = entry.time; - this.target = entry.target; - this.rootBounds = entry.rootBounds; - this.boundingClientRect = entry.boundingClientRect; - this.intersectionRect = entry.intersectionRect || getEmptyRect(); - this.isIntersecting = !!entry.intersectionRect; - - // Calculates the intersection ratio. - const targetRect = this.boundingClientRect; - const targetArea = targetRect.width * targetRect.height; - const intersectionRect = this.intersectionRect; - const intersectionArea = intersectionRect.width * intersectionRect.height; - - // Sets intersection ratio. - if (targetArea) { - // Round the intersection ratio to avoid floating point math issues: - // https://github.com/w3c/IntersectionObserver/issues/324 - this.intersectionRatio = Number((intersectionArea / targetArea).toFixed(4)); - } else { - // If area is zero and is intersecting, sets to 1, otherwise to 0 - this.intersectionRatio = this.isIntersecting ? 1 : 0; - } -} - -export default class IntersectionObserver { - /** - * The minimum interval within which the document will be checked for - * intersection changes. - */ - THROTTLE_TIMEOUT = 100; - - /** - * The frequency in which the polyfill polls for intersection changes. - * this can be updated on a per instance basis and must be set prior to - * calling `observe` on the first target. - */ - POLL_INTERVAL = null; - - /** - * Use a mutation observer on the root element - * to detect intersection changes. - */ - USE_MUTATION_OBSERVER = true; - - /** - * Creates the global IntersectionObserver constructor. - * https://w3c.github.io/IntersectionObserver/#intersection-observer-interface - * @param {Function} callback The function to be invoked after intersection - * changes have queued. The function is not invoked if the queue has - * been emptied by calling the `takeRecords` method. - * @param {Object=} optOptions Optional configuration options. - * @constructor - */ - constructor(callback, optOptions) { - const options = optOptions || {}; - - if (typeof callback != 'function') { - throw new Error('callback must be a function'); - } - - if (options.root && options.root.nodeType != 1) { - throw new Error('root must be an Element'); - } - - // Throttles `this._checkForIntersections`. - this._checkForIntersections = throttle(this._checkForIntersections, this.THROTTLE_TIMEOUT); - - // Private properties. - this._callback = callback; - this._observationTargets = []; - this._queuedEntries = []; - this._rootMarginValues = this._parseRootMargin(options.rootMargin); - - // Public properties. - this.thresholds = this._initThresholds(options.threshold); - this.root = options.root || null; - this.rootMargin = this._rootMarginValues.map((margin) => margin.value + margin.unit).join(' '); - } - - /** - * Starts observing a target element for intersection changes based on - * the thresholds values. - * @param {Element} target The DOM element to observe. - */ - observe(target) { - const isTargetAlreadyObserved = this._observationTargets.some((item) => item.element === target); - - if (isTargetAlreadyObserved) { - return; - } - - if (!(target && target.nodeType == 1)) { - throw new Error('target must be an Element'); - } - - this._registerInstance(); - this._observationTargets.push({element: target, entry: null}); - this._monitorIntersections(); - this._checkForIntersections(); - } - - /** - * Stops observing a target element for intersection changes. - * @param {Element} target The DOM element to observe. - */ - unobserve(target) { - this._observationTargets = - this._observationTargets.filter(function(item) { - return item.element !== target; - }); - if (!this._observationTargets.length) { - this._unmonitorIntersections(); - this._unregisterInstance(); - } - } - - /** - * Stops observing all target elements for intersection changes. - */ - disconnect() { - this._observationTargets = []; - this._unmonitorIntersections(); - this._unregisterInstance(); - } - - /** - * Returns any queue entries that have not yet been reported to the - * callback and clears the queue. This can be used in conjunction with the - * callback to obtain the absolute most up-to-date intersection information. - * @return {Array} The currently queued entries. - */ - takeRecords() { - const records = this._queuedEntries.slice(); - this._queuedEntries = []; - return records; - } - - /** - * Accepts the threshold value from the user configuration object and - * returns a sorted array of unique threshold values. If a value is not - * between 0 and 1 and error is thrown. - * @private - * @param {Array|number=} optThreshold An optional threshold value or - * a list of threshold values, defaulting to [0]. - * @return {Array} A sorted list of unique and valid threshold values. - */ - _initThresholds(optThreshold) { - let threshold = optThreshold || [0]; - if (!Array.isArray(threshold)) threshold = [threshold]; - - return threshold.sort().filter(function(t, i, a) { - if (typeof t != 'number' || isNaN(t) || t < 0 || t > 1) { - throw new Error('threshold must be a number between 0 and 1 inclusively'); - } - return t !== a[i - 1]; - }); - } - - /** - * Accepts the rootMargin value from the user configuration object - * and returns an array of the four margin values as an object containing - * the value and unit properties. If any of the values are not properly - * formatted or use a unit other than px or %, and error is thrown. - * @private - * @param {string=} optRootMargin An optional rootMargin value, - * defaulting to '0px'. - * @return {Array} An array of margin objects with the keys - * value and unit. - */ - _parseRootMargin(optRootMargin) { - let marginString = optRootMargin || '0px'; - let margins = marginString.split(/\s+/).map(function(margin) { - let parts = /^(-?\d*\.?\d+)(px|%)$/.exec(margin); - if (!parts) { - throw new Error('rootMargin must be specified in pixels or percent'); - } - return { value: parseFloat(parts[1]), unit: parts[2] }; - }); - - // Handles shorthand. - margins[1] = margins[1] || margins[0]; - margins[2] = margins[2] || margins[0]; - margins[3] = margins[3] || margins[1]; - - return margins; - } - - /** - * Starts polling for intersection changes if the polling is not already - * happening, and if the page's visibility state is visible. - * @private - */ - _monitorIntersections() { - if (!this._monitoringIntersections) { - this._monitoringIntersections = true; - - // If a poll interval is set, use polling instead of listening to - // resize and scroll events or DOM mutations. - if (this.POLL_INTERVAL) { - this._monitoringInterval = setInterval(this._checkForIntersections, this.POLL_INTERVAL); - } else { - addEvent(window, 'resize', this._checkForIntersections, true); - addEvent(document, 'scroll', this._checkForIntersections, true); - - if (this.USE_MUTATION_OBSERVER && 'MutationObserver' in window) { - this._domObserver = new MutationObserver(this._checkForIntersections); - this._domObserver.observe(document, { - attributes: true, - childList: true, - characterData: true, - subtree: true - }); - } - } - } - } - - /** - * Stops polling for intersection changes. - * @private - */ - _unmonitorIntersections() { - if (this._monitoringIntersections) { - this._monitoringIntersections = false; - - clearInterval(this._monitoringInterval); - this._monitoringInterval = null; - - removeEvent(window, 'resize', this._checkForIntersections, true); - removeEvent(document, 'scroll', this._checkForIntersections, true); - - if (this._domObserver) { - this._domObserver.disconnect(); - this._domObserver = null; - } - } - } - - /** - * Scans each observation target for intersection changes and adds them - * to the internal entries queue. If new entries are found, it - * schedules the callback to be invoked. - * @NOTE Using arrow function to bind to `this` instance. - * @private - */ - _checkForIntersections = () => { - let rootIsInDom = this._rootIsInDom(); - let rootRect = rootIsInDom ? this._getRootRect() : getEmptyRect(); - - this._observationTargets.forEach(function(item) { - let target = item.element; - let targetRect = getBoundingClientRect(target); - let rootContainsTarget = this._rootContainsTarget(target); - let oldEntry = item.entry; - let intersectionRect = rootIsInDom && rootContainsTarget && - this._computeTargetAndRootIntersection(target, rootRect); - - let newEntry = item.entry = new IntersectionObserverEntry({ - time: now(), - target: target, - boundingClientRect: targetRect, - rootBounds: rootRect, - intersectionRect: intersectionRect - }); - - if (!oldEntry) { - this._queuedEntries.push(newEntry); - } else if (rootIsInDom && rootContainsTarget) { - // If the new entry intersection ratio has crossed any of the - // thresholds, add a new entry. - if (this._hasCrossedThreshold(oldEntry, newEntry)) { - this._queuedEntries.push(newEntry); - } - } else { - // If the root is not in the DOM or target is not contained within - // root but the previous entry for this target had an intersection, - // add a new record indicating removal. - if (oldEntry && oldEntry.isIntersecting) { - this._queuedEntries.push(newEntry); - } - } - }, this); - - if (this._queuedEntries.length) { - this._callback(this.takeRecords(), this); - } - } - - /** - * Accepts a target and root rect computes the intersection between then - * following the algorithm in the spec. - * TODO(philipwalton): at this time clip-path is not considered. - * https://w3c.github.io/IntersectionObserver/#calculate-intersection-rect-algo - * @param {Element} target The target DOM element - * @param {Object} rootRect The bounding rect of the root after being - * expanded by the rootMargin value. - * @return {?Object} The final intersection rect object or undefined if no - * intersection is found. - * @private - */ - _computeTargetAndRootIntersection(target, rootRect) { - // If the element isn't displayed, an intersection can't happen. - if (window.getComputedStyle(target).display == 'none') return; - - let targetRect = getBoundingClientRect(target); - let intersectionRect = targetRect; - let parent = getParentNode(target); - let atRoot = false; - - while (!atRoot) { - let parentRect = null; - let parentComputedStyle = parent.nodeType == 1 ? - window.getComputedStyle(parent) : {}; - - // If the parent isn't displayed, an intersection can't happen. - if (parentComputedStyle.display === 'none') return; - - if (parent === this.root || parent === document) { - atRoot = true; - parentRect = rootRect; - } else { - // If the element has a non-visible overflow, and it's not the - // or element, update the intersection rect. - // Note: and cannot be clipped to a rect that's not also - // the document rect, so no need to compute a new intersection. - if (parent !== document.body && - parent !== document.documentElement && - parentComputedStyle.overflow !== 'visible') { - parentRect = getBoundingClientRect(parent); - } - } - - // If either of the above conditionals set a new parentRect, - // calculate new intersection data. - if (parentRect) { - intersectionRect = computeRectIntersection(parentRect, intersectionRect); - - if (!intersectionRect) break; - } - parent = getParentNode(parent); - } - return intersectionRect; - } - - /** - * Returns the root rect after being expanded by the rootMargin value. - * @return {Object} The expanded root rect. - * @private - */ - _getRootRect() { - let rootRect; - if (this.root) { - rootRect = getBoundingClientRect(this.root); - } else { - // Use / instead of window since scroll bars affect size. - let html = document.documentElement; - let body = document.body; - rootRect = { - top: 0, - left: 0, - right: html.clientWidth || body.clientWidth, - width: html.clientWidth || body.clientWidth, - bottom: html.clientHeight || body.clientHeight, - height: html.clientHeight || body.clientHeight - }; - } - return this._expandRectByRootMargin(rootRect); - } - - /** - * Accepts a rect and expands it by the rootMargin value. - * @param {Object} rect The rect object to expand. - * @return {Object} The expanded rect. - * @private - */ - _expandRectByRootMargin(rect) { - let margins = this._rootMarginValues.map(function(margin, i) { - return margin.unit === 'px' ? margin.value : - margin.value * (i % 2 ? rect.width : rect.height) / 100; - }); - let newRect = { - top: rect.top - margins[0], - right: rect.right + margins[1], - bottom: rect.bottom + margins[2], - left: rect.left - margins[3] - }; - newRect.width = newRect.right - newRect.left; - newRect.height = newRect.bottom - newRect.top; - - return newRect; - } - - /** - * Accepts an old and new entry and returns true if at least one of the - * threshold values has been crossed. - * @param {?IntersectionObserverEntry} oldEntry The previous entry for a - * particular target element or null if no previous entry exists. - * @param {IntersectionObserverEntry} newEntry The current entry for a - * particular target element. - * @return {boolean} Returns true if a any threshold has been crossed. - * @private - */ - _hasCrossedThreshold(oldEntry, newEntry) { - // To make comparing easier, an entry that has a ratio of 0 - // but does not actually intersect is given a value of -1 - const oldRatio = oldEntry && oldEntry.isIntersecting ? - oldEntry.intersectionRatio || 0 : -1; - const newRatio = newEntry.isIntersecting ? - newEntry.intersectionRatio || 0 : -1; - - // Ignore unchanged ratios - if (oldRatio === newRatio) return; - - for (let i = 0; i < this.thresholds.length; i++) { - const threshold = this.thresholds[i]; - - // Return true if an entry matches a threshold or if the new ratio - // and the old ratio are on the opposite sides of a threshold. - if (threshold == oldRatio || threshold == newRatio || - threshold < oldRatio !== threshold < newRatio) { - return true; - } - } - } - - /** - * Returns whether or not the root element is an element and is in the DOM. - * @return {boolean} True if the root element is an element and is in the DOM. - * @private - */ - _rootIsInDom() { - return !this.root || containsDeep(document, this.root); - } - - /** - * Returns whether or not the target element is a child of root. - * @param {Element} target The target element to check. - * @return {boolean} True if the target element is a child of root. - * @private - */ - _rootContainsTarget(target) { - return containsDeep(this.root || document, target); - } - - /** - * Adds the instance to the global IntersectionObserver registry if it isn't - * already present. - * @private - */ - _registerInstance() { - if (registry.indexOf(this) < 0) { - registry.push(this); - } - } - - /** - * Removes the instance from the global IntersectionObserver registry. - * @private - */ - _unregisterInstance() { - const index = registry.indexOf(this); - if (index !== -1) registry.splice(index, 1); - } -} - -/** - * Returns the result of the performance.now() method or null in browsers - * that don't support the API. - * @return {number} The elapsed time since the page was requested. - */ -function now() { - return window.performance && performance.now && performance.now(); -} - - -/** - * Throttles a function and delays its execution, so it's only called at most - * once within a given time period. - * @param {Function} fn The function to throttle. - * @param {number} timeout The amount of time that must pass before the - * function can be called again. - * @return {Function} The throttled function. - */ -function throttle(fn, timeout) { - let timer = null; - return function() { - if (!timer) { - timer = setTimeout(function() { - fn(); - timer = null; - }, timeout); - } - }; -} - - -/** - * Adds an event handler to a DOM node ensuring cross-browser compatibility. - * @param {Node} node The DOM node to add the event handler to. - * @param {string} event The event name. - * @param {Function} fn The event handler to add. - * @param {boolean} opt_useCapture Optionally adds the even to the capture - * phase. Note: this only works in modern browsers. - */ -function addEvent(node, event, fn, opt_useCapture) { - if (typeof node.addEventListener == 'function') { - node.addEventListener(event, fn, opt_useCapture || false); - } else if (typeof node.attachEvent == 'function') { - node.attachEvent('on' + event, fn); - } -} - - -/** - * Removes a previously added event handler from a DOM node. - * @param {Node} node The DOM node to remove the event handler from. - * @param {string} event The event name. - * @param {Function} fn The event handler to remove. - * @param {boolean} opt_useCapture If the event handler was added with this - * flag set to true, it should be set to true here in order to remove it. - */ -function removeEvent(node, event, fn, opt_useCapture) { - if (typeof node.removeEventListener == 'function') { - node.removeEventListener(event, fn, opt_useCapture || false); - } else if (typeof node.detatchEvent == 'function') { - node.detatchEvent('on' + event, fn); - } -} - - -/** - * Returns the intersection between two rect objects. - * @param {Object} rect1 The first rect. - * @param {Object} rect2 The second rect. - * @return {?Object} The intersection rect or undefined if no intersection - * is found. - */ -function computeRectIntersection(rect1, rect2) { - const top = Math.max(rect1.top, rect2.top); - const bottom = Math.min(rect1.bottom, rect2.bottom); - const left = Math.max(rect1.left, rect2.left); - const right = Math.min(rect1.right, rect2.right); - const width = right - left; - const height = bottom - top; - - return width >= 0 && height >= 0 && { top, bottom, left, right, width, height }; -} - - -/** - * Shims the native getBoundingClientRect for compatibility with older IE. - * @param {Element} el The element whose bounding rect to get. - * @return {Object} The (possibly shimmed) rect of the element. - */ -function getBoundingClientRect(el) { - let rect; - - try { - rect = el.getBoundingClientRect(); - } catch (err) { - // Ignore Windows 7 IE11 "Unspecified error" - // https://github.com/w3c/IntersectionObserver/pull/205 - } - - if (!rect) return getEmptyRect(); - - // Older IE - if (!(rect.width && rect.height)) { - rect = { - top: rect.top, - right: rect.right, - bottom: rect.bottom, - left: rect.left, - width: rect.right - rect.left, - height: rect.bottom - rect.top - }; - } - return rect; -} - - -/** - * Returns an empty rect object. An empty rect is returned when an element - * is not in the DOM. - * @return {Object} The empty rect. - */ -function getEmptyRect() { - return { - top: 0, - bottom: 0, - left: 0, - right: 0, - width: 0, - height: 0 - }; -} - -/** - * Checks to see if a parent element contains a child element (including inside - * shadow DOM). - * @param {Node} parent The parent element. - * @param {Node} child The child element. - * @return {boolean} True if the parent node contains the child node. - */ -function containsDeep(parent, child) { - let node = child; - while (node) { - if (node === parent) return true; - - node = getParentNode(node); - } - return false; -} - - -/** - * Gets the parent node of an element or its host element if the parent node - * is a shadow root. - * @param {Node} node The node whose parent to get. - * @return {Node|null} The parent node or null if no parent exists. - */ -function getParentNode(node) { - let parent = node.parentNode; - - if (parent && parent.nodeType == 11 && parent.host) { - // If the parent is a shadow root, return the host element. - return parent.host; - } - - if (parent && parent.assignedSlot) { - // If the parent is distributed in a , return the parent of a slot. - return parent.assignedSlot.parentNode; - } - - return parent; -} diff --git a/packages/runtime-shared/src/appear/index.js b/packages/runtime-shared/src/appear/index.js deleted file mode 100644 index 4ce175147e..0000000000 --- a/packages/runtime-shared/src/appear/index.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Simulate appear & disappear events. - */ -import { createIntersectionObserver, destroyIntersectionObserver, observerElement } from './intersectionObserverManager'; - -// hijack Node.prototype.addEventListener -const injectEventListenerHook = (instances = [], Node) => { - let nativeAddEventListener = Node.prototype.addEventListener; - - Node.prototype.addEventListener = function(eventName, eventHandler, useCapture, doNotWatch) { - const lowerCaseEventName = eventName && String(eventName).toLowerCase(); - const isAppearEvent = lowerCaseEventName === 'appear' || lowerCaseEventName === 'disappear'; - if (isAppearEvent) observerElement(this); - - nativeAddEventListener.call(this, eventName, eventHandler, useCapture); - }; - - return function unsetup() { - Node.prototype.addEventListener = nativeAddEventListener; - destroyIntersectionObserver(); - }; -}; - -export function setupAppear(win = window) { - createIntersectionObserver(); - return injectEventListenerHook([], win.Node); -} - diff --git a/packages/runtime-shared/src/appear/intersectionObserverManager.js b/packages/runtime-shared/src/appear/intersectionObserverManager.js deleted file mode 100644 index c796df0d60..0000000000 --- a/packages/runtime-shared/src/appear/intersectionObserverManager.js +++ /dev/null @@ -1,61 +0,0 @@ -import PolyfilledIntersectionObserver from './IntersectionObserver'; - -// Shared intersectionObserver instance. -let intersectionObserver; -const IntersectionObserver = (function(window) { - if ('IntersectionObserver' in window && - 'IntersectionObserverEntry' in window && - 'intersectionRatio' in window.IntersectionObserverEntry.prototype) { - // features are natively supported - return window.IntersectionObserver; - } else { - // polyfilled IntersectionObserver - return PolyfilledIntersectionObserver; - } -})(window); -const defaultOptions = { - root: null, - rootMargin: '0px', - threshold: 0.0 -}; - -export function createIntersectionObserver(options = defaultOptions) { - intersectionObserver = new IntersectionObserver(handleIntersect, options); -} - -export function destroyIntersectionObserver() { - if (intersectionObserver) { - intersectionObserver.disconnect(); - intersectionObserver = null; - } -} - -export function observerElement(element) { - if (!intersectionObserver) createIntersectionObserver(); - - if (element === document) element = document.documentElement; - - intersectionObserver.observe(element); -} - -function handleIntersect(entries) { - entries.forEach((entry) => { - const { target, intersectionRatio } = entry; - - // is in view - if (intersectionRatio > 0) { - target.dataset.appeared = true; - target.dispatchEvent(createEvent('appear')); - } else if (target.dataset.appeared) { - target.dataset.appeared = false; - target.dispatchEvent(createEvent('disappear')); - } - }); -} - -function createEvent(eventName) { - return new CustomEvent(eventName, { - bubbles: false, - cancelable: true, - }); -} diff --git a/packages/runtime-shared/src/array.es6.js b/packages/runtime-shared/src/array.es6.js deleted file mode 100644 index 68045e2f39..0000000000 --- a/packages/runtime-shared/src/array.es6.js +++ /dev/null @@ -1,133 +0,0 @@ -/* eslint-disable no-bitwise, no-extend-native, radix, no-self-compare, consistent-this */ - -/** - * Creates an array from array like objects. - * - * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from - */ -export function ArrayFrom(arrayLike /* , mapFn, thisArg */) { - if (arrayLike == null) { - throw new TypeError('Object is null or undefined'); - } - - // Optional args. - var mapFn = arguments[1]; - var thisArg = arguments[2]; - - var C = this; - var items = Object(arrayLike); - var symbolIterator = - typeof Symbol === 'function' ? Symbol.iterator : '@@iterator'; - var mapping = typeof mapFn === 'function'; - var usingIterator = typeof items[symbolIterator] === 'function'; - var key = 0; - var ret; - var value; - - if (usingIterator) { - ret = typeof C === 'function' ? new C() : []; - var it = items[symbolIterator](); - var next; - - while (!(next = it.next()).done) { - value = next.value; - - if (mapping) { - value = mapFn.call(thisArg, value, key); - } - - ret[key] = value; - key += 1; - } - - ret.length = key; - return ret; - } - - var len = items.length; - if (isNaN(len) || len < 0) { - len = 0; - } - - ret = typeof C === 'function' ? new C(len) : new Array(len); - - while (key < len) { - value = items[key]; - - if (mapping) { - value = mapFn.call(thisArg, value, key); - } - - ret[key] = value; - - key += 1; - } - - ret.length = key; - return ret; -} - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/of#Polyfill -export function ArrayOf() { - return Array.prototype.slice.call(arguments); -} - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex -export function findIndex(predicate, context) { - if (this == null) { - throw new TypeError( - 'Array.prototype.findIndex called on null or undefined', - ); - } - if (typeof predicate !== 'function') { - throw new TypeError('predicate must be a function'); - } - var list = Object(this); - var length = list.length >>> 0; - for (var i = 0; i < length; i++) { - if (predicate.call(context, list[i], i, list)) { - return i; - } - } - return -1; -} - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find -export function find(predicate, context) { - if (this == null) { - throw new TypeError('Array.prototype.find called on null or undefined'); - } - var index = findIndex.call(this, predicate, context); - return index === -1 ? undefined : this[index]; -} - -/** - * polyfill ES6 Array - */ -export function polyfill(ArrayConstructor = Array) { - if (!ArrayConstructor.from) { - ArrayConstructor.from = ArrayFrom; - } - - if (!ArrayConstructor.of) { - ArrayConstructor.of = ArrayOf; - } - - if (!ArrayConstructor.prototype.findIndex) { - Object.defineProperty(ArrayConstructor.prototype, 'findIndex', { - enumerable: false, - writable: true, - configurable: true, - value: findIndex, - }); - } - - if (!ArrayConstructor.prototype.find) { - Object.defineProperty(ArrayConstructor.prototype, 'find', { - enumerable: false, - writable: true, - configurable: true, - value: find, - }); - } -} diff --git a/packages/runtime-shared/src/array.es7.js b/packages/runtime-shared/src/array.es7.js deleted file mode 100644 index 31329c10e2..0000000000 --- a/packages/runtime-shared/src/array.es7.js +++ /dev/null @@ -1,46 +0,0 @@ -/* eslint-disable no-bitwise, no-extend-native, radix, no-self-compare, consistent-this */ - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes -export function ArrayIncludes(searchElement) { - var O = Object(this); - var len = parseInt(O.length) || 0; - if (len === 0) { - return false; - } - var n = parseInt(arguments[1]) || 0; - var k; - if (n >= 0) { - k = n; - } else { - k = len + n; - if (k < 0) { - k = 0; - } - } - var currentElement; - while (k < len) { - currentElement = O[k]; - if ( - searchElement === currentElement || - searchElement !== searchElement && currentElement !== currentElement - ) { - return true; - } - k++; - } - return false; -} - -/** - * polyfill ES7 Array - */ -export function polyfill(ArrayConstructor = Array) { - if (!ArrayConstructor.prototype.includes) { - Object.defineProperty(ArrayConstructor.prototype, 'includes', { - enumerable: false, - writable: true, - configurable: true, - value: ArrayIncludes, - }); - } -} diff --git a/packages/runtime-shared/src/fontface.js b/packages/runtime-shared/src/fontface.js deleted file mode 100644 index 2d06723948..0000000000 --- a/packages/runtime-shared/src/fontface.js +++ /dev/null @@ -1,8 +0,0 @@ -class FontFace { - constructor(family, source) { - this.family = family; - this.source = source; - } -} - -module.exports = FontFace; \ No newline at end of file diff --git a/packages/runtime-shared/src/index.js b/packages/runtime-shared/src/index.js deleted file mode 100644 index 28232b3970..0000000000 --- a/packages/runtime-shared/src/index.js +++ /dev/null @@ -1,34 +0,0 @@ - - -module.exports = { - get Promise() { - return require('./promise'); - }, - get Symbol() { - return require('./symbol'); - }, - get Map() { - return require('./map'); - }, - get Set() { - return require('./set'); - }, - get WeakMap() { - return require('./weakmap'); - }, - get WeakSet() { - return require('./weakset'); - }, - get FontFace() { - return require('./fontface'); - }, - get URL() { - return require('./url'); - }, - get URLSearchParams() { - return require('./url-search-params'); - }, - get matchMedia() { - return require('./matchMedia'); - }, -}; diff --git a/packages/runtime-shared/src/map.js b/packages/runtime-shared/src/map.js deleted file mode 100644 index 513b286049..0000000000 --- a/packages/runtime-shared/src/map.js +++ /dev/null @@ -1,158 +0,0 @@ -/* eslint no-extend-native: "off" */ -const Symbol = require('./symbol'); - -// Deleted map items mess with iterator pointers, so rather than removing them mark them as deleted. Can't use undefined or null since those both valid keys so use a private symbol. -const undefMarker = Symbol('undef'); -// NaN cannot be found in an array using indexOf, so we encode NaNs using a private symbol. -const NaNMarker = Symbol('NaN'); -var ACCESSOR_SUPPORT = true; - -function encodeKey(key) { - // Number.isNaN not extist in iOS 8.x - return key !== key ? NaNMarker : key; -} - -function decodeKey(encodedKey) { - return encodedKey === NaNMarker ? NaN : encodedKey; -} - -function makeIterator(mapInst, getter) { - var nextIdx = 0; - var done = false; - return { - next: function() { - if (nextIdx === mapInst._keys.length) done = true; - if (!done) { - while (mapInst._keys[nextIdx] === undefMarker) nextIdx++; - return {value: getter.call(mapInst, nextIdx++), done: false}; - } else { - return {value: void 0, done: true}; - } - } - }; -} - -function calcSize(mapInst) { - var size = 0; - for (var i = 0, s = mapInst._keys.length; i < s; i++) { - if (mapInst._keys[i] !== undefMarker) size++; - } - return size; -} - -function hasProtoMethod(instance, method) { - return typeof instance[method] === 'function'; -} - -var Map = function(data) { - this._keys = []; - this._values = []; - // If `data` is iterable (indicated by presence of a forEach method), pre-populate the map - if (data && hasProtoMethod(data, 'forEach')) { - // Fastpath: If `data` is a Map, shortcircuit all following the checks - if (data instanceof Map || - // If `data` is not an instance of Map, it could be because you have a Map from an iframe or a worker or something. - // Check if `data` has all the `Map` methods and if so, assume data is another Map - hasProtoMethod(data, 'clear') && - hasProtoMethod(data, 'delete') && - hasProtoMethod(data, 'entries') && - hasProtoMethod(data, 'forEach') && - hasProtoMethod(data, 'get') && - hasProtoMethod(data, 'has') && - hasProtoMethod(data, 'keys') && - hasProtoMethod(data, 'set') && - hasProtoMethod(data, 'values')) { - data.forEach(function(value, key) { - this.set.apply(this, [key, value]); - }, this); - } else { - data.forEach(function(item) { - this.set.apply(this, item); - }, this); - } - } - - if (!ACCESSOR_SUPPORT) this.size = calcSize(this); -}; -Map.prototype = {}; - -// Some old engines do not support ES5 getters/setters. Since Map only requires these for the size property, we can fall back to setting the size property statically each time the size of the map changes. -try { - Object.defineProperty(Map.prototype, 'size', { - get: function() { - return calcSize(this); - } - }); -} catch (e) { - ACCESSOR_SUPPORT = false; -} - -Map.prototype.get = function(key) { - var idx = this._keys.indexOf(encodeKey(key)); - return idx !== -1 ? this._values[idx] : undefined; -}; -Map.prototype.set = function(key, value) { - var idx = this._keys.indexOf(encodeKey(key)); - if (idx !== -1) { - this._values[idx] = value; - } else { - this._keys.push(encodeKey(key)); - this._values.push(value); - if (!ACCESSOR_SUPPORT) this.size = calcSize(this); - } - return this; -}; -Map.prototype.has = function(key) { - return this._keys.indexOf(encodeKey(key)) !== -1; -}; -Map.prototype.delete = function(key) { - var idx = this._keys.indexOf(encodeKey(key)); - if (idx === -1) return false; - this._keys[idx] = undefMarker; - this._values[idx] = undefMarker; - if (!ACCESSOR_SUPPORT) this.size = calcSize(this); - return true; -}; -Map.prototype.clear = function() { - this._keys = this._values = []; - if (!ACCESSOR_SUPPORT) this.size = 0; -}; -Map.prototype.values = function() { - return makeIterator(this, function(i) { - return this._values[i]; - }); -}; -Map.prototype.keys = function() { - return makeIterator(this, function(i) { - return decodeKey(this._keys[i]); - }); -}; -Map.prototype.entries = -Map.prototype[Symbol.iterator] = function() { - return makeIterator(this, function(i) { - return [decodeKey(this._keys[i]), this._values[i]]; - }); -}; -Map.prototype.forEach = function(callbackFn, thisArg) { - thisArg = thisArg || global; - var iterator = this.entries(); - var result = iterator.next(); - while (result.done === false) { - callbackFn.call(thisArg, result.value[1], result.value[0], this); - result = iterator.next(); - } -}; - -Map.prototype[Symbol.species] = Map; - -Object.defineProperty(Map, 'constructor', { - value: Map -}); - -try { - Object.defineProperty(Map, 'length', { - value: 0 - }); -} catch (e) {} - -module.exports = Map; diff --git a/packages/runtime-shared/src/matchMedia.js b/packages/runtime-shared/src/matchMedia.js deleted file mode 100644 index 92f3dba2d8..0000000000 --- a/packages/runtime-shared/src/matchMedia.js +++ /dev/null @@ -1,115 +0,0 @@ -// https://github.com/ericf/css-mediaquery - -const RE_MEDIA_QUERY = /^(?:(only|not)?\s*([_a-z][_a-z0-9-]*)|(\([^\)]+\)))(?:\s*and\s*(.*))?$/i, - RE_MQ_EXPRESSION = /^\(\s*([_a-z-][_a-z0-9-]*)\s*(?:\:\s*([^\)]+))?\s*\)$/, - RE_MQ_FEATURE = /^(?:(min|max)-)?(.+)/; - -function _matches(media, values) { - return _parseQuery(media).some((query) => { - const inverse = query.inverse; - - const typeMatch = query.type === 'all' || values.type === query.type; - - if (typeMatch && inverse || !(typeMatch || inverse)) { - return false; - } - - const expressionsMatch = query.expressions.every((expression) => { - let feature = expression.feature, - modifier = expression.modifier, - expValue = expression.value, - value = values[feature]; - - if (!value) { - return false; - } - - switch (feature) { - case 'width': - case 'height': - expValue = parseFloat(expValue); - value = parseFloat(value); - break; - } - - switch (modifier) { - case 'min': return value >= expValue; - case 'max': return value <= expValue; - default: return value === expValue; - } - }); - - return expressionsMatch && !inverse || !expressionsMatch && inverse; - }); -}; - -function _parseQuery(media) { - return media.split(',').map((query) => { - query = query.trim(); - - const captures = query.match(RE_MEDIA_QUERY); - - if (!captures) { - throw new SyntaxError(`Invalid CSS media query: "${query}"`); - } - - let modifier = captures[1], - type = captures[2], - expressions = ((captures[3] || '') + (captures[4] || '')).trim(), - parsed = {}; - - parsed.inverse = !!modifier && modifier.toLowerCase() === 'not'; - parsed.type = type ? type.toLowerCase() : 'all'; - - if (!expressions) { - parsed.expressions = []; - return parsed; - } - - expressions = expressions.match(/\([^\)]+\)/g); - - if (!expressions) { - throw new SyntaxError(`Invalid CSS media query: "${query}"`); - } - - parsed.expressions = expressions.map((expression) => { - const captures = expression.match(RE_MQ_EXPRESSION); - - if (!captures) { - throw new SyntaxError(`Invalid CSS media query: "${query}"`); - } - - const feature = captures[1].toLowerCase().match(RE_MQ_FEATURE); - - return { - modifier: feature[1], - feature: feature[2], - value: captures[2] - }; - }); - - return parsed; - }); -}; - -function matchMedia(media) { - let mql = { - matches: false, - media: media - }; - - if (media === '') { - mql.matches = true; - return mql; - } - - mql.matches = _matches(media, { - type: 'screen', - width: window.screen.width, - height: window.screen.height - }); - - return mql; -} - -module.exports = matchMedia; diff --git a/packages/runtime-shared/src/number.es6.js b/packages/runtime-shared/src/number.es6.js deleted file mode 100644 index b739546261..0000000000 --- a/packages/runtime-shared/src/number.es6.js +++ /dev/null @@ -1,60 +0,0 @@ -// https://github.com/dherman/tc39-codex-wiki/blob/master/data/es6/number/index.md - -const globalIsNaN = isNaN; -const globalIsFinite = isFinite; -const floor = Math.floor; - -export function isInteger(value) { - return typeof value === 'number' && globalIsFinite(value) && - value > -9007199254740992 && value < 9007199254740992 && - floor(value) === value; -} - -export function isNaN(value) { - return typeof value === 'number' && globalIsFinite(value); -} - -/** - * polyfill Number - */ -export function polyfill(NumberConstructor = Number) { - if (NumberConstructor.EPSILON === undefined) { - Object.defineProperty(NumberConstructor, 'EPSILON', { - value: Math.pow(2, -52), - }); - } - - if (NumberConstructor.MAX_SAFE_INTEGER === undefined) { - Object.defineProperty(NumberConstructor, 'MAX_SAFE_INTEGER', { - value: Math.pow(2, 53) - 1, - }); - } - - if (NumberConstructor.MIN_SAFE_INTEGER === undefined) { - Object.defineProperty(NumberConstructor, 'MIN_SAFE_INTEGER', { - value: -(Math.pow(2, 53) - 1), - }); - } - - if (!NumberConstructor.isNaN) { - definePty(NumberConstructor, 'isNaN', isNaN); - } - - if (!NumberConstructor.isFinite) { - definePty(NumberConstructor, 'isFinite', isNaN); - } - - if (!NumberConstructor.isInteger) { - definePty(NumberConstructor, 'isInteger', isInteger); - } -} - - -function definePty(obj, key, val) { - Object.defineProperty(obj, key, { - value: val, - configurable: true, - enumerable: false, - writable: true - }); -} diff --git a/packages/runtime-shared/src/object.es6.js b/packages/runtime-shared/src/object.es6.js deleted file mode 100644 index 11a7a4db8e..0000000000 --- a/packages/runtime-shared/src/object.es6.js +++ /dev/null @@ -1,40 +0,0 @@ -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign -export function assign(target, sources) { - for (var nextIndex = 1; nextIndex < arguments.length; nextIndex++) { - var nextSource = arguments[nextIndex]; - if (nextSource == null) { - continue; - } - - for (var key in nextSource) { - target[key] = nextSource[key]; - } - } - - return target; -} - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is -function is(x, y) { - // SameValue algorithm - if (x === y) { // Steps 1-5, 7-10 - // Steps 6.b-6.e: +0 != -0 - return x !== 0 || 1 / x === 1 / y; - } else { - // Step 6.a: NaN == NaN - return x !== x && y !== y; - } -} - -/** - * polyfill Object - */ -export function polyfill(ObjectConstructor = Object) { - if (!ObjectConstructor.assign) { - ObjectConstructor.assign = assign; - } - - if (!ObjectConstructor.is) { - ObjectConstructor.is = is; - } -} diff --git a/packages/runtime-shared/src/object.es8.js b/packages/runtime-shared/src/object.es8.js deleted file mode 100644 index e16c307e38..0000000000 --- a/packages/runtime-shared/src/object.es8.js +++ /dev/null @@ -1,52 +0,0 @@ -const hasOwnProperty = Object.prototype.hasOwnProperty; - -/** - * Returns an array of the given object's own enumerable entries. - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries - */ -export function entries(object) { - // `null` and `undefined` values are not allowed. - if (object == null) { - throw new TypeError('Object.entries called on non-object'); - } - - const entries = []; - for (const key in object) { - if (hasOwnProperty.call(object, key)) { - entries.push([key, object[key]]); - } - } - return entries; -} - -/** - * Returns an array of the given object's own enumerable entries. - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values - */ -export function values(object) { - // `null` and `undefined` values are not allowed. - if (object == null) { - throw new TypeError('Object.values called on non-object'); - } - - const values = []; - for (const key in object) { - if (hasOwnProperty.call(object, key)) { - values.push(object[key]); - } - } - return values; -} - -/** - * polyfull Object ES8 - */ -export function polyfill(ObjectConstructor = Object) { - if (!ObjectConstructor.values) { - ObjectConstructor.values = values; - } - - if (!ObjectConstructor.entries) { - ObjectConstructor.entries = entries; - } -} diff --git a/packages/runtime-shared/src/promise.js b/packages/runtime-shared/src/promise.js deleted file mode 100644 index a86d3fa8c6..0000000000 --- a/packages/runtime-shared/src/promise.js +++ /dev/null @@ -1,222 +0,0 @@ -/* eslint no-extend-native: "off" */ - -function noop() {} - -// Use polyfill for setImmediate for performance gains -var asap = typeof setImmediate === 'function' && setImmediate || - function(fn) { - if (typeof setTimeout === 'function') { - setTimeout(fn, 0); - } else { - fn(); - } - }; - -var onUnhandledRejection = function(err) { - if (typeof console !== 'undefined' && console) { - console.log('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console - } -}; - -// Polyfill for Function.prototype.bind -function bind(fn, thisArg) { - return function() { - fn.apply(thisArg, arguments); - }; -} - -function Promise(fn) { - if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new'); - if (typeof fn !== 'function') throw new TypeError('Promise resolver is not a function'); - this._state = 0; - this._handled = false; - this._value = undefined; - this._deferreds = []; - - doResolve(fn, this); -} - -function handle(self, deferred) { - while (self._state === 3) { - self = self._value; - } - if (self._state === 0) { - self._deferreds.push(deferred); - return; - } - self._handled = true; - asap(function() { - var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; - if (cb === null) { - (self._state === 1 ? resolve : reject)(deferred.promise, self._value); - return; - } - var ret; - try { - ret = cb(self._value); - } catch (e) { - reject(deferred.promise, e); - return; - } - resolve(deferred.promise, ret); - }); -} - -function resolve(self, newValue) { - try { - // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure - if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); - if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { - var then = newValue.then; - if (newValue instanceof Promise) { - self._state = 3; - self._value = newValue; - finale(self); - return; - } else if (typeof then === 'function') { - doResolve(bind(then, newValue), self); - return; - } - } - self._state = 1; - self._value = newValue; - finale(self); - } catch (e) { - reject(self, e); - } -} - -function reject(self, newValue) { - self._state = 2; - self._value = newValue; - finale(self); -} - -function finale(self) { - if (self._state === 2 && self._deferreds.length === 0) { - asap(function() { - if (!self._handled) { - onUnhandledRejection(self._value); - } - }); - } - - for (var i = 0, len = self._deferreds.length; i < len; i++) { - handle(self, self._deferreds[i]); - } - self._deferreds = null; -} - -function Handler(onFulfilled, onRejected, promise) { - this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; - this.onRejected = typeof onRejected === 'function' ? onRejected : null; - this.promise = promise; -} - -/** - * Take a potentially misbehaving resolver function and make sure - * onFulfilled and onRejected are only called once. - * - * Makes no guarantees about asynchrony. - */ -function doResolve(fn, self) { - var done = false; - try { - fn(function(value) { - if (done) return; - done = true; - resolve(self, value); - }, function(reason) { - if (done) return; - done = true; - reject(self, reason); - }); - } catch (ex) { - if (done) return; - done = true; - reject(self, ex); - } -} - -Promise.prototype.catch = function(onRejected) { - return this.then(null, onRejected); -}; - -Promise.prototype.then = function(onFulfilled, onRejected) { - var prom = new this.constructor(noop); - - handle(this, new Handler(onFulfilled, onRejected, prom)); - return prom; -}; - -Promise.all = function(arr) { - var args = Array.prototype.slice.call(arr); - - return new Promise(function(resolve, reject) { - if (args.length === 0) return resolve([]); - var remaining = args.length; - - function res(i, val) { - try { - if (val && (typeof val === 'object' || typeof val === 'function')) { - var then = val.then; - if (typeof then === 'function') { - then.call(val, function(val) { - res(i, val); - }, reject); - return; - } - } - args[i] = val; - if (--remaining === 0) { - resolve(args); - } - } catch (ex) { - reject(ex); - } - } - - for (var i = 0; i < args.length; i++) { - res(i, args[i]); - } - }); -}; - -Promise.resolve = function(value) { - if (value && typeof value === 'object' && value.constructor === Promise) { - return value; - } - - return new Promise(function(resolve) { - resolve(value); - }); -}; - -Promise.reject = function(value) { - return new Promise(function(resolve, reject) { - reject(value); - }); -}; - -Promise.race = function(values) { - return new Promise(function(resolve, reject) { - for (var i = 0, len = values.length; i < len; i++) { - values[i].then(resolve, reject); - } - }); -}; - -/** - * Set the immediate function to execute callbacks - * @param fn {function} Function to execute - * @private - */ -Promise._setImmediateFn = function _setImmediateFn(fn) { - asap = fn; -}; - -Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) { - onUnhandledRejection = fn; -}; - -module.exports = Promise; diff --git a/packages/runtime-shared/src/set.js b/packages/runtime-shared/src/set.js deleted file mode 100644 index 0179720452..0000000000 --- a/packages/runtime-shared/src/set.js +++ /dev/null @@ -1,121 +0,0 @@ -/* eslint no-extend-native: "off" */ -const Symbol = require('./symbol'); - -// Deleted map items mess with iterator pointers, so rather than removing them mark them as deleted. Can't use undefined or null since those both valid keys so use a private symbol. -const undefMarker = Symbol('undef'); - -// NaN cannot be found in an array using indexOf, so we encode NaNs using a private symbol. -const NaNMarker = Symbol('NaN'); - -var ACCESSOR_SUPPORT = true; - -function encodeVal(data) { - // Number.isNaN not extist in iOS 8.x - return data !== data ? NaNMarker : data; -} - -function decodeVal(encodedData) { - return encodedData === NaNMarker ? NaN : encodedData; -} - -function makeIterator(setInst, getter) { - var nextIdx = 0; - return { - next: function() { - while (setInst._values[nextIdx] === undefMarker) nextIdx++; - if (nextIdx === setInst._values.length) { - return {value: void 0, done: true}; - } else { - return {value: getter.call(setInst, nextIdx++), done: false}; - } - } - }; -} - -function calcSize(setInst) { - var size = 0; - for (var i = 0, s = setInst._values.length; i < s; i++) { - if (setInst._values[i] !== undefMarker) size++; - } - return size; -} - -var Set = function(data) { - this._values = []; - - // If `data` is iterable (indicated by presence of a forEach method), pre-populate the set - data && typeof data.forEach === 'function' && data.forEach(function(item) { - this.add.call(this, item); - }, this); - - if (!ACCESSOR_SUPPORT) this.size = calcSize(this); -}; - -// Some old engines do not support ES5 getters/setters. Since Set only requires these for the size property, we can fall back to setting the size property statically each time the size of the set changes. -try { - Object.defineProperty(Set.prototype, 'size', { - get: function() { - return calcSize(this); - } - }); -} catch (e) { - ACCESSOR_SUPPORT = false; -} - -Set.prototype.add = function(value) { - value = encodeVal(value); - if (this._values.indexOf(value) === -1) { - this._values.push(value); - if (!ACCESSOR_SUPPORT) this.size = calcSize(this); - } - return this; -}; -Set.prototype.has = function(value) { - return this._values.indexOf(encodeVal(value)) !== -1; -}; -Set.prototype.delete = function(value) { - var idx = this._values.indexOf(encodeVal(value)); - if (idx === -1) return false; - this._values[idx] = undefMarker; - if (!ACCESSOR_SUPPORT) this.size = calcSize(this); - return true; -}; -Set.prototype.clear = function() { - this._values = []; - if (!ACCESSOR_SUPPORT) this.size = 0; -}; -Set.prototype.values = -Set.prototype.keys = function() { - return makeIterator(this, function(i) { - return decodeVal(this._values[i]); - }); -}; -Set.prototype.entries = -Set.prototype[Symbol.iterator] = function() { - return makeIterator(this, function(i) { - return [decodeVal(this._values[i]), decodeVal(this._values[i])]; - }); -}; -Set.prototype.forEach = function(callbackFn, thisArg) { - thisArg = thisArg || global; - var iterator = this.entries(); - var result = iterator.next(); - while (result.done === false) { - callbackFn.call(thisArg, result.value[1], result.value[0], this); - result = iterator.next(); - } -}; - -Set.prototype[Symbol.species] = Set; - -Object.defineProperty(Set, 'constructor', { - value: Set -}); - -try { - Object.defineProperty(Set, 'length', { - value: 0 - }); -} catch (e) {} - -module.exports = Set; diff --git a/packages/runtime-shared/src/string.es6.js b/packages/runtime-shared/src/string.es6.js deleted file mode 100644 index 5dba9ce1b0..0000000000 --- a/packages/runtime-shared/src/string.es6.js +++ /dev/null @@ -1,126 +0,0 @@ -/* eslint-disable no-extend-native, no-bitwise */ - -export function startsWith(search) { - 'use strict'; - if (this == null) { - throw new TypeError(); - } - var string = String(this); - var pos = arguments.length > 1 ? Number(arguments[1]) || 0 : 0; - var start = Math.min(Math.max(pos, 0), string.length); - return string.indexOf(String(search), pos) === start; -}; - -export function endsWith(search) { - 'use strict'; - if (this == null) { - throw new TypeError(); - } - var string = String(this); - var stringLength = string.length; - var searchString = String(search); - var pos = arguments.length > 1 ? Number(arguments[1]) || 0 : stringLength; - var end = Math.min(Math.max(pos, 0), stringLength); - var start = end - searchString.length; - if (start < 0) { - return false; - } - return string.lastIndexOf(searchString, start) === start; -} - -export function repeat(count) { - 'use strict'; - if (this == null) { - throw new TypeError(); - } - var string = String(this); - count = Number(count) || 0; - if (count < 0 || count === Infinity) { - throw new RangeError(); - } - if (count === 1) { - return string; - } - var result = ''; - while (count) { - if (count & 1) { - result += string; - } - if (count >>= 1) { - string += string; - } - } - return result; -} - -export function includes(search, start) { - 'use strict'; - if (typeof start !== 'number') { - start = 0; - } - - if (start + search.length > this.length) { - return false; - } else { - return this.indexOf(search, start) !== -1; - } -} - -export function codePointAt(position) { - if (this == null) { - throw new TypeError(); - } - var string = String(this); - var size = string.length; - // `ToInteger` - var index = position ? Number(position) : 0; - if (Number.isNaN(index)) { - index = 0; - } - // Account for out-of-bounds indices: - if (index < 0 || index >= size) { - return undefined; - } - // Get the first code unit - var first = string.charCodeAt(index); - var second; - if ( - // check if it’s the start of a surrogate pair - first >= 0xd800 && - first <= 0xdbff && // high surrogate - size > index + 1 // there is a next code unit - ) { - second = string.charCodeAt(index + 1); - if (second >= 0xdc00 && second <= 0xdfff) { - // low surrogate - // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae - return (first - 0xd800) * 0x400 + second - 0xdc00 + 0x10000; - } - } - return first; -} - -/** - * polyfill String - */ -export function polyfill(StringConstructor = String) { - if (!StringConstructor.prototype.startsWith) { - StringConstructor.prototype.startsWith = startsWith; - } - - if (!StringConstructor.prototype.endsWith) { - StringConstructor.prototype.endsWith = endsWith; - } - - if (!StringConstructor.prototype.repeat) { - StringConstructor.prototype.repeat = repeat; - } - - if (!StringConstructor.prototype.includes) { - StringConstructor.prototype.includes = includes; - } - - if (!StringConstructor.prototype.codePointAt) { - StringConstructor.prototype.codePointAt = codePointAt; - } -} diff --git a/packages/runtime-shared/src/string.es7.js b/packages/runtime-shared/src/string.es7.js deleted file mode 100644 index 04b87eb2a1..0000000000 --- a/packages/runtime-shared/src/string.es7.js +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-disable no-extend-native, no-bitwise */ - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd -export function padEnd(targetLength, padString) { - targetLength = targetLength >> 0; // floor if number or convert non-number to 0; - padString = String(typeof padString !== 'undefined' ? padString : ' '); - if (this.length > targetLength) { - return String(this); - } else { - targetLength = targetLength - this.length; - if (targetLength > padString.length) { - padString += padString.repeat(targetLength / padString.length); // append to original to ensure we are longer than needed - } - return String(this) + padString.slice(0, targetLength); - } -} - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart -export function padStart(targetLength, padString) { - targetLength = targetLength >> 0; // truncate if number or convert non-number to 0; - padString = String(typeof padString !== 'undefined' ? padString : ' '); - if (this.length > targetLength) { - return String(this); - } else { - targetLength = targetLength - this.length; - if (targetLength > padString.length) { - padString += padString.repeat(targetLength / padString.length); // append to original to ensure we are longer than needed - } - return padString.slice(0, targetLength) + String(this); - } -} - -/** - * polyfill String - */ -export function polyfill(StringConstructor = String) { - if (!StringConstructor.prototype.padStart) { - StringConstructor.prototype.padStart = padStart; - } - - if (!StringConstructor.prototype.padEnd) { - StringConstructor.prototype.padEnd = padEnd; - } -} diff --git a/packages/runtime-shared/src/symbol.js b/packages/runtime-shared/src/symbol.js deleted file mode 100644 index 5a639eedfa..0000000000 --- a/packages/runtime-shared/src/symbol.js +++ /dev/null @@ -1,116 +0,0 @@ -/* eslint no-extend-native: "off", new-cap: "off" */ - -var defineProperties = Object.defineProperties, - defineProperty = Object.defineProperty, - SymbolPolyfill, - HiddenSymbol, - globalSymbols = Object.create(null); - -function isSymbol(x) { - if (!x) return false; - if (typeof x === 'symbol') return true; - if (!x.constructor) return false; - if (x.constructor.name !== 'Symbol') return false; - return x[x.constructor.toStringTag] === 'Symbol'; -} - -function validateSymbol(value) { - if (!isSymbol(value)) throw new TypeError(value + ' is not a symbol'); - return value; -} - -var generateName = (function() { - var created = Object.create(null); - return function(desc) { - var postfix = 0, name; - while (created[desc + (postfix || '')]) ++postfix; - desc += postfix || ''; - created[desc] = true; - name = '@@' + desc; - return name; - }; -}()); - -// Internal constructor (not one exposed) for creating Symbol instances. -// This one is used to ensure that `someSymbol instanceof Symbol` always return false -HiddenSymbol = function Symbol(description) { - if (this instanceof HiddenSymbol) throw new TypeError('Symbol is not a constructor'); - return SymbolPolyfill(description); -}; - -// Exposed `Symbol` constructor -// (returns instances of HiddenSymbol) -module.exports = SymbolPolyfill = function Symbol(description) { - var symbol; - if (this instanceof Symbol) throw new TypeError('Symbol is not a constructor'); - symbol = Object.create(HiddenSymbol.prototype); - description = description === undefined ? '' : String(description); - return defineProperties(symbol, { - __description__: {value: description}, - __name__: {value: generateName(description)} - }); -}; -defineProperties(SymbolPolyfill, { - for: {value: function(key) { - if (globalSymbols[key]) return globalSymbols[key]; - return globalSymbols[key] = SymbolPolyfill(String(key)); - }}, - keyFor: {value: function(s) { - var key; - validateSymbol(s); - for (key in globalSymbols) if (globalSymbols[key] === s) return key; - }}, - - // To ensure proper interoperability with other native functions (e.g. Array.from) - // fallback to eventual native implementation of given symbol - hasInstance: {value: SymbolPolyfill('hasInstance')}, - isConcatSpreadable: {value: SymbolPolyfill('isConcatSpreadable')}, - iterator: {value: SymbolPolyfill('iterator')}, - match: {value: SymbolPolyfill('match')}, - replace: {value: SymbolPolyfill('replace')}, - search: {value: SymbolPolyfill('search')}, - species: {value: SymbolPolyfill('species')}, - split: {value: SymbolPolyfill('split')}, - toPrimitive: {value: SymbolPolyfill('toPrimitive')}, - toStringTag: {value: SymbolPolyfill('toStringTag')}, - unscopables: {value: SymbolPolyfill('unscopables')} -}); - -// Internal tweaks for real symbol producer -defineProperties(HiddenSymbol.prototype, { - constructor: {value: SymbolPolyfill}, - toString: {value: function() { - return this.__name__; - }} -}); - -// Proper implementation of methods exposed on Symbol.prototype -// They won't be accessible on produced symbol instances as they derive from HiddenSymbol.prototype -defineProperties(SymbolPolyfill.prototype, { - toString: {value: function() { - return 'Symbol (' + validateSymbol(this).__description__ + ')'; - }}, - valueOf: {value: function() { - return validateSymbol(this); - }} -}); - -defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toPrimitive, { - value: function() { - var symbol = validateSymbol(this); - if (typeof symbol === 'symbol') return symbol; - return symbol.toString(); - } -}); -defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toStringTag, {value: 'Symbol'}); - -// Proper implementaton of toPrimitive and toStringTag for returned symbol instances -defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toStringTag, - {value: SymbolPolyfill.prototype[SymbolPolyfill.toStringTag]}); - -// Note: It's important to define `toPrimitive` as last one, as some implementations -// implement `toPrimitive` natively without implementing `toStringTag` (or other specified symbols) -// And that may invoke error in definition flow: -// See: https://github.com/medikoo/es6-symbol/issues/13#issuecomment-164146149 -defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toPrimitive, - {value: SymbolPolyfill.prototype[SymbolPolyfill.toPrimitive]}); diff --git a/packages/runtime-shared/src/url-search-params.js b/packages/runtime-shared/src/url-search-params.js deleted file mode 100644 index d3188c23ec..0000000000 --- a/packages/runtime-shared/src/url-search-params.js +++ /dev/null @@ -1,172 +0,0 @@ -// https://github.com/WebReflection/url-search-params -const Symbol = require('./symbol'); - -const find = /[!'\(\)~]|%20|%00/g; -const plus = /\+/g; -const replace = { - '!': '%21', - "'": '%27', - '(': '%28', - ')': '%29', - '~': '%7E', - '%20': '+', - '%00': '\x00' -}; -const replacer = function(match) { - return replace[match]; -}; -const secret = '__URLSearchParams__'; - -function encode(str) { - return encodeURIComponent(str).replace(find, replacer); -} - -function decode(str) { - return decodeURIComponent(str.replace(plus, ' ')); -} - -class URLSearchParams { - constructor(query) { - this[secret] = Object.create(null); - if (!query) return; - if (query.charAt(0) === '?') { - query = query.slice(1); - } - for (var - index, value, - pairs = (query || '').split('&'), - i = 0, - length = pairs.length; i < length; i++ - ) { - value = pairs[i]; - index = value.indexOf('='); - if (-1 < index) { - this.append( - decode(value.slice(0, index)), - decode(value.slice(index + 1)) - ); - } else if (value.length) { - this.append( - decode(value), - '' - ); - } - } - } - - append(name, value) { - var dict = this[secret]; - if (name in dict) { - dict[name].push('' + value); - } else { - dict[name] = ['' + value]; - } - } - - delete(name) { - delete this[secret][name]; - } - - get(name) { - var dict = this[secret]; - return name in dict ? dict[name][0] : null; - } - - getAll(name) { - var dict = this[secret]; - return name in dict ? dict[name].slice(0) : []; - } - - has(name) { - return name in this[secret]; - } - - set(name, value) { - this[secret][name] = ['' + value]; - } - - forEach(callback, thisArg) { - var dict = this[secret]; - Object.getOwnPropertyNames(dict).forEach(function(name) { - dict[name].forEach(function(value) { - callback.call(thisArg, value, name, this); - }, this); - }, this); - } - - keys() { - var items = []; - this.forEach(function(value, name) { - items.push(name); - }); - var iterator = { - next: function() { - var value = items.shift(); - return {done: value === undefined, value: value}; - } - }; - - iterator[Symbol.iterator] = function() { - return iterator; - }; - - return iterator; - } - - values() { - var items = []; - this.forEach(function(value) { - items.push(value); - }); - var iterator = { - next: function() { - var value = items.shift(); - return {done: value === undefined, value: value}; - } - }; - - iterator[Symbol.iterator] = function() { - return iterator; - }; - - return iterator; - } - - entries() { - var items = []; - this.forEach(function(value, name) { - items.push([name, value]); - }); - var iterator = { - next: function() { - var value = items.shift(); - return {done: value === undefined, value: value}; - } - }; - - iterator[Symbol.iterator] = function() { - return iterator; - }; - - return iterator; - } - - toString() { - var dict = this[secret], query = [], i, key, name, value; - for (key in dict) { - name = encode(key); - for ( - i = 0, - value = dict[key]; - i < value.length; i++ - ) { - query.push(name + '=' + encode(value[i])); - } - } - return query.join('&'); - } -} - -URLSearchParams.prototype[Symbol.iterator] = URLSearchParams.prototype.entries; - -module.exports = URLSearchParams; diff --git a/packages/runtime-shared/src/url.js b/packages/runtime-shared/src/url.js deleted file mode 100644 index 6d74d65459..0000000000 --- a/packages/runtime-shared/src/url.js +++ /dev/null @@ -1,589 +0,0 @@ -// https://github.com/Polymer/URL - -var URLSearchParams = require('./url-search-params'); - -var relative = Object.create(null); -relative.ftp = 21; -relative.file = 0; -relative.gopher = 70; -relative.http = 80; -relative.https = 443; -relative.ws = 80; -relative.wss = 443; - -var relativePathDotMapping = Object.create(null); -relativePathDotMapping['%2e'] = '.'; -relativePathDotMapping['.%2e'] = '..'; -relativePathDotMapping['%2e.'] = '..'; -relativePathDotMapping['%2e%2e'] = '..'; - -function isRelativeScheme(scheme) { - return relative[scheme] !== undefined; -} - -function invalid() { - clear.call(this); - this._isInvalid = true; -} - -function IDNAToASCII(h) { - if ('' == h) { - invalid.call(this); - } - // XXX - return h.toLowerCase(); -} - -function percentEscape(c) { - var unicode = c.charCodeAt(0); - if (unicode > 0x20 && - unicode < 0x7F && - // " # < > ? ` - [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) == -1 - ) { - return c; - } - return encodeURIComponent(c); -} - -function percentEscapeQuery(c) { - // XXX This actually needs to encode c using encoding and then - // convert the bytes one-by-one. - - var unicode = c.charCodeAt(0); - if (unicode > 0x20 && - unicode < 0x7F && - // " # < > ` (do not escape '?') - [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) == -1 - ) { - return c; - } - return encodeURIComponent(c); -} - -var EOF = undefined, - ALPHA = /[a-zA-Z]/, - ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/; - -function parse(input, stateOverride, base) { - function err(message) { - errors.push(message); - } - - var state = stateOverride || 'scheme start', - cursor = 0, - buffer = '', - seenAt = false, - seenBracket = false, - errors = []; - - loop: while ((input[cursor - 1] != EOF || cursor == 0) && !this._isInvalid) { - var c = input[cursor]; - switch (state) { - case 'scheme start': - if (c && ALPHA.test(c)) { - buffer += c.toLowerCase(); // ASCII-safe - state = 'scheme'; - } else if (!stateOverride) { - buffer = ''; - state = 'no scheme'; - continue; - } else { - err('Invalid scheme.'); - break loop; - } - break; - - case 'scheme': - if (c && ALPHANUMERIC.test(c)) { - buffer += c.toLowerCase(); // ASCII-safe - } else if (':' == c) { - this._scheme = buffer; - buffer = ''; - if (stateOverride) { - break loop; - } - if (isRelativeScheme(this._scheme)) { - this._isRelative = true; - } - if ('file' == this._scheme) { - state = 'relative'; - } else if (this._isRelative && base && base._scheme == this._scheme) { - state = 'relative or authority'; - } else if (this._isRelative) { - state = 'authority first slash'; - } else { - state = 'scheme data'; - } - } else if (!stateOverride) { - buffer = ''; - cursor = 0; - state = 'no scheme'; - continue; - } else if (EOF == c) { - break loop; - } else { - err('Code point not allowed in scheme: ' + c); - break loop; - } - break; - - case 'scheme data': - if ('?' == c) { - state = 'query'; - } else if ('#' == c) { - this._fragment = '#'; - state = 'fragment'; - } else { - // XXX error handling - if (EOF != c && '\t' != c && '\n' != c && '\r' != c) { - this._schemeData += percentEscape(c); - } - } - break; - - case 'no scheme': - if (!base || !isRelativeScheme(base._scheme)) { - err('Missing scheme.'); - invalid.call(this); - } else { - state = 'relative'; - continue; - } - break; - - case 'relative or authority': - if ('/' == c && '/' == input[cursor + 1]) { - state = 'authority ignore slashes'; - } else { - err('Expected /, got: ' + c); - state = 'relative'; - continue; - } - break; - - case 'relative': - this._isRelative = true; - if ('file' != this._scheme) - this._scheme = base._scheme; - if (EOF == c) { - this._host = base._host; - this._port = base._port; - this._path = base._path.slice(); - this._query = base._query; - this._username = base._username; - this._password = base._password; - break loop; - } else if ('/' == c || '\\' == c) { - if ('\\' == c) - err('\\ is an invalid code point.'); - state = 'relative slash'; - } else if ('?' == c) { - this._host = base._host; - this._port = base._port; - this._path = base._path.slice(); - this._query = '?'; - this._username = base._username; - this._password = base._password; - state = 'query'; - } else if ('#' == c) { - this._host = base._host; - this._port = base._port; - this._path = base._path.slice(); - this._query = base._query; - this._fragment = '#'; - this._username = base._username; - this._password = base._password; - state = 'fragment'; - } else { - var nextC = input[cursor + 1]; - var nextNextC = input[cursor + 2]; - if ( - 'file' != this._scheme || !ALPHA.test(c) || - nextC != ':' && nextC != '|' || - EOF != nextNextC && '/' != nextNextC && '\\' != nextNextC && '?' != nextNextC && '#' != nextNextC) { - this._host = base._host; - this._port = base._port; - this._username = base._username; - this._password = base._password; - this._path = base._path.slice(); - this._path.pop(); - } - state = 'relative path'; - continue; - } - break; - - case 'relative slash': - if ('/' == c || '\\' == c) { - if ('\\' == c) { - err('\\ is an invalid code point.'); - } - if ('file' == this._scheme) { - state = 'file host'; - } else { - state = 'authority ignore slashes'; - } - } else { - if ('file' != this._scheme) { - this._host = base._host; - this._port = base._port; - this._username = base._username; - this._password = base._password; - } - state = 'relative path'; - continue; - } - break; - - case 'authority first slash': - if ('/' == c) { - state = 'authority second slash'; - } else { - err("Expected '/', got: " + c); - state = 'authority ignore slashes'; - continue; - } - break; - - case 'authority second slash': - state = 'authority ignore slashes'; - if ('/' != c) { - err("Expected '/', got: " + c); - continue; - } - break; - - case 'authority ignore slashes': - if ('/' != c && '\\' != c) { - state = 'authority'; - continue; - } else { - err('Expected authority, got: ' + c); - } - break; - - case 'authority': - if ('@' == c) { - if (seenAt) { - err('@ already seen.'); - buffer += '%40'; - } - seenAt = true; - for (var i = 0; i < buffer.length; i++) { - var cp = buffer[i]; - if ('\t' == cp || '\n' == cp || '\r' == cp) { - err('Invalid whitespace in authority.'); - continue; - } - // XXX check URL code points - if (':' == cp && null === this._password) { - this._password = ''; - continue; - } - var tempC = percentEscape(cp); - null !== this._password ? this._password += tempC : this._username += tempC; - } - buffer = ''; - } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) { - cursor -= buffer.length; - buffer = ''; - state = 'host'; - continue; - } else { - buffer += c; - } - break; - - case 'file host': - if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) { - if (buffer.length == 2 && ALPHA.test(buffer[0]) && (buffer[1] == ':' || buffer[1] == '|')) { - state = 'relative path'; - } else if (buffer.length == 0) { - state = 'relative path start'; - } else { - this._host = IDNAToASCII.call(this, buffer); - buffer = ''; - state = 'relative path start'; - } - continue; - } else if ('\t' == c || '\n' == c || '\r' == c) { - err('Invalid whitespace in file host.'); - } else { - buffer += c; - } - break; - - case 'host': - case 'hostname': - if (':' == c && !seenBracket) { - // XXX host parsing - this._host = IDNAToASCII.call(this, buffer); - buffer = ''; - state = 'port'; - if ('hostname' == stateOverride) { - break loop; - } - } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c) { - this._host = IDNAToASCII.call(this, buffer); - buffer = ''; - state = 'relative path start'; - if (stateOverride) { - break loop; - } - continue; - } else if ('\t' != c && '\n' != c && '\r' != c) { - if ('[' == c) { - seenBracket = true; - } else if (']' == c) { - seenBracket = false; - } - buffer += c; - } else { - err('Invalid code point in host/hostname: ' + c); - } - break; - - case 'port': - if (/[0-9]/.test(c)) { - buffer += c; - } else if (EOF == c || '/' == c || '\\' == c || '?' == c || '#' == c || stateOverride) { - if ('' != buffer) { - var temp = parseInt(buffer, 10); - if (temp != relative[this._scheme]) { - this._port = temp + ''; - } - buffer = ''; - } - if (stateOverride) { - break loop; - } - state = 'relative path start'; - continue; - } else if ('\t' == c || '\n' == c || '\r' == c) { - err('Invalid code point in port: ' + c); - } else { - invalid.call(this); - } - break; - - case 'relative path start': - if ('\\' == c) - err("'\\' not allowed in path."); - state = 'relative path'; - if ('/' != c && '\\' != c) { - continue; - } - break; - - case 'relative path': - if (EOF == c || '/' == c || '\\' == c || !stateOverride && ('?' == c || '#' == c)) { - if ('\\' == c) { - err('\\ not allowed in relative path.'); - } - var tmp; - if (tmp = relativePathDotMapping[buffer.toLowerCase()]) { - buffer = tmp; - } - if ('..' == buffer) { - this._path.pop(); - if ('/' != c && '\\' != c) { - this._path.push(''); - } - } else if ('.' == buffer && '/' != c && '\\' != c) { - this._path.push(''); - } else if ('.' != buffer) { - if ('file' == this._scheme && this._path.length == 0 && buffer.length == 2 && ALPHA.test(buffer[0]) && buffer[1] == '|') { - buffer = buffer[0] + ':'; - } - this._path.push(buffer); - } - buffer = ''; - if ('?' == c) { - this._query = '?'; - state = 'query'; - } else if ('#' == c) { - this._fragment = '#'; - state = 'fragment'; - } - } else if ('\t' != c && '\n' != c && '\r' != c) { - buffer += percentEscape(c); - } - break; - - case 'query': - if (!stateOverride && '#' == c) { - this._fragment = '#'; - state = 'fragment'; - } else if (EOF != c && '\t' != c && '\n' != c && '\r' != c) { - this._query += percentEscapeQuery(c); - } - break; - - case 'fragment': - if (EOF != c && '\t' != c && '\n' != c && '\r' != c) { - this._fragment += c; - } - break; - } - - cursor++; - } -} - -function clear() { - this._scheme = ''; - this._schemeData = ''; - this._username = ''; - this._password = null; - this._host = ''; - this._port = ''; - this._path = []; - this._query = ''; - this._fragment = ''; - this._isInvalid = false; - this._isRelative = false; -} - -// Does not process domain names or IP addresses. -// Does not handle encoding for the query parameter. -function URL(url, base /* , encoding */) { - if (base !== undefined && !(base instanceof URL)) - base = new URL(String(base)); - - this._url = url; - clear.call(this); - - var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, ''); - // encoding = encoding || 'utf-8' - - parse.call(this, input, null, base); -} - -URL.prototype = { - toString: function() { - return this.href; - }, - get href() { - if (this._isInvalid) - return this._url; - - var authority = ''; - if ('' != this._username || null != this._password) { - authority = this._username + - (null != this._password ? ':' + this._password : '') + '@'; - } - - return this.protocol + - (this._isRelative ? '//' + authority + this.host : '') + - this.pathname + this._query + this._fragment; - }, - set href(href) { - clear.call(this); - parse.call(this, href); - }, - - get protocol() { - return this._scheme + ':'; - }, - set protocol(protocol) { - if (this._isInvalid) - return; - parse.call(this, protocol + ':', 'scheme start'); - }, - - get host() { - return this._isInvalid ? '' : this._port ? - this._host + ':' + this._port : this._host; - }, - set host(host) { - if (this._isInvalid || !this._isRelative) - return; - parse.call(this, host, 'host'); - }, - - get hostname() { - return this._host; - }, - set hostname(hostname) { - if (this._isInvalid || !this._isRelative) - return; - parse.call(this, hostname, 'hostname'); - }, - - get port() { - return this._port; - }, - set port(port) { - if (this._isInvalid || !this._isRelative) - return; - parse.call(this, port, 'port'); - }, - - get pathname() { - return this._isInvalid ? '' : this._isRelative ? - '/' + this._path.join('/') : this._schemeData; - }, - set pathname(pathname) { - if (this._isInvalid || !this._isRelative) - return; - this._path = []; - parse.call(this, pathname, 'relative path start'); - }, - - get search() { - return this._isInvalid || !this._query || '?' == this._query ? - '' : this._query; - }, - set search(search) { - if (this._isInvalid || !this._isRelative) - return; - this._query = '?'; - if ('?' == search[0]) - search = search.slice(1); - parse.call(this, search, 'query'); - }, - - get searchParams() { - return new URLSearchParams(this.search); - }, - - get hash() { - return this._isInvalid || !this._fragment || '#' == this._fragment ? - '' : this._fragment; - }, - set hash(hash) { - if (this._isInvalid) - return; - this._fragment = '#'; - if ('#' == hash[0]) - hash = hash.slice(1); - parse.call(this, hash, 'fragment'); - }, - - get origin() { - var host; - if (this._isInvalid || !this._scheme) { - return ''; - } - // javascript: Gecko returns String(""), WebKit/Blink String("null") - // Gecko throws error for "data://" - // data: Gecko returns "", Blink returns "data://", WebKit returns "null" - // Gecko returns String("") for file: mailto: - // WebKit/Blink returns String("SCHEME://") for file: mailto: - switch (this._scheme) { - case 'data': - case 'file': - case 'javascript': - case 'mailto': - return 'null'; - } - host = this.host; - if (!host) { - return ''; - } - return this._scheme + '://' + host; - } -}; - -module.exports = URL; diff --git a/packages/runtime-shared/src/weakmap.js b/packages/runtime-shared/src/weakmap.js deleted file mode 100644 index 4251c3b34b..0000000000 --- a/packages/runtime-shared/src/weakmap.js +++ /dev/null @@ -1,46 +0,0 @@ -/* eslint no-extend-native: "off" */ - -var defineProperty = Object.defineProperty; -var counter = Date.now() % 1e9; - -var WeakMap = function(data) { - this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__'); - - // If data is iterable (indicated by presence of a forEach method), pre-populate the map - data && data.forEach && data.forEach(function(item) { - this.set.apply(this, item); - }, this); -}; - -WeakMap.prototype.set = function(key, value) { - if (typeof key !== 'object' && typeof key !== 'function') - throw new TypeError('Invalid value used as weak map key'); - - var entry = key[this.name]; - if (entry && entry[0] === key) - entry[1] = value; - else - defineProperty(key, this.name, {value: [key, value], writable: true}); - return this; -}; - -WeakMap.prototype.get = function(key) { - var entry; - return (entry = key[this.name]) && entry[0] === key ? - entry[1] : undefined; -}; - -WeakMap.prototype.delete = function(key) { - var entry = key[this.name]; - if (!entry || entry[0] !== key) return false; - entry[0] = entry[1] = undefined; - return true; -}; - -WeakMap.prototype.has = function(key) { - var entry = key[this.name]; - if (!entry) return false; - return entry[0] === key; -}; - -module.exports = WeakMap; diff --git a/packages/runtime-shared/src/weakset.js b/packages/runtime-shared/src/weakset.js deleted file mode 100644 index 471f3a6b36..0000000000 --- a/packages/runtime-shared/src/weakset.js +++ /dev/null @@ -1,26 +0,0 @@ -/* eslint no-extend-native: "off" */ - -var counter = Date.now() % 1e9; - -var WeakSet = function WeakSet(data) { - this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__'); - data && data.forEach && data.forEach(this.add, this); -}; - -WeakSet.prototype.add = function(obj) { - var name = this.name; - if (!obj[name]) Object.defineProperty(obj, name, {value: true, writable: true}); - return this; -}; - -WeakSet.prototype.delete = function(obj) { - if (!obj[this.name]) return false; - obj[this.name] = undefined; - return true; -}; - -WeakSet.prototype.has = function(obj) { - return !!obj[this.name]; -}; - -module.exports = WeakSet; diff --git a/packages/web-rax-framework/README.md b/packages/web-rax-framework/README.md deleted file mode 100644 index 784f2d0b74..0000000000 --- a/packages/web-rax-framework/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# web-rax-framework - -## Global API Rax Framework provide - -* `document` - * fonts - * add - - -* `FontFace` - ```js - API: - var iconFontFace = new FontFace('iconfont', 'url(http://at.alicdn.com/t/font_pkm0oq8is8fo5hfr.ttf)'); - document.fonts.add(iconFontFace); - - ELEMENT: - {'\uE601'} - ``` diff --git a/packages/web-rax-framework/package.json b/packages/web-rax-framework/package.json deleted file mode 100644 index 09a7ded532..0000000000 --- a/packages/web-rax-framework/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "web-rax-framework", - "version": "0.6.5", - "description": "Rax framework for web.", - "license": "BSD-3-Clause", - "main": "dist/framework.web.js", - "repository": { - "type": "git", - "url": "git+https://github.com/alibaba/rax.git" - }, - "bugs": { - "url": "https://github.com/alibaba/rax/issues" - }, - "homepage": "https://github.com/alibaba/rax#readme", - "dependencies": { - "raf": "^3.3.0", - "rax": "^0.6.5", - "runtime-shared": "^0.6.5", - "whatwg-fetch": "^2.0.1" - } -} diff --git a/packages/web-rax-framework/src/appear.js b/packages/web-rax-framework/src/appear.js deleted file mode 100644 index a12e3cf071..0000000000 --- a/packages/web-rax-framework/src/appear.js +++ /dev/null @@ -1,82 +0,0 @@ -import Registry, { config, getOffset, pushElement } from './appearRegistry'; -import createIntersectionObserver, { observerElement, isExistIntersection } from './intersectionObserver'; - -let instance = null; -const existIntersection = isExistIntersection(); - -const appear = () => { - if (existIntersection) { - createIntersectionObserver(); - injectEventListenerHook(); - } else { - let instances = []; - - Registry.createEvent(); - injectEventListenerHook(instances); - - instance = new Registry({ - container: window - }); - instances.push(instance); - - let control = { - config, - }; - - return control; - } -}; - - -// hijack addEventListener、removeEventListener -const injectEventListenerHook = (instances = []) => { - let nativeAddEventListener = Node.prototype.addEventListener; - let nativeRemoveEventListener = Node.prototype.removeEventListener; - - Node.prototype.addEventListener = function(eventName, eventHandler, useCapture, doNotWatch) { - const lowerCaseEventName = eventName && String(eventName).toLowerCase(); - const isAppearEvent = lowerCaseEventName === 'appear' || lowerCaseEventName === 'disappear'; - if (isAppearEvent) { - if (existIntersection) { - observerElement(this); - } else { - pushElement(this); - } - } - - if (!existIntersection) { - if (instance && isAppearEvent) { - instance.check([this]); - } - - if (lowerCaseEventName === 'scroll' && !doNotWatch) { - instance = new Registry({ - container: this - }); - instances.push(instance); - } - } - - nativeAddEventListener.call(this, eventName, eventHandler, useCapture); - }; - - Node.prototype.removeEventListener = function(eventName, eventHandler, useCapture, doNotWatch) { - let lowerCaseEventName = eventName && String(eventName).toLowerCase(); ; - - // destroy scroller - if (!existIntersection && lowerCaseEventName === 'scroll' && !doNotWatch) { - instances.forEach((instance, index) => { - if (instance.__handle && instance.container === this) { - this.removeEventListener('scroll', instance.__handle, false, true); - instance.__handle = null; - instance.appearWatchElements = []; - instance.container = null; - instances.splice(index, 1); - } - }); - } - nativeRemoveEventListener.call(this, eventName, eventHandler, useCapture); - }; -}; - -export default appear(); diff --git a/packages/web-rax-framework/src/appearRegistry.js b/packages/web-rax-framework/src/appearRegistry.js deleted file mode 100644 index d8763a7b41..0000000000 --- a/packages/web-rax-framework/src/appearRegistry.js +++ /dev/null @@ -1,258 +0,0 @@ -let offsetTop = 0; -let appearEvt, disappearEvt; -let _appearDoms = []; - -class AppearRegistry { - static createEvent() { - appearEvt = document.createEvent('HTMLEvents'); - disappearEvt = document.createEvent('HTMLEvents'); - appearEvt.initEvent('appear', false, true); - disappearEvt.initEvent('disappear', false, true); - } - - constructor(elements) { - this.current = []; - this.elements = elements; - - this.options = { - container: window, - wait: 100, - x: 0, - y: 0, - cls: 'appear', - once: false, - onReset: function() {}, - onAppear: function() {}, - onDisappear: function() {} - }; - this.container = null; - this.appearWatchElements = null; - - this.initConfig.apply(this, arguments); - } - - initConfig(opts) { - this.extend(this.options, opts || (opts = {})); - this.appearWatchElements = this.appearWatchElements || this.getElements(); - this.bindEvent(); - } - - extend(target, el) { - for (let k in el) { - if (el.hasOwnProperty(k)) { - target[k] = el[k]; - } - } - return target; - } - - inViewport(element, offset, type) { - let { top, right, bottom, left } = element.getBoundingClientRect(); - - left = offset.right > left && offset.left < right; - top = offset.bottom > top - offsetTop && offset.top < bottom; - return left && top; - } - - getElements(type) { - let container = this.options.container; - let appearWatchElements; - this.container = container; - - appearWatchElements = _appearDoms || []; - appearWatchElements = [].slice.call(appearWatchElements, null); - - return appearWatchElements; - } - - // check dom inview - check(nodes) { - raf(() => { - this.calculate(nodes); - }); - } - - // calculate everyone dom inview - calculate(nodes) { - let container = this.container; - let elements = nodes || this.getElements(); - let containerOffset = getOffset(window, { - x: this.options.x, - y: this.options.y - }); - let isOnce = this.options.once; - let ev = arguments[0] || {}; - - if (!container) { - return; - } - - if (elements && elements.length > 0) { - [].forEach.call(elements, (ele, i) => { - if (ele) { - if (ele.isOnce && ele._hasAppear) { - _appearDoms.splice(i, 1); - elements.splice(i, 1); - return; - } - this.checkEveryDom(ele, containerOffset, isOnce, appearEvt, disappearEvt, 'normal', i); - } - }); - } - } - - checkEveryDom(ele, containerOffset, isOnce, cacheAppearEvt, cacheDisappearEvt, type, pos) { - let eleOffset = getOffset(ele); - let direction = this.getDirection(ele._eleOffset, eleOffset); - let isInView = this.inViewport(ele, containerOffset, type); - let appear = ele._appear; - let _hasAppear = ele._hasAppear; - let _hasDisAppear = ele._hasDisAppear; - ele._eleOffset = eleOffset; - - cacheAppearEvt.direction = direction; - cacheDisappearEvt.direction = direction; - if (isInView && !appear) { - if (isOnce && !_hasAppear || !isOnce) { - ele.dispatchEvent(cacheAppearEvt); - ele._hasAppear = true; - ele._appear = true; - } - } else if (!isInView && appear) { - if (isOnce && !_hasDisAppear || !isOnce) { - ele.dispatchEvent(cacheDisappearEvt); - ele._hasDisAppear = true; - ele._appear = false; - } - } - } - - // reset - reset(opts) { - this.initConfig(opts); - this.appearWatchElements.forEach((ele) => { - delete ele._hasAppear; - delete ele._hasDisAppear; - delete ele._appear; - }); - return this; - } - bindEvent() { - let handle = throttle(() => { - this.check(); - }, this.options.wait); - if (this.__handle) { - this.container.removeEventListener('scroll', this.__handle, false, true); - this.__handle = null; - } - this.__handle = handle; - this.container.addEventListener('scroll', handle, false, true); - } - - getDirection(beforeOffset, nowOffset) { - var direction = 'none'; - var horizental = beforeOffset.left - nowOffset.left; - var vertical = beforeOffset.top - nowOffset.top; - if (vertical == 0) { - if (horizental != 0) { - direction = horizental > 0 ? 'left' : 'right'; - } else { - direction = 'none'; - } - } - if (horizental == 0) { - if (vertical != 0) { - direction = vertical > 0 ? 'up' : 'down'; - } else { - direction = 'none'; - } - } - return direction; - } -} - -let raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || function(c) { - setTimeout(c, 1 / 60 * 1e3); -}; - -function throttle(fn, wait) { - let context, args, result; - let timeout = null; - let previous = 0; - - const later = () => { - previous = Date.now(); - timeout = null; - result = fn.apply(context, args); - }; - return function() { - const now = Date.now(); - const remaining = wait - (now - previous); - context = this; - args = arguments; - - if (remaining <= 0) { - clearTimeout(timeout); - timeout = null; - previous = now; - result = fn.apply(context, args); - } else if (!timeout) { - timeout = setTimeout(later, remaining); - } - return result; - }; -} - -export function config(opts) { - if (opts.offsetTop && typeof opts.offsetTop === 'number') { - offsetTop = opts.offsetTop; - } -} - -export function getOffset(el, param) { - let l, r, b, t; - if (!el) { - return; - } - if (!param) { - param = {x: 0, y: 0}; - } - - if (el === window) { - l = 0; - t = 0; - r = l + el.innerWidth; - b = t + el.innerHeight; - } else if (el.parentNode === null) { - l = 0; - t = 0; - r = 0; - b = 0; - } else { - const { top, right, bottom, left } = el.getBoundingClientRect(); - l = left; - t = top; - r = right; - b = bottom; - } - - return { - 'left': l, - 'top': t, - 'right': r + param.x, - 'bottom': b + param.y - }; -} - -// add element -export function pushElement(node) { - if (_appearDoms.indexOf(node) === -1 && !node.appended) { - let isOnce = Boolean(node.getAttribute('isonce')) || Boolean(node.getAttribute('data-once')); - node.isOnce = isOnce; - node.appended = true; - _appearDoms.push(node); - node._eleOffset = getOffset(node); - } -} - -export default AppearRegistry; diff --git a/packages/web-rax-framework/src/array.js b/packages/web-rax-framework/src/array.js deleted file mode 100644 index 0fc27d7774..0000000000 --- a/packages/web-rax-framework/src/array.js +++ /dev/null @@ -1,82 +0,0 @@ -// Production steps of ECMA-262, Edition 6, 22.1.2.1 -// Reference: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from -if (!Array.from) { - Array.from = (function() { - var toStr = Object.prototype.toString; - var isCallable = function(fn) { - return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; - }; - var toInteger = function(value) { - var number = Number(value); - if (isNaN(number)) { - return 0; - } - if (number === 0 || !isFinite(number)) { - return number; - } - return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); - }; - var maxSafeInteger = Math.pow(2, 53) - 1; - var toLength = function(value) { - var len = toInteger(value); - return Math.min(Math.max(len, 0), maxSafeInteger); - }; - - // The length property of the from method is 1. - return function from(arrayLike/* , mapFn, thisArg */) { - // 1. Let C be the this value. - var C = this; - - // 2. Let items be ToObject(arrayLike). - var items = Object(arrayLike); - - // 3. ReturnIfAbrupt(items). - if (arrayLike == null) { - throw new TypeError('Array.from requires an array-like object - not null or undefined'); - } - - // 4. If mapfn is undefined, then let mapping be false. - var mapFn = arguments.length > 1 ? arguments[1] : void undefined; - var T; - if (typeof mapFn !== 'undefined') { - // 5. else - // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. - if (!isCallable(mapFn)) { - throw new TypeError('Array.from: when provided, the second argument must be a function'); - } - - // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. - if (arguments.length > 2) { - T = arguments[2]; - } - } - - // 10. Let lenValue be Get(items, "length"). - // 11. Let len be ToLength(lenValue). - var len = toLength(items.length); - - // 13. If IsConstructor(C) is true, then - // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len. - // 14. a. Else, Let A be ArrayCreate(len). - var A = isCallable(C) ? Object(new C(len)) : new Array(len); - - // 16. Let k be 0. - var k = 0; - // 17. Repeat, while k < len… (also steps a - h) - var kValue; - while (k < len) { - kValue = items[k]; - if (mapFn) { - A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); - } else { - A[k] = kValue; - } - k += 1; - } - // 18. Let putStatus be Put(A, "length", len, true). - A.length = len; - // 20. Return A. - return A; - }; - }()); -} diff --git a/packages/web-rax-framework/src/index.js b/packages/web-rax-framework/src/index.js deleted file mode 100644 index 992c000b7c..0000000000 --- a/packages/web-rax-framework/src/index.js +++ /dev/null @@ -1,78 +0,0 @@ -const global = window; - -const shared = require('runtime-shared'); - -// ES -require('./number'); -require('./object'); -require('./array'); - -if (!global.Promise) { - global.Promise = shared.Promise; -} - -if (!global.Symbol) { - global.Symbol = shared.Symbol; -} - -if (!global.Map) { - global.Map = shared.Map; -} - -if (!global.Set) { - global.Set = shared.Set; -} - -if (!global.WeakMap) { - global.WeakMap = shared.WeakMap; -} - -if (!global.WeakSet) { - global.WeakSet = shared.WeakSet; -} - -// W3C -require('whatwg-fetch'); -require('raf/polyfill'); - -if (!global.FontFace) { - global.FontFace = shared.FontFace; -} - -if (!global.matchMedia) { - global.matchMedia = shared.matchMedia; -} - -if (!global.URL) { - global.URL = shared.URL; -} - -if (!global.URLSearchParams) { - global.URLSearchParams = shared.URLSearchParams; -} - -if (!document.fonts) { - document.fonts = { - add: function(fontFace) { - let fontFaceRule = `@font-face { - font-family: ${fontFace.family}; - src: ${fontFace.source} - }`; - - let styleElement = document.createElement('style'); - styleElement.innerHTML = fontFaceRule; - document.head.appendChild(styleElement); - } - }; -} - -// ModuleJS -require('./require'); - -// Polyfills for weex -require('./appear'); - -// Default Builtin modules -global.define('rax', function(req, exports, module) { - module.exports = require('rax'); -}); diff --git a/packages/web-rax-framework/src/intersectionObserver.js b/packages/web-rax-framework/src/intersectionObserver.js deleted file mode 100644 index c808458eee..0000000000 --- a/packages/web-rax-framework/src/intersectionObserver.js +++ /dev/null @@ -1,43 +0,0 @@ -const options = { - root: null, - rootMargin: '0px', - threshold: 0.0 -}; -let appearEvt, disappearEvt; -let intersectionObserver; - -function initIntersection() { - appearEvt = document.createEvent('HTMLEvents'); - disappearEvt = document.createEvent('HTMLEvents'); - appearEvt.initEvent('appear', false, true); - disappearEvt.initEvent('disappear', false, true); - - intersectionObserver = new IntersectionObserver(handleIntersect, options); -} - -function handleIntersect(entries) { - entries.forEach((entry) => { - const { target, boundingClientRect, intersectionRatio } = entry; - - // is inview - if (intersectionRatio > 0) { - target.dataset.appeared = true; - target.dispatchEvent(appearEvt); - } else if (target.dataset.appeared) { - target.dataset.appeared = false; - target.dispatchEvent(disappearEvt); - } - }); -} - -export function observerElement(element) { - intersectionObserver.observe(element); -} - -export function isExistIntersection() { - return typeof IntersectionObserver === 'function'; -} - -export default function createIntersectionObserver() { - initIntersection(); -} diff --git a/packages/web-rax-framework/src/number.js b/packages/web-rax-framework/src/number.js deleted file mode 100644 index be8f7394ac..0000000000 --- a/packages/web-rax-framework/src/number.js +++ /dev/null @@ -1,6 +0,0 @@ -if (!Number.isNaN) { - // http://www.ecma-international.org/ecma-262/6.0/#sec-number.isnan - Number.isNaN = function isNaN(value) { - return value !== value; - }; -} diff --git a/packages/web-rax-framework/src/object.js b/packages/web-rax-framework/src/object.js deleted file mode 100644 index 1da2639102..0000000000 --- a/packages/web-rax-framework/src/object.js +++ /dev/null @@ -1,146 +0,0 @@ -// WARNING: This is an optimized version that fails on hasOwnProperty checks -// and non objects. It's not spec-compliant. It's a perf optimization. -/* eslint strict:0 */ -if (!Object.assign) { - Object.assign = function(target, sources) { - for (let nextIndex = 1; nextIndex < arguments.length; nextIndex++) { - let nextSource = arguments[nextIndex]; - if (nextSource == null) { - continue; - } - - // We don't currently support accessors nor proxies. Therefore this - // copy cannot throw. If we ever supported this then we must handle - // exceptions and side-effects. - for (let key in nextSource) { - target[key] = nextSource[key]; - } - } - - return target; - }; -} - -const hasOwnProperty = Object.prototype.hasOwnProperty; - -/** - * Returns an array of the given object's own enumerable entries. - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries - * - */ -if (!Object.entries) { - Object.entries = function(object) { - // `null` and `undefined` values are not allowed. - if (object == null) { - throw new TypeError('Object.entries called on non-object'); - } - - let entries = []; - for (let key in object) { - if (hasOwnProperty.call(object, key)) { - entries.push([key, object[key]]); - } - } - return entries; - }; -} - - -/** - * Returns an array of the given object's own enumerable entries. - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values - * - */ -if (!Object.values) { - Object.values = function(object) { - // `null` and `undefined` values are not allowed. - if (object == null) { - throw new TypeError('Object.values called on non-object'); - } - - let values = []; - for (let key in object) { - if (hasOwnProperty.call(object, key)) { - values.push(object[key]); - } - } - return values; - }; -} - -if (!Object.defineProperties) { - Object.defineProperties = function(object, descriptors) { - for (var property in descriptors) { - Object.defineProperty(object, property, descriptors[property]); - } - return object; - }; -} - -// https://gist.github.com/WebReflection/5593554 -if (!Object.setPrototypeOf) { - Object.setPrototypeOf = (function(Object, magic) { - var set; - function setPrototypeOf(O, proto) { - set.call(O, proto); - return O; - } - try { - // this works already in Firefox and Safari - set = Object.getOwnPropertyDescriptor(Object.prototype, magic).set; - set.call({}, null); - } catch (e) { - if ( - // IE < 11 cannot be shimmed - Object.prototype !== {}[magic] || - // neither can any browser that actually - // implemented __proto__ correctly - // (all but old V8 will return here) - {__proto__: null}.__proto__ === void 0 - // this case means null objects cannot be passed - // through setPrototypeOf in a reliable way - // which means here a **Sham** is needed instead - ) { - return; - } - // nodejs 0.8 and 0.10 are (buggy and..) fine here - // probably Chrome or some old Mobile stock browser - set = function(proto) { - this[magic] = proto; - }; - // please note that this will **not** work - // in those browsers that do not inherit - // __proto__ by mistake from Object.prototype - // in these cases we should probably throw an error - // or at least be informed about the issue - setPrototypeOf.polyfill = setPrototypeOf( - setPrototypeOf({}, null), - Object.prototype - ) instanceof Object; - // setPrototypeOf.polyfill === true means it works as meant - // setPrototypeOf.polyfill === false means it's not 100% reliable - // setPrototypeOf.polyfill === undefined - // or - // setPrototypeOf.polyfill == null means it's not a polyfill - // which means it works as expected - // we can even delete Object.prototype.__proto__; - } - return setPrototypeOf; - }(Object, '__proto__')); -} - -if (!Object.is) { - Object.is = function(x, y) { - if (x === y) { - // 0 === -0, but they are not identical - return x !== 0 || 1 / x === 1 / y; - } - - // NaN !== NaN, but they are identical. - // NaNs are the only non-reflexive value, i.e., if x !== x, - // then x is a NaN. - // isNaN is broken: it converts its argument to number, so - // isNaN("foo") => true - return x !== x && y !== y; - }; -} diff --git a/packages/web-rax-framework/src/require.js b/packages/web-rax-framework/src/require.js deleted file mode 100644 index b31ff17fce..0000000000 --- a/packages/web-rax-framework/src/require.js +++ /dev/null @@ -1,91 +0,0 @@ -(function(global) { - if (global.define) { - return; - } - - /* eslint strict:0 */ - var modules = {}; - var inGuard = false; - - function def(id, deps, factory) { - if (deps instanceof Function) { - factory = deps; - deps = []; - } - - modules[id] = { - factory: factory, - deps: deps, - module: {exports: {}}, - isInitialized: false, - hasError: false, - }; - } - - function req(id) { - // Weex built-in modules - if (id.indexOf('@weex-module') === 0) { - return {}; - } - - var originId = id; - var mod = modules[id]; - // Node like require - if (!mod) { - id = id + '/index'; - mod = modules[id]; - } - - if (mod && mod.isInitialized) { - return mod.module.exports; - } - - return requireImpl(id, originId); - } - - function requireImpl(id, originId) { - if (global.ErrorUtils && !inGuard) { - inGuard = true; - var returnValue; - try { - returnValue = requireImpl.apply(this, arguments); - } catch (e) { - global.ErrorUtils.reportFatalError(e); - } - inGuard = false; - return returnValue; - } - - var mod = modules[id]; - if (!mod) { - throw new Error( - 'Requiring unknown module "' + originId + '"' - ); - } - - if (mod.hasError) { - throw new Error( - 'Requiring module "' + originId + '" which threw an exception' - ); - } - - try { - // We must optimistically mark mod as initialized before running the factory to keep any - // require cycles inside the factory from causing an infinite require loop. - mod.isInitialized = true; - - // keep args in sync with with defineModuleCode in - // rax/bundler/src/resolver.js - mod.factory(req, mod.module.exports, mod.module); - } catch (e) { - mod.hasError = true; - mod.isInitialized = false; - throw e; - } - - return mod.module.exports; - } - - global.define = def; - global.require = req; -})(this || typeof global === 'object' && global || typeof window === 'object' && window); diff --git a/packages/weex-rax-framework-api/README.md b/packages/weex-rax-framework-api/README.md deleted file mode 100644 index 4c528e5696..0000000000 --- a/packages/weex-rax-framework-api/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# weex-rax-framework-api - -## Global API Rax Framework provide - -* `window` - * devicePixelRatio - * open() - * postMessage() - * addEventListener() - * removeEventListener() -* `document` - * fonts - * add -* `navigator` - * platform - * product - * appName - * appVersion -* `screen` - * width - * height - * availWidth - * availHeight - * colorDepth - * pixelDepth -* `location` - * hash - * search - * pathname - * port - * hostname - * host - * protocol - * origin - * href -* [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) -* `FontFace` - ```js - var bitterFontFace = new FontFace('Bitter', 'url(https://fonts.gstatic.com/s/bitter/v7/HEpP8tJXlWaYHimsnXgfCOvvDin1pK8aKteLpeZ5c0A.woff2)'); - document.fonts.add(bitterFontFace); - - var oxygenFontFace = new FontFace('Oxygen', 'url(https://fonts.gstatic.com/s/oxygen/v5/qBSyz106i5ud7wkBU-FrPevvDin1pK8aKteLpeZ5c0A.woff2)'); - document.fonts.add(oxygenFontFace); - ``` -* [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) - * href - * origin - * searchParams - * toString() -* [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) - * append() - * delete() - * entries() - * get() - * getAll() - * has() - * keys() - * set() - * values() - * toString() -* `alert` -* `define` -* `require` -* `__weex_downgrade__` -* `__weex_env__` -* `__weex_define__` -* `__weex_require__` diff --git a/packages/weex-rax-framework-api/package.json b/packages/weex-rax-framework-api/package.json deleted file mode 100644 index a12967f497..0000000000 --- a/packages/weex-rax-framework-api/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "weex-rax-framework-api", - "version": "0.6.5", - "description": "Rax framework api for weex.", - "license": "BSD-3-Clause", - "main": "dist/framework.weex.js", - "repository": { - "type": "git", - "url": "git+https://github.com/alibaba/rax.git" - }, - "scripts": { - "build:jsfm": "./build" - }, - "bugs": { - "url": "https://github.com/alibaba/rax/issues" - }, - "homepage": "https://github.com/alibaba/rax#readme", - "dependencies": { - "event-target-shim": "^2.0.0", - "rax": "^0.6.5", - "runtime-shared": "^0.6.5" - }, - "devDependencies": { - "weex-runtime-js": "^0.19.8", - "weex-vdom-tester": "^0.2.0" - } -} diff --git a/packages/weex-rax-framework-api/src/__tests__/index.js b/packages/weex-rax-framework-api/src/__tests__/index.js deleted file mode 100644 index d933a59983..0000000000 --- a/packages/weex-rax-framework-api/src/__tests__/index.js +++ /dev/null @@ -1,379 +0,0 @@ -// 'use strict'; - -import * as framework from '../index'; - -let instanceContext = { - bundleUrl: 'http://example.com', - document: { - taskCenter: { - callbackManager: { - lastCallbackId: 0, - } - } - }, - __weex_options__: { - debug: true, - weex: { - config: {}, - requireModule: () => { - // mock - return { - error: () => {}, // nativeInstanceWrap - alert: () => {}, // modal - addEventListener: () => {}, // globalEvent - WebSocket: () => {}, // websocket - onmessage: () => {}, // websocket - onopen: () => {}, // websocket - onclose: () => {}, // websocket - onerror: () => {}, // websocket - setTimeout: (handler, time) => { - handler(); - }, // timer - clearTimeout: (n) => {}, // timer - setInterval: (handler, time) => { - handler(); - }, // timer - clearInterval: (n) => {}, // timer - push: () => {}, // weexNavigator - close: () => {}, // weexNavigator - }; - }, - isRegisteredModule: () => { - return true; - }, - isRegisteredComponent: () => { - return true; - }, - }, - } -}; -global.BroadcastChannel = { - onmessage: (listener) => { - listener(); - } -}; -global.callNative = () => {}; -global.WXEnvironment = { - 'scale': 2, - 'appVersion': '1.8.3', - 'deviceModel': 'iPhone7,2', - 'appName': 'WeexDemo', - 'platform': 'iOS', - 'osVersion': '9.3', - 'weexVersion': '0.7.0', - 'deviceHeight': 1334, - 'deviceWidth': 750, - 'logLevel': 'log', - ttid: '123456', - utdid: 'VXViP5AJ2Q0zCzWp0L', -}; - -let window = framework.resetInstanceContext(instanceContext); - -describe('frameworkapi', () => { - /* - api test - */ - - it('window.Promise', () => { - let myFirstPromise = new Promise(function(resolve, reject) { - setTimeout(function() { - resolve('hi'); - }, 250); - }); - myFirstPromise.then(function(successMessage) { - expect(successMessage).toEqual('hi'); - }); - }); - - it('window.Symbol', () => { - expect(typeof Symbol()).toEqual('symbol'); - }); - - it('window.Map', () => { - var myMap = new Map(); - myMap.set(NaN, 'not a number'); - expect(myMap.get(NaN)).toEqual('not a number'); - }); - - it('window.Set', () => { - let mySet = new Set(); - mySet.add(1); - expect(mySet.has(1)).toEqual(true); - }); - - it('window.WeakMap', () => { - var wm = new WeakMap(); - var o = {}; - wm.set(o, 37); - expect(wm.get(o)).toEqual(37); - }); - - it('window.WeakSet', () => { - var ws = new WeakSet(); - var obj = {}; - ws.add(obj); - expect(ws.has(obj)).toEqual(true); - }); - - it('window.name', () => { - expect(window.name).toEqual(''); - }); - - it('window.closed', () => { - expect(window.closed).toEqual(false); - }); - - it('window.atob', () => { - expect(window.atob('aGk=')).toEqual('hi'); - }); - - it('window.btoa', () => { - expect(window.btoa('hi')).toEqual('aGk='); - }); - - it('window.performance', () => { - expect(window.performance.timing.unloadEventStart).toEqual(0); - expect(window.performance.timing.loadEventStart).toEqual(0); - }); - - it('window.location', () => { - expect(window.location.href).toEqual('http://example.com/'); - }); - - it('window.navigator', () => { - expect(window.navigator.product).toEqual('Weex'); - expect(window.navigator.platform).toEqual('iOS'); - expect(window.navigator.appName).toEqual('WeexDemo'); - expect(window.navigator.appVersion).toEqual('1.8.3'); - expect(window.navigator.userAgent).toEqual('Weex/0.7.0 iOS/9.3 (iPhone7,2) WeexDemo/1.8.3'); - }); - - it('window.screen', () => { - expect(window.screen.width).toEqual(750); - expect(window.screen.height).toEqual(1334); - expect(window.screen.availWidth).toEqual(750); - expect(window.screen.availHeight).toEqual(1334); - expect(window.screen.colorDepth).toEqual(24); - expect(window.screen.pixelDepth).toEqual(24); - }); - - it('window.location', () => { - expect(window.devicePixelRatio).toEqual(2); - }); - - it('window.fetch', () => { - // TODO - window.fetch('http://example.com').then(function(response) { - if (response.status != -1 && response.ok) { - return response.json(); - } else { - return Promise.reject(response); - } - }).then(function(data) { - expect(data).toEqual(null); - console.log('fetch response data', data); - }); - }); - - it('window.Headers', () => { - var r = new window.Response('{"foo":"bar"}', {headers: {'content-type': 'application/json'}}); - expect(r.headers instanceof window.Headers).toEqual(true); - }); - - it('window.Response', () => { - var res = new window.Response(); - expect(res.status).toEqual(200); - }); - - it('window.Request request construct with url', () => { - var request = new window.Request('https://fetch.spec.whatwg.org/'); - expect(request.url).toEqual('https://fetch.spec.whatwg.org/'); - }); - - it('window.Request construct with Request and override headers', () => { - var request1 = new window.Request('https://fetch.spec.whatwg.org/', { - method: 'post', - body: 'I work out', - headers: { - accept: 'application/json', - 'X-Request-ID': '123' - } - }); - var request2 = new window.Request(request1, { - headers: { 'x-test': '42' } - }); - - var val1 = request2.headers.get('accept'); - var val2 = request2.headers.get('x-request-id'); - var val3 = request2.headers.get('x-test'); - - expect([val1, val2, val3]).toEqual([null, null, '42']); - }); - - it('window.URL', () => { - var a = new window.URL('/', 'https://developer.mozilla.org'); // Creates a URL pointing to 'https://developer.mozilla.org/' - var b = new window.URL('https://developer.mozilla.org'); // Creates a URL pointing to 'https://developer.mozilla.org/' - var c = new window.URL('en-US/docs', b); // Creates a URL pointing to 'https://developer.mozilla.org/en-US/docs' - var d = new window.URL('/en-US/docs', b); // Creates a URL pointing to 'https://developer.mozilla.org/en-US/docs' - var f = new window.URL('/en-US/docs', d); // Creates a URL pointing to 'https://developer.mozilla.org/en-US/docs' - var g = new window.URL('/en-US/docs', 'https://developer.mozilla.org/fr-FR/toto'); - // Creates a URL pointing to 'https://developer.mozilla.org/en-US/docs' - var h = new window.URL('/en-US/docs', a); // Creates a URL pointing to 'https://developer.mozilla.org/en-US/docs' - var i = new window.URL('/en-US/docs', ''); // Raises a SYNTAX ERROR exception as '/en-US/docs' is not valid - var j = new window.URL('/en-US/docs'); // Raises a SYNTAX ERROR exception as 'about:blank/en-US/docs' is not valid - var k = new window.URL('http://www.example.com', 'https://developers.mozilla.com'); - // Creates a URL pointing to 'http://www.example.com/' - var l = new window.URL('http://www.example.com', b); // Creates a URL pointing to 'http://www.example.com/' - - expect(l.toString()).toEqual('http://www.example.com/'); - }); - - it('window.URL.searchParams', () => { - var params = new window.URL('https://developer.mozilla.org?hello=world').searchParams; - expect(params.get('hello')).toEqual('world'); - }); - - it('window.URLSearchParams', () => { - var paramsString = 'q=URLUtils.searchParams&topic=api'; - var searchParams = new window.URLSearchParams(paramsString); - searchParams.has('topic') === true; // true - searchParams.get('topic') === 'api'; // true - searchParams.getAll('topic'); // ["api"] - searchParams.get('foo') === null; // true - searchParams.append('topic', 'webdev'); - searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev" - searchParams.set('topic', 'More webdev'); - searchParams.toString(); // "q=URLUtils.searchParams&topic=More+webdev" - searchParams.delete('topic'); - searchParams.toString(); // "q=URLUtils.searchParams" - - expect(searchParams.toString()).toEqual('q=URLUtils.searchParams'); - }); - - it('window.FontFace', () => { - var bitterFontFace = new window.FontFace('Bitter', 'url(https://fonts.gstatic.com/s/bitter/v7/HEpP8tJXlWaYHimsnXgfCOvvDin1pK8aKteLpeZ5c0A.woff2)'); - expect(bitterFontFace.family).toEqual('Bitter'); - }); - - it('window.WebSocket', () => { - const ws = new window.WebSocket('ws://echo.websocket.org'); - expect(ws.readyState).toEqual(0); - }); - - - it('window.CustomEvent', () => { - var ev = new window.CustomEvent('click', { - detail: 'custom' - }); - expect(ev.type).toEqual('click'); - }); - - - it('window.matchMedia', () => { - var mql = window.matchMedia('(min-width: 400px)').matches; - expect(mql).toEqual(false); - }); - - - it('window.setTimeout', () => { - const callback = jest.fn(); - var id = window.setTimeout(callback, 10); - window.clearTimeout(id); - expect(callback).toHaveBeenCalled(); - }); - - it('window.setInterval', () => { - const callback = jest.fn(); - var id = window.setInterval(callback, 10); - window.clearInterval(id); - expect(callback).toHaveBeenCalled(); - }); - - it('window.requestAnimationFrame', () => { - const callback = jest.fn(); - var id = window.requestAnimationFrame(callback); - window.cancelAnimationFrame(id); - expect(callback).toHaveBeenCalled(); - }); - - it('window.frameworkVersion', () => { - var frameworkVersion = window.frameworkVersion; - expect(frameworkVersion).toEqual('0.6.0'); - }); - - it('window.alert', () => { - expect(typeof window.alert).toEqual('function'); - }); - - it('window.open', () => { - expect(typeof window.open).toEqual('function'); - }); - - it('window.close', () => { - expect(typeof window.close).toEqual('function'); - }); - - it('window.onerror', () => { - const callback = jest.fn(); - window.onerror = callback; - window.onerror(); - expect(callback).toHaveBeenCalled(); - }); - - it('window.define', () => { - const callback = jest.fn(); - window.define('hello', callback, callback); - const hello = window.require('hello'); - expect(callback).toHaveBeenCalled(); - expect(hello).toEqual({}); - }); - - it('window.callNative', () => { - expect(typeof window.callNative).toEqual('function'); - }); - - it('window is window.window', () => { - expect(window.window).toEqual(window); - }); - - it('self is window', () => { - expect(window.self).toEqual(window); - }); - - it('deletes headers', () => { - var headers = new window.Headers(); - headers.set('Content-Type', 'application/json'); - var trueValue = headers.has('Content-Type'); - headers.delete('Content-Type'); - var falseValue = headers.has('Content-Type'); - var nullValue = headers.get('Content-Type'); - - expect([trueValue, falseValue, nullValue]).toEqual([true, false, null]); - }); - - it('downgrade', () => { - let a = window.__weex_downgrade__({ - ios: { - osVersion: '>1.0.0', - appVersion: '>1.0.0', - weexVersion: '>1.0.0', - deviceModel: ['modelA', 'modelB'] - }, - android: { - osVersion: '>1.0.0', - appVersion: '>1.0.0', - weexVersion: '>1.0.0', - deviceModel: ['modelA', 'modelB'] - } - }); - - expect(a).toEqual(true); - }); - - it('weex supports', () => { - var moduleExisted = window.__weex_module_supports__('webSocket.send'); - var tagExisted = window.__weex_tag_supports__('div'); - expect([moduleExisted, tagExisted]).toEqual([true, true]); - }); -}); diff --git a/packages/weex-rax-framework-api/src/base64.weex.js b/packages/weex-rax-framework-api/src/base64.weex.js deleted file mode 100644 index eda0ac2b11..0000000000 --- a/packages/weex-rax-framework-api/src/base64.weex.js +++ /dev/null @@ -1,55 +0,0 @@ -/* eslint indent: "off" */ - -module.exports = function() { - var base64 = {}; - var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - - // encoder - // [https://gist.github.com/999166] by [https://github.com/nignag] - base64.btoa = function(input) { - var str = String(input); - for ( - // initialize result and counter - var block, charCode, idx = 0, map = chars, output = ''; - // if the next str index does not exist: - // change the mapping table to "=" - // check if d has no fractional digits - str.charAt(idx | 0) || (map = '=', idx % 1); - // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8 - output += map.charAt(63 & block >> 8 - idx % 1 * 8) - ) { - charCode = str.charCodeAt(idx += 3 / 4); - if (charCode > 0xFF) { - throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range."); - } - block = block << 8 | charCode; - } - return output; - }; - - // decoder - // [https://gist.github.com/1020396] by [https://github.com/atk] - base64.atob = function(input) { - var str = String(input).replace(/=+$/, ''); - if (str.length % 4 == 1) { - throw new Error("'atob' failed: The string to be decoded is not correctly encoded."); - } - for ( - // initialize result and counters - var bc = 0, bs, buffer, idx = 0, output = ''; - // get next character - buffer = str.charAt(idx++); - // character found in table? initialize bit storage and add its ascii value; - ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, - // and if not first of each 4 characters, - // convert the first 8 bits to one ascii character - bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0 - ) { - // try to find character in table (0-63, not found => -1) - buffer = chars.indexOf(buffer); - } - return output; - }; - - return base64; -}; diff --git a/packages/weex-rax-framework-api/src/builtin.js b/packages/weex-rax-framework-api/src/builtin.js deleted file mode 100644 index c0986f7549..0000000000 --- a/packages/weex-rax-framework-api/src/builtin.js +++ /dev/null @@ -1,3 +0,0 @@ -export let ModuleFactories = { - 'rax': require('rax/dist/rax.factory') -}; diff --git a/packages/weex-rax-framework-api/src/define.weex.js b/packages/weex-rax-framework-api/src/define.weex.js deleted file mode 100644 index b25d7a5f95..0000000000 --- a/packages/weex-rax-framework-api/src/define.weex.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = function(modules) { - function define(name, deps, factory) { - if (deps instanceof Function) { - factory = deps; - deps = []; - } - - modules[name] = { - factory: factory, - deps: deps, - module: {exports: {}}, - isInitialized: false, - hasError: false, - }; - } - - return define; -}; diff --git a/packages/weex-rax-framework-api/src/document.weex.js b/packages/weex-rax-framework-api/src/document.weex.js deleted file mode 100644 index 0884be689f..0000000000 --- a/packages/weex-rax-framework-api/src/document.weex.js +++ /dev/null @@ -1,90 +0,0 @@ -import EventEmitter from './emitter'; - -const DOM_MODULE = '@weex-module/dom'; -const VISIBLE = 'visible'; -const HIDDEN = 'hidden'; -const VISIBILITY_CHANGE_EVENT = 'visibilitychange'; - -function addBodyAppearListener(document) { - document.body.addEvent('viewappear', function(e) { - document.visibilityState = VISIBLE; - e.type = VISIBILITY_CHANGE_EVENT; - document.dispatchEvent(e); - }); - - document.body.addEvent('viewdisappear', function(e) { - document.visibilityState = HIDDEN; - e.type = VISIBILITY_CHANGE_EVENT; - document.dispatchEvent(e); - }); -} - -function removeBodyAppearListener(document) { - if (document.body) { - document.body.removeEvent('viewappear'); - document.body.removeEvent('viewdisappear'); - } -} - -module.exports = function(__weex_require__, document) { - // Add w3c events - const documentEmitter = new EventEmitter(); - let hasVisibilityEventPending = false; - - // Weex freezed the document maybe throw error - try { - document.addEventListener = (type, listener) => { - if (type === VISIBILITY_CHANGE_EVENT) { - if (document.body) { - addBodyAppearListener(document); - } else { - hasVisibilityEventPending = true; - } - } - documentEmitter.on(type, listener); - }; - - document.removeEventListener = (type, listener) => { - if (type === VISIBILITY_CHANGE_EVENT) { - removeBodyAppearListener(document); - } - documentEmitter.off(type, listener); - }; - - document.dispatchEvent = (e) => { - documentEmitter.emit(e.type, e); - }; - - // FontFace - document.fonts = { - add: function(fontFace) { - var domModule = __weex_require__(DOM_MODULE); - domModule.addRule('fontFace', { - fontFamily: fontFace.family, - src: fontFace.source // url('uri') : single quotes are required around uri, and double quotes can not work in weex - }); - } - }; - - // Init visibility state - document.visibilityState = VISIBLE; - - // Hijack the origin createBody - const originCreateBody = document.createBody; - - Object.defineProperty(document, 'createBody', { - value: function() { - var body = originCreateBody.apply(document, arguments); - - if (hasVisibilityEventPending) { - addBodyAppearListener(document); - } - return body; - } - }); - } catch (e) { - console.log(e); - } - - return document; -}; diff --git a/packages/weex-rax-framework-api/src/downgrade.weex.js b/packages/weex-rax-framework-api/src/downgrade.weex.js deleted file mode 100644 index b6c4448685..0000000000 --- a/packages/weex-rax-framework-api/src/downgrade.weex.js +++ /dev/null @@ -1,122 +0,0 @@ -/* global WXEnvironment */ - -import semver from './semver'; - -function normalizeVersion(v) { - if (v == '*') { - return v; - } - v = typeof v === 'string' ? v : ''; - let split = v.split('.'); - let i = 0; - let result = []; - - while (i < 3) { - let s = typeof split[i] === 'string' && split[i] ? split[i] : '0'; - result.push(s); - i++; - } - - return result.join('.'); -} - -function getError(key, val, criteria) { - let result = { - isDowngrade: true, - errorType: 1, - code: 1000 - }; - let getMsg = function(key, val, criteria) { - return 'Downgrade[' + key + '] :: deviceInfo ' - + val + ' matched criteria ' + criteria; - }; - let _key = key.toLowerCase(); - - if (_key.indexOf('osversion') >= 0) { - result.code = 1001; - } else if (_key.indexOf('appversion') >= 0) { - result.code = 1002; - } else if (_key.indexOf('weexversion') >= 0) { - result.code = 1003; - } else if (_key.indexOf('devicemodel') >= 0) { - result.code = 1004; - } - - result.errorMessage = getMsg(key, val, criteria); - return result; -} - -/** - * config - * - * { - * ios: { - * osVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0' - * appVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0' - * weexVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0' - * deviceModel: ['modelA', 'modelB', ...] - * }, - * android: { - * osVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0' - * appVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0' - * weexVersion: '>1.0.0' or '>=1.0.0' or '<1.0.0' or '<=1.0.0' or '1.0.0' - * deviceModel: ['modelA', 'modelB', ...] - * } - * } - * - */ -function check(config) { - let result = { - isDowngrade: false - }; - - let deviceInfo = WXEnvironment; - - let platform = deviceInfo.platform || 'unknow'; - let dPlatform = platform.toLowerCase(); - let cObj = config[dPlatform] || {}; - - for (let i in deviceInfo) { - let key = i; - let keyLower = key.toLowerCase(); - let val = deviceInfo[i]; - let isVersion = keyLower.indexOf('version') >= 0; - let isDeviceModel = keyLower.indexOf('devicemodel') >= 0; - let criteria = cObj[i]; - - if (criteria && isVersion) { - let c = normalizeVersion(criteria); - let d = normalizeVersion(deviceInfo[i]); - - if (semver.satisfies(d, c)) { - result = getError(key, val, criteria); - break; - } - } else if (isDeviceModel) { - let _criteria = Array.isArray(criteria) ? criteria : [criteria]; - - if (_criteria.indexOf(val) >= 0) { - result = getError(key, val, criteria); - break; - } - } - } - - return result; -} - -module.exports = function(__weex_require__) { - return (config) => { - let nativeInstanceWrap = __weex_require__('@weex-module/instanceWrap'); - let result = check(config); - if (result.isDowngrade) { - nativeInstanceWrap.error( - result.errorType, - result.code, - result.errorMessage - ); - return true; - } - return false; - }; -}; diff --git a/packages/weex-rax-framework-api/src/emitter.js b/packages/weex-rax-framework-api/src/emitter.js deleted file mode 100644 index e44c09a65c..0000000000 --- a/packages/weex-rax-framework-api/src/emitter.js +++ /dev/null @@ -1,73 +0,0 @@ -export default class EventEmitter { - constructor() { - this._listeners = {}; - } - - /** - * Adds a listener function to the specified event. - * @param {String} type - * @param {Function} listener - * @param {Boolean} once - */ - _addListener(type, listener, once) { - this._listeners[type] = this._listeners[type] || []; - this._listeners[type].push({listener, once}); - return this; - } - - /** - * Adds a listener function to the specified event. - * @param {String} type - * @param {Function} listener - * @return {Object} Current instance of EventEmitter for chaining. - */ - on(type, listener) { - return this._addListener(type, listener, false); - } - - once(type, listener) { - return this._addListener(type, listener, true); - } - - /** - * Removes a listener function to the specified event. - * @param {String} type - * @param {Function} listener - * @return {Object} Current instance of EventEmitter for chaining. - */ - off(type, listener) { // alias - if (!this._listeners[type]) { - return this; - } - if (!this._listeners[type].length) { - return this; - } - if (!listener) { - delete this._listeners[type]; - return this; - } - this._listeners[type] = this._listeners[type].filter( - _listener => !(_listener.listener === listener) - ); - return this; - } - - /** - * Emits an specified event. - * @param {String} type - * @param {Object} payload - * @return {Object} Current instance of EventEmitter for chaining. - */ - emit(type, payload) { - if (!this._listeners[type]) { - return this; - } - this._listeners[type].forEach(_listener => { - _listener.listener.apply(this, [payload]); - if (_listener.once) { - this.removeListener(type, _listener.listener); - } - }); - return this; - } -} diff --git a/packages/weex-rax-framework-api/src/event.weex.js b/packages/weex-rax-framework-api/src/event.weex.js deleted file mode 100644 index 3518a123cf..0000000000 --- a/packages/weex-rax-framework-api/src/event.weex.js +++ /dev/null @@ -1,22 +0,0 @@ - -module.exports = function() { - class Event { - constructor(type, params = {}) { - this.type = type; - this.bubbles = Boolean(params.bubbles); - this.cancelable = Boolean(params.cancelable); - } - } - - class CustomEvent extends Event { - constructor(type, params = {}) { - super(type, params); - this.detail = params.detail; - } - } - - return { - Event, - CustomEvent - }; -}; diff --git a/packages/weex-rax-framework-api/src/fetch.weex.js b/packages/weex-rax-framework-api/src/fetch.weex.js deleted file mode 100644 index c65140821a..0000000000 --- a/packages/weex-rax-framework-api/src/fetch.weex.js +++ /dev/null @@ -1,254 +0,0 @@ -const STREAM_MODULE = '@weex-module/stream'; - -module.exports = function(__weex_require__, Promise) { - function normalizeName(name) { - if (typeof name !== 'string') { - name = String(name); - } - // FIXME: In spdy the response header has name like ":version" that is invalid - // if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { - // throw new TypeError('Invalid character in header field name'); - // } - return name.toLowerCase(); - } - - function normalizeValue(value) { - if (typeof value !== 'string') { - value = String(value); - } - return value; - } - - function Headers(headers) { - this.originHeaders = headers; - this.map = {}; - - if (headers instanceof Headers) { - headers.forEach(function(value, name) { - this.append(name, value); - }, this); - } else if (headers) { - Object.getOwnPropertyNames(headers).forEach(function(name) { - this.append(name, headers[name]); - }, this); - } - } - - Headers.prototype.append = function(name, value) { - name = normalizeName(name); - value = normalizeValue(value); - var oldValue = this.map[name]; - this.map[name] = oldValue ? oldValue + ',' + value : value; - }; - - Headers.prototype.delete = function(name) { - delete this.map[normalizeName(name)]; - }; - - Headers.prototype.get = function(name) { - name = normalizeName(name); - return this.has(name) ? this.map[name] : null; - }; - - Headers.prototype.has = function(name) { - return this.map.hasOwnProperty(normalizeName(name)); - }; - - Headers.prototype.set = function(name, value) { - this.map[normalizeName(name)] = [normalizeValue(value)]; - }; - - Headers.prototype.forEach = function(callback, thisArg) { - for (var name in this.map) { - if (this.map.hasOwnProperty(name)) { - callback.call(thisArg, this.map[name], name, this); - } - } - }; - - function consumed(body) { - if (body.bodyUsed) { - return Promise.reject(new TypeError('Already read')); - } - body.bodyUsed = true; - } - - function Body() { - this.bodyUsed = false; - - this._initBody = function(body, options) { - this._bodyInit = body; - if (typeof body === 'string') { - this._bodyText = body; - } else if (!body) { - this._bodyText = ''; - } else { - throw new Error('unsupported BodyInit type'); - } - }; - - this.text = function() { - var rejected = consumed(this); - return rejected ? rejected : Promise.resolve(this._bodyText); - }; - - this.json = function() { - return this.text().then(JSON.parse); - }; - - return this; - } - - // HTTP methods whose capitalization should be normalized - var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']; - - function normalizeMethod(method) { - var upcased = method.toUpperCase(); - return methods.indexOf(upcased) > -1 ? upcased : method; - } - - function Request(input, options) { - options = options || {}; - var body = options.body; - if (Request.prototype.isPrototypeOf(input)) { - if (input.bodyUsed) { - throw new TypeError('Already read'); - } - this.url = input.url; - this.credentials = input.credentials; - if (!options.headers) { - this.headers = new Headers(input.headers); - } - this.method = input.method; - this.mode = input.mode; - if (!body) { - body = input._bodyInit; - input.bodyUsed = true; - } - } else { - this.url = input; - } - - this.credentials = options.credentials || this.credentials || 'omit'; - if (options.headers || !this.headers) { - this.headers = new Headers(options.headers); - } - this.method = normalizeMethod(options.method || this.method || 'GET'); - this.mode = options.mode || this.mode || null; - this.referrer = null; - - if ((this.method === 'GET' || this.method === 'HEAD') && body) { - throw new TypeError('Body not allowed for GET or HEAD requests'); - } - this._initBody(body, options); - } - - Request.prototype.clone = function() { - return new Request(this); - }; - - function headers(xhr) { - var head = new Headers(); - var pairs = xhr.getAllResponseHeaders().trim().split('\n'); - pairs.forEach(function(header) { - var split = header.trim().split(':'); - var key = split.shift().trim(); - var value = split.join(':').trim(); - head.append(key, value); - }); - return head; - } - - Body.call(Request.prototype); - - function Response(bodyInit, options) { - if (!options) { - options = {}; - } - - this.type = 'default'; - this.status = 'status' in options ? options.status : 200; - this.ok = this.status >= 200 && this.status < 300; - this.statusText = 'statusText' in options ? options.statusText : 'OK'; - this.headers = new Headers(options.headers); - this.url = options.url || ''; - this._initBody(bodyInit, options); - } - - Body.call(Response.prototype); - - Response.prototype.clone = function() { - return new Response(this._bodyInit, { - status: this.status, - statusText: this.statusText, - headers: new Headers(this.headers), - url: this.url - }); - }; - - Response.error = function() { - var response = new Response(null, {status: 0, statusText: ''}); - response.type = 'error'; - return response; - }; - - var redirectStatuses = [301, 302, 303, 307, 308]; - - Response.redirect = function(url, status) { - if (redirectStatuses.indexOf(status) === -1) { - throw new RangeError('Invalid status code'); - } - - return new Response(null, {status: status, headers: {location: url}}); - }; - - let fetch = function(input, init) { - return new Promise(function(resolve, reject) { - var request; - if (Request.prototype.isPrototypeOf(input) && !init) { - request = input; - } else { - request = new Request(input, init); - } - - let params = { - url: request.url, - method: request.method, - headers: request.headers && request.headers.originHeaders - }; - - if (typeof request._bodyInit !== 'undefined') { - params.body = request._bodyInit; - } - - params.type = init && init.dataType ? init.dataType : 'text'; - - var nativeFetch = __weex_require__(STREAM_MODULE).fetch; - nativeFetch(params, (response) => { - try { - typeof response === 'string' && (response = JSON.parse(response)); - let data = typeof response.data === 'string' ? response.data : JSON.stringify(response.data); - - let res = new Response(data, { - status: response.status, - statusText: response.statusText, - headers: response.headers, - url: request.url - }); - resolve(res); - } catch (err) { - reject(err); - } - }, (progress) => { - - }); - }); - }; - - return { - fetch, - Headers, - Request, - Response - }; -}; diff --git a/packages/weex-rax-framework-api/src/index.js b/packages/weex-rax-framework-api/src/index.js deleted file mode 100644 index 4708a9e009..0000000000 --- a/packages/weex-rax-framework-api/src/index.js +++ /dev/null @@ -1,291 +0,0 @@ -/* global BroadcastChannel */ -'use strict'; - -import {ModuleFactories} from './builtin'; -import EventEmitter from './emitter'; - -let NativeComponents = {}; -let NativeModules = {}; - -let Document; -let Element; -let Comment; - -const MODULE_NAME_PREFIX = '@weex-module/'; -const MODAL_MODULE = MODULE_NAME_PREFIX + 'modal'; -const NAVIGATOR_MODULE = MODULE_NAME_PREFIX + 'navigator'; -const GLOBAL_EVENT_MODULE = MODULE_NAME_PREFIX + 'globalEvent'; -const noop = function() {}; -let weex = {}; - -function genBuiltinModules(modules, moduleFactories, context) { - for (let moduleName in moduleFactories) { - modules[moduleName] = { - factory: moduleFactories[moduleName].bind(context), - module: {exports: {}}, - isInitialized: false, - }; - } - return modules; -} - -export function injectContext() { - let instanceContext = new Function('return this')(); - var window = resetInstanceContext(instanceContext); - for (var key in window) { - if (typeof instanceContext[key] === 'undefined' && key != '__weex_data__') { - instanceContext[key] = window[key]; - } - } -} - -/** - * create a Weex instance - * - * @param {string} instanceId - * @param {string} __weex_code__ - * @param {object} [__weex_options__] {bundleUrl, debug} - */ -export function resetInstanceContext(instanceContext) { - let { - instanceId, - document, - bundleUrl, - __weex_document__, - __weex_options__, - __weex_data__, - __weex_config__ - } = instanceContext; - - weex = __weex_options__.weex; - - // Mark start time - const responseEnd = Date.now(); - const __weex_env__ = typeof WXEnvironment === 'object' && WXEnvironment || {}; - // For better performance use built-in promise first - const shared = require('runtime-shared/dist/shared.function')(); - - const Promise = typeof Promise === 'function' ? Promise : shared.Promise; - const Symbol = typeof Symbol === 'function' ? Symbol : shared.Symbol; - const Set = typeof Set === 'function' ? Set : shared.Set; - const Map = typeof Map === 'function' ? Map : shared.Map; - const WeakMap = typeof WeakMap === 'function' ? WeakMap : shared.WeakMap; - const WeakSet = typeof WeakSet === 'function' ? WeakSet : shared.WeakSet; - const {URL, URLSearchParams, FontFace, matchMedia} = shared; - - const documentURL = new URL(bundleUrl); - const modules = {}; - - // Generate native modules map at instance init - const __weex_define__ = require('./define.weex')(modules); - const __weex_require__ = require('./require.weex')(modules, weex); - const __weex_downgrade__ = require('./downgrade.weex')(__weex_require__); - // Extend document - require('./document.weex')(__weex_require__, document); - - const location = require('./location.weex')(__weex_require__, documentURL); - const { - fetch, - Headers, - Request, - Response - } = require('./fetch.weex')(__weex_require__, Promise); - - const XMLHttpRequest = require('./xmlhttprequest.weex')(__weex_require__); - const WebSocket = require('./websocket.weex')(__weex_require__); - - const { - setTimeout, - clearTimeout, - setInterval, - clearInterval, - requestAnimationFrame, - cancelAnimationFrame - } = require('./timer.weex')(__weex_require__, document); - - const { - atob, - btoa - } = require('./base64.weex')(); - - const performance = require('./performance.weex')(responseEnd); - const {Event, CustomEvent} = require('./event.weex')(); - - const windowEmitter = new EventEmitter(); - - let errorHandler = null; - function registerErrorHandler() { - if (registerErrorHandler.once) return; - - const globalEvent = __weex_require__(GLOBAL_EVENT_MODULE); - globalEvent.addEventListener('exception', (e) => { - // TODO: miss lineno and colno - // window.onerror = function(messageOrEvent, source, lineno, colno, error) { ... } - errorHandler(e.exception, e.bundleUrl, 0, 0, new Error(e.exception, e.bundleUrl, 0)); - }); - - registerErrorHandler.once = true; - } - - const window = { - // ES - Promise, - Symbol, - Map, - Set, - WeakMap, - WeakSet, - // W3C: https://www.w3.org/TR/html5/browsers.html#browsing-context-name - name: '', - // This read-only property indicates whether the referenced window is closed or not. - closed: false, - atob, - btoa, - performance, - // W3C - document, - location, - // https://www.w3.org/TR/2009/WD-html5-20090423/browsers.html#dom-navigator - navigator: { - product: 'Weex', - platform: __weex_env__.platform, - appName: __weex_env__.appName, - appVersion: __weex_env__.appVersion, - // Weex/0.12 iOS/9.3 (iPhone7,2) AppName/0.12 - userAgent: `Weex/${__weex_env__.weexVersion} ${__weex_env__.platform}/${__weex_env__.osVersion} (${__weex_env__.deviceModel}) ${__weex_env__.appName}/${__weex_env__.appVersion}` - }, - // https://drafts.csswg.org/cssom-view/#the-screen-interface - screen: { - width: __weex_env__.deviceWidth, - height: __weex_env__.deviceHeight, - availWidth: __weex_env__.deviceWidth, - availHeight: __weex_env__.deviceHeight, - colorDepth: 24, - pixelDepth: 24, - }, - devicePixelRatio: __weex_env__.scale, - fetch, - Headers, - Response, - Request, - XMLHttpRequest, - URL, - URLSearchParams, - FontFace, - WebSocket, - Event, - CustomEvent, - matchMedia, - setTimeout, - clearTimeout, - setInterval, - clearInterval, - requestAnimationFrame, - cancelAnimationFrame, - setImmediate: typeof setImmediate === 'function' && setImmediate || - function(fn) { - setTimeout(fn, 0); - }, - clearImmediate: typeof setImmediate === 'function' && setImmediate || - function(id) { - clearTimeout(id); - }, - frameworkVersion: '0.6.0', // for debug - alert: (message) => { - const modal = __weex_require__(MODAL_MODULE); - modal.alert({ - message - }, function() {}); - }, - open: (url) => { - const weexNavigator = __weex_require__(NAVIGATOR_MODULE); - weexNavigator.push({ - url, - animated: true, - }, noop); - }, - close: () => { - const weexNavigator = __weex_require__(NAVIGATOR_MODULE); - weexNavigator.close({ - animated: true - }, noop, noop); - }, - postMessage: (message, targetOrigin) => { - var event = { - origin: location.origin, - data: JSON.parse(JSON.stringify(message)), - type: 'message', - source: window, // FIXME: maybe not export window - }; - - if (typeof BroadcastChannel === 'function') { - if (targetOrigin == '*') { - var stack = new BroadcastChannel('message'); - stack.postMessage(event); - } else { - var stack = new BroadcastChannel('message' + targetOrigin); - stack.postMessage(event); - } - } - }, - addEventListener: (type, listener) => { - if (type === 'message') { - if (typeof BroadcastChannel === 'function') { - var stack = new BroadcastChannel('message'); - var thisStack = new BroadcastChannel('message' + bundleUrl); - stack.onmessage = (e) => { - listener(e.data); - }; - thisStack.onmessage = (e) => { - listener(e.data); - }; - } - } else { - windowEmitter.on(type, listener); - } - }, - removeEventListener: (type, listener) => { - windowEmitter.off(type, listener); - }, - dispatchEvent: (e) => { - windowEmitter.emit(e.type, e); - }, - set onerror(handler) { - if (typeof handler == 'function') { - errorHandler = handler; - registerErrorHandler(); - } else { - errorHandler = null; - } - }, - get onerror() { - return errorHandler; - }, - // ModuleJS - define: __weex_define__, - require: __weex_require__, - // Weex - callNative: () => {}, // compatible original API - __weex_document__, - __weex_module_supports__: weex.isRegisteredModule, - __weex_tag_supports__: weex.isRegisteredComponent, - __weex_define__, - __weex_require__, - __weex_downgrade__, - __weex_env__, - __weex_code__: '', - __weex_options__, - __weex_data__, - __weex_config__ - }; - - genBuiltinModules( - modules, - ModuleFactories, - window - ); - - window.self = window.window = window; - - return window; -} diff --git a/packages/weex-rax-framework-api/src/location.weex.js b/packages/weex-rax-framework-api/src/location.weex.js deleted file mode 100644 index a8cad0608e..0000000000 --- a/packages/weex-rax-framework-api/src/location.weex.js +++ /dev/null @@ -1,26 +0,0 @@ -const LOCATION_MODULE = '@weex-module/location'; -const NAVIGATOR_MODULE = '@weex-module/navigator'; - -module.exports = function(__weex_require__, location) { - location.assign = (url) => { - const weexNavigator = __weex_require__(NAVIGATOR_MODULE); - weexNavigator.push({ - url, - animated: 'true', - }, function(e) { - // noop - }); - }; - - location.replace = (url) => { - const weexLocation = __weex_require__(LOCATION_MODULE); - weexLocation.replace(url); - }; - - location.reload = (forceReload = false) => { - const weexLocation = __weex_require__(LOCATION_MODULE); - weexLocation.reload(forceReload); - }; - - return location; -}; diff --git a/packages/weex-rax-framework-api/src/performance.weex.js b/packages/weex-rax-framework-api/src/performance.weex.js deleted file mode 100644 index 4f0ec77f76..0000000000 --- a/packages/weex-rax-framework-api/src/performance.weex.js +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = function(responseEnd) { - let performance = {}; - // TODO: current can not get navigationStart time - performance.timing = { - unloadEventStart: 0, - unloadEventEnd: 0, - navigationStart: responseEnd, - redirectStart: 0, - redirectEnd: 0, - fetchStart: responseEnd, - domainLookupStart: responseEnd, - domainLookupEnd: responseEnd, - connectStart: responseEnd, - secureConnectionStart: responseEnd, - connectStart: responseEnd, - requestStart: responseEnd, - responseStart: responseEnd, - responseEnd, - domLoading: 0, - domInteractive: 0, - domComplete: 0, - domContentLoadedEventStart: 0, - domContentLoadedEventEnd: 0, - loadEventStart: 0, - loadEventEnd: 0 - }; - performance.now = function() { - return Date.now() - performance.timing.navigationStart; - }; - - return performance; -}; diff --git a/packages/weex-rax-framework-api/src/require.weex.js b/packages/weex-rax-framework-api/src/require.weex.js deleted file mode 100644 index 35862171aa..0000000000 --- a/packages/weex-rax-framework-api/src/require.weex.js +++ /dev/null @@ -1,48 +0,0 @@ -const MODULE_NAME_PREFIX = '@weex-module/'; - -module.exports = function(modules, weex) { - function require(name) { - var mod = modules[name]; - - // if retuire '@weex-module/' - if (name.split(MODULE_NAME_PREFIX).length > 1) { - const weexModuleName = name.split(MODULE_NAME_PREFIX)[1]; - if (weex.isRegisteredModule(weexModuleName)) { - return weex.requireModule(weexModuleName); - } else { - throw new Error( - 'Requiring unknown weex module "' + name + '"' - ); - } - } - - if (mod && mod.isInitialized) { - return mod.module.exports; - } - - if (!mod) { - throw new Error( - 'Requiring unknown module "' + name + '"' - ); - } - - if (mod.hasError) { - throw new Error( - 'Requiring module "' + name + '" which threw an exception' - ); - } - - try { - mod.isInitialized = true; - mod.factory(require, mod.module.exports, mod.module); - } catch (e) { - mod.hasError = true; - mod.isInitialized = false; - throw e; - } - - return mod.module.exports; - } - - return require; -}; diff --git a/packages/weex-rax-framework-api/src/semver.js b/packages/weex-rax-framework-api/src/semver.js deleted file mode 100644 index 88eb0a4020..0000000000 --- a/packages/weex-rax-framework-api/src/semver.js +++ /dev/null @@ -1,58 +0,0 @@ -export default { - satisfies(left, right) { - let regex = /(\W+)?([\d|.]+)/; - - if (typeof left + typeof right != 'stringstring') - return false; - - if (right == '*') { - return true; - } - - let arr = right.match(regex); - let a = left.split('.'), - i = 0, - b = arr[2].split('.'), - len = Math.max(a.length, b.length); - - let flag = 0; - for (let i = 0; i < len; i++) { - if (a[i] && !b[i] && parseInt(a[i]) > 0 || parseInt(a[i]) > parseInt(b[i])) { - flag = 1; - break; - } else if (b[i] && !a[i] && parseInt(b[i]) > 0 || parseInt(a[i]) < parseInt(b[i])) { - flag = -1; - break; - } - } - - switch (arr[1]) { - case '<': - if (flag === -1) { - return true; - } - break; - case '<=': - if (flag !== 1) { - return true; - } - break; - case '>': - if (flag === 1) { - return true; - } - break; - case '>=': - if (flag !== -1) { - return true; - } - break; - default: - if (flag === 0) { - return true; - } - break; - } - return false; - } -}; diff --git a/packages/weex-rax-framework-api/src/timer.weex.js b/packages/weex-rax-framework-api/src/timer.weex.js deleted file mode 100644 index b74e390e39..0000000000 --- a/packages/weex-rax-framework-api/src/timer.weex.js +++ /dev/null @@ -1,44 +0,0 @@ -const TIMER_MODULE = '@weex-module/timer'; - -module.exports = function(__weex_require__, document) { - const setTimeout = (handler, time) => { - const timer = __weex_require__(TIMER_MODULE); - timer.setTimeout(handler, time); - return document.taskCenter.callbackManager.lastCallbackId.toString(); - }; - - const setInterval = (handler, time) => { - const timer = __weex_require__(TIMER_MODULE); - timer.setInterval(handler, time); - return document.taskCenter.callbackManager.lastCallbackId.toString(); - }; - - const clearTimeout = (n) => { - const timer = __weex_require__(TIMER_MODULE); - timer.clearTimeout(n); - }; - - const clearInterval = (n) => { - const timer = __weex_require__(TIMER_MODULE); - timer.clearInterval(n); - }; - - const requestAnimationFrame = (callback) => { - const timer = __weex_require__(TIMER_MODULE); - return timer.setTimeout(callback, 16); - }; - - const cancelAnimationFrame = (n) => { - const timer = __weex_require__(TIMER_MODULE); - timer.clearTimeout(n); - }; - - return { - setTimeout, - clearTimeout, - setInterval, - clearInterval, - requestAnimationFrame, - cancelAnimationFrame - }; -}; diff --git a/packages/weex-rax-framework-api/src/websocket.weex.js b/packages/weex-rax-framework-api/src/websocket.weex.js deleted file mode 100644 index 950475587b..0000000000 --- a/packages/weex-rax-framework-api/src/websocket.weex.js +++ /dev/null @@ -1,99 +0,0 @@ -const eventTarget = require('event-target-shim'); - -const WEB_SOCKET_MODULE = '@weex-module/webSocket'; - -const CONNECTING = 0; -const OPEN = 1; -const CLOSING = 2; -const CLOSED = 3; - -const CLOSE_NORMAL = 1000; - -const WEBSOCKET_EVENTS = [ - 'close', - 'error', - 'message', - 'open', -]; - -/** - * Event object passed to the `onopen`, `onclose`, `onmessage`, `onerror` - * callbacks of `WebSocket`. - * - * The `type` property is "open", "close", "message", "error" respectively. - * - * In case of "message", the `data` property contains the incoming data. - */ -class WebSocketEvent { - constructor(type, eventInitDict) { - this.type = type.toString(); - Object.assign(this, eventInitDict); - } -} - -module.exports = function(__weex_require__) { - /** - * Browser-compatible WebSockets implementation. - * - * See https://developer.mozilla.org/en-US/docs/Web/API/WebSocket - * See https://github.com/websockets/ws - */ - class WebSocket extends eventTarget(WEBSOCKET_EVENTS) { - static CONNECTING = CONNECTING; - static OPEN = OPEN; - static CLOSING = CLOSING; - static CLOSED = CLOSED; - - constructor(url, protocols) { - super(); - - let websocket = __weex_require__(WEB_SOCKET_MODULE); - // eslint-disable-next-line new-cap - websocket.WebSocket(url, protocols); - this.readyState = CONNECTING; - this.websocket = websocket; - - websocket.onmessage(ev => { - this.dispatchEvent(new WebSocketEvent('message', ev)); - }); - - websocket.onopen(ev => { - this.readyState = OPEN; - this.dispatchEvent(new WebSocketEvent('open')); - }); - - websocket.onclose(ev => { - this.readyState = CLOSED; - this.dispatchEvent(new WebSocketEvent('close', { - code: ev.code, - reason: ev.reason, - })); - }); - - websocket.onerror(ev => { - this.dispatchEvent(new WebSocketEvent('error', ev)); - }); - } - - close(code, reason) { - if (this.readyState === CLOSING || - this.readyState === CLOSED) { - return; - } - - this.readyState = CLOSING; - this.websocket.close(code, reason); - } - - send(data) { - if (typeof data === 'string') { - this.websocket.send(data); - return; - } - - throw new Error('Unsupported data type'); - } - } - - return WebSocket; -}; diff --git a/packages/weex-rax-framework-api/src/xmlhttprequest.weex.js b/packages/weex-rax-framework-api/src/xmlhttprequest.weex.js deleted file mode 100644 index 5e3c211337..0000000000 --- a/packages/weex-rax-framework-api/src/xmlhttprequest.weex.js +++ /dev/null @@ -1,259 +0,0 @@ -const STREAM_MODULE = '@weex-module/stream'; -const eventTarget = require('event-target-shim'); - -const UNSENT = 0; -const OPENED = 1; -const HEADERS_RECEIVED = 2; -const LOADING = 3; -const DONE = 4; - -const XHR_EVENTS = [ - 'abort', - 'error', - 'load', - 'loadstart', - 'progress', - 'timeout', - 'loadend', - 'readystatechange' -]; - -module.exports = function(__weex_require__) { - class XMLHttpRequest extends eventTarget(...XHR_EVENTS) { - static UNSENT = UNSENT; - static OPENED = OPENED; - static HEADERS_RECEIVED = HEADERS_RECEIVED; - static LOADING = LOADING; - static DONE = DONE; - - UNSENT = UNSENT; - OPENED = OPENED; - HEADERS_RECEIVED = HEADERS_RECEIVED; - LOADING = LOADING; - DONE = DONE; - - // EventTarget automatically initializes these to `null`. - onload; - onloadstart; - onprogress; - ontimeout; - onerror; - onabort; - onloadend; - onreadystatechange; - - readyState = UNSENT; - responseHeaders; - status = 0; - statusText = ''; - timeout = 0; - - _aborted = false; - _hasError = false; - _headers; - _lowerCaseResponseHeaders; - _method = null; - _response; - _responseType; - _response = ''; - _sent; - _url = null; - _timedOut = false; - - constructor() { - super(); - this._reset(); - } - - _reset() { - this.readyState = this.UNSENT; - this.responseHeaders = undefined; - this.status = 0; - - this._hasError = false; - this._headers = {}; - this._response = ''; - this._responseType = ''; - this._sent = false; - this._lowerCaseResponseHeaders = {}; - - this._timedOut = false; - } - - get responseType() { - return this._responseType; - } - - set responseType(responseType) { - if (this._sent) { - throw new Error( - 'Failed to set the \'responseType\' property on \'XMLHttpRequest\': The ' + - 'response type cannot be set after the request has been sent.' - ); - } - - this._responseType = responseType; - } - - get responseText() { - if (this._responseType !== '' && this._responseType !== 'text') { - throw new Error( - "The 'responseText' property is only available if 'responseType' " + - `is set to '' or 'text', but it is '${this._responseType}'.` - ); - } - if (this.readyState < LOADING) { - return ''; - } - return this._response; - } - - get response() { - const {responseType} = this; - if (responseType === '' || responseType === 'text') { - return this.readyState < LOADING || this._hasError - ? '' - : this._response; - } - - if (this.readyState !== DONE) { - return null; - } - } - - getAllResponseHeaders() { - if (!this.responseHeaders) { - // according to the spec, return null if no response has been received - return null; - } - var headers = this.responseHeaders || {}; - return Object.keys(headers).map((headerName) => { - return headerName + ': ' + headers[headerName]; - }).join('\r\n'); - } - - getResponseHeader(header) { - var value = this._lowerCaseResponseHeaders[header.toLowerCase()]; - return value !== undefined ? value : null; - } - - setRequestHeader(header, value) { - if (this.readyState !== this.OPENED) { - throw new Error('Request has not been opened'); - } - this._headers[header.toLowerCase()] = String(value); - } - - open(method, url, async) { - /* Other optional arguments are not supported yet */ - if (this.readyState !== this.UNSENT) { - throw new Error('Cannot open, already sending'); - } - if (async !== undefined && !async) { - // async is default - throw new Error('Synchronous http requests are not supported'); - } - if (!url) { - throw new Error('Cannot load an empty url'); - } - this._method = method.toUpperCase(); - this._url = url; - this._aborted = false; - this.setReadyState(this.OPENED); - } - - send(data: any) { - if (this.readyState !== this.OPENED) { - throw new Error('Request has not been opened'); - } - if (this._sent) { - throw new Error('Request has already been sent'); - } - this._sent = true; - - var nativeFetch = __weex_require__(STREAM_MODULE).fetch; - - nativeFetch({ - method: this._method, - url: this._url, - headers: this._headers, - body: data, - type: 'text', - }, (response) => { - try { - typeof response === 'string' && (response = JSON.parse(response)); - - this.status = response.status; - this.statusText = response.statusText; - this.setResponseHeaders(response.headers); - - if (response.ok) { - this._response = response.data; - } else { - if (this._responseType === '' || this._responseType === 'text') { - this._response = response.data; - } - this._hasError = true; - } - } catch (err) { - - } - - this.setReadyState(this.DONE); - }, (progress) => { - this.status = progress.status; - this.statusText = progress.statusText; - this.setResponseHeaders(progress.headers); - this.setReadyState(progress.readyState); - }); - } - - abort() { - this._aborted = true; - - // TODO: Weex native not support abort now - - // only call onreadystatechange if there is something to abort, - // below logic is per spec - if (!(this.readyState === this.UNSENT || - this.readyState === this.OPENED && !this._sent || - this.readyState === this.DONE)) { - this._reset(); - this.setReadyState(this.DONE); - } - // Reset again after, in case modified in handler - this._reset(); - } - - setResponseHeaders(responseHeaders) { - this.responseHeaders = responseHeaders || null; - var headers = responseHeaders || {}; - this._lowerCaseResponseHeaders = - Object.keys(headers).reduce((lcaseHeaders, headerName) => { - lcaseHeaders[headerName.toLowerCase()] = headers[headerName]; - return lcaseHeaders; - }, {}); - } - - setReadyState(newState) { - this.readyState = newState; - this.dispatchEvent({type: 'readystatechange'}); - if (newState === this.DONE) { - if (this._aborted) { - this.dispatchEvent({type: 'abort'}); - } else if (this._hasError) { - if (this._timedOut) { - this.dispatchEvent({type: 'timeout'}); - } else { - this.dispatchEvent({type: 'error'}); - } - } else { - this.dispatchEvent({type: 'load'}); - } - this.dispatchEvent({type: 'loadend'}); - } - } - } - - return XMLHttpRequest; -}; diff --git a/packages/weex-rax-framework/.gitignore b/packages/weex-rax-framework/.gitignore deleted file mode 100644 index ed2c3abe0f..0000000000 --- a/packages/weex-rax-framework/.gitignore +++ /dev/null @@ -1 +0,0 @@ -weex diff --git a/packages/weex-rax-framework/README.md b/packages/weex-rax-framework/README.md deleted file mode 100644 index 52befc3c9b..0000000000 --- a/packages/weex-rax-framework/README.md +++ /dev/null @@ -1,150 +0,0 @@ -# weex-rax-framework - -## How to custom builtin modules? - -### 1. Build module use factory mode - -```js -const webpack = require('webpack'); -const RaxPlugin = require('rax-webpack-plugin'); - -module.exports = { - target: 'node', - entry: { - // Entry name should ends with `.factory` - 'your-module.factory' : './src/index.js', - }, - output: { - path: './dist/', - filename: '[name].js', - }, - plugins: [ - new RaxPlugin({ - // Your could config builtinModules here - externalBuiltinModules: false, - builtinModules: RaxPlugin.BuiltinModules, - }); - ], - module: { - loaders: [{ - test: /\.jsx?$/, - exclude: /(node_modules|bower_components)/, - loader: 'babel', // 'babel-loader' is also a legal name to reference - query: { - presets: ['es2015', 'rax'] - } - }] - } -} -``` - -Then publish module with factory build file to npm registry: -```sh -npm publish -``` - -Or [`link`](https://docs.npmjs.com/cli/link) module in local: -```sh -npm link -``` - -### 2. Config `builtin.js` in framework source - -Install builtin module from npm: -```sh -npm install your-module --save -``` - -Or link from local: -```sh -npm link your-module -``` - -Config `builtin.js` and add your custom builtin module: -```js -export let ModuleFactories = { - 'rax': require('rax/dist/rax.factory'), - // Add your builtin module - 'your-module': require('your-module/dist/your-module.factory'), -}; -``` - -### 3. Build framework use framework mode - -```js -const webpack = require('webpack'); -const RaxPlugin = require('rax-webpack-plugin'); - -module.exports = { - target: 'node', - entry: { - // Entry name should ends with `.framework` - 'rax.framework': './packages/weex-rax-framework/src/index.js', - }, - output: { - path: './packages/weex-rax-framework/dist/', - filename: '[name].js', - }, - plugins: [ - new RaxPlugin(); - ], - module: { - loaders: [{ - test: /\.jsx?$/, - exclude: /(node_modules|bower_components)/, - loader: 'babel', // 'babel-loader' is also a legal name to reference - query: { - presets: ['es2015'] - } - }] - } -} -``` - -## How to build weex `jsfm` including `weex-rax-framework`? - -### 1. Clone the weex repository and install prerequisites - -```sh -git clone git@github.com:alibaba/weex.git -cd weex -npm install -``` - -### 2. Install or link `weex-rax-framework` - -```sh -npm install weex-rax-framework -``` -Or - -```sh -npm link weex-rax-framework -``` - -### 3. Config `weex-rax-framework` - -Update `html5/frameworks/index.js` file with below content: - -```js -import * as Weex from './legacy/index' -import Rax from 'weex-rax-framework' - -export default { - Rax, - Weex -} -``` - -### 4. Build `jsfm` for native renderer to `dist/native.js` - -```sh -npm run build:native -``` - -### 5. Copy `dist/native.js` to `weex-sdk` - -```sh -cp -vf ./dist/native.js ./android/sdk/assets/main.js -cp -vf ./dist/native.js ./ios/sdk/WeexSDK/Resources/main.js -``` diff --git a/packages/weex-rax-framework/build b/packages/weex-rax-framework/build deleted file mode 100755 index f5683925bb..0000000000 --- a/packages/weex-rax-framework/build +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash - -# Example: ./build -n tnpm -b - -# Reset in case getopts has been used previously in the shell. -OPTIND=1 - -# Initialize our own variables: -npm="npm" -install="link" -onlyBuild=0 - -while getopts "bin:" opt; do - case "$opt" in - b) onlyBuild=1 - ;; - i) install="install" - ;; - n) npm=$OPTARG - ;; - esac -done - -shift $((OPTIND-1)) - -[ "$1" = "--" ] && shift - -echo "Make sure you has been build `weex-rax-framework` by `npm run dist` in `rax` project root" - -echo "Creates global weex-rax-framework link:" -$npm link - -if [[ $onlyBuild == 1 ]]; then - - echo "Build without prerequisites:" - cd weex - -else - - echo "Clone the weex repository and install prerequisites:" - git clone https://github.com/alibaba/weex.git --depth=1 - cd weex - $npm install - -fi - -echo "Install/Link the weex-rax-framework of your dependency:" -npm $install weex-rax-framework - -echo "Config weex/html5/frameworks/index.js" -echo -e "import * as Weex from './legacy/index'\nimport Rax from 'weex-rax-framework'\nexport default {\n Rax, Weex\n}" > html5/frameworks/index.js - -echo "Build jsfm for native renderer to weex/dist/native.js" -$npm run build:native - -echo "Done" diff --git a/packages/weex-rax-framework/package.json b/packages/weex-rax-framework/package.json deleted file mode 100644 index d434800f65..0000000000 --- a/packages/weex-rax-framework/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "weex-rax-framework", - "version": "0.6.5", - "description": "Rax framework for weex.", - "license": "BSD-3-Clause", - "main": "dist/framework.weex.js", - "repository": { - "type": "git", - "url": "git+https://github.com/alibaba/rax.git" - }, - "scripts": { - "build:jsfm": "./build" - }, - "bugs": { - "url": "https://github.com/alibaba/rax/issues" - }, - "homepage": "https://github.com/alibaba/rax#readme", - "dependencies": { - "event-target-shim": "^2.0.0", - "rax": "^0.6.5", - "runtime-shared": "^0.6.5" - }, - "devDependencies": { - "weex-runtime-js": "^0.19.8", - "weex-vdom-tester": "^0.2.0" - } -} diff --git a/packages/weex-rax-framework/src/__tests__/index.js b/packages/weex-rax-framework/src/__tests__/index.js deleted file mode 100644 index fbdd569083..0000000000 --- a/packages/weex-rax-framework/src/__tests__/index.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict'; - -// require('weex-runtime-js').freezePrototype(); - -import WeexRuntime from '../mock/weex-rax-js-runtime'; -import * as framework from '../index'; - -WeexRuntime.config.frameworks = { Rax: framework }; -const context = WeexRuntime.init(WeexRuntime.config); -const { Document, Element, Comment } = WeexRuntime.config; - -global.callNative = () => { }; -global.WXEnvironment = { - 'scale': 2, - 'appVersion': '1.8.3', - 'deviceModel': 'iPhone7,2', - 'appName': 'WeexDemo', - 'platform': 'iOS', - 'osVersion': '9.3', - 'weexVersion': '0.7.0', - 'deviceHeight': 1334, - 'deviceWidth': 750, - 'logLevel': 'log', - ttid: '123456', - utdid: 'VXViP5AJ2Q0zCzWp0L', -}; - -describe('framework', () => { - let instance; - let runtime; - let __weex_options__ = { - bundleUrl: 'http://example.com', - debug: true - }; - let __weex_callbacks__; - let __weex_data__; - let sendTasksHandler = () => { }; - let sendTasks = function() { - return sendTasksHandler.apply(null, arguments); - }; - - beforeEach(() => { - Document.handler = sendTasks; - framework.init({ Document, Element, Comment }); - }); - - afterEach(() => { - delete Document.handler; - instance = null; - }); - - it('render a text', () => { - const code = ` - define("rax-test", function(require) { - 'use strict'; - - var Rax = require('rax'); - function App() { - return Rax.createElement('text', null, 'Hello'); - } - Rax.render(Rax.createElement(App, null)); - }); - - require("rax-test"); - `; - - const instance = context.createInstance(1, `// { "framework": "Rax" }\n${code}`, __weex_options__) || {}; - expect(context.getRoot(1)).toEqual({ - type: 'div', - ref: '_root', - children: [{ type: 'text', ref: '8', attr: { value: 'Hello' } }] - }); - }); -}); diff --git a/packages/weex-rax-framework/src/document.weex.js b/packages/weex-rax-framework/src/document.weex.js deleted file mode 100644 index 0884be689f..0000000000 --- a/packages/weex-rax-framework/src/document.weex.js +++ /dev/null @@ -1,90 +0,0 @@ -import EventEmitter from './emitter'; - -const DOM_MODULE = '@weex-module/dom'; -const VISIBLE = 'visible'; -const HIDDEN = 'hidden'; -const VISIBILITY_CHANGE_EVENT = 'visibilitychange'; - -function addBodyAppearListener(document) { - document.body.addEvent('viewappear', function(e) { - document.visibilityState = VISIBLE; - e.type = VISIBILITY_CHANGE_EVENT; - document.dispatchEvent(e); - }); - - document.body.addEvent('viewdisappear', function(e) { - document.visibilityState = HIDDEN; - e.type = VISIBILITY_CHANGE_EVENT; - document.dispatchEvent(e); - }); -} - -function removeBodyAppearListener(document) { - if (document.body) { - document.body.removeEvent('viewappear'); - document.body.removeEvent('viewdisappear'); - } -} - -module.exports = function(__weex_require__, document) { - // Add w3c events - const documentEmitter = new EventEmitter(); - let hasVisibilityEventPending = false; - - // Weex freezed the document maybe throw error - try { - document.addEventListener = (type, listener) => { - if (type === VISIBILITY_CHANGE_EVENT) { - if (document.body) { - addBodyAppearListener(document); - } else { - hasVisibilityEventPending = true; - } - } - documentEmitter.on(type, listener); - }; - - document.removeEventListener = (type, listener) => { - if (type === VISIBILITY_CHANGE_EVENT) { - removeBodyAppearListener(document); - } - documentEmitter.off(type, listener); - }; - - document.dispatchEvent = (e) => { - documentEmitter.emit(e.type, e); - }; - - // FontFace - document.fonts = { - add: function(fontFace) { - var domModule = __weex_require__(DOM_MODULE); - domModule.addRule('fontFace', { - fontFamily: fontFace.family, - src: fontFace.source // url('uri') : single quotes are required around uri, and double quotes can not work in weex - }); - } - }; - - // Init visibility state - document.visibilityState = VISIBLE; - - // Hijack the origin createBody - const originCreateBody = document.createBody; - - Object.defineProperty(document, 'createBody', { - value: function() { - var body = originCreateBody.apply(document, arguments); - - if (hasVisibilityEventPending) { - addBodyAppearListener(document); - } - return body; - } - }); - } catch (e) { - console.log(e); - } - - return document; -}; diff --git a/packages/weex-rax-framework/src/emitter.js b/packages/weex-rax-framework/src/emitter.js deleted file mode 100644 index e44c09a65c..0000000000 --- a/packages/weex-rax-framework/src/emitter.js +++ /dev/null @@ -1,73 +0,0 @@ -export default class EventEmitter { - constructor() { - this._listeners = {}; - } - - /** - * Adds a listener function to the specified event. - * @param {String} type - * @param {Function} listener - * @param {Boolean} once - */ - _addListener(type, listener, once) { - this._listeners[type] = this._listeners[type] || []; - this._listeners[type].push({listener, once}); - return this; - } - - /** - * Adds a listener function to the specified event. - * @param {String} type - * @param {Function} listener - * @return {Object} Current instance of EventEmitter for chaining. - */ - on(type, listener) { - return this._addListener(type, listener, false); - } - - once(type, listener) { - return this._addListener(type, listener, true); - } - - /** - * Removes a listener function to the specified event. - * @param {String} type - * @param {Function} listener - * @return {Object} Current instance of EventEmitter for chaining. - */ - off(type, listener) { // alias - if (!this._listeners[type]) { - return this; - } - if (!this._listeners[type].length) { - return this; - } - if (!listener) { - delete this._listeners[type]; - return this; - } - this._listeners[type] = this._listeners[type].filter( - _listener => !(_listener.listener === listener) - ); - return this; - } - - /** - * Emits an specified event. - * @param {String} type - * @param {Object} payload - * @return {Object} Current instance of EventEmitter for chaining. - */ - emit(type, payload) { - if (!this._listeners[type]) { - return this; - } - this._listeners[type].forEach(_listener => { - _listener.listener.apply(this, [payload]); - if (_listener.once) { - this.removeListener(type, _listener.listener); - } - }); - return this; - } -} diff --git a/packages/weex-rax-framework/src/index.js b/packages/weex-rax-framework/src/index.js deleted file mode 100644 index f34d30eccf..0000000000 --- a/packages/weex-rax-framework/src/index.js +++ /dev/null @@ -1,115 +0,0 @@ -'use strict'; - -let Document; -let Element; -let Comment; - -// Instance hub -const instances = {}; - -export function getInstance(instanceId) { - const instance = instances[instanceId]; - if (!instance) { - throw new Error(`Invalid instance id "${instanceId}"`); - } - return instance; -} - -// TODO: delete (future) -export function init(config) { - Document = config.Document; - Element = config.Element; - Comment = config.Comment; -} - -/** - * create a Weex instance - * - * @param {string} instanceId - * @param {object} [__weex_options__] {bundleUrl, debug} - * @param {object} __weex_data__ - */ -export function createInstanceContext(instanceId, __weex_options__, __weex_data__) { - let instance = instances[instanceId]; - const weex = __weex_options__.weex; - - if (instance == undefined) { - let bundleUrl = weex.config.bundleUrl; - if (!bundleUrl) { - console.error('Error: Must have bundleUrl option when createInstance, downgrade to "about:blank".'); - bundleUrl = 'about:blank'; - } else if (!bundleUrl.split('//')[0]) { - bundleUrl = 'https:' + bundleUrl; - } - - const document = new Document(instanceId, bundleUrl); - - instance = instances[instanceId] = { - document, - instanceId, - bundleUrl, - __weex_data__, - uid: 0 - }; - - const instanceContext = { - instanceId, - bundleUrl, - document, - __weex_document__: document, - __weex_options__, - __weex_data__: __weex_data__ || {}, - // Weex - callNative: () => {}, - __weex_config__: __weex_options__ - }; - - return instanceContext; - } else { - throw new Error(`Instance id "${instanceId}" existed when create instance`); - } -} - -/** - * refresh a Weex instance - * - * @param {string} instanceId - * @param {object} data - */ -export function refreshInstance(instanceId, data) { - let instance = getInstance(instanceId); - let document = instance.document; - document.documentElement.fireEvent('refresh', { - timestamp: Date.now(), - data, - }); - document.taskCenter.send('dom', { action: 'refreshFinish' }, []); -} - -/** - * destroy a Weex instance - * @param {string} instanceId - */ -export function destroyInstance(instanceId) { - let instance = getInstance(instanceId); - let bundleCode = instance.bundleCode; - // instance.window.closed = true; - - let document = instance.document; - document.documentElement.fireEvent('destory', { - timestamp: Date.now() - }); - - if (document.destroy) { - document.destroy(); - } - - if (document.taskCenter && document.taskCenter.destroyCallback) { - document.taskCenter.destroyCallback(); - } - - delete instances[instanceId]; -} - -// FIXME: Hack for rollup build "import Rax from 'weex-rax-framework'", in rollup if `module.exports` has `__esModule` key must return by export default -export default exports; diff --git a/packages/weex-rax-framework/src/mock/builtin.js b/packages/weex-rax-framework/src/mock/builtin.js deleted file mode 100644 index c0986f7549..0000000000 --- a/packages/weex-rax-framework/src/mock/builtin.js +++ /dev/null @@ -1,3 +0,0 @@ -export let ModuleFactories = { - 'rax': require('rax/dist/rax.factory') -}; diff --git a/packages/weex-rax-framework/src/mock/define.weex.js b/packages/weex-rax-framework/src/mock/define.weex.js deleted file mode 100644 index b25d7a5f95..0000000000 --- a/packages/weex-rax-framework/src/mock/define.weex.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = function(modules) { - function define(name, deps, factory) { - if (deps instanceof Function) { - factory = deps; - deps = []; - } - - modules[name] = { - factory: factory, - deps: deps, - module: {exports: {}}, - isInitialized: false, - hasError: false, - }; - } - - return define; -}; diff --git a/packages/weex-rax-framework/src/mock/require.weex.js b/packages/weex-rax-framework/src/mock/require.weex.js deleted file mode 100644 index 5bb3983dc8..0000000000 --- a/packages/weex-rax-framework/src/mock/require.weex.js +++ /dev/null @@ -1,34 +0,0 @@ -module.exports = function(modules) { - function require(name) { - var mod = modules[name]; - - if (mod && mod.isInitialized) { - return mod.module.exports; - } - - if (!mod) { - throw new Error( - 'Requiring unknown module "' + name + '"' - ); - } - - if (mod.hasError) { - throw new Error( - 'Requiring module "' + name + '" which threw an exception' - ); - } - - try { - mod.isInitialized = true; - mod.factory(require, mod.module.exports, mod.module); - } catch (e) { - mod.hasError = true; - mod.isInitialized = false; - throw e; - } - - return mod.module.exports; - } - - return require; -}; diff --git a/packages/weex-rax-framework/src/mock/weex-rax-js-runtime.js b/packages/weex-rax-framework/src/mock/weex-rax-js-runtime.js deleted file mode 100644 index 49fb6fc94f..0000000000 --- a/packages/weex-rax-framework/src/mock/weex-rax-js-runtime.js +++ /dev/null @@ -1,2803 +0,0 @@ -/* global define,callNative */ -/* Weex JS Runtime 0.23.6, Build 2018-01-04 13:39. */ - -import {ModuleFactories} from './builtin'; - -(function(global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - global.WeexJSRuntime = factory(); -}(this, function() { - 'use strict'; - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * Get a unique id. - */ - var nextNodeRef = 1; - function uniqueId() { - return (nextNodeRef++).toString(); - } - - function typof(v) { - var s = Object.prototype.toString.call(v); - return s.substring(8, s.length - 1); - } - - function bufferToBase64(buffer) { - if (typeof btoa !== 'function') { - return ''; - } - var string = Array.prototype.map.call( - new Uint8Array(buffer), - function(code) { - return String.fromCharCode(code); - } - ).join(''); - return btoa(string); // eslint-disable-line no-undef - } - - function base64ToBuffer(base64) { - if (typeof atob !== 'function') { - return new ArrayBuffer(0); - } - var string = atob(base64); // eslint-disable-line no-undef - var array = new Uint8Array(string.length); - Array.prototype.forEach.call(string, function(ch, i) { - array[i] = ch.charCodeAt(0); - }); - return array.buffer; - } - - /** - * Detect if the param is falsy or empty - * @param {any} any - */ - function isEmpty(any) { - if (!any || typeof any !== 'object') { - return true; - } - - for (var key in any) { - if (Object.prototype.hasOwnProperty.call(any, key)) { - return false; - } - } - return true; - } - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * Normalize a primitive value. - * @param {any} v - * @return {primitive} - */ - function normalizePrimitive(v) { - var type = typof(v); - - switch (type) { - case 'Undefined': - case 'Null': - return ''; - - case 'RegExp': - return v.toString(); - case 'Date': - return v.toISOString(); - - case 'Number': - case 'String': - case 'Boolean': - case 'Array': - case 'Object': - return v; - - case 'ArrayBuffer': - return { - '@type': 'binary', - dataType: type, - base64: bufferToBase64(v) - }; - - case 'Int8Array': - case 'Uint8Array': - case 'Uint8ClampedArray': - case 'Int16Array': - case 'Uint16Array': - case 'Int32Array': - case 'Uint32Array': - case 'Float32Array': - case 'Float64Array': - return { - '@type': 'binary', - dataType: type, - base64: bufferToBase64(v.buffer) - }; - - default: - return JSON.stringify(v); - } - } - - function decodePrimitive(data) { - if (typof(data) === 'Object') { - // decode base64 into binary - if (data['@type'] && data['@type'] === 'binary') { - return base64ToBuffer(data.base64 || ''); - } - - var realData = {}; - for (var key in data) { - realData[key] = decodePrimitive(data[key]); - } - return realData; - } - if (typof(data) === 'Array') { - return data.map(decodePrimitive); - } - return data; - } - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - function getHookKey(componentId, type, hookName) { - return type + '@' + hookName + '#' + componentId; - } - - /** - * For general callback management of a certain Weex instance. - * Because function can not passed into native, so we create callback - * callback id for each function and pass the callback id into native - * in fact. And when a callback called from native, we can find the real - * callback through the callback id we have passed before. - */ - var CallbackManager = function CallbackManager(instanceId) { - this.instanceId = String(instanceId); - this.lastCallbackId = 0; - this.callbacks = {}; - this.hooks = {}; - }; - CallbackManager.prototype.add = function add(callback) { - this.lastCallbackId++; - this.callbacks[this.lastCallbackId] = callback; - return this.lastCallbackId; - }; - CallbackManager.prototype.remove = function remove(callbackId) { - var callback = this.callbacks[callbackId]; - delete this.callbacks[callbackId]; - return callback; - }; - CallbackManager.prototype.registerHook = function registerHook(componentId, type, hookName, hookFunction) { - // TODO: validate arguments - var key = getHookKey(componentId, type, hookName); - if (this.hooks[key]) { - console.warn('[JS Framework] Override an existing component hook "' + key + '".'); - } - this.hooks[key] = hookFunction; - }; - CallbackManager.prototype.triggerHook = function triggerHook(componentId, type, hookName, options) { - if ( options === void 0 ) options = {}; - - // TODO: validate arguments - var key = getHookKey(componentId, type, hookName); - var hookFunction = this.hooks[key]; - if (typeof hookFunction !== 'function') { - console.error('[JS Framework] Invalid hook function type (' + typeof hookFunction + ') on "' + key + '".'); - return null; - } - var result = null; - try { - result = hookFunction.apply(null, options.args || []); - } catch (e) { - console.error('[JS Framework] Failed to execute the hook function on "' + key + '".'); - } - return result; - }; - CallbackManager.prototype.consume = function consume(callbackId, data, ifKeepAlive) { - var callback = this.callbacks[callbackId]; - if (typeof ifKeepAlive === 'undefined' || ifKeepAlive === false) { - delete this.callbacks[callbackId]; - } - if (typeof callback === 'function') { - return callback(decodePrimitive(data)); - } - return new Error('invalid callback id "' + callbackId + '"'); - }; - CallbackManager.prototype.close = function close() { - this.callbacks = {}; - this.hooks = {}; - }; - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var docMap = {}; - - /** - * Add a document object into docMap. - * @param {string} id - * @param {object} document - */ - function addDoc(id, doc) { - if (id) { - docMap[id] = doc; - } - } - - /** - * Get the document object by id. - * @param {string} id - */ - function getDoc(id) { - return docMap[id]; - } - - /** - * Remove the document from docMap by id. - * @param {string} id - */ - function removeDoc(id) { - delete docMap[id]; - } - - /** - * @deprecated - * Get listener by document id. - * @param {string} id - * @return {object} listener - */ - - - /** - * Get TaskCenter instance by id. - * @param {string} id - * @return {object} TaskCenter - */ - function getTaskCenter(id) { - var doc = docMap[id]; - if (doc && doc.taskCenter) { - return doc.taskCenter; - } - return null; - } - - /** - * Append body node to documentElement. - * @param {object} document - * @param {object} node - * @param {object} before - */ - function appendBody(doc, node, before) { - var documentElement = doc.documentElement; - - if (documentElement.pureChildren.length > 0 || node.parentNode) { - return; - } - var children = documentElement.children; - var beforeIndex = children.indexOf(before); - if (beforeIndex < 0) { - children.push(node); - } else { - children.splice(beforeIndex, 0, node); - } - - if (node.nodeType === 1) { - if (node.role === 'body') { - node.docId = doc.id; - node.ownerDocument = doc; - node.parentNode = documentElement; - linkParent(node, documentElement); - } else { - node.children.forEach(function(child) { - child.parentNode = node; - }); - setBody(doc, node); - node.docId = doc.id; - node.ownerDocument = doc; - linkParent(node, documentElement); - delete doc.nodeMap[node.nodeId]; - } - documentElement.pureChildren.push(node); - sendBody(doc, node); - } else { - node.parentNode = documentElement; - doc.nodeMap[node.ref] = node; - } - } - - function sendBody(doc, node) { - var body = node.toJSON(); - if (doc && doc.taskCenter && typeof doc.taskCenter.send === 'function') { - doc.taskCenter.send('dom', { action: 'createBody' }, [body]); - } - } - - /** - * Set up body node. - * @param {object} document - * @param {object} element - */ - function setBody(doc, el) { - el.role = 'body'; - el.depth = 1; - delete doc.nodeMap[el.nodeId]; - el.ref = '_root'; - doc.nodeMap._root = el; - doc.body = el; - } - - /** - * Establish the connection between parent and child node. - * @param {object} child node - * @param {object} parent node - */ - function linkParent(node, parent) { - node.parentNode = parent; - if (parent.docId) { - node.docId = parent.docId; - node.ownerDocument = parent.ownerDocument; - node.ownerDocument.nodeMap[node.nodeId] = node; - node.depth = parent.depth + 1; - } - node.children.forEach(function(child) { - linkParent(child, node); - }); - } - - /** - * Get the next sibling element. - * @param {object} node - */ - function nextElement(node) { - while (node) { - if (node.nodeType === 1) { - return node; - } - node = node.nextSibling; - } - } - - /** - * Get the previous sibling element. - * @param {object} node - */ - function previousElement(node) { - while (node) { - if (node.nodeType === 1) { - return node; - } - node = node.previousSibling; - } - } - - /** - * Insert a node into list at the specified index. - * @param {object} target node - * @param {array} list - * @param {number} newIndex - * @param {boolean} changeSibling - * @return {number} newIndex - */ - function insertIndex(target, list, newIndex, changeSibling) { - /* istanbul ignore next */ - if (newIndex < 0) { - newIndex = 0; - } - var before = list[newIndex - 1]; - var after = list[newIndex]; - list.splice(newIndex, 0, target); - if (changeSibling) { - before && (before.nextSibling = target); - target.previousSibling = before; - target.nextSibling = after; - after && (after.previousSibling = target); - } - return newIndex; - } - - /** - * Move the node to a new index in list. - * @param {object} target node - * @param {array} list - * @param {number} newIndex - * @param {boolean} changeSibling - * @return {number} newIndex - */ - function moveIndex(target, list, newIndex, changeSibling) { - var index = list.indexOf(target); - /* istanbul ignore next */ - if (index < 0) { - return -1; - } - if (changeSibling) { - var before = list[index - 1]; - var after = list[index + 1]; - before && (before.nextSibling = after); - after && (after.previousSibling = before); - } - list.splice(index, 1); - var newIndexAfter = newIndex; - if (index <= newIndex) { - newIndexAfter = newIndex - 1; - } - var beforeNew = list[newIndexAfter - 1]; - var afterNew = list[newIndexAfter]; - list.splice(newIndexAfter, 0, target); - if (changeSibling) { - beforeNew && (beforeNew.nextSibling = target); - target.previousSibling = beforeNew; - target.nextSibling = afterNew; - afterNew && (afterNew.previousSibling = target); - } - if (index === newIndexAfter) { - return -1; - } - return newIndex; - } - - /** - * Remove the node from list. - * @param {object} target node - * @param {array} list - * @param {boolean} changeSibling - */ - function removeIndex(target, list, changeSibling) { - var index = list.indexOf(target); - /* istanbul ignore next */ - if (index < 0) { - return; - } - if (changeSibling) { - var before = list[index - 1]; - var after = list[index + 1]; - before && (before.nextSibling = after); - after && (after.previousSibling = before); - } - list.splice(index, 1); - } - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var Node = function Node() { - this.nodeId = uniqueId(); - this.ref = this.nodeId; - this.children = []; - this.pureChildren = []; - this.parentNode = null; - this.nextSibling = null; - this.previousSibling = null; - }; - - /** -* Destroy current node, and remove itself form nodeMap. -*/ - Node.prototype.destroy = function destroy() { - var doc = getDoc(this.docId); - if (doc) { - delete this.docId; - delete doc.nodeMap[this.nodeId]; - } - this.children.forEach(function(child) { - child.destroy(); - }); - }; - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - var Element$2; - - function setElement(El) { - Element$2 = El; - } - - /** - * A map which stores all type of elements. - * @type {Object} - */ - var registeredElements = {}; - - /** - * Register an extended element type with component methods. - * @param {string} type component type - * @param {array} methods a list of method names - */ - function registerElement(type, methods) { - // Skip when no special component methods. - if (!methods || !methods.length) { - return; - } - - // Init constructor. - var WeexElement = (function(Element) { - function WeexElement() { - Element.apply(this, arguments); - } if ( Element ) WeexElement.__proto__ = Element; - WeexElement.prototype = Object.create( Element && Element.prototype ); - WeexElement.prototype.constructor = WeexElement; - - - return WeexElement; - }(Element$2)); - - // Add methods to prototype. - methods.forEach(function(methodName) { - WeexElement.prototype[methodName] = function() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - var taskCenter = getTaskCenter(this.docId); - if (taskCenter) { - return taskCenter.send('component', { - ref: this.ref, - component: type, - method: methodName - }, args); - } - }; - }); - - // Add to element type map. - registeredElements[type] = WeexElement; - } - - - function getWeexElement(type) { - return registeredElements[type]; - } - - - /** - * Clear all element types. Only for testing. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var DEFAULT_TAG_NAME = 'div'; - var BUBBLE_EVENTS = [ - 'click', 'longpress', 'touchstart', 'touchmove', 'touchend', - 'panstart', 'panmove', 'panend', 'horizontalpan', 'verticalpan', 'swipe' - ]; - - function registerNode(docId, node) { - var doc = getDoc(docId); - doc.nodeMap[node.nodeId] = node; - } - - var Element = (function(Node$$1) { - function Element(type, props, isExtended) { - if ( type === void 0 ) type = DEFAULT_TAG_NAME; - - Node$$1.call(this); - - var WeexElement = getWeexElement(type); - if (WeexElement && !isExtended) { - return new WeexElement(type, props, true); - } - - props = props || {}; - this.nodeType = 1; - this.nodeId = uniqueId(); - this.ref = this.nodeId; - this.type = type; - this.attr = props.attr || {}; - this.style = props.style || {}; - this.classStyle = props.classStyle || {}; - this.classList = props.classList || []; - this.event = {}; - this.children = []; - this.pureChildren = []; - } - - if ( Node$$1 ) Element.__proto__ = Node$$1; - Element.prototype = Object.create( Node$$1 && Node$$1.prototype ); - Element.prototype.constructor = Element; - - /** - * Append a child node. - * @param {object} node - * @return {undefined | number} the signal sent by native - */ - Element.prototype.appendChild = function appendChild(node) { - if (node.parentNode && node.parentNode !== this) { - return; - } - /* istanbul ignore else */ - if (!node.parentNode) { - linkParent(node, this); - insertIndex(node, this.children, this.children.length, true); - if (this.docId) { - registerNode(this.docId, node); - } - if (node.nodeType === 1) { - insertIndex(node, this.pureChildren, this.pureChildren.length); - var taskCenter = getTaskCenter(this.docId); - if (taskCenter) { - return taskCenter.send( - 'dom', - { action: 'addElement' }, - [this.ref, node.toJSON(), -1] - ); - } - } - } else { - moveIndex(node, this.children, this.children.length, true); - if (node.nodeType === 1) { - var index = moveIndex(node, this.pureChildren, this.pureChildren.length); - var taskCenter$1 = getTaskCenter(this.docId); - if (taskCenter$1 && index >= 0) { - return taskCenter$1.send( - 'dom', - { action: 'moveElement' }, - [node.ref, this.ref, index] - ); - } - } - } - }; - - /** - * Insert a node before specified node. - * @param {object} node - * @param {object} before - * @return {undefined | number} the signal sent by native - */ - Element.prototype.insertBefore = function insertBefore(node, before) { - if (node.parentNode && node.parentNode !== this) { - return; - } - if (node === before || node.nextSibling && node.nextSibling === before) { - return; - } - if (!node.parentNode) { - linkParent(node, this); - insertIndex(node, this.children, this.children.indexOf(before), true); - if (this.docId) { - registerNode(this.docId, node); - } - if (node.nodeType === 1) { - var pureBefore = nextElement(before); - var index = insertIndex( - node, - this.pureChildren, - pureBefore - ? this.pureChildren.indexOf(pureBefore) - : this.pureChildren.length - ); - var taskCenter = getTaskCenter(this.docId); - if (taskCenter) { - return taskCenter.send( - 'dom', - { action: 'addElement' }, - [this.ref, node.toJSON(), index] - ); - } - } - } else { - moveIndex(node, this.children, this.children.indexOf(before), true); - if (node.nodeType === 1) { - var pureBefore$1 = nextElement(before); - /* istanbul ignore next */ - var index$1 = moveIndex( - node, - this.pureChildren, - pureBefore$1 - ? this.pureChildren.indexOf(pureBefore$1) - : this.pureChildren.length - ); - var taskCenter$1 = getTaskCenter(this.docId); - if (taskCenter$1 && index$1 >= 0) { - return taskCenter$1.send( - 'dom', - { action: 'moveElement' }, - [node.ref, this.ref, index$1] - ); - } - } - } - }; - - /** - * Insert a node after specified node. - * @param {object} node - * @param {object} after - * @return {undefined | number} the signal sent by native - */ - Element.prototype.insertAfter = function insertAfter(node, after) { - if (node.parentNode && node.parentNode !== this) { - return; - } - if (node === after || node.previousSibling && node.previousSibling === after) { - return; - } - if (!node.parentNode) { - linkParent(node, this); - insertIndex(node, this.children, this.children.indexOf(after) + 1, true); - /* istanbul ignore else */ - if (this.docId) { - registerNode(this.docId, node); - } - if (node.nodeType === 1) { - var index = insertIndex( - node, - this.pureChildren, - this.pureChildren.indexOf(previousElement(after)) + 1 - ); - var taskCenter = getTaskCenter(this.docId); - /* istanbul ignore else */ - if (taskCenter) { - return taskCenter.send( - 'dom', - { action: 'addElement' }, - [this.ref, node.toJSON(), index] - ); - } - } - } else { - moveIndex(node, this.children, this.children.indexOf(after) + 1, true); - if (node.nodeType === 1) { - var index$1 = moveIndex( - node, - this.pureChildren, - this.pureChildren.indexOf(previousElement(after)) + 1 - ); - var taskCenter$1 = getTaskCenter(this.docId); - if (taskCenter$1 && index$1 >= 0) { - return taskCenter$1.send( - 'dom', - { action: 'moveElement' }, - [node.ref, this.ref, index$1] - ); - } - } - } - }; - - /** - * Remove a child node, and decide whether it should be destroyed. - * @param {object} node - * @param {boolean} preserved - */ - Element.prototype.removeChild = function removeChild(node, preserved) { - if (node.parentNode) { - removeIndex(node, this.children, true); - if (node.nodeType === 1) { - removeIndex(node, this.pureChildren); - var taskCenter = getTaskCenter(this.docId); - if (taskCenter) { - taskCenter.send( - 'dom', - { action: 'removeElement' }, - [node.ref] - ); - } - } - } - if (!preserved) { - node.destroy(); - } - }; - - /** - * Clear all child nodes. - */ - Element.prototype.clear = function clear() { - var taskCenter = getTaskCenter(this.docId); - /* istanbul ignore else */ - if (taskCenter) { - this.pureChildren.forEach(function(node) { - taskCenter.send( - 'dom', - { action: 'removeElement' }, - [node.ref] - ); - }); - } - this.children.forEach(function(node) { - node.destroy(); - }); - this.children.length = 0; - this.pureChildren.length = 0; - }; - - /** - * Set an attribute, and decide whether the task should be send to native. - * @param {string} key - * @param {string | number} value - * @param {boolean} silent - */ - Element.prototype.setAttr = function setAttr(key, value, silent) { - if (this.attr[key] === value && silent !== false) { - return; - } - this.attr[key] = value; - var taskCenter = getTaskCenter(this.docId); - if (!silent && taskCenter) { - var result = {}; - result[key] = value; - taskCenter.send( - 'dom', - { action: 'updateAttrs' }, - [this.ref, result] - ); - } - }; - - /** - * Set batched attributes. - * @param {object} batchedAttrs - * @param {boolean} silent - */ - Element.prototype.setAttrs = function setAttrs(batchedAttrs, silent) { - var this$1 = this; - - if (isEmpty(batchedAttrs)) { - return; - } - var mutations = {}; - for (var key in batchedAttrs) { - if (this$1.attr[key] !== batchedAttrs[key]) { - this$1.attr[key] = batchedAttrs[key]; - mutations[key] = batchedAttrs[key]; - } - } - if (!isEmpty(mutations)) { - var taskCenter = getTaskCenter(this.docId); - if (!silent && taskCenter) { - taskCenter.send( - 'dom', - { action: 'updateAttrs' }, - [this.ref, mutations] - ); - } - } - }; - - /** - * Set a style property, and decide whether the task should be send to native. - * @param {string} key - * @param {string | number} value - * @param {boolean} silent - */ - Element.prototype.setStyle = function setStyle(key, value, silent) { - if (this.style[key] === value && silent !== false) { - return; - } - this.style[key] = value; - var taskCenter = getTaskCenter(this.docId); - if (!silent && taskCenter) { - var result = {}; - result[key] = value; - taskCenter.send( - 'dom', - { action: 'updateStyle' }, - [this.ref, result] - ); - } - }; - - /** - * Set batched style properties. - * @param {object} batchedStyles - * @param {boolean} silent - */ - Element.prototype.setStyles = function setStyles(batchedStyles, silent) { - var this$1 = this; - - if (isEmpty(batchedStyles)) { - return; - } - var mutations = {}; - for (var key in batchedStyles) { - if (this$1.style[key] !== batchedStyles[key]) { - this$1.style[key] = batchedStyles[key]; - mutations[key] = batchedStyles[key]; - } - } - if (!isEmpty(mutations)) { - var taskCenter = getTaskCenter(this.docId); - if (!silent && taskCenter) { - taskCenter.send( - 'dom', - { action: 'updateStyle' }, - [this.ref, mutations] - ); - } - } - }; - - /** - * TODO: deprecated - * Set style properties from class. - * @param {object} classStyle - */ - Element.prototype.setClassStyle = function setClassStyle(classStyle) { - var this$1 = this; - - // reset previous class style to empty string - for (var key in this$1.classStyle) { - this$1.classStyle[key] = ''; - } - - Object.assign(this.classStyle, classStyle); - var taskCenter = getTaskCenter(this.docId); - if (taskCenter) { - taskCenter.send( - 'dom', - { action: 'updateStyle' }, - [this.ref, this.toStyle()] - ); - } - }; - - /** - * Set class list. - * @param {array} classList - */ - Element.prototype.setClassList = function setClassList(classList) { - var classes = typeof classList === 'string' - ? classList.split(/\s+/) - : Array.from(classList); - if (Array.isArray(classes) && classes.length > 0) { - this.classList = classes; - var taskCenter = getTaskCenter(this.docId); - if (taskCenter) { - taskCenter.send( - 'dom', - { action: 'updateClassList' }, - [this.ref, this.classList.slice()] - ); - } - } - }; - - /** - * Add an event handler. - * @param {string} event type - * @param {function} event handler - */ - Element.prototype.addEvent = function addEvent(type, handler, params) { - if (!this.event) { - this.event = {}; - } - if (!this.event[type]) { - this.event[type] = { handler: handler, params: params }; - var taskCenter = getTaskCenter(this.docId); - if (taskCenter) { - taskCenter.send( - 'dom', - { action: 'addEvent' }, - [this.ref, type] - ); - } - } - }; - - /** - * Remove an event handler. - * @param {string} event type - */ - Element.prototype.removeEvent = function removeEvent(type) { - if (this.event && this.event[type]) { - delete this.event[type]; - var taskCenter = getTaskCenter(this.docId); - if (taskCenter) { - taskCenter.send( - 'dom', - { action: 'removeEvent' }, - [this.ref, type] - ); - } - } - }; - - /** - * Fire an event manually. - * @param {string} type type - * @param {function} event handler - * @param {boolean} isBubble whether or not event bubble - * @param {boolean} options - * @return {} anything returned by handler function - */ - Element.prototype.fireEvent = function fireEvent(type, event, isBubble, options) { - var result = null; - var isStopPropagation = false; - var eventDesc = this.event[type]; - if (eventDesc && event) { - var handler = eventDesc.handler; - event.stopPropagation = function() { - isStopPropagation = true; - }; - if (options && options.params) { - result = handler.call.apply(handler, [ this ].concat( options.params, [event] )); - } else { - result = handler.call(this, event); - } - } - - if (!isStopPropagation - && isBubble - && BUBBLE_EVENTS.indexOf(type) !== -1 - && this.parentNode - && this.parentNode.fireEvent) { - event.currentTarget = this.parentNode; - this.parentNode.fireEvent(type, event, isBubble); // no options - } - - return result; - }; - - /** - * Get all styles of current element. - * @return {object} style - */ - Element.prototype.toStyle = function toStyle() { - return Object.assign({}, this.classStyle, this.style); - }; - - /** - * Convert current element to JSON like object. - * @return {object} element - */ - Element.prototype.toJSON = function toJSON() { - var this$1 = this; - - var result = { - ref: this.ref.toString(), - type: this.type - }; - if (!isEmpty(this.attr)) { - result.attr = this.attr; - } - if (this.classList.length > 0) { - result.classList = this.classList.slice(); - } - var style = this.toStyle(); - if (!isEmpty(style)) { - result.style = style; - } - var event = []; - for (var type in this$1.event) { - var ref = this$1.event[type]; - var params = ref.params; - if (!params) { - event.push(type); - } else { - event.push({ type: type, params: params }); - } - } - if (event.length) { - result.event = event; - } - if (this.pureChildren.length) { - result.children = this.pureChildren.map(function(child) { - return child.toJSON(); - }); - } - return result; - }; - - /** - * Convert to HTML element tag string. - * @return {stirng} html - */ - Element.prototype.toString = function toString() { - return '<' + this.type + - ' attr=' + JSON.stringify(this.attr) + - ' style=' + JSON.stringify(this.toStyle()) + '>' + - this.pureChildren.map(function(child) { - return child.toString(); - }).join('') + - ''; - }; - - return Element; - }(Node)); - - setElement(Element); - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var fallback = function() {}; - - // The API of TaskCenter would be re-design. - var TaskCenter = function TaskCenter(id, sendTasks) { - Object.defineProperty(this, 'instanceId', { - enumerable: true, - value: String(id) - }); - Object.defineProperty(this, 'callbackManager', { - enumerable: true, - value: new CallbackManager(id) - }); - fallback = sendTasks || function() {}; - }; - - TaskCenter.prototype.callback = function callback(callbackId, data, ifKeepAlive) { - return this.callbackManager.consume(callbackId, data, ifKeepAlive); - }; - - TaskCenter.prototype.registerHook = function registerHook() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - return (ref = this.callbackManager).registerHook.apply(ref, args); - var ref; - }; - - TaskCenter.prototype.triggerHook = function triggerHook() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - return (ref = this.callbackManager).triggerHook.apply(ref, args); - var ref; - }; - - TaskCenter.prototype.updateData = function updateData(componentId, newData, callback) { - this.send('module', { - module: 'dom', - method: 'updateComponentData' - }, [componentId, newData, callback]); - }; - - TaskCenter.prototype.destroyCallback = function destroyCallback() { - return this.callbackManager.close(); - }; - - /** - * Normalize a value. Specially, if the value is a function, then generate a function id - * and save it to `CallbackManager`, at last return the function id. - * @param{any} v - * @return {primitive} - */ - TaskCenter.prototype.normalize = function normalize(v) { - var type = typof(v); - if (v && v instanceof Element) { - return v.ref; - } - if (v && v._isVue && v.$el instanceof Element) { - return v.$el.ref; - } - if (type === 'Function') { - return this.callbackManager.add(v).toString(); - } - return normalizePrimitive(v); - }; - - TaskCenter.prototype.send = function send(type, params, args, options) { - var this$1 = this; - - var action = params.action; - var component = params.component; - var ref = params.ref; - var module = params.module; - var method = params.method; - - args = args.map(function(arg) { - return this$1.normalize(arg); - }); - - switch (type) { - case 'dom': - return this[action](this.instanceId, args); - case 'component': - return this.componentHandler(this.instanceId, ref, method, args, Object.assign({ component: component }, options)); - default: - return this.moduleHandler(this.instanceId, module, method, args, options); - } - }; - - TaskCenter.prototype.callDOM = function callDOM(action, args) { - return this[action](this.instanceId, args); - }; - - TaskCenter.prototype.callComponent = function callComponent(ref, method, args, options) { - return this.componentHandler(this.instanceId, ref, method, args, options); - }; - - TaskCenter.prototype.callModule = function callModule(module, method, args, options) { - return this.moduleHandler(this.instanceId, module, method, args, options); - }; - - function init$1() { - var DOM_METHODS = { - createFinish: global.callCreateFinish, - updateFinish: global.callUpdateFinish, - refreshFinish: global.callRefreshFinish, - - createBody: global.callCreateBody, - registerStyleSheets: global.callRegisterStyleSheets, - addElement: global.callAddElement, - removeElement: global.callRemoveElement, - moveElement: global.callMoveElement, - updateAttrs: global.callUpdateAttrs, - updateStyle: global.callUpdateStyle, - updateClassList: global.callUpdateClassList, - - addEvent: global.callAddEvent, - removeEvent: global.callRemoveEvent - }; - var proto = TaskCenter.prototype; - - var loop = function( name ) { - var method = DOM_METHODS[name]; - proto[name] = method ? - function(id, args) { - return method.apply(void 0, [ id ].concat( args )); - } : - function(id, args) { - return fallback(id, [{ module: 'dom', method: name, args: args }], '-1'); - }; - }; - - for (var name in DOM_METHODS) loop( name ); - - proto.componentHandler = global.callNativeComponent || - function(id, ref, method, args, options) { - return fallback(id, [{ component: options.component, ref: ref, method: method, args: args }]); - }; - - proto.moduleHandler = global.callNativeModule || - function(id, module, method, args) { - return fallback(id, [{ module: module, method: method, args: args }]); - }; - } - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - function fireEvent(document, nodeId, type, event, domChanges, params) { - var el = document.getRef(nodeId); - if (el) { - return document.fireEvent(el, type, event, domChanges, params); - } - return new Error('invalid element reference "' + nodeId + '"'); - } - - function callback(document, callbackId, data, ifKeepAlive) { - return document.taskCenter.callback(callbackId, data, ifKeepAlive); - } - - function componentHook(document, componentId, type, hook, options) { - if (!document || !document.taskCenter) { - console.error("[JS Framework] Can't find \"document\" or \"taskCenter\"."); - return null; - } - var result = null; - try { - result = document.taskCenter.triggerHook(componentId, type, hook, options); - } catch (e) { - console.error('[JS Framework] Failed to trigger the "' + type + '@' + hook + '" hook on ' + componentId + '.'); - } - return result; - } - - /** - * Accept calls from native (event or callback). - * - * @param {string} id - * @param {array} tasks list with `method` and `args` - */ - function receiveTasks(id, tasks) { - var document = getDoc(id); - if (!document) { - return new Error('[JS Framework] Failed to receiveTasks, ' - + 'instance (' + id + ') is not available.'); - } - if (Array.isArray(tasks)) { - return tasks.map(function(task) { - switch (task.method) { - case 'callback': return callback.apply(void 0, [ document ].concat( task.args )); - case 'fireEventSync': - case 'fireEvent': return fireEvent.apply(void 0, [ document ].concat( task.args )); - case 'componentHook': return componentHook.apply(void 0, [ document ].concat( task.args )); - } - }); - } - } - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var weexModules = {}; - - /** - * Register native modules information. - * @param {object} newModules - */ - function registerModules(newModules) { - var loop = function( name ) { - if (!weexModules[name]) { - weexModules[name] = {}; - } - newModules[name].forEach(function(method) { - if (typeof method === 'string') { - weexModules[name][method] = true; - } else { - weexModules[name][method.name] = method.args; - } - }); - }; - - for (var name in newModules) loop( name ); - } - - /** - * Check whether the module or the method has been registered. - * @param {String} module name - * @param {String} method name (optional) - */ - function isRegisteredModule(name, method) { - if (typeof method === 'string') { - return !!(weexModules[name] && weexModules[name][method]); - } - return !!weexModules[name]; - } - - function getModuleDescription(name) { - return weexModules[name]; - } - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var weexComponents = {}; - - /** - * Register native components information. - * @param {array} newComponents - */ - function registerComponents(newComponents) { - if (Array.isArray(newComponents)) { - newComponents.forEach(function(component) { - if (!component) { - return; - } - if (typeof component === 'string') { - weexComponents[component] = true; - } else if (typeof component === 'object' && typeof component.type === 'string') { - weexComponents[component.type] = component; - registerElement(component.type, component.methods); - } - }); - } - } - - /** - * Check whether the component has been registered. - * @param {String} component name - */ - function isRegisteredComponent(name) { - return !!weexComponents[name]; - } - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - // JS Services - - var services = []; - - /** - * Register a JavaScript service. - * A JavaScript service options could have a set of lifecycle methods - * for each Weex instance. For example: create, refresh, destroy. - * For the JS framework maintainer if you want to supply some features - * which need to work well in different Weex instances, even in different - * frameworks separately. You can make a JavaScript service to init - * its variables or classes for each Weex instance when it's created - * and recycle them when it's destroyed. - * @param {object} options Could have { create, refresh, destroy } - * lifecycle methods. In create method it should - * return an object of what variables or classes - * would be injected into the Weex instance. - */ - function register(name, options) { - if (has(name)) { - console.warn('Service "' + name + '" has been registered already!'); - } else { - options = Object.assign({}, options); - services.push({ name: name, options: options }); - } - } - - /** - * Unregister a JavaScript service by name - * @param {string} name - */ - function unregister(name) { - services.some(function(service, index) { - if (service.name === name) { - services.splice(index, 1); - return true; - } - }); - } - - /** - * Check if a JavaScript service with a certain name existed. - * @param {string} name - * @return {Boolean} - */ - function has(name) { - return indexOf(name) >= 0; - } - - /** - * Find the index of a JavaScript service by name - * @param {string} name - * @return {number} - */ - function indexOf(name) { - return services.map(function(service) { - return service.name; - }).indexOf(name); - } - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - function track(id, type, value) { - var taskCenter = getTaskCenter(id); - if (!taskCenter || typeof taskCenter.send !== 'function') { - console.error('[JS Framework] Failed to create tracker!'); - return; - } - if (!type || !value) { - console.warn('[JS Framework] Invalid track type (' + type + ') or value (' + value + ')'); - return; - } - var label = 'jsfm.' + type + '.' + value; - try { - if (isRegisteredModule('userTrack', 'addPerfPoint')) { - var message = Object.create(null); - message[label] = '4'; - taskCenter.send('module', { - module: 'userTrack', - method: 'addPerfPoint' - }, [message]); - } - } catch (err) { - console.error('[JS Framework] Failed to trace "' + label + '"!'); - } - } - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var Comment = (function(Node$$1) { - function Comment(value) { - Node$$1.call(this); - - this.nodeType = 8; - this.nodeId = uniqueId(); - this.ref = this.nodeId; - this.type = 'comment'; - this.value = value; - this.children = []; - this.pureChildren = []; - } - - if ( Node$$1 ) Comment.__proto__ = Node$$1; - Comment.prototype = Object.create( Node$$1 && Node$$1.prototype ); - Comment.prototype.constructor = Comment; - - /** - * Convert to HTML comment string. - * @return {stirng} html - */ - Comment.prototype.toString = function toString() { - return ''; - }; - - return Comment; - }(Node)); - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** -* Create the action object. -* @param {string} name -* @param {array} arguments -* @return {object} action -*/ - function createAction(name, args) { - if ( args === void 0 ) args = []; - - return { module: 'dom', method: name, args: args }; - } - - var Listener = function Listener(id, handler) { - this.id = id; - this.batched = false; - this.updates = []; - if (typeof handler === 'function') { - Object.defineProperty(this, 'handler', { - configurable: true, - enumerable: true, - writable: true, - value: handler - }); - } else { - console.error('[JS Runtime] invalid parameter, handler must be a function'); - } - }; - - /** - * Send the "createFinish" signal. - * @param {function} callback - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.createFinish = function createFinish(callback) { - var handler = this.handler; - return handler([createAction('createFinish')], callback); - }; - - /** - * Send the "updateFinish" signal. - * @param {function} callback - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.updateFinish = function updateFinish(callback) { - var handler = this.handler; - return handler([createAction('updateFinish')], callback); - }; - - /** - * Send the "refreshFinish" signal. - * @param {function} callback - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.refreshFinish = function refreshFinish(callback) { - var handler = this.handler; - return handler([createAction('refreshFinish')], callback); - }; - - /** - * Send the "createBody" signal. - * @param {object} element - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.createBody = function createBody(element) { - var body = element.toJSON(); - var children = body.children; - delete body.children; - var actions = [createAction('createBody', [body])]; - if (children) { - actions.push.apply(actions, children.map(function(child) { - return createAction('addElement', [body.ref, child, -1]); - })); - } - return this.addActions(actions); - }; - - /** - * Send the "addElement" signal. - * @param {object} element - * @param {stirng} reference id - * @param {number} index - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.addElement = function addElement(element, ref, index) { - if (!(index >= 0)) { - index = -1; - } - return this.addActions(createAction('addElement', [ref, element.toJSON(), index])); - }; - - /** - * Send the "removeElement" signal. - * @param {stirng} reference id - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.removeElement = function removeElement(ref) { - if (Array.isArray(ref)) { - var actions = ref.map(function(r) { - return createAction('removeElement', [r]); - }); - return this.addActions(actions); - } - return this.addActions(createAction('removeElement', [ref])); - }; - - /** - * Send the "moveElement" signal. - * @param {stirng} target reference id - * @param {stirng} parent reference id - * @param {number} index - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.moveElement = function moveElement(targetRef, parentRef, index) { - return this.addActions(createAction('moveElement', [targetRef, parentRef, index])); - }; - - /** - * Send the "updateAttrs" signal. - * @param {stirng} reference id - * @param {stirng} key - * @param {stirng} value - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.setAttr = function setAttr(ref, key, value) { - var result = {}; - result[key] = value; - return this.addActions(createAction('updateAttrs', [ref, result])); - }; - - /** - * Send the "updateStyle" signal, update a sole style. - * @param {stirng} reference id - * @param {stirng} key - * @param {stirng} value - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.setStyle = function setStyle(ref, key, value) { - var result = {}; - result[key] = value; - return this.addActions(createAction('updateStyle', [ref, result])); - }; - - /** - * Send the "updateStyle" signal. - * @param {stirng} reference id - * @param {object} style - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.setStyles = function setStyles(ref, style) { - return this.addActions(createAction('updateStyle', [ref, style])); - }; - - /** - * Send the "addEvent" signal. - * @param {stirng} reference id - * @param {string} event type - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.addEvent = function addEvent(ref, type) { - return this.addActions(createAction('addEvent', [ref, type])); - }; - - /** - * Send the "removeEvent" signal. - * @param {stirng} reference id - * @param {string} event type - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.removeEvent = function removeEvent(ref, type) { - return this.addActions(createAction('removeEvent', [ref, type])); - }; - - /** - * Default handler. - * @param {object | array} actions - * @param {function} callback - * @return {} anything returned by callback function - */ - Listener.prototype.handler = function handler(actions, cb) { - return cb && cb(); - }; - - /** - * Add actions into updates. - * @param {object | array} actions - * @return {undefined | number} the signal sent by native - */ - Listener.prototype.addActions = function addActions(actions) { - var updates = this.updates; - var handler = this.handler; - - if (!Array.isArray(actions)) { - actions = [actions]; - } - - if (this.batched) { - updates.push.apply(updates, actions); - } else { - return handler(actions); - } - }; - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * @fileOverview - * Task handler for communication between javascript and native. - */ - - var handlerMap = { - createBody: 'callCreateBody', - addElement: 'callAddElement', - removeElement: 'callRemoveElement', - moveElement: 'callMoveElement', - updateAttrs: 'callUpdateAttrs', - updateStyle: 'callUpdateStyle', - addEvent: 'callAddEvent', - removeEvent: 'callRemoveEvent' - }; - - /** - * Create a task handler. - * @param {string} id - * @param {function} handler - * @return {function} taskHandler - */ - function createHandler(id, handler) { - var defaultHandler = handler || global.callNative; - - /* istanbul ignore if */ - if (typeof defaultHandler !== 'function') { - console.error('[JS Runtime] no default handler'); - } - - return function taskHandler(tasks) { - /* istanbul ignore if */ - if (!Array.isArray(tasks)) { - tasks = [tasks]; - } - for (var i = 0; i < tasks.length; i++) { - var returnValue = dispatchTask(id, tasks[i], defaultHandler); - if (returnValue === -1) { - return returnValue; - } - } - }; - } - - /** - * Check if there is a corresponding available handler in the environment. - * @param {string} module - * @param {string} method - * @return {boolean} - */ - function hasAvailableHandler(module, method) { - return module === 'dom' - && handlerMap[method] - && typeof global[handlerMap[method]] === 'function'; - } - - /** - * Dispatch the task to the specified handler. - * @param {string} id - * @param {object} task - * @param {function} defaultHandler - * @return {number} signal returned from native - */ - function dispatchTask(id, task, defaultHandler) { - var module = task.module; - var method = task.method; - var args = task.args; - - if (hasAvailableHandler(module, method)) { - return global[handlerMap[method]].apply(global, [ id ].concat( args, ['-1'] )); - } - - return defaultHandler(id, [task], '-1'); - } - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * Update all changes for an element. - * @param {object} element - * @param {object} changes - */ - function updateElement(el, changes) { - var attrs = changes.attrs || {}; - for (var name in attrs) { - el.setAttr(name, attrs[name], true); - } - var style = changes.style || {}; - for (var name$1 in style) { - el.setStyle(name$1, style[name$1], true); - } - } - - var Document = function Document(id, url, handler) { - id = id ? id.toString() : ''; - this.id = id; - this.URL = url; - - addDoc(id, this); - this.nodeMap = {}; - var L = Document.Listener || Listener; - this.listener = new L(id, handler || createHandler(id, Document.handler)); // deprecated - this.taskCenter = new TaskCenter(id, handler ? function(id) { - var args = [], len = arguments.length - 1; - while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; - - return handler.apply(void 0, args); - } : Document.handler); - this.createDocumentElement(); - }; - - /** -* Get the node from nodeMap. -* @param {string} reference id -* @return {object} node -*/ - Document.prototype.getRef = function getRef(ref) { - return this.nodeMap[ref]; - }; - - /** -* Turn on batched updates. -*/ - Document.prototype.open = function open() { - this.listener.batched = false; - }; - - /** -* Turn off batched updates. -*/ - Document.prototype.close = function close() { - this.listener.batched = true; - }; - - /** -* Create the document element. -* @return {object} documentElement -*/ - Document.prototype.createDocumentElement = function createDocumentElement() { - var this$1 = this; - - if (!this.documentElement) { - var el = new Element('document'); - el.docId = this.id; - el.ownerDocument = this; - el.role = 'documentElement'; - el.depth = 0; - el.ref = '_documentElement'; - this.nodeMap._documentElement = el; - this.documentElement = el; - - Object.defineProperty(el, 'appendChild', { - configurable: true, - enumerable: true, - writable: true, - value: function(node) { - appendBody(this$1, node); - } - }); - - Object.defineProperty(el, 'insertBefore', { - configurable: true, - enumerable: true, - writable: true, - value: function(node, before) { - appendBody(this$1, node, before); - } - }); - } - - return this.documentElement; - }; - - /** -* Create the body element. -* @param {string} type -* @param {objct} props -* @return {object} body element -*/ - Document.prototype.createBody = function createBody(type, props) { - if (!this.body) { - var el = new Element(type, props); - setBody(this, el); - } - - return this.body; - }; - - /** -* Create an element. -* @param {string} tagName -* @param {objct} props -* @return {object} element -*/ - Document.prototype.createElement = function createElement(tagName, props) { - return new Element(tagName, props); - }; - - /** -* Create an comment. -* @param {string} text -* @return {object} comment -*/ - Document.prototype.createComment = function createComment(text) { - return new Comment(text); - }; - - /** -* Register StyleSheets. -* @param {string} scopeId -* @return {array} styleSheets -*/ - Document.prototype.registerStyleSheets = function registerStyleSheets(scopeId, styleSheets) { - var sheets = Array.isArray(styleSheets) ? styleSheets : [styleSheets]; - if (this.taskCenter && sheets.length) { - return this.taskCenter.send( - 'dom', - { action: 'registerStyleSheets' }, - [scopeId, sheets] - ); - } - }; - - /** -* Fire an event on specified element manually. -* @param {object} element -* @param {string} event type -* @param {object} event object -* @param {object} dom changes -* @param {object} options -* @return {} anything returned by handler function -*/ - Document.prototype.fireEvent = function fireEvent(el, type, event, domChanges, options) { - if (!el) { - return; - } - event = event || {}; - event.type = event.type || type; - event.target = el; - event.currentTarget = el; - event.timestamp = Date.now(); - if (domChanges) { - updateElement(el, domChanges); - } - var isBubble = this.getRef('_root').attr.bubble === 'true'; - return el.fireEvent(type, event, isBubble, options); - }; - - /** -* Destroy current document, and remove itself form docMap. -*/ - Document.prototype.destroy = function destroy() { - this.taskCenter.destroyCallback(); - delete this.listener; - delete this.nodeMap; - delete this.taskCenter; - removeDoc(this.id); - }; - - // default task handler - Document.handler = null; - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var moduleProxies = {}; - - function setId(weex, id) { - Object.defineProperty(weex, '[[CurrentInstanceId]]', { value: id }); - } - - function getId(weex) { - return weex['[[CurrentInstanceId]]']; - } - - function moduleGetter(id, module, method) { - var taskCenter = getTaskCenter(id); - if (!taskCenter || typeof taskCenter.send !== 'function') { - console.error('[JS Framework] Failed to find taskCenter (' + id + ').'); - return null; - } - return function() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - return taskCenter.send('module', { module: module, method: method }, args); - }; - } - - function moduleSetter(id, module, method, fn) { - var taskCenter = getTaskCenter(id); - if (!taskCenter || typeof taskCenter.send !== 'function') { - console.error('[JS Framework] Failed to find taskCenter (' + id + ').'); - return null; - } - if (typeof fn !== 'function') { - console.error('[JS Framework] ' + module + '.' + method + ' must be assigned as a function.'); - return null; - } - return function(fn) { - return taskCenter.send('module', { module: module, method: method }, [fn]); - }; - } - - var WeexInstance = function WeexInstance(id, config) { - setId(this, String(id)); - this.config = config || {}; - this.document = new Document(id, this.config.bundleUrl); - this.requireModule = this.requireModule.bind(this); - this.isRegisteredModule = isRegisteredModule; - this.isRegisteredComponent = isRegisteredComponent; - }; - - WeexInstance.prototype.requireModule = function requireModule(moduleName) { - var id = getId(this); - if (!(id && this.document && this.document.taskCenter)) { - console.error('[JS Framework] Failed to requireModule("' + moduleName + '"), ' - + 'instance (' + id + ") doesn't exist anymore."); - return; - } - - // warn for unknown module - if (!isRegisteredModule(moduleName)) { - console.warn('[JS Framework] using unregistered weex module "' + moduleName + '"'); - return; - } - - // create new module proxy - var proxyName = moduleName + '#' + id; - if (!moduleProxies[proxyName]) { - // create registered module apis - var moduleDefine = getModuleDescription(moduleName); - var moduleApis = {}; - var loop = function( methodName ) { - Object.defineProperty(moduleApis, methodName, { - enumerable: true, - configurable: true, - get: function() { - return moduleGetter(id, moduleName, methodName); - }, - set: function(fn) { - return moduleSetter(id, moduleName, methodName, fn); - } - }); - }; - - for (var methodName in moduleDefine) loop( methodName ); - - // create module Proxy - if (typeof Proxy === 'function') { - moduleProxies[proxyName] = new Proxy(moduleApis, { - get: function get(target, methodName) { - if (methodName in target) { - return target[methodName]; - } - console.warn('[JS Framework] using unregistered method "' + moduleName + '.' + methodName + '"'); - return moduleGetter(id, moduleName, methodName); - } - }); - } else { - moduleProxies[proxyName] = moduleApis; - } - } - - return moduleProxies[proxyName]; - }; - - WeexInstance.prototype.supports = function supports(condition) { - if (typeof condition !== 'string') { - return null; - } - - var res = condition.match(/^@(\w+)\/(\w+)(\.(\w+))?$/i); - if (res) { - var type = res[1]; - var name = res[2]; - var method = res[4]; - switch (type) { - case 'module': return isRegisteredModule(name, method); - case 'component': return isRegisteredComponent(name); - } - } - - return null; - }; - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var frameworks; - var runtimeConfig; - - var versionRegExp = /^\s*\/\/ *(\{[^}]*\}) *\r?\n/; - - /** - * Detect a JS Bundle code and make sure which framework it's based to. Each JS - * Bundle should make sure that it starts with a line of JSON comment and is - * more that one line. - * @param {string} code - * @return {object} - */ - function getBundleType(code) { - var result = versionRegExp.exec(code); - if (result) { - try { - var info = JSON.parse(result[1]); - return info.framework; - } catch (e) {} - } - - // default bundle type - return 'Weex'; - } - - function createServices(id, env, config) { - // Init JavaScript services for this instance. - var serviceMap = Object.create(null); - serviceMap.service = Object.create(null); - services.forEach(function(ref) { - var name = ref.name; - var options = ref.options; - - { - console.debug('[JS Runtime] create service ' + name + '.'); - } - var create = options.create; - if (create) { - try { - var result = create(id, env, config); - Object.assign(serviceMap.service, result); - Object.assign(serviceMap, result.instance); - } catch (e) { - console.error('[JS Runtime] Failed to create service ' + name + '.'); - } - } - }); - delete serviceMap.service.instance; - Object.freeze(serviceMap.service); - return serviceMap; - } - - var instanceTypeMap = {}; - function getFrameworkType(id) { - return instanceTypeMap[id]; - } - - function createInstanceContext(id, options, data) { - if ( options === void 0 ) options = {}; - - var weex = new WeexInstance(id, options); - Object.freeze(weex); - - var bundleType = options.bundleType || 'Vue'; - instanceTypeMap[id] = bundleType; - var framework = runtimeConfig.frameworks[bundleType]; - if (!framework) { - return new Error('[JS Framework] Invalid bundle type "' + bundleType + '".'); - } - track(id, 'bundleType', bundleType); - - // prepare js service - var services$$1 = createServices(id, { - weex: weex, - config: options, - created: Date.now(), - framework: bundleType, - bundleType: bundleType - }, runtimeConfig); - Object.freeze(services$$1); - - // prepare runtime context - var runtimeContext = Object.create(null); - Object.assign(runtimeContext, services$$1, { - weex: weex, - services: services$$1 // Temporary compatible with some legacy APIs in Rax - }); - Object.freeze(runtimeContext); - - // prepare instance context - var instanceContext = Object.assign({}, runtimeContext); - if (typeof framework.createInstanceContext === 'function') { - Object.assign(instanceContext, framework.createInstanceContext(id, runtimeContext, data)); - } - Object.freeze(instanceContext); - return instanceContext; - } - - /** - * Check which framework a certain JS Bundle code based to. And create instance - * by this framework. - * @param {string} id - * @param {string} code - * @param {object} config - * @param {object} data - */ - function createInstance(id, code, config, data) { - if (instanceTypeMap[id]) { - return new Error('The instance id "' + id + '" has already been used!'); - } - - // Init instance info. - var bundleType = getBundleType(code); - instanceTypeMap[id] = bundleType; - - // Init instance config. - config.env = JSON.parse(JSON.stringify(global.WXEnvironment || {})); - config.bundleType = bundleType; - - var framework = runtimeConfig.frameworks[bundleType]; - if (!framework) { - return new Error('[JS Framework] Invalid bundle type "' + bundleType + '".'); - } - if (bundleType === 'Weex') { - console.error('[JS Framework] COMPATIBILITY WARNING: ' - + 'Weex DSL 1.0 (.we) framework is no longer supported! ' - + 'It will be removed in the next version of WeexSDK, ' - + 'your page would be crash if you still using the ".we" framework. ' - + 'Please upgrade it to Vue.js or Rax.'); - } - - - let modules = {}; - var instanceContext = Object.assign({ - define: require('./define.weex')(modules), - require: require('./require.weex')(modules), - document: { // for mock - open: () => {} - } - }, createInstanceContext(id, config, data)); - modules.rax = { - factory: ModuleFactories.rax.bind(instanceContext), - module: {exports: {}}, - isInitialized: false, - }; - - // if (typeof framework.createInstance === 'function') { - // // Temporary compatible with some legacy APIs in Rax, - // // some Rax page is using the legacy ".we" framework. - // if (bundleType === 'Rax' || bundleType === 'Weex') { - // var raxInstanceContext = Object.assign({ - // config: config, - // created: Date.now(), - // framework: bundleType - // }, instanceContext); - // return framework.createInstance(id, code, config, data, raxInstanceContext) - // } - // return framework.createInstance(id, code, config, data, instanceContext) - // } - // console.error(`[JS Framework] Can't find available "createInstance" method in ${bundleType}!`) - - return runInContext(code, instanceContext); - } - - /** - * Run js code in a specific context. - * @param {string} code - * @param {object} context - */ - function runInContext(code, context) { - var keys = []; - var args = []; - - for (var key in context) { - keys.push(key); - args.push(context[key]); - } - - var bundle = '\n (function (global) {\n ' + code + '\n })(Object.create(self))\n '; - return (new (Function.prototype.bind.apply( Function, [ null ].concat( keys, [bundle]) ))).apply(void 0, args); - } - - /** - * Get the JSON object of the root element. - * @param {string} instanceId - */ - function getRoot(instanceId) { - var document = getDoc(instanceId); - try { - if (document && document.body) { - return document.body.toJSON(); - } - } catch (e) { - console.error('[JS Framework] Failed to get the virtual dom tree.'); - return; - } - } - - var methods = { - createInstance: createInstance, - createInstanceContext: createInstanceContext, - getRoot: getRoot, - getDocument: getDoc, - registerService: register, - unregisterService: unregister, - callJS: function callJS(id, tasks) { - var framework = frameworks[getFrameworkType(id)]; - if (framework && typeof framework.receiveTasks === 'function') { - return framework.receiveTasks(id, tasks); - } - return receiveTasks(id, tasks); - } - }; - - /** - * Register methods which will be called for each instance. - * @param {string} methodName - */ - function genInstance(methodName) { - methods[methodName] = function() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - var id = args[0]; - var type = getFrameworkType(id); - if (type && frameworks[type]) { - var result = (ref = frameworks[type])[methodName].apply(ref, args); - var info = { framework: type }; - - // Lifecycle methods - if (methodName === 'refreshInstance') { - services.forEach(function(service) { - var refresh = service.options.refresh; - if (refresh) { - refresh(id, { info: info, runtime: runtimeConfig }); - } - }); - } else if (methodName === 'destroyInstance') { - services.forEach(function(service) { - var destroy = service.options.destroy; - if (destroy) { - destroy(id, { info: info, runtime: runtimeConfig }); - } - }); - delete instanceTypeMap[id]; - } - - return result; - } - return new Error('[JS Framework] Using invalid instance id ' - + '"' + id + '" when calling ' + methodName + '.'); - var ref; - }; - } - - /** - * Register methods which init each frameworks. - * @param {string} methodName - * @param {function} sharedMethod - */ - function adaptMethod(methodName, sharedMethod) { - methods[methodName] = function() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - if (typeof sharedMethod === 'function') { - sharedMethod.apply(void 0, args); - } - - // TODO: deprecated - for (var name in runtimeConfig.frameworks) { - var framework = runtimeConfig.frameworks[name]; - if (framework && framework[methodName]) { - framework[methodName].apply(framework, args); - } - } - }; - } - - function init$$1(config) { - runtimeConfig = config || {}; - frameworks = runtimeConfig.frameworks || {}; - init$1(); - - // Init each framework by `init` method and `config` which contains three - // virtual-DOM Class: `Document`, `Element` & `Comment`, and a JS bridge method: - // `sendTasks(...args)`. - for (var name in frameworks) { - var framework = frameworks[name]; - if (typeof framework.init === 'function') { - try { - framework.init(config); - } catch (e) {} - } - } - - adaptMethod('registerComponents', registerComponents); - adaptMethod('registerModules', registerModules); - adaptMethod('registerMethods') - - ; ['destroyInstance', 'refreshInstance'].forEach(genInstance); - - return methods; - } - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var config = { - Document: Document, Element: Element, Comment: Comment, Listener: Listener, - TaskCenter: TaskCenter, - sendTasks: function sendTasks() { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - if (typeof callNative === 'function') { - return callNative.apply(void 0, args); - } - return (global.callNative || function() {}).apply(void 0, args); - } - }; - - Document.handler = config.sendTasks; - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /* istanbul ignore next */ - function freezePrototype() { - // Object.freeze(config.Element) - Object.freeze(config.Comment); - Object.freeze(config.Listener); - Object.freeze(config.Document.prototype); - // Object.freeze(config.Element.prototype) - Object.freeze(config.Comment.prototype); - Object.freeze(config.Listener.prototype); - } - - var index = { - service: { register: register, unregister: unregister, has: has }, - freezePrototype: freezePrototype, - init: init$$1, - config: config - }; - - return index; -})); -// # sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzIjpbIi4uLy4uL3J1bnRpbWUvc2hhcmVkL3V0aWxzLmpzIiwiLi4vLi4vcnVudGltZS9icmlkZ2Uvbm9ybWFsaXplLmpzIiwiLi4vLi4vcnVudGltZS9icmlkZ2UvQ2FsbGJhY2tNYW5hZ2VyLmpzIiwiLi4vLi4vcnVudGltZS92ZG9tL29wZXJhdGlvbi5qcyIsIi4uLy4uL3J1bnRpbWUvdmRvbS9Ob2RlLmpzIiwiLi4vLi4vcnVudGltZS92ZG9tL1dlZXhFbGVtZW50LmpzIiwiLi4vLi4vcnVudGltZS92ZG9tL0VsZW1lbnQuanMiLCIuLi8uLi9ydW50aW1lL2JyaWRnZS9UYXNrQ2VudGVyLmpzIiwiLi4vLi4vcnVudGltZS9icmlkZ2UvcmVjZWl2ZXIuanMiLCIuLi8uLi9ydW50aW1lL2FwaS9tb2R1bGUuanMiLCIuLi8uLi9ydW50aW1lL2FwaS9jb21wb25lbnQuanMiLCIuLi8uLi9ydW50aW1lL2FwaS9zZXJ2aWNlLmpzIiwiLi4vLi4vcnVudGltZS9icmlkZ2UvZGVidWcuanMiLCIuLi8uLi9ydW50aW1lL3Zkb20vQ29tbWVudC5qcyIsIi4uLy4uL3J1bnRpbWUvYnJpZGdlL0xpc3RlbmVyLmpzIiwiLi4vLi4vcnVudGltZS9icmlkZ2UvSGFuZGxlci5qcyIsIi4uLy4uL3J1bnRpbWUvdmRvbS9Eb2N1bWVudC5qcyIsIi4uLy4uL3J1bnRpbWUvYXBpL1dlZXhJbnN0YW5jZS5qcyIsIi4uLy4uL3J1bnRpbWUvYXBpL2luaXQuanMiLCIuLi8uLi9ydW50aW1lL3Zkb20vaW5kZXguanMiLCIuLi8uLi9ydW50aW1lL2FwaS9jb25maWcuanMiLCIuLi8uLi9ydW50aW1lL2FwaS9pbmRleC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZVxuICogb3IgbW9yZSBjb250cmlidXRvciBsaWNlbnNlIGFncmVlbWVudHMuICBTZWUgdGhlIE5PVElDRSBmaWxlXG4gKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvblxuICogcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZVxuICogdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZVxuICogXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsXG4gKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhblxuICogXCJBUyBJU1wiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcbiAqIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZVxuICogc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9uc1xuICogdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBHZXQgYSB1bmlxdWUgaWQuXG4gKi9cbmxldCBuZXh0Tm9kZVJlZiA9IDFcbmV4cG9ydCBmdW5jdGlvbiB1bmlxdWVJZCAoKSB7XG4gIHJldHVybiAobmV4dE5vZGVSZWYrKykudG9TdHJpbmcoKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdHlwb2YgKHYpIHtcbiAgY29uc3QgcyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2KVxuICByZXR1cm4gcy5zdWJzdHJpbmcoOCwgcy5sZW5ndGggLSAxKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVmZmVyVG9CYXNlNjQgKGJ1ZmZlcikge1xuICBpZiAodHlwZW9mIGJ0b2EgIT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gJydcbiAgfVxuICBjb25zdCBzdHJpbmcgPSBBcnJheS5wcm90b3R5cGUubWFwLmNhbGwoXG4gICAgbmV3IFVpbnQ4QXJyYXkoYnVmZmVyKSxcbiAgICBjb2RlID0+IFN0cmluZy5mcm9tQ2hhckNvZGUoY29kZSlcbiAgKS5qb2luKCcnKVxuICByZXR1cm4gYnRvYShzdHJpbmcpIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJhc2U2NFRvQnVmZmVyIChiYXNlNjQpIHtcbiAgaWYgKHR5cGVvZiBhdG9iICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIG5ldyBBcnJheUJ1ZmZlcigwKVxuICB9XG4gIGNvbnN0IHN0cmluZyA9IGF0b2IoYmFzZTY0KSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG4gIGNvbnN0IGFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoc3RyaW5nLmxlbmd0aClcbiAgQXJyYXkucHJvdG90eXBlLmZvckVhY2guY2FsbChzdHJpbmcsIChjaCwgaSkgPT4ge1xuICAgIGFycmF5W2ldID0gY2guY2hhckNvZGVBdCgwKVxuICB9KVxuICByZXR1cm4gYXJyYXkuYnVmZmVyXG59XG5cbi8qKlxuICogRGV0ZWN0IGlmIHRoZSBwYXJhbSBpcyBmYWxzeSBvciBlbXB0eVxuICogQHBhcmFtIHthbnl9IGFueVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eSAoYW55KSB7XG4gIGlmICghYW55IHx8IHR5cGVvZiBhbnkgIT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIGZvciAoY29uc3Qga2V5IGluIGFueSkge1xuICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYW55LCBrZXkpKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWVcbn1cbiIsIi8qXG4gKiBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lXG4gKiBvciBtb3JlIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGVcbiAqIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uXG4gKiByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlXG4gKiB0byB5b3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlXG4gKiBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqIHdpdGggdGhlIExpY2Vuc2UuICBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZyxcbiAqIHNvZnR3YXJlIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuXG4gKiBcIkFTIElTXCIgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxuICogS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlXG4gKiBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25zXG4gKiB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyB0eXBvZiwgYnVmZmVyVG9CYXNlNjQsIGJhc2U2NFRvQnVmZmVyIH0gZnJvbSAnLi4vc2hhcmVkL3V0aWxzJ1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHByaW1pdGl2ZSB2YWx1ZS5cbiAqIEBwYXJhbSAge2FueX0gICAgICAgIHZcbiAqIEByZXR1cm4ge3ByaW1pdGl2ZX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZVByaW1pdGl2ZSAodikge1xuICBjb25zdCB0eXBlID0gdHlwb2YodilcblxuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlICdVbmRlZmluZWQnOlxuICAgIGNhc2UgJ051bGwnOlxuICAgICAgcmV0dXJuICcnXG5cbiAgICBjYXNlICdSZWdFeHAnOlxuICAgICAgcmV0dXJuIHYudG9TdHJpbmcoKVxuICAgIGNhc2UgJ0RhdGUnOlxuICAgICAgcmV0dXJuIHYudG9JU09TdHJpbmcoKVxuXG4gICAgY2FzZSAnTnVtYmVyJzpcbiAgICBjYXNlICdTdHJpbmcnOlxuICAgIGNhc2UgJ0Jvb2xlYW4nOlxuICAgIGNhc2UgJ0FycmF5JzpcbiAgICBjYXNlICdPYmplY3QnOlxuICAgICAgcmV0dXJuIHZcblxuICAgIGNhc2UgJ0FycmF5QnVmZmVyJzpcbiAgICAgIHJldHVybiB7XG4gICAgICAgICdAdHlwZSc6ICdiaW5hcnknLFxuICAgICAgICBkYXRhVHlwZTogdHlwZSxcbiAgICAgICAgYmFzZTY0OiBidWZmZXJUb0Jhc2U2NCh2KVxuICAgICAgfVxuXG4gICAgY2FzZSAnSW50OEFycmF5JzpcbiAgICBjYXNlICdVaW50OEFycmF5JzpcbiAgICBjYXNlICdVaW50OENsYW1wZWRBcnJheSc6XG4gICAgY2FzZSAnSW50MTZBcnJheSc6XG4gICAgY2FzZSAnVWludDE2QXJyYXknOlxuICAgIGNhc2UgJ0ludDMyQXJyYXknOlxuICAgIGNhc2UgJ1VpbnQzMkFycmF5JzpcbiAgICBjYXNlICdGbG9hdDMyQXJyYXknOlxuICAgIGNhc2UgJ0Zsb2F0NjRBcnJheSc6XG4gICAgICByZXR1cm4ge1xuICAgICAgICAnQHR5cGUnOiAnYmluYXJ5JyxcbiAgICAgICAgZGF0YVR5cGU6IHR5cGUsXG4gICAgICAgIGJhc2U2NDogYnVmZmVyVG9CYXNlNjQodi5idWZmZXIpXG4gICAgICB9XG5cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHYpXG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVByaW1pdGl2ZSAoZGF0YSkge1xuICBpZiAodHlwb2YoZGF0YSkgPT09ICdPYmplY3QnKSB7XG4gICAgLy8gZGVjb2RlIGJhc2U2NCBpbnRvIGJpbmFyeVxuICAgIGlmIChkYXRhWydAdHlwZSddICYmIGRhdGFbJ0B0eXBlJ10gPT09ICdiaW5hcnknKSB7XG4gICAgICByZXR1cm4gYmFzZTY0VG9CdWZmZXIoZGF0YS5iYXNlNjQgfHwgJycpXG4gICAgfVxuXG4gICAgY29uc3QgcmVhbERhdGEgPSB7fVxuICAgIGZvciAoY29uc3Qga2V5IGluIGRhdGEpIHtcbiAgICAgIHJlYWxEYXRhW2tleV0gPSBkZWNvZGVQcmltaXRpdmUoZGF0YVtrZXldKVxuICAgIH1cbiAgICByZXR1cm4gcmVhbERhdGFcbiAgfVxuICBpZiAodHlwb2YoZGF0YSkgPT09ICdBcnJheScpIHtcbiAgICByZXR1cm4gZGF0YS5tYXAoZGVjb2RlUHJpbWl0aXZlKVxuICB9XG4gIHJldHVybiBkYXRhXG59XG4iLCIvKlxuICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZVxuICogb3IgbW9yZSBjb250cmlidXRvciBsaWNlbnNlIGFncmVlbWVudHMuICBTZWUgdGhlIE5PVElDRSBmaWxlXG4gKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvblxuICogcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZVxuICogdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZVxuICogXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsXG4gKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhblxuICogXCJBUyBJU1wiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcbiAqIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZVxuICogc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9uc1xuICogdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgZGVjb2RlUHJpbWl0aXZlIH0gZnJvbSAnLi9ub3JtYWxpemUnXG5cbmZ1bmN0aW9uIGdldEhvb2tLZXkgKGNvbXBvbmVudElkLCB0eXBlLCBob29rTmFtZSkge1xuICByZXR1cm4gYCR7dHlwZX1AJHtob29rTmFtZX0jJHtjb21wb25lbnRJZH1gXG59XG5cbi8qKlxuICogRm9yIGdlbmVyYWwgY2FsbGJhY2sgbWFuYWdlbWVudCBvZiBhIGNlcnRhaW4gV2VleCBpbnN0YW5jZS5cbiAqIEJlY2F1c2UgZnVuY3Rpb24gY2FuIG5vdCBwYXNzZWQgaW50byBuYXRpdmUsIHNvIHdlIGNyZWF0ZSBjYWxsYmFja1xuICogY2FsbGJhY2sgaWQgZm9yIGVhY2ggZnVuY3Rpb24gYW5kIHBhc3MgdGhlIGNhbGxiYWNrIGlkIGludG8gbmF0aXZlXG4gKiBpbiBmYWN0LiBBbmQgd2hlbiBhIGNhbGxiYWNrIGNhbGxlZCBmcm9tIG5hdGl2ZSwgd2UgY2FuIGZpbmQgdGhlIHJlYWxcbiAqIGNhbGxiYWNrIHRocm91Z2ggdGhlIGNhbGxiYWNrIGlkIHdlIGhhdmUgcGFzc2VkIGJlZm9yZS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ2FsbGJhY2tNYW5hZ2VyIHtcbiAgY29uc3RydWN0b3IgKGluc3RhbmNlSWQpIHtcbiAgICB0aGlzLmluc3RhbmNlSWQgPSBTdHJpbmcoaW5zdGFuY2VJZClcbiAgICB0aGlzLmxhc3RDYWxsYmFja0lkID0gMFxuICAgIHRoaXMuY2FsbGJhY2tzID0ge31cbiAgICB0aGlzLmhvb2tzID0ge31cbiAgfVxuICBhZGQgKGNhbGxiYWNrKSB7XG4gICAgdGhpcy5sYXN0Q2FsbGJhY2tJZCsrXG4gICAgdGhpcy5jYWxsYmFja3NbdGhpcy5sYXN0Q2FsbGJhY2tJZF0gPSBjYWxsYmFja1xuICAgIHJldHVybiB0aGlzLmxhc3RDYWxsYmFja0lkXG4gIH1cbiAgcmVtb3ZlIChjYWxsYmFja0lkKSB7XG4gICAgY29uc3QgY2FsbGJhY2sgPSB0aGlzLmNhbGxiYWNrc1tjYWxsYmFja0lkXVxuICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tjYWxsYmFja0lkXVxuICAgIHJldHVybiBjYWxsYmFja1xuICB9XG4gIHJlZ2lzdGVySG9vayAoY29tcG9uZW50SWQsIHR5cGUsIGhvb2tOYW1lLCBob29rRnVuY3Rpb24pIHtcbiAgICAvLyBUT0RPOiB2YWxpZGF0ZSBhcmd1bWVudHNcbiAgICBjb25zdCBrZXkgPSBnZXRIb29rS2V5KGNvbXBvbmVudElkLCB0eXBlLCBob29rTmFtZSlcbiAgICBpZiAodGhpcy5ob29rc1trZXldKSB7XG4gICAgICBjb25zb2xlLndhcm4oYFtKUyBGcmFtZXdvcmtdIE92ZXJyaWRlIGFuIGV4aXN0aW5nIGNvbXBvbmVudCBob29rIFwiJHtrZXl9XCIuYClcbiAgICB9XG4gICAgdGhpcy5ob29rc1trZXldID0gaG9va0Z1bmN0aW9uXG4gIH1cbiAgdHJpZ2dlckhvb2sgKGNvbXBvbmVudElkLCB0eXBlLCBob29rTmFtZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgLy8gVE9ETzogdmFsaWRhdGUgYXJndW1lbnRzXG4gICAgY29uc3Qga2V5ID0gZ2V0SG9va0tleShjb21wb25lbnRJZCwgdHlwZSwgaG9va05hbWUpXG4gICAgY29uc3QgaG9va0Z1bmN0aW9uID0gdGhpcy5ob29rc1trZXldXG4gICAgaWYgKHR5cGVvZiBob29rRnVuY3Rpb24gIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoYFtKUyBGcmFtZXdvcmtdIEludmFsaWQgaG9vayBmdW5jdGlvbiB0eXBlICgke3R5cGVvZiBob29rRnVuY3Rpb259KSBvbiBcIiR7a2V5fVwiLmApXG4gICAgICByZXR1cm4gbnVsbFxuICAgIH1cbiAgICBsZXQgcmVzdWx0ID0gbnVsbFxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBob29rRnVuY3Rpb24uYXBwbHkobnVsbCwgb3B0aW9ucy5hcmdzIHx8IFtdKVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS5lcnJvcihgW0pTIEZyYW1ld29ya10gRmFpbGVkIHRvIGV4ZWN1dGUgdGhlIGhvb2sgZnVuY3Rpb24gb24gXCIke2tleX1cIi5gKVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cbiAgY29uc3VtZSAoY2FsbGJhY2tJZCwgZGF0YSwgaWZLZWVwQWxpdmUpIHtcbiAgICBjb25zdCBjYWxsYmFjayA9IHRoaXMuY2FsbGJhY2tzW2NhbGxiYWNrSWRdXG4gICAgaWYgKHR5cGVvZiBpZktlZXBBbGl2ZSA9PT0gJ3VuZGVmaW5lZCcgfHwgaWZLZWVwQWxpdmUgPT09IGZhbHNlKSB7XG4gICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbY2FsbGJhY2tJZF1cbiAgICB9XG4gICAgaWYgKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKGRlY29kZVByaW1pdGl2ZShkYXRhKSlcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBFcnJvcihgaW52YWxpZCBjYWxsYmFjayBpZCBcIiR7Y2FsbGJhY2tJZH1cImApXG4gIH1cbiAgY2xvc2UgKCkge1xuICAgIHRoaXMuY2FsbGJhY2tzID0ge31cbiAgICB0aGlzLmhvb2tzID0ge31cbiAgfVxufVxuIiwiLypcbiAqIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiAoQVNGKSB1bmRlciBvbmVcbiAqIG9yIG1vcmUgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZVxuICogZGlzdHJpYnV0ZWQgd2l0aCB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb25cbiAqIHJlZ2FyZGluZyBjb3B5cmlnaHQgb3duZXJzaGlwLiAgVGhlIEFTRiBsaWNlbnNlcyB0aGlzIGZpbGVcbiAqIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGVcbiAqIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogd2l0aCB0aGUgTGljZW5zZS4gIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLFxuICogc29mdHdhcmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW5cbiAqIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXG4gKiBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLiAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGVcbiAqIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnNcbiAqIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmNvbnN0IGRvY01hcCA9IHt9XG5cbi8qKlxuICogQWRkIGEgZG9jdW1lbnQgb2JqZWN0IGludG8gZG9jTWFwLlxuICogQHBhcmFtIHtzdHJpbmd9IGlkXG4gKiBAcGFyYW0ge29iamVjdH0gZG9jdW1lbnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZERvYyAoaWQsIGRvYykge1xuICBpZiAoaWQpIHtcbiAgICBkb2NNYXBbaWRdID0gZG9jXG4gIH1cbn1cblxuLyoqXG4gKiBHZXQgdGhlIGRvY3VtZW50IG9iamVjdCBieSBpZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpZFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RG9jIChpZCkge1xuICByZXR1cm4gZG9jTWFwW2lkXVxufVxuXG4vKipcbiAqIFJlbW92ZSB0aGUgZG9jdW1lbnQgZnJvbSBkb2NNYXAgYnkgaWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gaWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZURvYyAoaWQpIHtcbiAgZGVsZXRlIGRvY01hcFtpZF1cbn1cblxuLyoqXG4gKiBAZGVwcmVjYXRlZFxuICogR2V0IGxpc3RlbmVyIGJ5IGRvY3VtZW50IGlkLlxuICogQHBhcmFtIHtzdHJpbmd9IGlkXG4gKiBAcmV0dXJuIHtvYmplY3R9IGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRMaXN0ZW5lciAoaWQpIHtcbiAgY29uc3QgZG9jID0gZG9jTWFwW2lkXVxuICBpZiAoZG9jICYmIGRvYy5saXN0ZW5lcikge1xuICAgIHJldHVybiBkb2MubGlzdGVuZXJcbiAgfVxuICByZXR1cm4gbnVsbFxufVxuXG4vKipcbiAqIEdldCBUYXNrQ2VudGVyIGluc3RhbmNlIGJ5IGlkLlxuICogQHBhcmFtIHtzdHJpbmd9IGlkXG4gKiBAcmV0dXJuIHtvYmplY3R9IFRhc2tDZW50ZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFRhc2tDZW50ZXIgKGlkKSB7XG4gIGNvbnN0IGRvYyA9IGRvY01hcFtpZF1cbiAgaWYgKGRvYyAmJiBkb2MudGFza0NlbnRlcikge1xuICAgIHJldHVybiBkb2MudGFza0NlbnRlclxuICB9XG4gIHJldHVybiBudWxsXG59XG5cbi8qKlxuICogQXBwZW5kIGJvZHkgbm9kZSB0byBkb2N1bWVudEVsZW1lbnQuXG4gKiBAcGFyYW0ge29iamVjdH0gZG9jdW1lbnRcbiAqIEBwYXJhbSB7b2JqZWN0fSBub2RlXG4gKiBAcGFyYW0ge29iamVjdH0gYmVmb3JlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBlbmRCb2R5IChkb2MsIG5vZGUsIGJlZm9yZSkge1xuICBjb25zdCB7IGRvY3VtZW50RWxlbWVudCB9ID0gZG9jXG5cbiAgaWYgKGRvY3VtZW50RWxlbWVudC5wdXJlQ2hpbGRyZW4ubGVuZ3RoID4gMCB8fCBub2RlLnBhcmVudE5vZGUpIHtcbiAgICByZXR1cm5cbiAgfVxuICBjb25zdCBjaGlsZHJlbiA9IGRvY3VtZW50RWxlbWVudC5jaGlsZHJlblxuICBjb25zdCBiZWZvcmVJbmRleCA9IGNoaWxkcmVuLmluZGV4T2YoYmVmb3JlKVxuICBpZiAoYmVmb3JlSW5kZXggPCAwKSB7XG4gICAgY2hpbGRyZW4ucHVzaChub2RlKVxuICB9XG4gIGVsc2Uge1xuICAgIGNoaWxkcmVuLnNwbGljZShiZWZvcmVJbmRleCwgMCwgbm9kZSlcbiAgfVxuXG4gIGlmIChub2RlLm5vZGVUeXBlID09PSAxKSB7XG4gICAgaWYgKG5vZGUucm9sZSA9PT0gJ2JvZHknKSB7XG4gICAgICBub2RlLmRvY0lkID0gZG9jLmlkXG4gICAgICBub2RlLm93bmVyRG9jdW1lbnQgPSBkb2NcbiAgICAgIG5vZGUucGFyZW50Tm9kZSA9IGRvY3VtZW50RWxlbWVudFxuICAgICAgbGlua1BhcmVudChub2RlLCBkb2N1bWVudEVsZW1lbnQpXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgbm9kZS5jaGlsZHJlbi5mb3JFYWNoKGNoaWxkID0+IHtcbiAgICAgICAgY2hpbGQucGFyZW50Tm9kZSA9IG5vZGVcbiAgICAgIH0pXG4gICAgICBzZXRCb2R5KGRvYywgbm9kZSlcbiAgICAgIG5vZGUuZG9jSWQgPSBkb2MuaWRcbiAgICAgIG5vZGUub3duZXJEb2N1bWVudCA9IGRvY1xuICAgICAgbGlua1BhcmVudChub2RlLCBkb2N1bWVudEVsZW1lbnQpXG4gICAgICBkZWxldGUgZG9jLm5vZGVNYXBbbm9kZS5ub2RlSWRdXG4gICAgfVxuICAgIGRvY3VtZW50RWxlbWVudC5wdXJlQ2hpbGRyZW4ucHVzaChub2RlKVxuICAgIHNlbmRCb2R5KGRvYywgbm9kZSlcbiAgfVxuICBlbHNlIHtcbiAgICBub2RlLnBhcmVudE5vZGUgPSBkb2N1bWVudEVsZW1lbnRcbiAgICBkb2Mubm9kZU1hcFtub2RlLnJlZl0gPSBub2RlXG4gIH1cbn1cblxuZnVuY3Rpb24gc2VuZEJvZHkgKGRvYywgbm9kZSkge1xuICBjb25zdCBib2R5ID0gbm9kZS50b0pTT04oKVxuICBpZiAoZG9jICYmIGRvYy50YXNrQ2VudGVyICYmIHR5cGVvZiBkb2MudGFza0NlbnRlci5zZW5kID09PSAnZnVuY3Rpb24nKSB7XG4gICAgZG9jLnRhc2tDZW50ZXIuc2VuZCgnZG9tJywgeyBhY3Rpb246ICdjcmVhdGVCb2R5JyB9LCBbYm9keV0pXG4gIH1cbn1cblxuLyoqXG4gKiBTZXQgdXAgYm9keSBub2RlLlxuICogQHBhcmFtIHtvYmplY3R9IGRvY3VtZW50XG4gKiBAcGFyYW0ge29iamVjdH0gZWxlbWVudFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0Qm9keSAoZG9jLCBlbCkge1xuICBlbC5yb2xlID0gJ2JvZHknXG4gIGVsLmRlcHRoID0gMVxuICBkZWxldGUgZG9jLm5vZGVNYXBbZWwubm9kZUlkXVxuICBlbC5yZWYgPSAnX3Jvb3QnXG4gIGRvYy5ub2RlTWFwLl9yb290ID0gZWxcbiAgZG9jLmJvZHkgPSBlbFxufVxuXG4vKipcbiAqIEVzdGFibGlzaCB0aGUgY29ubmVjdGlvbiBiZXR3ZWVuIHBhcmVudCBhbmQgY2hpbGQgbm9kZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSBjaGlsZCBub2RlXG4gKiBAcGFyYW0ge29iamVjdH0gcGFyZW50IG5vZGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpbmtQYXJlbnQgKG5vZGUsIHBhcmVudCkge1xuICBub2RlLnBhcmVudE5vZGUgPSBwYXJlbnRcbiAgaWYgKHBhcmVudC5kb2NJZCkge1xuICAgIG5vZGUuZG9jSWQgPSBwYXJlbnQuZG9jSWRcbiAgICBub2RlLm93bmVyRG9jdW1lbnQgPSBwYXJlbnQub3duZXJEb2N1bWVudFxuICAgIG5vZGUub3duZXJEb2N1bWVudC5ub2RlTWFwW25vZGUubm9kZUlkXSA9IG5vZGVcbiAgICBub2RlLmRlcHRoID0gcGFyZW50LmRlcHRoICsgMVxuICB9XG4gIG5vZGUuY2hpbGRyZW4uZm9yRWFjaChjaGlsZCA9PiB7XG4gICAgbGlua1BhcmVudChjaGlsZCwgbm9kZSlcbiAgfSlcbn1cblxuLyoqXG4gKiBHZXQgdGhlIG5leHQgc2libGluZyBlbGVtZW50LlxuICogQHBhcmFtIHtvYmplY3R9IG5vZGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5leHRFbGVtZW50IChub2RlKSB7XG4gIHdoaWxlIChub2RlKSB7XG4gICAgaWYgKG5vZGUubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgIHJldHVybiBub2RlXG4gICAgfVxuICAgIG5vZGUgPSBub2RlLm5leHRTaWJsaW5nXG4gIH1cbn1cblxuLyoqXG4gKiBHZXQgdGhlIHByZXZpb3VzIHNpYmxpbmcgZWxlbWVudC5cbiAqIEBwYXJhbSB7b2JqZWN0fSBub2RlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmV2aW91c0VsZW1lbnQgKG5vZGUpIHtcbiAgd2hpbGUgKG5vZGUpIHtcbiAgICBpZiAobm9kZS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgcmV0dXJuIG5vZGVcbiAgICB9XG4gICAgbm9kZSA9IG5vZGUucHJldmlvdXNTaWJsaW5nXG4gIH1cbn1cblxuLyoqXG4gKiBJbnNlcnQgYSBub2RlIGludG8gbGlzdCBhdCB0aGUgc3BlY2lmaWVkIGluZGV4LlxuICogQHBhcmFtIHtvYmplY3R9IHRhcmdldCBub2RlXG4gKiBAcGFyYW0ge2FycmF5fSBsaXN0XG4gKiBAcGFyYW0ge251bWJlcn0gbmV3SW5kZXhcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gY2hhbmdlU2libGluZ1xuICogQHJldHVybiB7bnVtYmVyfSBuZXdJbmRleFxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5zZXJ0SW5kZXggKHRhcmdldCwgbGlzdCwgbmV3SW5kZXgsIGNoYW5nZVNpYmxpbmcpIHtcbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgaWYgKG5ld0luZGV4IDwgMCkge1xuICAgIG5ld0luZGV4ID0gMFxuICB9XG4gIGNvbnN0IGJlZm9yZSA9IGxpc3RbbmV3SW5kZXggLSAxXVxuICBjb25zdCBhZnRlciA9IGxpc3RbbmV3SW5kZXhdXG4gIGxpc3Quc3BsaWNlKG5ld0luZGV4LCAwLCB0YXJnZXQpXG4gIGlmIChjaGFuZ2VTaWJsaW5nKSB7XG4gICAgYmVmb3JlICYmIChiZWZvcmUubmV4dFNpYmxpbmcgPSB0YXJnZXQpXG4gICAgdGFyZ2V0LnByZXZpb3VzU2libGluZyA9IGJlZm9yZVxuICAgIHRhcmdldC5uZXh0U2libGluZyA9IGFmdGVyXG4gICAgYWZ0ZXIgJiYgKGFmdGVyLnByZXZpb3VzU2libGluZyA9IHRhcmdldClcbiAgfVxuICByZXR1cm4gbmV3SW5kZXhcbn1cblxuLyoqXG4gKiBNb3ZlIHRoZSBub2RlIHRvIGEgbmV3IGluZGV4IGluIGxpc3QuXG4gKiBAcGFyYW0ge29iamVjdH0gdGFyZ2V0IG5vZGVcbiAqIEBwYXJhbSB7YXJyYXl9IGxpc3RcbiAqIEBwYXJhbSB7bnVtYmVyfSBuZXdJbmRleFxuICogQHBhcmFtIHtib29sZWFufSBjaGFuZ2VTaWJsaW5nXG4gKiBAcmV0dXJuIHtudW1iZXJ9IG5ld0luZGV4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtb3ZlSW5kZXggKHRhcmdldCwgbGlzdCwgbmV3SW5kZXgsIGNoYW5nZVNpYmxpbmcpIHtcbiAgY29uc3QgaW5kZXggPSBsaXN0LmluZGV4T2YodGFyZ2V0KVxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBpZiAoaW5kZXggPCAwKSB7XG4gICAgcmV0dXJuIC0xXG4gIH1cbiAgaWYgKGNoYW5nZVNpYmxpbmcpIHtcbiAgICBjb25zdCBiZWZvcmUgPSBsaXN0W2luZGV4IC0gMV1cbiAgICBjb25zdCBhZnRlciA9IGxpc3RbaW5kZXggKyAxXVxuICAgIGJlZm9yZSAmJiAoYmVmb3JlLm5leHRTaWJsaW5nID0gYWZ0ZXIpXG4gICAgYWZ0ZXIgJiYgKGFmdGVyLnByZXZpb3VzU2libGluZyA9IGJlZm9yZSlcbiAgfVxuICBsaXN0LnNwbGljZShpbmRleCwgMSlcbiAgbGV0IG5ld0luZGV4QWZ0ZXIgPSBuZXdJbmRleFxuICBpZiAoaW5kZXggPD0gbmV3SW5kZXgpIHtcbiAgICBuZXdJbmRleEFmdGVyID0gbmV3SW5kZXggLSAxXG4gIH1cbiAgY29uc3QgYmVmb3JlTmV3ID0gbGlzdFtuZXdJbmRleEFmdGVyIC0gMV1cbiAgY29uc3QgYWZ0ZXJOZXcgPSBsaXN0W25ld0luZGV4QWZ0ZXJdXG4gIGxpc3Quc3BsaWNlKG5ld0luZGV4QWZ0ZXIsIDAsIHRhcmdldClcbiAgaWYgKGNoYW5nZVNpYmxpbmcpIHtcbiAgICBiZWZvcmVOZXcgJiYgKGJlZm9yZU5ldy5uZXh0U2libGluZyA9IHRhcmdldClcbiAgICB0YXJnZXQucHJldmlvdXNTaWJsaW5nID0gYmVmb3JlTmV3XG4gICAgdGFyZ2V0Lm5leHRTaWJsaW5nID0gYWZ0ZXJOZXdcbiAgICBhZnRlck5ldyAmJiAoYWZ0ZXJOZXcucHJldmlvdXNTaWJsaW5nID0gdGFyZ2V0KVxuICB9XG4gIGlmIChpbmRleCA9PT0gbmV3SW5kZXhBZnRlcikge1xuICAgIHJldHVybiAtMVxuICB9XG4gIHJldHVybiBuZXdJbmRleFxufVxuXG4vKipcbiAqIFJlbW92ZSB0aGUgbm9kZSBmcm9tIGxpc3QuXG4gKiBAcGFyYW0ge29iamVjdH0gdGFyZ2V0IG5vZGVcbiAqIEBwYXJhbSB7YXJyYXl9IGxpc3RcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gY2hhbmdlU2libGluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlSW5kZXggKHRhcmdldCwgbGlzdCwgY2hhbmdlU2libGluZykge1xuICBjb25zdCBpbmRleCA9IGxpc3QuaW5kZXhPZih0YXJnZXQpXG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gIGlmIChpbmRleCA8IDApIHtcbiAgICByZXR1cm5cbiAgfVxuICBpZiAoY2hhbmdlU2libGluZykge1xuICAgIGNvbnN0IGJlZm9yZSA9IGxpc3RbaW5kZXggLSAxXVxuICAgIGNvbnN0IGFmdGVyID0gbGlzdFtpbmRleCArIDFdXG4gICAgYmVmb3JlICYmIChiZWZvcmUubmV4dFNpYmxpbmcgPSBhZnRlcilcbiAgICBhZnRlciAmJiAoYWZ0ZXIucHJldmlvdXNTaWJsaW5nID0gYmVmb3JlKVxuICB9XG4gIGxpc3Quc3BsaWNlKGluZGV4LCAxKVxufVxuIiwiLypcbiAqIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiAoQVNGKSB1bmRlciBvbmVcbiAqIG9yIG1vcmUgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZVxuICogZGlzdHJpYnV0ZWQgd2l0aCB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb25cbiAqIHJlZ2FyZGluZyBjb3B5cmlnaHQgb3duZXJzaGlwLiAgVGhlIEFTRiBsaWNlbnNlcyB0aGlzIGZpbGVcbiAqIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGVcbiAqIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogd2l0aCB0aGUgTGljZW5zZS4gIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLFxuICogc29mdHdhcmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW5cbiAqIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXG4gKiBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLiAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGVcbiAqIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnNcbiAqIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IHVuaXF1ZUlkIH0gZnJvbSAnLi4vc2hhcmVkL3V0aWxzJ1xuaW1wb3J0IHsgZ2V0RG9jIH0gZnJvbSAnLi9vcGVyYXRpb24nXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE5vZGUge1xuICBjb25zdHJ1Y3RvciAoKSB7XG4gICAgdGhpcy5ub2RlSWQgPSB1bmlxdWVJZCgpXG4gICAgdGhpcy5yZWYgPSB0aGlzLm5vZGVJZFxuICAgIHRoaXMuY2hpbGRyZW4gPSBbXVxuICAgIHRoaXMucHVyZUNoaWxkcmVuID0gW11cbiAgICB0aGlzLnBhcmVudE5vZGUgPSBudWxsXG4gICAgdGhpcy5uZXh0U2libGluZyA9IG51bGxcbiAgICB0aGlzLnByZXZpb3VzU2libGluZyA9IG51bGxcbiAgfVxuXG4gIC8qKlxuICAqIERlc3Ryb3kgY3VycmVudCBub2RlLCBhbmQgcmVtb3ZlIGl0c2VsZiBmb3JtIG5vZGVNYXAuXG4gICovXG4gIGRlc3Ryb3kgKCkge1xuICAgIGNvbnN0IGRvYyA9IGdldERvYyh0aGlzLmRvY0lkKVxuICAgIGlmIChkb2MpIHtcbiAgICAgIGRlbGV0ZSB0aGlzLmRvY0lkXG4gICAgICBkZWxldGUgZG9jLm5vZGVNYXBbdGhpcy5ub2RlSWRdXG4gICAgfVxuICAgIHRoaXMuY2hpbGRyZW4uZm9yRWFjaChjaGlsZCA9PiB7XG4gICAgICBjaGlsZC5kZXN0cm95KClcbiAgICB9KVxuICB9XG59XG4iLCIvKlxuICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZVxuICogb3IgbW9yZSBjb250cmlidXRvciBsaWNlbnNlIGFncmVlbWVudHMuICBTZWUgdGhlIE5PVElDRSBmaWxlXG4gKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvblxuICogcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZVxuICogdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZVxuICogXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsXG4gKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhblxuICogXCJBUyBJU1wiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcbiAqIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZVxuICogc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9uc1xuICogdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbmltcG9ydCB7IGdldFRhc2tDZW50ZXIgfSBmcm9tICcuL29wZXJhdGlvbidcblxubGV0IEVsZW1lbnRcblxuZXhwb3J0IGZ1bmN0aW9uIHNldEVsZW1lbnQgKEVsKSB7XG4gIEVsZW1lbnQgPSBFbFxufVxuXG4vKipcbiAqIEEgbWFwIHdoaWNoIHN0b3JlcyBhbGwgdHlwZSBvZiBlbGVtZW50cy5cbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbmNvbnN0IHJlZ2lzdGVyZWRFbGVtZW50cyA9IHt9XG5cbi8qKlxuICogUmVnaXN0ZXIgYW4gZXh0ZW5kZWQgZWxlbWVudCB0eXBlIHdpdGggY29tcG9uZW50IG1ldGhvZHMuXG4gKiBAcGFyYW0gIHtzdHJpbmd9IHR5cGUgICAgY29tcG9uZW50IHR5cGVcbiAqIEBwYXJhbSAge2FycmF5fSAgbWV0aG9kcyBhIGxpc3Qgb2YgbWV0aG9kIG5hbWVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckVsZW1lbnQgKHR5cGUsIG1ldGhvZHMpIHtcbiAgLy8gU2tpcCB3aGVuIG5vIHNwZWNpYWwgY29tcG9uZW50IG1ldGhvZHMuXG4gIGlmICghbWV0aG9kcyB8fCAhbWV0aG9kcy5sZW5ndGgpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vIEluaXQgY29uc3RydWN0b3IuXG4gIGNsYXNzIFdlZXhFbGVtZW50IGV4dGVuZHMgRWxlbWVudCB7fVxuXG4gIC8vIEFkZCBtZXRob2RzIHRvIHByb3RvdHlwZS5cbiAgbWV0aG9kcy5mb3JFYWNoKG1ldGhvZE5hbWUgPT4ge1xuICAgIFdlZXhFbGVtZW50LnByb3RvdHlwZVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICBjb25zdCB0YXNrQ2VudGVyID0gZ2V0VGFza0NlbnRlcih0aGlzLmRvY0lkKVxuICAgICAgaWYgKHRhc2tDZW50ZXIpIHtcbiAgICAgICAgcmV0dXJuIHRhc2tDZW50ZXIuc2VuZCgnY29tcG9uZW50Jywge1xuICAgICAgICAgIHJlZjogdGhpcy5yZWYsXG4gICAgICAgICAgY29tcG9uZW50OiB0eXBlLFxuICAgICAgICAgIG1ldGhvZDogbWV0aG9kTmFtZVxuICAgICAgICB9LCBhcmdzKVxuICAgICAgfVxuICAgIH1cbiAgfSlcblxuICAvLyBBZGQgdG8gZWxlbWVudCB0eXBlIG1hcC5cbiAgcmVnaXN0ZXJlZEVsZW1lbnRzW3R5cGVdID0gV2VleEVsZW1lbnRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVucmVnaXN0ZXJFbGVtZW50ICh0eXBlKSB7XG4gIGRlbGV0ZSByZWdpc3RlcmVkRWxlbWVudHNbdHlwZV1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFdlZXhFbGVtZW50ICh0eXBlKSB7XG4gIHJldHVybiByZWdpc3RlcmVkRWxlbWVudHNbdHlwZV1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzV2VleEVsZW1lbnQgKHR5cGUpIHtcbiAgcmV0dXJuICEhcmVnaXN0ZXJlZEVsZW1lbnRzW3R5cGVdXG59XG5cbi8qKlxuICogQ2xlYXIgYWxsIGVsZW1lbnQgdHlwZXMuIE9ubHkgZm9yIHRlc3RpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGVhcldlZXhFbGVtZW50cyAoKSB7XG4gIGZvciAoY29uc3QgdHlwZSBpbiByZWdpc3RlcmVkRWxlbWVudHMpIHtcbiAgICB1bnJlZ2lzdGVyRWxlbWVudCh0eXBlKVxuICB9XG59XG4iLCIvKlxuICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZVxuICogb3IgbW9yZSBjb250cmlidXRvciBsaWNlbnNlIGFncmVlbWVudHMuICBTZWUgdGhlIE5PVElDRSBmaWxlXG4gKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvblxuICogcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZVxuICogdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZVxuICogXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsXG4gKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhblxuICogXCJBUyBJU1wiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcbiAqIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZVxuICogc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9uc1xuICogdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IE5vZGUgZnJvbSAnLi9Ob2RlJ1xuaW1wb3J0IHtcbiAgZ2V0RG9jLFxuICBnZXRUYXNrQ2VudGVyLFxuICBsaW5rUGFyZW50LFxuICBuZXh0RWxlbWVudCxcbiAgcHJldmlvdXNFbGVtZW50LFxuICBpbnNlcnRJbmRleCxcbiAgbW92ZUluZGV4LFxuICByZW1vdmVJbmRleFxufSBmcm9tICcuL29wZXJhdGlvbidcbmltcG9ydCB7IHVuaXF1ZUlkLCBpc0VtcHR5IH0gZnJvbSAnLi4vc2hhcmVkL3V0aWxzJ1xuaW1wb3J0IHsgZ2V0V2VleEVsZW1lbnQsIHNldEVsZW1lbnQgfSBmcm9tICcuL1dlZXhFbGVtZW50J1xuXG5jb25zdCBERUZBVUxUX1RBR19OQU1FID0gJ2RpdidcbmNvbnN0IEJVQkJMRV9FVkVOVFMgPSBbXG4gICdjbGljaycsICdsb25ncHJlc3MnLCAndG91Y2hzdGFydCcsICd0b3VjaG1vdmUnLCAndG91Y2hlbmQnLFxuICAncGFuc3RhcnQnLCAncGFubW92ZScsICdwYW5lbmQnLCAnaG9yaXpvbnRhbHBhbicsICd2ZXJ0aWNhbHBhbicsICdzd2lwZSdcbl1cblxuZnVuY3Rpb24gcmVnaXN0ZXJOb2RlIChkb2NJZCwgbm9kZSkge1xuICBjb25zdCBkb2MgPSBnZXREb2MoZG9jSWQpXG4gIGRvYy5ub2RlTWFwW25vZGUubm9kZUlkXSA9IG5vZGVcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRWxlbWVudCBleHRlbmRzIE5vZGUge1xuICBjb25zdHJ1Y3RvciAodHlwZSA9IERFRkFVTFRfVEFHX05BTUUsIHByb3BzLCBpc0V4dGVuZGVkKSB7XG4gICAgc3VwZXIoKVxuXG4gICAgY29uc3QgV2VleEVsZW1lbnQgPSBnZXRXZWV4RWxlbWVudCh0eXBlKVxuICAgIGlmIChXZWV4RWxlbWVudCAmJiAhaXNFeHRlbmRlZCkge1xuICAgICAgcmV0dXJuIG5ldyBXZWV4RWxlbWVudCh0eXBlLCBwcm9wcywgdHJ1ZSlcbiAgICB9XG5cbiAgICBwcm9wcyA9IHByb3BzIHx8IHt9XG4gICAgdGhpcy5ub2RlVHlwZSA9IDFcbiAgICB0aGlzLm5vZGVJZCA9IHVuaXF1ZUlkKClcbiAgICB0aGlzLnJlZiA9IHRoaXMubm9kZUlkXG4gICAgdGhpcy50eXBlID0gdHlwZVxuICAgIHRoaXMuYXR0ciA9IHByb3BzLmF0dHIgfHwge31cbiAgICB0aGlzLnN0eWxlID0gcHJvcHMuc3R5bGUgfHwge31cbiAgICB0aGlzLmNsYXNzU3R5bGUgPSBwcm9wcy5jbGFzc1N0eWxlIHx8IHt9XG4gICAgdGhpcy5jbGFzc0xpc3QgPSBwcm9wcy5jbGFzc0xpc3QgfHwgW11cbiAgICB0aGlzLmV2ZW50ID0ge31cbiAgICB0aGlzLmNoaWxkcmVuID0gW11cbiAgICB0aGlzLnB1cmVDaGlsZHJlbiA9IFtdXG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIGEgY2hpbGQgbm9kZS5cbiAgICogQHBhcmFtIHtvYmplY3R9IG5vZGVcbiAgICogQHJldHVybiB7dW5kZWZpbmVkIHwgbnVtYmVyfSB0aGUgc2lnbmFsIHNlbnQgYnkgbmF0aXZlXG4gICAqL1xuICBhcHBlbmRDaGlsZCAobm9kZSkge1xuICAgIGlmIChub2RlLnBhcmVudE5vZGUgJiYgbm9kZS5wYXJlbnROb2RlICE9PSB0aGlzKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICBpZiAoIW5vZGUucGFyZW50Tm9kZSkge1xuICAgICAgbGlua1BhcmVudChub2RlLCB0aGlzKVxuICAgICAgaW5zZXJ0SW5kZXgobm9kZSwgdGhpcy5jaGlsZHJlbiwgdGhpcy5jaGlsZHJlbi5sZW5ndGgsIHRydWUpXG4gICAgICBpZiAodGhpcy5kb2NJZCkge1xuICAgICAgICByZWdpc3Rlck5vZGUodGhpcy5kb2NJZCwgbm9kZSlcbiAgICAgIH1cbiAgICAgIGlmIChub2RlLm5vZGVUeXBlID09PSAxKSB7XG4gICAgICAgIGluc2VydEluZGV4KG5vZGUsIHRoaXMucHVyZUNoaWxkcmVuLCB0aGlzLnB1cmVDaGlsZHJlbi5sZW5ndGgpXG4gICAgICAgIGNvbnN0IHRhc2tDZW50ZXIgPSBnZXRUYXNrQ2VudGVyKHRoaXMuZG9jSWQpXG4gICAgICAgIGlmICh0YXNrQ2VudGVyKSB7XG4gICAgICAgICAgcmV0dXJuIHRhc2tDZW50ZXIuc2VuZChcbiAgICAgICAgICAgICdkb20nLFxuICAgICAgICAgICAgeyBhY3Rpb246ICdhZGRFbGVtZW50JyB9LFxuICAgICAgICAgICAgW3RoaXMucmVmLCBub2RlLnRvSlNPTigpLCAtMV1cbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBtb3ZlSW5kZXgobm9kZSwgdGhpcy5jaGlsZHJlbiwgdGhpcy5jaGlsZHJlbi5sZW5ndGgsIHRydWUpXG4gICAgICBpZiAobm9kZS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICBjb25zdCBpbmRleCA9IG1vdmVJbmRleChub2RlLCB0aGlzLnB1cmVDaGlsZHJlbiwgdGhpcy5wdXJlQ2hpbGRyZW4ubGVuZ3RoKVxuICAgICAgICBjb25zdCB0YXNrQ2VudGVyID0gZ2V0VGFza0NlbnRlcih0aGlzLmRvY0lkKVxuICAgICAgICBpZiAodGFza0NlbnRlciAmJiBpbmRleCA+PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIHRhc2tDZW50ZXIuc2VuZChcbiAgICAgICAgICAgICdkb20nLFxuICAgICAgICAgICAgeyBhY3Rpb246ICdtb3ZlRWxlbWVudCcgfSxcbiAgICAgICAgICAgIFtub2RlLnJlZiwgdGhpcy5yZWYsIGluZGV4XVxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbnNlcnQgYSBub2RlIGJlZm9yZSBzcGVjaWZpZWQgbm9kZS5cbiAgICogQHBhcmFtIHtvYmplY3R9IG5vZGVcbiAgICogQHBhcmFtIHtvYmplY3R9IGJlZm9yZVxuICAgKiBAcmV0dXJuIHt1bmRlZmluZWQgfCBudW1iZXJ9IHRoZSBzaWduYWwgc2VudCBieSBuYXRpdmVcbiAgICovXG4gIGluc2VydEJlZm9yZSAobm9kZSwgYmVmb3JlKSB7XG4gICAgaWYgKG5vZGUucGFyZW50Tm9kZSAmJiBub2RlLnBhcmVudE5vZGUgIT09IHRoaXMpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBpZiAobm9kZSA9PT0gYmVmb3JlIHx8IChub2RlLm5leHRTaWJsaW5nICYmIG5vZGUubmV4dFNpYmxpbmcgPT09IGJlZm9yZSkpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBpZiAoIW5vZGUucGFyZW50Tm9kZSkge1xuICAgICAgbGlua1BhcmVudChub2RlLCB0aGlzKVxuICAgICAgaW5zZXJ0SW5kZXgobm9kZSwgdGhpcy5jaGlsZHJlbiwgdGhpcy5jaGlsZHJlbi5pbmRleE9mKGJlZm9yZSksIHRydWUpXG4gICAgICBpZiAodGhpcy5kb2NJZCkge1xuICAgICAgICByZWdpc3Rlck5vZGUodGhpcy5kb2NJZCwgbm9kZSlcbiAgICAgIH1cbiAgICAgIGlmIChub2RlLm5vZGVUeXBlID09PSAxKSB7XG4gICAgICAgIGNvbnN0IHB1cmVCZWZvcmUgPSBuZXh0RWxlbWVudChiZWZvcmUpXG4gICAgICAgIGNvbnN0IGluZGV4ID0gaW5zZXJ0SW5kZXgoXG4gICAgICAgICAgbm9kZSxcbiAgICAgICAgICB0aGlzLnB1cmVDaGlsZHJlbixcbiAgICAgICAgICBwdXJlQmVmb3JlXG4gICAgICAgICAgICA/IHRoaXMucHVyZUNoaWxkcmVuLmluZGV4T2YocHVyZUJlZm9yZSlcbiAgICAgICAgICAgIDogdGhpcy5wdXJlQ2hpbGRyZW4ubGVuZ3RoXG4gICAgICAgIClcbiAgICAgICAgY29uc3QgdGFza0NlbnRlciA9IGdldFRhc2tDZW50ZXIodGhpcy5kb2NJZClcbiAgICAgICAgaWYgKHRhc2tDZW50ZXIpIHtcbiAgICAgICAgICByZXR1cm4gdGFza0NlbnRlci5zZW5kKFxuICAgICAgICAgICAgJ2RvbScsXG4gICAgICAgICAgICB7IGFjdGlvbjogJ2FkZEVsZW1lbnQnIH0sXG4gICAgICAgICAgICBbdGhpcy5yZWYsIG5vZGUudG9KU09OKCksIGluZGV4XVxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIG1vdmVJbmRleChub2RlLCB0aGlzLmNoaWxkcmVuLCB0aGlzLmNoaWxkcmVuLmluZGV4T2YoYmVmb3JlKSwgdHJ1ZSlcbiAgICAgIGlmIChub2RlLm5vZGVUeXBlID09PSAxKSB7XG4gICAgICAgIGNvbnN0IHB1cmVCZWZvcmUgPSBuZXh0RWxlbWVudChiZWZvcmUpXG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIGNvbnN0IGluZGV4ID0gbW92ZUluZGV4KFxuICAgICAgICAgIG5vZGUsXG4gICAgICAgICAgdGhpcy5wdXJlQ2hpbGRyZW4sXG4gICAgICAgICAgcHVyZUJlZm9yZVxuICAgICAgICAgICAgPyB0aGlzLnB1cmVDaGlsZHJlbi5pbmRleE9mKHB1cmVCZWZvcmUpXG4gICAgICAgICAgICA6IHRoaXMucHVyZUNoaWxkcmVuLmxlbmd0aFxuICAgICAgICApXG4gICAgICAgIGNvbnN0IHRhc2tDZW50ZXIgPSBnZXRUYXNrQ2VudGVyKHRoaXMuZG9jSWQpXG4gICAgICAgIGlmICh0YXNrQ2VudGVyICYmIGluZGV4ID49IDApIHtcbiAgICAgICAgICByZXR1cm4gdGFza0NlbnRlci5zZW5kKFxuICAgICAgICAgICAgJ2RvbScsXG4gICAgICAgICAgICB7IGFjdGlvbjogJ21vdmVFbGVtZW50JyB9LFxuICAgICAgICAgICAgW25vZGUucmVmLCB0aGlzLnJlZiwgaW5kZXhdXG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluc2VydCBhIG5vZGUgYWZ0ZXIgc3BlY2lmaWVkIG5vZGUuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBub2RlXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhZnRlclxuICAgKiBAcmV0dXJuIHt1bmRlZmluZWQgfCBudW1iZXJ9IHRoZSBzaWduYWwgc2VudCBieSBuYXRpdmVcbiAgICovXG4gIGluc2VydEFmdGVyIChub2RlLCBhZnRlcikge1xuICAgIGlmIChub2RlLnBhcmVudE5vZGUgJiYgbm9kZS5wYXJlbnROb2RlICE9PSB0aGlzKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgaWYgKG5vZGUgPT09IGFmdGVyIHx8IChub2RlLnByZXZpb3VzU2libGluZyAmJiBub2RlLnByZXZpb3VzU2libGluZyA9PT0gYWZ0ZXIpKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgaWYgKCFub2RlLnBhcmVudE5vZGUpIHtcbiAgICAgIGxpbmtQYXJlbnQobm9kZSwgdGhpcylcbiAgICAgIGluc2VydEluZGV4KG5vZGUsIHRoaXMuY2hpbGRyZW4sIHRoaXMuY2hpbGRyZW4uaW5kZXhPZihhZnRlcikgKyAxLCB0cnVlKVxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICAgIGlmICh0aGlzLmRvY0lkKSB7XG4gICAgICAgIHJlZ2lzdGVyTm9kZSh0aGlzLmRvY0lkLCBub2RlKVxuICAgICAgfVxuICAgICAgaWYgKG5vZGUubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSBpbnNlcnRJbmRleChcbiAgICAgICAgICBub2RlLFxuICAgICAgICAgIHRoaXMucHVyZUNoaWxkcmVuLFxuICAgICAgICAgIHRoaXMucHVyZUNoaWxkcmVuLmluZGV4T2YocHJldmlvdXNFbGVtZW50KGFmdGVyKSkgKyAxXG4gICAgICAgIClcbiAgICAgICAgY29uc3QgdGFza0NlbnRlciA9IGdldFRhc2tDZW50ZXIodGhpcy5kb2NJZClcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICAgICAgaWYgKHRhc2tDZW50ZXIpIHtcbiAgICAgICAgICByZXR1cm4gdGFza0NlbnRlci5zZW5kKFxuICAgICAgICAgICAgJ2RvbScsXG4gICAgICAgICAgICB7IGFjdGlvbjogJ2FkZEVsZW1lbnQnIH0sXG4gICAgICAgICAgICBbdGhpcy5yZWYsIG5vZGUudG9KU09OKCksIGluZGV4XVxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIG1vdmVJbmRleChub2RlLCB0aGlzLmNoaWxkcmVuLCB0aGlzLmNoaWxkcmVuLmluZGV4T2YoYWZ0ZXIpICsgMSwgdHJ1ZSlcbiAgICAgIGlmIChub2RlLm5vZGVUeXBlID09PSAxKSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gbW92ZUluZGV4KFxuICAgICAgICAgIG5vZGUsXG4gICAgICAgICAgdGhpcy5wdXJlQ2hpbGRyZW4sXG4gICAgICAgICAgdGhpcy5wdXJlQ2hpbGRyZW4uaW5kZXhPZihwcmV2aW91c0VsZW1lbnQoYWZ0ZXIpKSArIDFcbiAgICAgICAgKVxuICAgICAgICBjb25zdCB0YXNrQ2VudGVyID0gZ2V0VGFza0NlbnRlcih0aGlzLmRvY0lkKVxuICAgICAgICBpZiAodGFza0NlbnRlciAmJiBpbmRleCA+PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIHRhc2tDZW50ZXIuc2VuZChcbiAgICAgICAgICAgICdkb20nLFxuICAgICAgICAgICAgeyBhY3Rpb246ICdtb3ZlRWxlbWVudCcgfSxcbiAgICAgICAgICAgIFtub2RlLnJlZiwgdGhpcy5yZWYsIGluZGV4XVxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYSBjaGlsZCBub2RlLCBhbmQgZGVjaWRlIHdoZXRoZXIgaXQgc2hvdWxkIGJlIGRlc3Ryb3llZC5cbiAgICogQHBhcmFtIHtvYmplY3R9IG5vZGVcbiAgICogQHBhcmFtIHtib29sZWFufSBwcmVzZXJ2ZWRcbiAgICovXG4gIHJlbW92ZUNoaWxkIChub2RlLCBwcmVzZXJ2ZWQpIHtcbiAgICBpZiAobm9kZS5wYXJlbnROb2RlKSB7XG4gICAgICByZW1vdmVJbmRleChub2RlLCB0aGlzLmNoaWxkcmVuLCB0cnVlKVxuICAgICAgaWYgKG5vZGUubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgICAgcmVtb3ZlSW5kZXgobm9kZSwgdGhpcy5wdXJlQ2hpbGRyZW4pXG4gICAgICAgIGNvbnN0IHRhc2tDZW50ZXIgPSBnZXRUYXNrQ2VudGVyKHRoaXMuZG9jSWQpXG4gICAgICAgIGlmICh0YXNrQ2VudGVyKSB7XG4gICAgICAgICAgdGFza0NlbnRlci5zZW5kKFxuICAgICAgICAgICAgJ2RvbScsXG4gICAgICAgICAgICB7IGFjdGlvbjogJ3JlbW92ZUVsZW1lbnQnIH0sXG4gICAgICAgICAgICBbbm9kZS5yZWZdXG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmICghcHJlc2VydmVkKSB7XG4gICAgICBub2RlLmRlc3Ryb3koKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhciBhbGwgY2hpbGQgbm9kZXMuXG4gICAqL1xuICBjbGVhciAoKSB7XG4gICAgY29uc3QgdGFza0NlbnRlciA9IGdldFRhc2tDZW50ZXIodGhpcy5kb2NJZClcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmICh0YXNrQ2VudGVyKSB7XG4gICAgICB0aGlzLnB1cmVDaGlsZHJlbi5mb3JFYWNoKG5vZGUgPT4ge1xuICAgICAgICB0YXNrQ2VudGVyLnNlbmQoXG4gICAgICAgICAgJ2RvbScsXG4gICAgICAgICAgeyBhY3Rpb246ICdyZW1vdmVFbGVtZW50JyB9LFxuICAgICAgICAgIFtub2RlLnJlZl1cbiAgICAgICAgKVxuICAgICAgfSlcbiAgICB9XG4gICAgdGhpcy5jaGlsZHJlbi5mb3JFYWNoKG5vZGUgPT4ge1xuICAgICAgbm9kZS5kZXN0cm95KClcbiAgICB9KVxuICAgIHRoaXMuY2hpbGRyZW4ubGVuZ3RoID0gMFxuICAgIHRoaXMucHVyZUNoaWxkcmVuLmxlbmd0aCA9IDBcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgYW4gYXR0cmlidXRlLCBhbmQgZGVjaWRlIHdoZXRoZXIgdGhlIHRhc2sgc2hvdWxkIGJlIHNlbmQgdG8gbmF0aXZlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyfSB2YWx1ZVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNpbGVudFxuICAgKi9cbiAgc2V0QXR0ciAoa2V5LCB2YWx1ZSwgc2lsZW50KSB7XG4gICAgaWYgKHRoaXMuYXR0cltrZXldID09PSB2YWx1ZSAmJiBzaWxlbnQgIT09IGZhbHNlKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgdGhpcy5hdHRyW2tleV0gPSB2YWx1ZVxuICAgIGNvbnN0IHRhc2tDZW50ZXIgPSBnZXRUYXNrQ2VudGVyKHRoaXMuZG9jSWQpXG4gICAgaWYgKCFzaWxlbnQgJiYgdGFza0NlbnRlcikge1xuICAgICAgY29uc3QgcmVzdWx0ID0ge31cbiAgICAgIHJlc3VsdFtrZXldID0gdmFsdWVcbiAgICAgIHRhc2tDZW50ZXIuc2VuZChcbiAgICAgICAgJ2RvbScsXG4gICAgICAgIHsgYWN0aW9uOiAndXBkYXRlQXR0cnMnIH0sXG4gICAgICAgIFt0aGlzLnJlZiwgcmVzdWx0XVxuICAgICAgKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgYmF0Y2hlZCBhdHRyaWJ1dGVzLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYmF0Y2hlZEF0dHJzXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2lsZW50XG4gICAqL1xuICBzZXRBdHRycyAoYmF0Y2hlZEF0dHJzLCBzaWxlbnQpIHtcbiAgICBpZiAoaXNFbXB0eShiYXRjaGVkQXR0cnMpKSByZXR1cm5cbiAgICBjb25zdCBtdXRhdGlvbnMgPSB7fVxuICAgIGZvciAoY29uc3Qga2V5IGluIGJhdGNoZWRBdHRycykge1xuICAgICAgaWYgKHRoaXMuYXR0cltrZXldICE9PSBiYXRjaGVkQXR0cnNba2V5XSkge1xuICAgICAgICB0aGlzLmF0dHJba2V5XSA9IGJhdGNoZWRBdHRyc1trZXldXG4gICAgICAgIG11dGF0aW9uc1trZXldID0gYmF0Y2hlZEF0dHJzW2tleV1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFpc0VtcHR5KG11dGF0aW9ucykpIHtcbiAgICAgIGNvbnN0IHRhc2tDZW50ZXIgPSBnZXRUYXNrQ2VudGVyKHRoaXMuZG9jSWQpXG4gICAgICBpZiAoIXNpbGVudCAmJiB0YXNrQ2VudGVyKSB7XG4gICAgICAgIHRhc2tDZW50ZXIuc2VuZChcbiAgICAgICAgICAnZG9tJyxcbiAgICAgICAgICB7IGFjdGlvbjogJ3VwZGF0ZUF0dHJzJyB9LFxuICAgICAgICAgIFt0aGlzLnJlZiwgbXV0YXRpb25zXVxuICAgICAgICApXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldCBhIHN0eWxlIHByb3BlcnR5LCBhbmQgZGVjaWRlIHdoZXRoZXIgdGhlIHRhc2sgc2hvdWxkIGJlIHNlbmQgdG8gbmF0aXZlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyfSB2YWx1ZVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNpbGVudFxuICAgKi9cbiAgc2V0U3R5bGUgKGtleSwgdmFsdWUsIHNpbGVudCkge1xuICAgIGlmICh0aGlzLnN0eWxlW2tleV0gPT09IHZhbHVlICYmIHNpbGVudCAhPT0gZmFsc2UpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICB0aGlzLnN0eWxlW2tleV0gPSB2YWx1ZVxuICAgIGNvbnN0IHRhc2tDZW50ZXIgPSBnZXRUYXNrQ2VudGVyKHRoaXMuZG9jSWQpXG4gICAgaWYgKCFzaWxlbnQgJiYgdGFza0NlbnRlcikge1xuICAgICAgY29uc3QgcmVzdWx0ID0ge31cbiAgICAgIHJlc3VsdFtrZXldID0gdmFsdWVcbiAgICAgIHRhc2tDZW50ZXIuc2VuZChcbiAgICAgICAgJ2RvbScsXG4gICAgICAgIHsgYWN0aW9uOiAndXBkYXRlU3R5bGUnIH0sXG4gICAgICAgIFt0aGlzLnJlZiwgcmVzdWx0XVxuICAgICAgKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgYmF0Y2hlZCBzdHlsZSBwcm9wZXJ0aWVzLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYmF0Y2hlZFN0eWxlc1xuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNpbGVudFxuICAgKi9cbiAgc2V0U3R5bGVzIChiYXRjaGVkU3R5bGVzLCBzaWxlbnQpIHtcbiAgICBpZiAoaXNFbXB0eShiYXRjaGVkU3R5bGVzKSkgcmV0dXJuXG4gICAgY29uc3QgbXV0YXRpb25zID0ge31cbiAgICBmb3IgKGNvbnN0IGtleSBpbiBiYXRjaGVkU3R5bGVzKSB7XG4gICAgICBpZiAodGhpcy5zdHlsZVtrZXldICE9PSBiYXRjaGVkU3R5bGVzW2tleV0pIHtcbiAgICAgICAgdGhpcy5zdHlsZVtrZXldID0gYmF0Y2hlZFN0eWxlc1trZXldXG4gICAgICAgIG11dGF0aW9uc1trZXldID0gYmF0Y2hlZFN0eWxlc1trZXldXG4gICAgICB9XG4gICAgfVxuICAgIGlmICghaXNFbXB0eShtdXRhdGlvbnMpKSB7XG4gICAgICBjb25zdCB0YXNrQ2VudGVyID0gZ2V0VGFza0NlbnRlcih0aGlzLmRvY0lkKVxuICAgICAgaWYgKCFzaWxlbnQgJiYgdGFza0NlbnRlcikge1xuICAgICAgICB0YXNrQ2VudGVyLnNlbmQoXG4gICAgICAgICAgJ2RvbScsXG4gICAgICAgICAgeyBhY3Rpb246ICd1cGRhdGVTdHlsZScgfSxcbiAgICAgICAgICBbdGhpcy5yZWYsIG11dGF0aW9uc11cbiAgICAgICAgKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUT0RPOiBkZXByZWNhdGVkXG4gICAqIFNldCBzdHlsZSBwcm9wZXJ0aWVzIGZyb20gY2xhc3MuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBjbGFzc1N0eWxlXG4gICAqL1xuICBzZXRDbGFzc1N0eWxlIChjbGFzc1N0eWxlKSB7XG4gICAgLy8gcmVzZXQgcHJldmlvdXMgY2xhc3Mgc3R5bGUgdG8gZW1wdHkgc3RyaW5nXG4gICAgZm9yIChjb25zdCBrZXkgaW4gdGhpcy5jbGFzc1N0eWxlKSB7XG4gICAgICB0aGlzLmNsYXNzU3R5bGVba2V5XSA9ICcnXG4gICAgfVxuXG4gICAgT2JqZWN0LmFzc2lnbih0aGlzLmNsYXNzU3R5bGUsIGNsYXNzU3R5bGUpXG4gICAgY29uc3QgdGFza0NlbnRlciA9IGdldFRhc2tDZW50ZXIodGhpcy5kb2NJZClcbiAgICBpZiAodGFza0NlbnRlcikge1xuICAgICAgdGFza0NlbnRlci5zZW5kKFxuICAgICAgICAnZG9tJyxcbiAgICAgICAgeyBhY3Rpb246ICd1cGRhdGVTdHlsZScgfSxcbiAgICAgICAgW3RoaXMucmVmLCB0aGlzLnRvU3R5bGUoKV1cbiAgICAgIClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0IGNsYXNzIGxpc3QuXG4gICAqIEBwYXJhbSB7YXJyYXl9IGNsYXNzTGlzdFxuICAgKi9cbiAgc2V0Q2xhc3NMaXN0IChjbGFzc0xpc3QpIHtcbiAgICBjb25zdCBjbGFzc2VzID0gdHlwZW9mIGNsYXNzTGlzdCA9PT0gJ3N0cmluZydcbiAgICAgID8gY2xhc3NMaXN0LnNwbGl0KC9cXHMrLylcbiAgICAgIDogQXJyYXkuZnJvbShjbGFzc0xpc3QpXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY2xhc3NlcykgJiYgY2xhc3Nlcy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLmNsYXNzTGlzdCA9IGNsYXNzZXNcbiAgICAgIGNvbnN0IHRhc2tDZW50ZXIgPSBnZXRUYXNrQ2VudGVyKHRoaXMuZG9jSWQpXG4gICAgICBpZiAodGFza0NlbnRlcikge1xuICAgICAgICB0YXNrQ2VudGVyLnNlbmQoXG4gICAgICAgICAgJ2RvbScsXG4gICAgICAgICAgeyBhY3Rpb246ICd1cGRhdGVDbGFzc0xpc3QnIH0sXG4gICAgICAgICAgW3RoaXMucmVmLCB0aGlzLmNsYXNzTGlzdC5zbGljZSgpXVxuICAgICAgICApXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhbiBldmVudCBoYW5kbGVyLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnQgdHlwZVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBldmVudCBoYW5kbGVyXG4gICAqL1xuICBhZGRFdmVudCAodHlwZSwgaGFuZGxlciwgcGFyYW1zKSB7XG4gICAgaWYgKCF0aGlzLmV2ZW50KSB7XG4gICAgICB0aGlzLmV2ZW50ID0ge31cbiAgICB9XG4gICAgaWYgKCF0aGlzLmV2ZW50W3R5cGVdKSB7XG4gICAgICB0aGlzLmV2ZW50W3R5cGVdID0geyBoYW5kbGVyLCBwYXJhbXMgfVxuICAgICAgY29uc3QgdGFza0NlbnRlciA9IGdldFRhc2tDZW50ZXIodGhpcy5kb2NJZClcbiAgICAgIGlmICh0YXNrQ2VudGVyKSB7XG4gICAgICAgIHRhc2tDZW50ZXIuc2VuZChcbiAgICAgICAgICAnZG9tJyxcbiAgICAgICAgICB7IGFjdGlvbjogJ2FkZEV2ZW50JyB9LFxuICAgICAgICAgIFt0aGlzLnJlZiwgdHlwZV1cbiAgICAgICAgKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYW4gZXZlbnQgaGFuZGxlci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50IHR5cGVcbiAgICovXG4gIHJlbW92ZUV2ZW50ICh0eXBlKSB7XG4gICAgaWYgKHRoaXMuZXZlbnQgJiYgdGhpcy5ldmVudFt0eXBlXSkge1xuICAgICAgZGVsZXRlIHRoaXMuZXZlbnRbdHlwZV1cbiAgICAgIGNvbnN0IHRhc2tDZW50ZXIgPSBnZXRUYXNrQ2VudGVyKHRoaXMuZG9jSWQpXG4gICAgICBpZiAodGFza0NlbnRlcikge1xuICAgICAgICB0YXNrQ2VudGVyLnNlbmQoXG4gICAgICAgICAgJ2RvbScsXG4gICAgICAgICAgeyBhY3Rpb246ICdyZW1vdmVFdmVudCcgfSxcbiAgICAgICAgICBbdGhpcy5yZWYsIHR5cGVdXG4gICAgICAgIClcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRmlyZSBhbiBldmVudCBtYW51YWxseS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgdHlwZVxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBldmVudCBoYW5kbGVyXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNCdWJibGUgd2hldGhlciBvciBub3QgZXZlbnQgYnViYmxlXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0aW9uc1xuICAgKiBAcmV0dXJuIHt9IGFueXRoaW5nIHJldHVybmVkIGJ5IGhhbmRsZXIgZnVuY3Rpb25cbiAgICovXG4gIGZpcmVFdmVudCAodHlwZSwgZXZlbnQsIGlzQnViYmxlLCBvcHRpb25zKSB7XG4gICAgbGV0IHJlc3VsdCA9IG51bGxcbiAgICBsZXQgaXNTdG9wUHJvcGFnYXRpb24gPSBmYWxzZVxuICAgIGNvbnN0IGV2ZW50RGVzYyA9IHRoaXMuZXZlbnRbdHlwZV1cbiAgICBpZiAoZXZlbnREZXNjICYmIGV2ZW50KSB7XG4gICAgICBjb25zdCBoYW5kbGVyID0gZXZlbnREZXNjLmhhbmRsZXJcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbiA9ICgpID0+IHtcbiAgICAgICAgaXNTdG9wUHJvcGFnYXRpb24gPSB0cnVlXG4gICAgICB9XG4gICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnBhcmFtcykge1xuICAgICAgICByZXN1bHQgPSBoYW5kbGVyLmNhbGwodGhpcywgLi4ub3B0aW9ucy5wYXJhbXMsIGV2ZW50KVxuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHJlc3VsdCA9IGhhbmRsZXIuY2FsbCh0aGlzLCBldmVudClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWlzU3RvcFByb3BhZ2F0aW9uXG4gICAgICAmJiBpc0J1YmJsZVxuICAgICAgJiYgKEJVQkJMRV9FVkVOVFMuaW5kZXhPZih0eXBlKSAhPT0gLTEpXG4gICAgICAmJiB0aGlzLnBhcmVudE5vZGVcbiAgICAgICYmIHRoaXMucGFyZW50Tm9kZS5maXJlRXZlbnQpIHtcbiAgICAgIGV2ZW50LmN1cnJlbnRUYXJnZXQgPSB0aGlzLnBhcmVudE5vZGVcbiAgICAgIHRoaXMucGFyZW50Tm9kZS5maXJlRXZlbnQodHlwZSwgZXZlbnQsIGlzQnViYmxlKSAvLyBubyBvcHRpb25zXG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhbGwgc3R5bGVzIG9mIGN1cnJlbnQgZWxlbWVudC5cbiAgICogQHJldHVybiB7b2JqZWN0fSBzdHlsZVxuICAgKi9cbiAgdG9TdHlsZSAoKSB7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIHRoaXMuY2xhc3NTdHlsZSwgdGhpcy5zdHlsZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGN1cnJlbnQgZWxlbWVudCB0byBKU09OIGxpa2Ugb2JqZWN0LlxuICAgKiBAcmV0dXJuIHtvYmplY3R9IGVsZW1lbnRcbiAgICovXG4gIHRvSlNPTiAoKSB7XG4gICAgY29uc3QgcmVzdWx0ID0ge1xuICAgICAgcmVmOiB0aGlzLnJlZi50b1N0cmluZygpLFxuICAgICAgdHlwZTogdGhpcy50eXBlXG4gICAgfVxuICAgIGlmICghaXNFbXB0eSh0aGlzLmF0dHIpKSB7XG4gICAgICByZXN1bHQuYXR0ciA9IHRoaXMuYXR0clxuICAgIH1cbiAgICBpZiAodGhpcy5jbGFzc0xpc3QubGVuZ3RoID4gMCkge1xuICAgICAgcmVzdWx0LmNsYXNzTGlzdCA9IHRoaXMuY2xhc3NMaXN0LnNsaWNlKClcbiAgICB9XG4gICAgY29uc3Qgc3R5bGUgPSB0aGlzLnRvU3R5bGUoKVxuICAgIGlmICghaXNFbXB0eShzdHlsZSkpIHtcbiAgICAgIHJlc3VsdC5zdHlsZSA9IHN0eWxlXG4gICAgfVxuICAgIGNvbnN0IGV2ZW50ID0gW11cbiAgICBmb3IgKGNvbnN0IHR5cGUgaW4gdGhpcy5ldmVudCkge1xuICAgICAgY29uc3QgeyBwYXJhbXMgfSA9IHRoaXMuZXZlbnRbdHlwZV1cbiAgICAgIGlmICghcGFyYW1zKSB7XG4gICAgICAgIGV2ZW50LnB1c2godHlwZSlcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBldmVudC5wdXNoKHsgdHlwZSwgcGFyYW1zIH0pXG4gICAgICB9XG4gICAgfVxuICAgIGlmIChldmVudC5sZW5ndGgpIHtcbiAgICAgIHJlc3VsdC5ldmVudCA9IGV2ZW50XG4gICAgfVxuICAgIGlmICh0aGlzLnB1cmVDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgIHJlc3VsdC5jaGlsZHJlbiA9IHRoaXMucHVyZUNoaWxkcmVuLm1hcCgoY2hpbGQpID0+IGNoaWxkLnRvSlNPTigpKVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCB0byBIVE1MIGVsZW1lbnQgdGFnIHN0cmluZy5cbiAgICogQHJldHVybiB7c3Rpcm5nfSBodG1sXG4gICAqL1xuICB0b1N0cmluZyAoKSB7XG4gICAgcmV0dXJuICc8JyArIHRoaXMudHlwZSArXG4gICAgJyBhdHRyPScgKyBKU09OLnN0cmluZ2lmeSh0aGlzLmF0dHIpICtcbiAgICAnIHN0eWxlPScgKyBKU09OLnN0cmluZ2lmeSh0aGlzLnRvU3R5bGUoKSkgKyAnPicgK1xuICAgIHRoaXMucHVyZUNoaWxkcmVuLm1hcCgoY2hpbGQpID0+IGNoaWxkLnRvU3RyaW5nKCkpLmpvaW4oJycpICtcbiAgICAnPC8nICsgdGhpcy50eXBlICsgJz4nXG4gIH1cbn1cblxuc2V0RWxlbWVudChFbGVtZW50KVxuIiwiLypcbiAqIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiAoQVNGKSB1bmRlciBvbmVcbiAqIG9yIG1vcmUgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZVxuICogZGlzdHJpYnV0ZWQgd2l0aCB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb25cbiAqIHJlZ2FyZGluZyBjb3B5cmlnaHQgb3duZXJzaGlwLiAgVGhlIEFTRiBsaWNlbnNlcyB0aGlzIGZpbGVcbiAqIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGVcbiAqIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogd2l0aCB0aGUgTGljZW5zZS4gIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLFxuICogc29mdHdhcmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW5cbiAqIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXG4gKiBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLiAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGVcbiAqIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnNcbiAqIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCBDYWxsYmFja01hbmFnZXIgZnJvbSAnLi9DYWxsYmFja01hbmFnZXInXG5pbXBvcnQgRWxlbWVudCBmcm9tICcuLi92ZG9tL0VsZW1lbnQnXG5pbXBvcnQgeyB0eXBvZiB9IGZyb20gJy4uL3NoYXJlZC91dGlscydcbmltcG9ydCB7IG5vcm1hbGl6ZVByaW1pdGl2ZSB9IGZyb20gJy4vbm9ybWFsaXplJ1xuXG5sZXQgZmFsbGJhY2sgPSBmdW5jdGlvbiAoKSB7fVxuXG4vLyBUaGUgQVBJIG9mIFRhc2tDZW50ZXIgd291bGQgYmUgcmUtZGVzaWduLlxuZXhwb3J0IGNsYXNzIFRhc2tDZW50ZXIge1xuICBjb25zdHJ1Y3RvciAoaWQsIHNlbmRUYXNrcykge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnaW5zdGFuY2VJZCcsIHtcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICB2YWx1ZTogU3RyaW5nKGlkKVxuICAgIH0pXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdjYWxsYmFja01hbmFnZXInLCB7XG4gICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgdmFsdWU6IG5ldyBDYWxsYmFja01hbmFnZXIoaWQpXG4gICAgfSlcbiAgICBmYWxsYmFjayA9IHNlbmRUYXNrcyB8fCBmdW5jdGlvbiAoKSB7fVxuICB9XG5cbiAgY2FsbGJhY2sgKGNhbGxiYWNrSWQsIGRhdGEsIGlmS2VlcEFsaXZlKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FsbGJhY2tNYW5hZ2VyLmNvbnN1bWUoY2FsbGJhY2tJZCwgZGF0YSwgaWZLZWVwQWxpdmUpXG4gIH1cblxuICByZWdpc3Rlckhvb2sgKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gdGhpcy5jYWxsYmFja01hbmFnZXIucmVnaXN0ZXJIb29rKC4uLmFyZ3MpXG4gIH1cblxuICB0cmlnZ2VySG9vayAoLi4uYXJncykge1xuICAgIHJldHVybiB0aGlzLmNhbGxiYWNrTWFuYWdlci50cmlnZ2VySG9vayguLi5hcmdzKVxuICB9XG5cbiAgdXBkYXRlRGF0YSAoY29tcG9uZW50SWQsIG5ld0RhdGEsIGNhbGxiYWNrKSB7XG4gICAgdGhpcy5zZW5kKCdtb2R1bGUnLCB7XG4gICAgICBtb2R1bGU6ICdkb20nLFxuICAgICAgbWV0aG9kOiAndXBkYXRlQ29tcG9uZW50RGF0YSdcbiAgICB9LCBbY29tcG9uZW50SWQsIG5ld0RhdGEsIGNhbGxiYWNrXSlcbiAgfVxuXG4gIGRlc3Ryb3lDYWxsYmFjayAoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FsbGJhY2tNYW5hZ2VyLmNsb3NlKClcbiAgfVxuXG4gIC8qKlxuICAgKiBOb3JtYWxpemUgYSB2YWx1ZS4gU3BlY2lhbGx5LCBpZiB0aGUgdmFsdWUgaXMgYSBmdW5jdGlvbiwgdGhlbiBnZW5lcmF0ZSBhIGZ1bmN0aW9uIGlkXG4gICAqIGFuZCBzYXZlIGl0IHRvIGBDYWxsYmFja01hbmFnZXJgLCBhdCBsYXN0IHJldHVybiB0aGUgZnVuY3Rpb24gaWQuXG4gICAqIEBwYXJhbSAge2FueX0gICAgICAgIHZcbiAgICogQHJldHVybiB7cHJpbWl0aXZlfVxuICAgKi9cbiAgbm9ybWFsaXplICh2KSB7XG4gICAgY29uc3QgdHlwZSA9IHR5cG9mKHYpXG4gICAgaWYgKHYgJiYgdiBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB2LnJlZlxuICAgIH1cbiAgICBpZiAodiAmJiB2Ll9pc1Z1ZSAmJiB2LiRlbCBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB2LiRlbC5yZWZcbiAgICB9XG4gICAgaWYgKHR5cGUgPT09ICdGdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiB0aGlzLmNhbGxiYWNrTWFuYWdlci5hZGQodikudG9TdHJpbmcoKVxuICAgIH1cbiAgICByZXR1cm4gbm9ybWFsaXplUHJpbWl0aXZlKHYpXG4gIH1cblxuICBzZW5kICh0eXBlLCBwYXJhbXMsIGFyZ3MsIG9wdGlvbnMpIHtcbiAgICBjb25zdCB7IGFjdGlvbiwgY29tcG9uZW50LCByZWYsIG1vZHVsZSwgbWV0aG9kIH0gPSBwYXJhbXNcblxuICAgIGFyZ3MgPSBhcmdzLm1hcChhcmcgPT4gdGhpcy5ub3JtYWxpemUoYXJnKSlcblxuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSAnZG9tJzpcbiAgICAgICAgcmV0dXJuIHRoaXNbYWN0aW9uXSh0aGlzLmluc3RhbmNlSWQsIGFyZ3MpXG4gICAgICBjYXNlICdjb21wb25lbnQnOlxuICAgICAgICByZXR1cm4gdGhpcy5jb21wb25lbnRIYW5kbGVyKHRoaXMuaW5zdGFuY2VJZCwgcmVmLCBtZXRob2QsIGFyZ3MsIE9iamVjdC5hc3NpZ24oeyBjb21wb25lbnQgfSwgb3B0aW9ucykpXG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gdGhpcy5tb2R1bGVIYW5kbGVyKHRoaXMuaW5zdGFuY2VJZCwgbW9kdWxlLCBtZXRob2QsIGFyZ3MsIG9wdGlvbnMpXG4gICAgfVxuICB9XG5cbiAgY2FsbERPTSAoYWN0aW9uLCBhcmdzKSB7XG4gICAgcmV0dXJuIHRoaXNbYWN0aW9uXSh0aGlzLmluc3RhbmNlSWQsIGFyZ3MpXG4gIH1cblxuICBjYWxsQ29tcG9uZW50IChyZWYsIG1ldGhvZCwgYXJncywgb3B0aW9ucykge1xuICAgIHJldHVybiB0aGlzLmNvbXBvbmVudEhhbmRsZXIodGhpcy5pbnN0YW5jZUlkLCByZWYsIG1ldGhvZCwgYXJncywgb3B0aW9ucylcbiAgfVxuXG4gIGNhbGxNb2R1bGUgKG1vZHVsZSwgbWV0aG9kLCBhcmdzLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIHRoaXMubW9kdWxlSGFuZGxlcih0aGlzLmluc3RhbmNlSWQsIG1vZHVsZSwgbWV0aG9kLCBhcmdzLCBvcHRpb25zKVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbml0ICgpIHtcbiAgY29uc3QgRE9NX01FVEhPRFMgPSB7XG4gICAgY3JlYXRlRmluaXNoOiBnbG9iYWwuY2FsbENyZWF0ZUZpbmlzaCxcbiAgICB1cGRhdGVGaW5pc2g6IGdsb2JhbC5jYWxsVXBkYXRlRmluaXNoLFxuICAgIHJlZnJlc2hGaW5pc2g6IGdsb2JhbC5jYWxsUmVmcmVzaEZpbmlzaCxcblxuICAgIGNyZWF0ZUJvZHk6IGdsb2JhbC5jYWxsQ3JlYXRlQm9keSxcbiAgICByZWdpc3RlclN0eWxlU2hlZXRzOiBnbG9iYWwuY2FsbFJlZ2lzdGVyU3R5bGVTaGVldHMsXG4gICAgYWRkRWxlbWVudDogZ2xvYmFsLmNhbGxBZGRFbGVtZW50LFxuICAgIHJlbW92ZUVsZW1lbnQ6IGdsb2JhbC5jYWxsUmVtb3ZlRWxlbWVudCxcbiAgICBtb3ZlRWxlbWVudDogZ2xvYmFsLmNhbGxNb3ZlRWxlbWVudCxcbiAgICB1cGRhdGVBdHRyczogZ2xvYmFsLmNhbGxVcGRhdGVBdHRycyxcbiAgICB1cGRhdGVTdHlsZTogZ2xvYmFsLmNhbGxVcGRhdGVTdHlsZSxcbiAgICB1cGRhdGVDbGFzc0xpc3Q6IGdsb2JhbC5jYWxsVXBkYXRlQ2xhc3NMaXN0LFxuXG4gICAgYWRkRXZlbnQ6IGdsb2JhbC5jYWxsQWRkRXZlbnQsXG4gICAgcmVtb3ZlRXZlbnQ6IGdsb2JhbC5jYWxsUmVtb3ZlRXZlbnRcbiAgfVxuICBjb25zdCBwcm90byA9IFRhc2tDZW50ZXIucHJvdG90eXBlXG5cbiAgZm9yIChjb25zdCBuYW1lIGluIERPTV9NRVRIT0RTKSB7XG4gICAgY29uc3QgbWV0aG9kID0gRE9NX01FVEhPRFNbbmFtZV1cbiAgICBwcm90b1tuYW1lXSA9IG1ldGhvZCA/XG4gICAgICAoaWQsIGFyZ3MpID0+IG1ldGhvZChpZCwgLi4uYXJncykgOlxuICAgICAgKGlkLCBhcmdzKSA9PiBmYWxsYmFjayhpZCwgW3sgbW9kdWxlOiAnZG9tJywgbWV0aG9kOiBuYW1lLCBhcmdzIH1dLCAnLTEnKVxuICB9XG5cbiAgcHJvdG8uY29tcG9uZW50SGFuZGxlciA9IGdsb2JhbC5jYWxsTmF0aXZlQ29tcG9uZW50IHx8XG4gICAgKChpZCwgcmVmLCBtZXRob2QsIGFyZ3MsIG9wdGlvbnMpID0+XG4gICAgICBmYWxsYmFjayhpZCwgW3sgY29tcG9uZW50OiBvcHRpb25zLmNvbXBvbmVudCwgcmVmLCBtZXRob2QsIGFyZ3MgfV0pKVxuXG4gIHByb3RvLm1vZHVsZUhhbmRsZXIgPSBnbG9iYWwuY2FsbE5hdGl2ZU1vZHVsZSB8fFxuICAgICgoaWQsIG1vZHVsZSwgbWV0aG9kLCBhcmdzKSA9PlxuICAgICAgZmFsbGJhY2soaWQsIFt7IG1vZHVsZSwgbWV0aG9kLCBhcmdzIH1dKSlcbn1cbiIsIi8qXG4gKiBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lXG4gKiBvciBtb3JlIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGVcbiAqIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uXG4gKiByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlXG4gKiB0byB5b3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlXG4gKiBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqIHdpdGggdGhlIExpY2Vuc2UuICBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZyxcbiAqIHNvZnR3YXJlIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuXG4gKiBcIkFTIElTXCIgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxuICogS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlXG4gKiBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25zXG4gKiB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBnZXREb2MgfSBmcm9tICcuLi92ZG9tL29wZXJhdGlvbidcblxuZnVuY3Rpb24gZmlyZUV2ZW50IChkb2N1bWVudCwgbm9kZUlkLCB0eXBlLCBldmVudCwgZG9tQ2hhbmdlcywgcGFyYW1zKSB7XG4gIGNvbnN0IGVsID0gZG9jdW1lbnQuZ2V0UmVmKG5vZGVJZClcbiAgaWYgKGVsKSB7XG4gICAgcmV0dXJuIGRvY3VtZW50LmZpcmVFdmVudChlbCwgdHlwZSwgZXZlbnQsIGRvbUNoYW5nZXMsIHBhcmFtcylcbiAgfVxuICByZXR1cm4gbmV3IEVycm9yKGBpbnZhbGlkIGVsZW1lbnQgcmVmZXJlbmNlIFwiJHtub2RlSWR9XCJgKVxufVxuXG5mdW5jdGlvbiBjYWxsYmFjayAoZG9jdW1lbnQsIGNhbGxiYWNrSWQsIGRhdGEsIGlmS2VlcEFsaXZlKSB7XG4gIHJldHVybiBkb2N1bWVudC50YXNrQ2VudGVyLmNhbGxiYWNrKGNhbGxiYWNrSWQsIGRhdGEsIGlmS2VlcEFsaXZlKVxufVxuXG5mdW5jdGlvbiBjb21wb25lbnRIb29rIChkb2N1bWVudCwgY29tcG9uZW50SWQsIHR5cGUsIGhvb2ssIG9wdGlvbnMpIHtcbiAgaWYgKCFkb2N1bWVudCB8fCAhZG9jdW1lbnQudGFza0NlbnRlcikge1xuICAgIGNvbnNvbGUuZXJyb3IoYFtKUyBGcmFtZXdvcmtdIENhbid0IGZpbmQgXCJkb2N1bWVudFwiIG9yIFwidGFza0NlbnRlclwiLmApXG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICBsZXQgcmVzdWx0ID0gbnVsbFxuICB0cnkge1xuICAgIHJlc3VsdCA9IGRvY3VtZW50LnRhc2tDZW50ZXIudHJpZ2dlckhvb2soY29tcG9uZW50SWQsIHR5cGUsIGhvb2ssIG9wdGlvbnMpXG4gIH1cbiAgY2F0Y2ggKGUpIHtcbiAgICBjb25zb2xlLmVycm9yKGBbSlMgRnJhbWV3b3JrXSBGYWlsZWQgdG8gdHJpZ2dlciB0aGUgXCIke3R5cGV9QCR7aG9va31cIiBob29rIG9uICR7Y29tcG9uZW50SWR9LmApXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG4vKipcbiAqIEFjY2VwdCBjYWxscyBmcm9tIG5hdGl2ZSAoZXZlbnQgb3IgY2FsbGJhY2spLlxuICpcbiAqIEBwYXJhbSAge3N0cmluZ30gaWRcbiAqIEBwYXJhbSAge2FycmF5fSB0YXNrcyBsaXN0IHdpdGggYG1ldGhvZGAgYW5kIGBhcmdzYFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVjZWl2ZVRhc2tzIChpZCwgdGFza3MpIHtcbiAgY29uc3QgZG9jdW1lbnQgPSBnZXREb2MoaWQpXG4gIGlmICghZG9jdW1lbnQpIHtcbiAgICByZXR1cm4gbmV3IEVycm9yKGBbSlMgRnJhbWV3b3JrXSBGYWlsZWQgdG8gcmVjZWl2ZVRhc2tzLCBgXG4gICAgICArIGBpbnN0YW5jZSAoJHtpZH0pIGlzIG5vdCBhdmFpbGFibGUuYClcbiAgfVxuICBpZiAoQXJyYXkuaXNBcnJheSh0YXNrcykpIHtcbiAgICByZXR1cm4gdGFza3MubWFwKHRhc2sgPT4ge1xuICAgICAgc3dpdGNoICh0YXNrLm1ldGhvZCkge1xuICAgICAgICBjYXNlICdjYWxsYmFjayc6IHJldHVybiBjYWxsYmFjayhkb2N1bWVudCwgLi4udGFzay5hcmdzKVxuICAgICAgICBjYXNlICdmaXJlRXZlbnRTeW5jJzpcbiAgICAgICAgY2FzZSAnZmlyZUV2ZW50JzogcmV0dXJuIGZpcmVFdmVudChkb2N1bWVudCwgLi4udGFzay5hcmdzKVxuICAgICAgICBjYXNlICdjb21wb25lbnRIb29rJzogcmV0dXJuIGNvbXBvbmVudEhvb2soZG9jdW1lbnQsIC4uLnRhc2suYXJncylcbiAgICAgIH1cbiAgICB9KVxuICB9XG59XG4iLCIvKlxuICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZVxuICogb3IgbW9yZSBjb250cmlidXRvciBsaWNlbnNlIGFncmVlbWVudHMuICBTZWUgdGhlIE5PVElDRSBmaWxlXG4gKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvblxuICogcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZVxuICogdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZVxuICogXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsXG4gKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhblxuICogXCJBUyBJU1wiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcbiAqIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZVxuICogc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9uc1xuICogdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuY29uc3Qgd2VleE1vZHVsZXMgPSB7fVxuXG4vKipcbiAqIFJlZ2lzdGVyIG5hdGl2ZSBtb2R1bGVzIGluZm9ybWF0aW9uLlxuICogQHBhcmFtIHtvYmplY3R9IG5ld01vZHVsZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyTW9kdWxlcyAobmV3TW9kdWxlcykge1xuICBmb3IgKGNvbnN0IG5hbWUgaW4gbmV3TW9kdWxlcykge1xuICAgIGlmICghd2VleE1vZHVsZXNbbmFtZV0pIHtcbiAgICAgIHdlZXhNb2R1bGVzW25hbWVdID0ge31cbiAgICB9XG4gICAgbmV3TW9kdWxlc1tuYW1lXS5mb3JFYWNoKG1ldGhvZCA9PiB7XG4gICAgICBpZiAodHlwZW9mIG1ldGhvZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgd2VleE1vZHVsZXNbbmFtZV1bbWV0aG9kXSA9IHRydWVcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICB3ZWV4TW9kdWxlc1tuYW1lXVttZXRob2QubmFtZV0gPSBtZXRob2QuYXJnc1xuICAgICAgfVxuICAgIH0pXG4gIH1cbn1cblxuLyoqXG4gKiBDaGVjayB3aGV0aGVyIHRoZSBtb2R1bGUgb3IgdGhlIG1ldGhvZCBoYXMgYmVlbiByZWdpc3RlcmVkLlxuICogQHBhcmFtIHtTdHJpbmd9IG1vZHVsZSBuYW1lXG4gKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kIG5hbWUgKG9wdGlvbmFsKVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZWdpc3RlcmVkTW9kdWxlIChuYW1lLCBtZXRob2QpIHtcbiAgaWYgKHR5cGVvZiBtZXRob2QgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuICEhKHdlZXhNb2R1bGVzW25hbWVdICYmIHdlZXhNb2R1bGVzW25hbWVdW21ldGhvZF0pXG4gIH1cbiAgcmV0dXJuICEhd2VleE1vZHVsZXNbbmFtZV1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE1vZHVsZURlc2NyaXB0aW9uIChuYW1lKSB7XG4gIHJldHVybiB3ZWV4TW9kdWxlc1tuYW1lXVxufVxuIiwiLypcbiAqIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiAoQVNGKSB1bmRlciBvbmVcbiAqIG9yIG1vcmUgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZVxuICogZGlzdHJpYnV0ZWQgd2l0aCB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb25cbiAqIHJlZ2FyZGluZyBjb3B5cmlnaHQgb3duZXJzaGlwLiAgVGhlIEFTRiBsaWNlbnNlcyB0aGlzIGZpbGVcbiAqIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGVcbiAqIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogd2l0aCB0aGUgTGljZW5zZS4gIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLFxuICogc29mdHdhcmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW5cbiAqIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXG4gKiBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLiAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGVcbiAqIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnNcbiAqIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IHJlZ2lzdGVyRWxlbWVudCB9IGZyb20gJy4uL3Zkb20vV2VleEVsZW1lbnQnXG5cbmNvbnN0IHdlZXhDb21wb25lbnRzID0ge31cblxuLyoqXG4gKiBSZWdpc3RlciBuYXRpdmUgY29tcG9uZW50cyBpbmZvcm1hdGlvbi5cbiAqIEBwYXJhbSB7YXJyYXl9IG5ld0NvbXBvbmVudHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyQ29tcG9uZW50cyAobmV3Q29tcG9uZW50cykge1xuICBpZiAoQXJyYXkuaXNBcnJheShuZXdDb21wb25lbnRzKSkge1xuICAgIG5ld0NvbXBvbmVudHMuZm9yRWFjaChjb21wb25lbnQgPT4ge1xuICAgICAgaWYgKCFjb21wb25lbnQpIHtcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIGNvbXBvbmVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgd2VleENvbXBvbmVudHNbY29tcG9uZW50XSA9IHRydWVcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKHR5cGVvZiBjb21wb25lbnQgPT09ICdvYmplY3QnICYmIHR5cGVvZiBjb21wb25lbnQudHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgd2VleENvbXBvbmVudHNbY29tcG9uZW50LnR5cGVdID0gY29tcG9uZW50XG4gICAgICAgIHJlZ2lzdGVyRWxlbWVudChjb21wb25lbnQudHlwZSwgY29tcG9uZW50Lm1ldGhvZHMpXG4gICAgICB9XG4gICAgfSlcbiAgfVxufVxuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgdGhlIGNvbXBvbmVudCBoYXMgYmVlbiByZWdpc3RlcmVkLlxuICogQHBhcmFtIHtTdHJpbmd9IGNvbXBvbmVudCBuYW1lXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1JlZ2lzdGVyZWRDb21wb25lbnQgKG5hbWUpIHtcbiAgcmV0dXJuICEhd2VleENvbXBvbmVudHNbbmFtZV1cbn1cbiIsIi8qXG4gKiBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lXG4gKiBvciBtb3JlIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGVcbiAqIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uXG4gKiByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlXG4gKiB0byB5b3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlXG4gKiBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqIHdpdGggdGhlIExpY2Vuc2UuICBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZyxcbiAqIHNvZnR3YXJlIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuXG4gKiBcIkFTIElTXCIgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxuICogS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlXG4gKiBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25zXG4gKiB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vLyBKUyBTZXJ2aWNlc1xuXG5leHBvcnQgY29uc3Qgc2VydmljZXMgPSBbXVxuXG4vKipcbiAqIFJlZ2lzdGVyIGEgSmF2YVNjcmlwdCBzZXJ2aWNlLlxuICogQSBKYXZhU2NyaXB0IHNlcnZpY2Ugb3B0aW9ucyBjb3VsZCBoYXZlIGEgc2V0IG9mIGxpZmVjeWNsZSBtZXRob2RzXG4gKiBmb3IgZWFjaCBXZWV4IGluc3RhbmNlLiBGb3IgZXhhbXBsZTogY3JlYXRlLCByZWZyZXNoLCBkZXN0cm95LlxuICogRm9yIHRoZSBKUyBmcmFtZXdvcmsgbWFpbnRhaW5lciBpZiB5b3Ugd2FudCB0byBzdXBwbHkgc29tZSBmZWF0dXJlc1xuICogd2hpY2ggbmVlZCB0byB3b3JrIHdlbGwgaW4gZGlmZmVyZW50IFdlZXggaW5zdGFuY2VzLCBldmVuIGluIGRpZmZlcmVudFxuICogZnJhbWV3b3JrcyBzZXBhcmF0ZWx5LiBZb3UgY2FuIG1ha2UgYSBKYXZhU2NyaXB0IHNlcnZpY2UgdG8gaW5pdFxuICogaXRzIHZhcmlhYmxlcyBvciBjbGFzc2VzIGZvciBlYWNoIFdlZXggaW5zdGFuY2Ugd2hlbiBpdCdzIGNyZWF0ZWRcbiAqIGFuZCByZWN5Y2xlIHRoZW0gd2hlbiBpdCdzIGRlc3Ryb3llZC5cbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zIENvdWxkIGhhdmUgeyBjcmVhdGUsIHJlZnJlc2gsIGRlc3Ryb3kgfVxuICogICAgICAgICAgICAgICAgICAgICAgICAgbGlmZWN5Y2xlIG1ldGhvZHMuIEluIGNyZWF0ZSBtZXRob2QgaXQgc2hvdWxkXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYW4gb2JqZWN0IG9mIHdoYXQgdmFyaWFibGVzIG9yIGNsYXNzZXNcbiAqICAgICAgICAgICAgICAgICAgICAgICAgIHdvdWxkIGJlIGluamVjdGVkIGludG8gdGhlIFdlZXggaW5zdGFuY2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlciAobmFtZSwgb3B0aW9ucykge1xuICBpZiAoaGFzKG5hbWUpKSB7XG4gICAgY29uc29sZS53YXJuKGBTZXJ2aWNlIFwiJHtuYW1lfVwiIGhhcyBiZWVuIHJlZ2lzdGVyZWQgYWxyZWFkeSFgKVxuICB9XG4gIGVsc2Uge1xuICAgIG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCBvcHRpb25zKVxuICAgIHNlcnZpY2VzLnB1c2goeyBuYW1lLCBvcHRpb25zIH0pXG4gIH1cbn1cblxuLyoqXG4gKiBVbnJlZ2lzdGVyIGEgSmF2YVNjcmlwdCBzZXJ2aWNlIGJ5IG5hbWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bnJlZ2lzdGVyIChuYW1lKSB7XG4gIHNlcnZpY2VzLnNvbWUoKHNlcnZpY2UsIGluZGV4KSA9PiB7XG4gICAgaWYgKHNlcnZpY2UubmFtZSA9PT0gbmFtZSkge1xuICAgICAgc2VydmljZXMuc3BsaWNlKGluZGV4LCAxKVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gIH0pXG59XG5cbi8qKlxuICogQ2hlY2sgaWYgYSBKYXZhU2NyaXB0IHNlcnZpY2Ugd2l0aCBhIGNlcnRhaW4gbmFtZSBleGlzdGVkLlxuICogQHBhcmFtICB7c3RyaW5nfSAgbmFtZVxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhcyAobmFtZSkge1xuICByZXR1cm4gaW5kZXhPZihuYW1lKSA+PSAwXG59XG5cbi8qKlxuICogRmluZCB0aGUgaW5kZXggb2YgYSBKYXZhU2NyaXB0IHNlcnZpY2UgYnkgbmFtZVxuICogQHBhcmFtICB7c3RyaW5nfSBuYW1lXG4gKiBAcmV0dXJuIHtudW1iZXJ9XG4gKi9cbmZ1bmN0aW9uIGluZGV4T2YgKG5hbWUpIHtcbiAgcmV0dXJuIHNlcnZpY2VzLm1hcChzZXJ2aWNlID0+IHNlcnZpY2UubmFtZSkuaW5kZXhPZihuYW1lKVxufVxuIiwiLypcbiAqIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiAoQVNGKSB1bmRlciBvbmVcbiAqIG9yIG1vcmUgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZVxuICogZGlzdHJpYnV0ZWQgd2l0aCB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb25cbiAqIHJlZ2FyZGluZyBjb3B5cmlnaHQgb3duZXJzaGlwLiAgVGhlIEFTRiBsaWNlbnNlcyB0aGlzIGZpbGVcbiAqIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGVcbiAqIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogd2l0aCB0aGUgTGljZW5zZS4gIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLFxuICogc29mdHdhcmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW5cbiAqIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXG4gKiBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLiAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGVcbiAqIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnNcbiAqIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IGdldFRhc2tDZW50ZXIgfSBmcm9tICcuLi92ZG9tL29wZXJhdGlvbidcbmltcG9ydCB7IGlzUmVnaXN0ZXJlZE1vZHVsZSB9IGZyb20gJy4uL2FwaS9tb2R1bGUnXG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFjayAoaWQsIHR5cGUsIHZhbHVlKSB7XG4gIGNvbnN0IHRhc2tDZW50ZXIgPSBnZXRUYXNrQ2VudGVyKGlkKVxuICBpZiAoIXRhc2tDZW50ZXIgfHwgdHlwZW9mIHRhc2tDZW50ZXIuc2VuZCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIGNvbnNvbGUuZXJyb3IoYFtKUyBGcmFtZXdvcmtdIEZhaWxlZCB0byBjcmVhdGUgdHJhY2tlciFgKVxuICAgIHJldHVyblxuICB9XG4gIGlmICghdHlwZSB8fCAhdmFsdWUpIHtcbiAgICBjb25zb2xlLndhcm4oYFtKUyBGcmFtZXdvcmtdIEludmFsaWQgdHJhY2sgdHlwZSAoJHt0eXBlfSkgb3IgdmFsdWUgKCR7dmFsdWV9KWApXG4gICAgcmV0dXJuXG4gIH1cbiAgY29uc3QgbGFiZWwgPSBganNmbS4ke3R5cGV9LiR7dmFsdWV9YFxuICB0cnkge1xuICAgIGlmIChpc1JlZ2lzdGVyZWRNb2R1bGUoJ3VzZXJUcmFjaycsICdhZGRQZXJmUG9pbnQnKSkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IE9iamVjdC5jcmVhdGUobnVsbClcbiAgICAgIG1lc3NhZ2VbbGFiZWxdID0gJzQnXG4gICAgICB0YXNrQ2VudGVyLnNlbmQoJ21vZHVsZScsIHtcbiAgICAgICAgbW9kdWxlOiAndXNlclRyYWNrJyxcbiAgICAgICAgbWV0aG9kOiAnYWRkUGVyZlBvaW50J1xuICAgICAgfSwgW21lc3NhZ2VdKVxuICAgIH1cbiAgfVxuICBjYXRjaCAoZXJyKSB7XG4gICAgY29uc29sZS5lcnJvcihgW0pTIEZyYW1ld29ya10gRmFpbGVkIHRvIHRyYWNlIFwiJHtsYWJlbH1cIiFgKVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlcnJvciAoLi4ubWVzc2FnZXMpIHtcbiAgaWYgKHR5cGVvZiBjb25zb2xlLmVycm9yID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY29uc29sZS5lcnJvcihgW0pTIEZyYW1ld29ya10gYCwgLi4ubWVzc2FnZXMpXG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhhbmRsZUV4Y2VwdGlvbiAoZXJyKSB7XG4gIGlmICh0eXBlb2YgY29uc29sZS5lcnJvciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHRyeSB7XG4gICAgICBjb25zb2xlLmVycm9yKGVyci50b1N0cmluZygpKVxuICAgIH1cbiAgICBjYXRjaCAoZSkge31cbiAgfVxuICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJykge1xuICAgIHRocm93IGVyclxuICB9XG59XG4iLCIvKlxuICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZVxuICogb3IgbW9yZSBjb250cmlidXRvciBsaWNlbnNlIGFncmVlbWVudHMuICBTZWUgdGhlIE5PVElDRSBmaWxlXG4gKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvblxuICogcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZVxuICogdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZVxuICogXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsXG4gKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhblxuICogXCJBUyBJU1wiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcbiAqIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZVxuICogc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9uc1xuICogdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IE5vZGUgZnJvbSAnLi9Ob2RlJ1xuaW1wb3J0IHsgdW5pcXVlSWQgfSBmcm9tICcuLi9zaGFyZWQvdXRpbHMnXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENvbW1lbnQgZXh0ZW5kcyBOb2RlIHtcbiAgY29uc3RydWN0b3IgKHZhbHVlKSB7XG4gICAgc3VwZXIoKVxuXG4gICAgdGhpcy5ub2RlVHlwZSA9IDhcbiAgICB0aGlzLm5vZGVJZCA9IHVuaXF1ZUlkKClcbiAgICB0aGlzLnJlZiA9IHRoaXMubm9kZUlkXG4gICAgdGhpcy50eXBlID0gJ2NvbW1lbnQnXG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlXG4gICAgdGhpcy5jaGlsZHJlbiA9IFtdXG4gICAgdGhpcy5wdXJlQ2hpbGRyZW4gPSBbXVxuICB9XG5cbiAgLyoqXG4gICogQ29udmVydCB0byBIVE1MIGNvbW1lbnQgc3RyaW5nLlxuICAqIEByZXR1cm4ge3N0aXJuZ30gaHRtbFxuICAqL1xuICB0b1N0cmluZyAoKSB7XG4gICAgcmV0dXJuICc8IS0tICcgKyB0aGlzLnZhbHVlICsgJyAtLT4nXG4gIH1cbn1cbiIsIi8qXG4gKiBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lXG4gKiBvciBtb3JlIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGVcbiAqIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uXG4gKiByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlXG4gKiB0byB5b3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlXG4gKiBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqIHdpdGggdGhlIExpY2Vuc2UuICBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZyxcbiAqIHNvZnR3YXJlIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuXG4gKiBcIkFTIElTXCIgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxuICogS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlXG4gKiBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25zXG4gKiB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiogQ3JlYXRlIHRoZSBhY3Rpb24gb2JqZWN0LlxuKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuKiBAcGFyYW0ge2FycmF5fSBhcmd1bWVudHNcbiogQHJldHVybiB7b2JqZWN0fSBhY3Rpb25cbiovXG5mdW5jdGlvbiBjcmVhdGVBY3Rpb24gKG5hbWUsIGFyZ3MgPSBbXSkge1xuICByZXR1cm4geyBtb2R1bGU6ICdkb20nLCBtZXRob2Q6IG5hbWUsIGFyZ3M6IGFyZ3MgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMaXN0ZW5lciB7XG4gIGNvbnN0cnVjdG9yIChpZCwgaGFuZGxlcikge1xuICAgIHRoaXMuaWQgPSBpZFxuICAgIHRoaXMuYmF0Y2hlZCA9IGZhbHNlXG4gICAgdGhpcy51cGRhdGVzID0gW11cbiAgICBpZiAodHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnaGFuZGxlcicsIHtcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgdmFsdWU6IGhhbmRsZXJcbiAgICAgIH0pXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgY29uc29sZS5lcnJvcignW0pTIFJ1bnRpbWVdIGludmFsaWQgcGFyYW1ldGVyLCBoYW5kbGVyIG11c3QgYmUgYSBmdW5jdGlvbicpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNlbmQgdGhlIFwiY3JlYXRlRmluaXNoXCIgc2lnbmFsLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKiBAcmV0dXJuIHt1bmRlZmluZWQgfCBudW1iZXJ9IHRoZSBzaWduYWwgc2VudCBieSBuYXRpdmVcbiAgICovXG4gIGNyZWF0ZUZpbmlzaCAoY2FsbGJhY2spIHtcbiAgICBjb25zdCBoYW5kbGVyID0gdGhpcy5oYW5kbGVyXG4gICAgcmV0dXJuIGhhbmRsZXIoW2NyZWF0ZUFjdGlvbignY3JlYXRlRmluaXNoJyldLCBjYWxsYmFjaylcbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kIHRoZSBcInVwZGF0ZUZpbmlzaFwiIHNpZ25hbC5cbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICogQHJldHVybiB7dW5kZWZpbmVkIHwgbnVtYmVyfSB0aGUgc2lnbmFsIHNlbnQgYnkgbmF0aXZlXG4gICAqL1xuICB1cGRhdGVGaW5pc2ggKGNhbGxiYWNrKSB7XG4gICAgY29uc3QgaGFuZGxlciA9IHRoaXMuaGFuZGxlclxuICAgIHJldHVybiBoYW5kbGVyKFtjcmVhdGVBY3Rpb24oJ3VwZGF0ZUZpbmlzaCcpXSwgY2FsbGJhY2spXG4gIH1cblxuICAvKipcbiAgICogU2VuZCB0aGUgXCJyZWZyZXNoRmluaXNoXCIgc2lnbmFsLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKiBAcmV0dXJuIHt1bmRlZmluZWQgfCBudW1iZXJ9IHRoZSBzaWduYWwgc2VudCBieSBuYXRpdmVcbiAgICovXG4gIHJlZnJlc2hGaW5pc2ggKGNhbGxiYWNrKSB7XG4gICAgY29uc3QgaGFuZGxlciA9IHRoaXMuaGFuZGxlclxuICAgIHJldHVybiBoYW5kbGVyKFtjcmVhdGVBY3Rpb24oJ3JlZnJlc2hGaW5pc2gnKV0sIGNhbGxiYWNrKVxuICB9XG5cbiAgLyoqXG4gICAqIFNlbmQgdGhlIFwiY3JlYXRlQm9keVwiIHNpZ25hbC5cbiAgICogQHBhcmFtIHtvYmplY3R9IGVsZW1lbnRcbiAgICogQHJldHVybiB7dW5kZWZpbmVkIHwgbnVtYmVyfSB0aGUgc2lnbmFsIHNlbnQgYnkgbmF0aXZlXG4gICAqL1xuICBjcmVhdGVCb2R5IChlbGVtZW50KSB7XG4gICAgY29uc3QgYm9keSA9IGVsZW1lbnQudG9KU09OKClcbiAgICBjb25zdCBjaGlsZHJlbiA9IGJvZHkuY2hpbGRyZW5cbiAgICBkZWxldGUgYm9keS5jaGlsZHJlblxuICAgIGNvbnN0IGFjdGlvbnMgPSBbY3JlYXRlQWN0aW9uKCdjcmVhdGVCb2R5JywgW2JvZHldKV1cbiAgICBpZiAoY2hpbGRyZW4pIHtcbiAgICAgIGFjdGlvbnMucHVzaC5hcHBseShhY3Rpb25zLCBjaGlsZHJlbi5tYXAoY2hpbGQgPT4ge1xuICAgICAgICByZXR1cm4gY3JlYXRlQWN0aW9uKCdhZGRFbGVtZW50JywgW2JvZHkucmVmLCBjaGlsZCwgLTFdKVxuICAgICAgfSkpXG4gICAgfVxuICAgIHJldHVybiB0aGlzLmFkZEFjdGlvbnMoYWN0aW9ucylcbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kIHRoZSBcImFkZEVsZW1lbnRcIiBzaWduYWwuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7c3Rpcm5nfSByZWZlcmVuY2UgaWRcbiAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4XG4gICAqIEByZXR1cm4ge3VuZGVmaW5lZCB8IG51bWJlcn0gdGhlIHNpZ25hbCBzZW50IGJ5IG5hdGl2ZVxuICAgKi9cbiAgYWRkRWxlbWVudCAoZWxlbWVudCwgcmVmLCBpbmRleCkge1xuICAgIGlmICghKGluZGV4ID49IDApKSB7XG4gICAgICBpbmRleCA9IC0xXG4gICAgfVxuICAgIHJldHVybiB0aGlzLmFkZEFjdGlvbnMoY3JlYXRlQWN0aW9uKCdhZGRFbGVtZW50JywgW3JlZiwgZWxlbWVudC50b0pTT04oKSwgaW5kZXhdKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kIHRoZSBcInJlbW92ZUVsZW1lbnRcIiBzaWduYWwuXG4gICAqIEBwYXJhbSB7c3Rpcm5nfSByZWZlcmVuY2UgaWRcbiAgICogQHJldHVybiB7dW5kZWZpbmVkIHwgbnVtYmVyfSB0aGUgc2lnbmFsIHNlbnQgYnkgbmF0aXZlXG4gICAqL1xuICByZW1vdmVFbGVtZW50IChyZWYpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShyZWYpKSB7XG4gICAgICBjb25zdCBhY3Rpb25zID0gcmVmLm1hcCgocikgPT4gY3JlYXRlQWN0aW9uKCdyZW1vdmVFbGVtZW50JywgW3JdKSlcbiAgICAgIHJldHVybiB0aGlzLmFkZEFjdGlvbnMoYWN0aW9ucylcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYWRkQWN0aW9ucyhjcmVhdGVBY3Rpb24oJ3JlbW92ZUVsZW1lbnQnLCBbcmVmXSkpXG4gIH1cblxuICAvKipcbiAgICogU2VuZCB0aGUgXCJtb3ZlRWxlbWVudFwiIHNpZ25hbC5cbiAgICogQHBhcmFtIHtzdGlybmd9IHRhcmdldCByZWZlcmVuY2UgaWRcbiAgICogQHBhcmFtIHtzdGlybmd9IHBhcmVudCByZWZlcmVuY2UgaWRcbiAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4XG4gICAqIEByZXR1cm4ge3VuZGVmaW5lZCB8IG51bWJlcn0gdGhlIHNpZ25hbCBzZW50IGJ5IG5hdGl2ZVxuICAgKi9cbiAgbW92ZUVsZW1lbnQgKHRhcmdldFJlZiwgcGFyZW50UmVmLCBpbmRleCkge1xuICAgIHJldHVybiB0aGlzLmFkZEFjdGlvbnMoY3JlYXRlQWN0aW9uKCdtb3ZlRWxlbWVudCcsIFt0YXJnZXRSZWYsIHBhcmVudFJlZiwgaW5kZXhdKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kIHRoZSBcInVwZGF0ZUF0dHJzXCIgc2lnbmFsLlxuICAgKiBAcGFyYW0ge3N0aXJuZ30gcmVmZXJlbmNlIGlkXG4gICAqIEBwYXJhbSB7c3Rpcm5nfSBrZXlcbiAgICogQHBhcmFtIHtzdGlybmd9IHZhbHVlXG4gICAqIEByZXR1cm4ge3VuZGVmaW5lZCB8IG51bWJlcn0gdGhlIHNpZ25hbCBzZW50IGJ5IG5hdGl2ZVxuICAgKi9cbiAgc2V0QXR0ciAocmVmLCBrZXksIHZhbHVlKSB7XG4gICAgY29uc3QgcmVzdWx0ID0ge31cbiAgICByZXN1bHRba2V5XSA9IHZhbHVlXG4gICAgcmV0dXJuIHRoaXMuYWRkQWN0aW9ucyhjcmVhdGVBY3Rpb24oJ3VwZGF0ZUF0dHJzJywgW3JlZiwgcmVzdWx0XSkpXG4gIH1cblxuICAvKipcbiAgICogU2VuZCB0aGUgXCJ1cGRhdGVTdHlsZVwiIHNpZ25hbCwgdXBkYXRlIGEgc29sZSBzdHlsZS5cbiAgICogQHBhcmFtIHtzdGlybmd9IHJlZmVyZW5jZSBpZFxuICAgKiBAcGFyYW0ge3N0aXJuZ30ga2V5XG4gICAqIEBwYXJhbSB7c3Rpcm5nfSB2YWx1ZVxuICAgKiBAcmV0dXJuIHt1bmRlZmluZWQgfCBudW1iZXJ9IHRoZSBzaWduYWwgc2VudCBieSBuYXRpdmVcbiAgICovXG4gIHNldFN0eWxlIChyZWYsIGtleSwgdmFsdWUpIHtcbiAgICBjb25zdCByZXN1bHQgPSB7fVxuICAgIHJlc3VsdFtrZXldID0gdmFsdWVcbiAgICByZXR1cm4gdGhpcy5hZGRBY3Rpb25zKGNyZWF0ZUFjdGlvbigndXBkYXRlU3R5bGUnLCBbcmVmLCByZXN1bHRdKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kIHRoZSBcInVwZGF0ZVN0eWxlXCIgc2lnbmFsLlxuICAgKiBAcGFyYW0ge3N0aXJuZ30gcmVmZXJlbmNlIGlkXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBzdHlsZVxuICAgKiBAcmV0dXJuIHt1bmRlZmluZWQgfCBudW1iZXJ9IHRoZSBzaWduYWwgc2VudCBieSBuYXRpdmVcbiAgICovXG4gIHNldFN0eWxlcyAocmVmLCBzdHlsZSkge1xuICAgIHJldHVybiB0aGlzLmFkZEFjdGlvbnMoY3JlYXRlQWN0aW9uKCd1cGRhdGVTdHlsZScsIFtyZWYsIHN0eWxlXSkpXG4gIH1cblxuICAvKipcbiAgICogU2VuZCB0aGUgXCJhZGRFdmVudFwiIHNpZ25hbC5cbiAgICogQHBhcmFtIHtzdGlybmd9IHJlZmVyZW5jZSBpZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnQgdHlwZVxuICAgKiBAcmV0dXJuIHt1bmRlZmluZWQgfCBudW1iZXJ9IHRoZSBzaWduYWwgc2VudCBieSBuYXRpdmVcbiAgICovXG4gIGFkZEV2ZW50IChyZWYsIHR5cGUpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRBY3Rpb25zKGNyZWF0ZUFjdGlvbignYWRkRXZlbnQnLCBbcmVmLCB0eXBlXSkpXG4gIH1cblxuICAvKipcbiAgICogU2VuZCB0aGUgXCJyZW1vdmVFdmVudFwiIHNpZ25hbC5cbiAgICogQHBhcmFtIHtzdGlybmd9IHJlZmVyZW5jZSBpZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnQgdHlwZVxuICAgKiBAcmV0dXJuIHt1bmRlZmluZWQgfCBudW1iZXJ9IHRoZSBzaWduYWwgc2VudCBieSBuYXRpdmVcbiAgICovXG4gIHJlbW92ZUV2ZW50IChyZWYsIHR5cGUpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRBY3Rpb25zKGNyZWF0ZUFjdGlvbigncmVtb3ZlRXZlbnQnLCBbcmVmLCB0eXBlXSkpXG4gIH1cblxuICAvKipcbiAgICogRGVmYXVsdCBoYW5kbGVyLlxuICAgKiBAcGFyYW0ge29iamVjdCB8IGFycmF5fSBhY3Rpb25zXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAqIEByZXR1cm4ge30gYW55dGhpbmcgcmV0dXJuZWQgYnkgY2FsbGJhY2sgZnVuY3Rpb25cbiAgICovXG4gIGhhbmRsZXIgKGFjdGlvbnMsIGNiKSB7XG4gICAgcmV0dXJuIGNiICYmIGNiKClcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYWN0aW9ucyBpbnRvIHVwZGF0ZXMuXG4gICAqIEBwYXJhbSB7b2JqZWN0IHwgYXJyYXl9IGFjdGlvbnNcbiAgICogQHJldHVybiB7dW5kZWZpbmVkIHwgbnVtYmVyfSB0aGUgc2lnbmFsIHNlbnQgYnkgbmF0aXZlXG4gICAqL1xuICBhZGRBY3Rpb25zIChhY3Rpb25zKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IHRoaXMudXBkYXRlc1xuICAgIGNvbnN0IGhhbmRsZXIgPSB0aGlzLmhhbmRsZXJcblxuICAgIGlmICghQXJyYXkuaXNBcnJheShhY3Rpb25zKSkge1xuICAgICAgYWN0aW9ucyA9IFthY3Rpb25zXVxuICAgIH1cblxuICAgIGlmICh0aGlzLmJhdGNoZWQpIHtcbiAgICAgIHVwZGF0ZXMucHVzaC5hcHBseSh1cGRhdGVzLCBhY3Rpb25zKVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHJldHVybiBoYW5kbGVyKGFjdGlvbnMpXG4gICAgfVxuICB9XG59XG4iLCIvKlxuICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZVxuICogb3IgbW9yZSBjb250cmlidXRvciBsaWNlbnNlIGFncmVlbWVudHMuICBTZWUgdGhlIE5PVElDRSBmaWxlXG4gKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvblxuICogcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZVxuICogdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZVxuICogXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsXG4gKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhblxuICogXCJBUyBJU1wiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcbiAqIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZVxuICogc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9uc1xuICogdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBAZmlsZU92ZXJ2aWV3XG4gKiBUYXNrIGhhbmRsZXIgZm9yIGNvbW11bmljYXRpb24gYmV0d2VlbiBqYXZhc2NyaXB0IGFuZCBuYXRpdmUuXG4gKi9cblxuY29uc3QgaGFuZGxlck1hcCA9IHtcbiAgY3JlYXRlQm9keTogJ2NhbGxDcmVhdGVCb2R5JyxcbiAgYWRkRWxlbWVudDogJ2NhbGxBZGRFbGVtZW50JyxcbiAgcmVtb3ZlRWxlbWVudDogJ2NhbGxSZW1vdmVFbGVtZW50JyxcbiAgbW92ZUVsZW1lbnQ6ICdjYWxsTW92ZUVsZW1lbnQnLFxuICB1cGRhdGVBdHRyczogJ2NhbGxVcGRhdGVBdHRycycsXG4gIHVwZGF0ZVN0eWxlOiAnY2FsbFVwZGF0ZVN0eWxlJyxcbiAgYWRkRXZlbnQ6ICdjYWxsQWRkRXZlbnQnLFxuICByZW1vdmVFdmVudDogJ2NhbGxSZW1vdmVFdmVudCdcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSB0YXNrIGhhbmRsZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gaWRcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGhhbmRsZXJcbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSB0YXNrSGFuZGxlclxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlSGFuZGxlciAoaWQsIGhhbmRsZXIpIHtcbiAgY29uc3QgZGVmYXVsdEhhbmRsZXIgPSBoYW5kbGVyIHx8IGdsb2JhbC5jYWxsTmF0aXZlXG5cbiAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gIGlmICh0eXBlb2YgZGVmYXVsdEhhbmRsZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICBjb25zb2xlLmVycm9yKCdbSlMgUnVudGltZV0gbm8gZGVmYXVsdCBoYW5kbGVyJylcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiB0YXNrSGFuZGxlciAodGFza3MpIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodGFza3MpKSB7XG4gICAgICB0YXNrcyA9IFt0YXNrc11cbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0YXNrcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgcmV0dXJuVmFsdWUgPSBkaXNwYXRjaFRhc2soaWQsIHRhc2tzW2ldLCBkZWZhdWx0SGFuZGxlcilcbiAgICAgIGlmIChyZXR1cm5WYWx1ZSA9PT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIHJldHVyblZhbHVlXG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgdGhlcmUgaXMgYSBjb3JyZXNwb25kaW5nIGF2YWlsYWJsZSBoYW5kbGVyIGluIHRoZSBlbnZpcm9ubWVudC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtb2R1bGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2RcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGhhc0F2YWlsYWJsZUhhbmRsZXIgKG1vZHVsZSwgbWV0aG9kKSB7XG4gIHJldHVybiBtb2R1bGUgPT09ICdkb20nXG4gICAgJiYgaGFuZGxlck1hcFttZXRob2RdXG4gICAgJiYgdHlwZW9mIGdsb2JhbFtoYW5kbGVyTWFwW21ldGhvZF1dID09PSAnZnVuY3Rpb24nXG59XG5cbi8qKlxuICogRGlzcGF0Y2ggdGhlIHRhc2sgdG8gdGhlIHNwZWNpZmllZCBoYW5kbGVyLlxuICogQHBhcmFtIHtzdHJpbmd9IGlkXG4gKiBAcGFyYW0ge29iamVjdH0gdGFza1xuICogQHBhcmFtIHtmdW5jdGlvbn0gZGVmYXVsdEhhbmRsZXJcbiAqIEByZXR1cm4ge251bWJlcn0gc2lnbmFsIHJldHVybmVkIGZyb20gbmF0aXZlXG4gKi9cbmZ1bmN0aW9uIGRpc3BhdGNoVGFzayAoaWQsIHRhc2ssIGRlZmF1bHRIYW5kbGVyKSB7XG4gIGNvbnN0IHsgbW9kdWxlLCBtZXRob2QsIGFyZ3MgfSA9IHRhc2tcblxuICBpZiAoaGFzQXZhaWxhYmxlSGFuZGxlcihtb2R1bGUsIG1ldGhvZCkpIHtcbiAgICByZXR1cm4gZ2xvYmFsW2hhbmRsZXJNYXBbbWV0aG9kXV0oaWQsIC4uLmFyZ3MsICctMScpXG4gIH1cblxuICByZXR1cm4gZGVmYXVsdEhhbmRsZXIoaWQsIFt0YXNrXSwgJy0xJylcbn1cbiIsIi8qXG4gKiBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lXG4gKiBvciBtb3JlIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGVcbiAqIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uXG4gKiByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlXG4gKiB0byB5b3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlXG4gKiBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqIHdpdGggdGhlIExpY2Vuc2UuICBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZyxcbiAqIHNvZnR3YXJlIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuXG4gKiBcIkFTIElTXCIgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxuICogS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlXG4gKiBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25zXG4gKiB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgQ29tbWVudCBmcm9tICcuL0NvbW1lbnQnXG5pbXBvcnQgRWxlbWVudCBmcm9tICcuL0VsZW1lbnQnXG5pbXBvcnQgTGlzdGVuZXIgZnJvbSAnLi4vYnJpZGdlL0xpc3RlbmVyJ1xuaW1wb3J0IHsgVGFza0NlbnRlciB9IGZyb20gJy4uL2JyaWRnZS9UYXNrQ2VudGVyJ1xuaW1wb3J0IHsgY3JlYXRlSGFuZGxlciB9IGZyb20gJy4uL2JyaWRnZS9IYW5kbGVyJ1xuaW1wb3J0IHsgYWRkRG9jLCByZW1vdmVEb2MsIGFwcGVuZEJvZHksIHNldEJvZHkgfSBmcm9tICcuL29wZXJhdGlvbidcblxuLyoqXG4gKiBVcGRhdGUgYWxsIGNoYW5nZXMgZm9yIGFuIGVsZW1lbnQuXG4gKiBAcGFyYW0ge29iamVjdH0gZWxlbWVudFxuICogQHBhcmFtIHtvYmplY3R9IGNoYW5nZXNcbiAqL1xuZnVuY3Rpb24gdXBkYXRlRWxlbWVudCAoZWwsIGNoYW5nZXMpIHtcbiAgY29uc3QgYXR0cnMgPSBjaGFuZ2VzLmF0dHJzIHx8IHt9XG4gIGZvciAoY29uc3QgbmFtZSBpbiBhdHRycykge1xuICAgIGVsLnNldEF0dHIobmFtZSwgYXR0cnNbbmFtZV0sIHRydWUpXG4gIH1cbiAgY29uc3Qgc3R5bGUgPSBjaGFuZ2VzLnN0eWxlIHx8IHt9XG4gIGZvciAoY29uc3QgbmFtZSBpbiBzdHlsZSkge1xuICAgIGVsLnNldFN0eWxlKG5hbWUsIHN0eWxlW25hbWVdLCB0cnVlKVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERvY3VtZW50IHtcbiAgY29uc3RydWN0b3IgKGlkLCB1cmwsIGhhbmRsZXIpIHtcbiAgICBpZCA9IGlkID8gaWQudG9TdHJpbmcoKSA6ICcnXG4gICAgdGhpcy5pZCA9IGlkXG4gICAgdGhpcy5VUkwgPSB1cmxcblxuICAgIGFkZERvYyhpZCwgdGhpcylcbiAgICB0aGlzLm5vZGVNYXAgPSB7fVxuICAgIGNvbnN0IEwgPSBEb2N1bWVudC5MaXN0ZW5lciB8fCBMaXN0ZW5lclxuICAgIHRoaXMubGlzdGVuZXIgPSBuZXcgTChpZCwgaGFuZGxlciB8fCBjcmVhdGVIYW5kbGVyKGlkLCBEb2N1bWVudC5oYW5kbGVyKSkgLy8gZGVwcmVjYXRlZFxuICAgIHRoaXMudGFza0NlbnRlciA9IG5ldyBUYXNrQ2VudGVyKGlkLCBoYW5kbGVyID8gKGlkLCAuLi5hcmdzKSA9PiBoYW5kbGVyKC4uLmFyZ3MpIDogRG9jdW1lbnQuaGFuZGxlcilcbiAgICB0aGlzLmNyZWF0ZURvY3VtZW50RWxlbWVudCgpXG4gIH1cblxuICAvKipcbiAgKiBHZXQgdGhlIG5vZGUgZnJvbSBub2RlTWFwLlxuICAqIEBwYXJhbSB7c3RyaW5nfSByZWZlcmVuY2UgaWRcbiAgKiBAcmV0dXJuIHtvYmplY3R9IG5vZGVcbiAgKi9cbiAgZ2V0UmVmIChyZWYpIHtcbiAgICByZXR1cm4gdGhpcy5ub2RlTWFwW3JlZl1cbiAgfVxuXG4gIC8qKlxuICAqIFR1cm4gb24gYmF0Y2hlZCB1cGRhdGVzLlxuICAqL1xuICBvcGVuICgpIHtcbiAgICB0aGlzLmxpc3RlbmVyLmJhdGNoZWQgPSBmYWxzZVxuICB9XG5cbiAgLyoqXG4gICogVHVybiBvZmYgYmF0Y2hlZCB1cGRhdGVzLlxuICAqL1xuICBjbG9zZSAoKSB7XG4gICAgdGhpcy5saXN0ZW5lci5iYXRjaGVkID0gdHJ1ZVxuICB9XG5cbiAgLyoqXG4gICogQ3JlYXRlIHRoZSBkb2N1bWVudCBlbGVtZW50LlxuICAqIEByZXR1cm4ge29iamVjdH0gZG9jdW1lbnRFbGVtZW50XG4gICovXG4gIGNyZWF0ZURvY3VtZW50RWxlbWVudCAoKSB7XG4gICAgaWYgKCF0aGlzLmRvY3VtZW50RWxlbWVudCkge1xuICAgICAgY29uc3QgZWwgPSBuZXcgRWxlbWVudCgnZG9jdW1lbnQnKVxuICAgICAgZWwuZG9jSWQgPSB0aGlzLmlkXG4gICAgICBlbC5vd25lckRvY3VtZW50ID0gdGhpc1xuICAgICAgZWwucm9sZSA9ICdkb2N1bWVudEVsZW1lbnQnXG4gICAgICBlbC5kZXB0aCA9IDBcbiAgICAgIGVsLnJlZiA9ICdfZG9jdW1lbnRFbGVtZW50J1xuICAgICAgdGhpcy5ub2RlTWFwLl9kb2N1bWVudEVsZW1lbnQgPSBlbFxuICAgICAgdGhpcy5kb2N1bWVudEVsZW1lbnQgPSBlbFxuXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZWwsICdhcHBlbmRDaGlsZCcsIHtcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgdmFsdWU6IChub2RlKSA9PiB7XG4gICAgICAgICAgYXBwZW5kQm9keSh0aGlzLCBub2RlKVxuICAgICAgICB9XG4gICAgICB9KVxuXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZWwsICdpbnNlcnRCZWZvcmUnLCB7XG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgIHZhbHVlOiAobm9kZSwgYmVmb3JlKSA9PiB7XG4gICAgICAgICAgYXBwZW5kQm9keSh0aGlzLCBub2RlLCBiZWZvcmUpXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZG9jdW1lbnRFbGVtZW50XG4gIH1cblxuICAvKipcbiAgKiBDcmVhdGUgdGhlIGJvZHkgZWxlbWVudC5cbiAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZVxuICAqIEBwYXJhbSB7b2JqY3R9IHByb3BzXG4gICogQHJldHVybiB7b2JqZWN0fSBib2R5IGVsZW1lbnRcbiAgKi9cbiAgY3JlYXRlQm9keSAodHlwZSwgcHJvcHMpIHtcbiAgICBpZiAoIXRoaXMuYm9keSkge1xuICAgICAgY29uc3QgZWwgPSBuZXcgRWxlbWVudCh0eXBlLCBwcm9wcylcbiAgICAgIHNldEJvZHkodGhpcywgZWwpXG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuYm9keVxuICB9XG5cbiAgLyoqXG4gICogQ3JlYXRlIGFuIGVsZW1lbnQuXG4gICogQHBhcmFtIHtzdHJpbmd9IHRhZ05hbWVcbiAgKiBAcGFyYW0ge29iamN0fSBwcm9wc1xuICAqIEByZXR1cm4ge29iamVjdH0gZWxlbWVudFxuICAqL1xuICBjcmVhdGVFbGVtZW50ICh0YWdOYW1lLCBwcm9wcykge1xuICAgIHJldHVybiBuZXcgRWxlbWVudCh0YWdOYW1lLCBwcm9wcylcbiAgfVxuXG4gIC8qKlxuICAqIENyZWF0ZSBhbiBjb21tZW50LlxuICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XG4gICogQHJldHVybiB7b2JqZWN0fSBjb21tZW50XG4gICovXG4gIGNyZWF0ZUNvbW1lbnQgKHRleHQpIHtcbiAgICByZXR1cm4gbmV3IENvbW1lbnQodGV4dClcbiAgfVxuXG4gIC8qKlxuICAqIFJlZ2lzdGVyIFN0eWxlU2hlZXRzLlxuICAqIEBwYXJhbSB7c3RyaW5nfSBzY29wZUlkXG4gICogQHJldHVybiB7YXJyYXk8b2JqZWN0Pn0gc3R5bGVTaGVldHNcbiAgKi9cbiAgcmVnaXN0ZXJTdHlsZVNoZWV0cyAoc2NvcGVJZCwgc3R5bGVTaGVldHMpIHtcbiAgICBjb25zdCBzaGVldHMgPSBBcnJheS5pc0FycmF5KHN0eWxlU2hlZXRzKSA/IHN0eWxlU2hlZXRzIDogW3N0eWxlU2hlZXRzXVxuICAgIGlmICh0aGlzLnRhc2tDZW50ZXIgJiYgc2hlZXRzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHRoaXMudGFza0NlbnRlci5zZW5kKFxuICAgICAgICAnZG9tJyxcbiAgICAgICAgeyBhY3Rpb246ICdyZWdpc3RlclN0eWxlU2hlZXRzJyB9LFxuICAgICAgICBbc2NvcGVJZCwgc2hlZXRzXVxuICAgICAgKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAqIEZpcmUgYW4gZXZlbnQgb24gc3BlY2lmaWVkIGVsZW1lbnQgbWFudWFsbHkuXG4gICogQHBhcmFtIHtvYmplY3R9IGVsZW1lbnRcbiAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnQgdHlwZVxuICAqIEBwYXJhbSB7b2JqZWN0fSBldmVudCBvYmplY3RcbiAgKiBAcGFyYW0ge29iamVjdH0gZG9tIGNoYW5nZXNcbiAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAqIEByZXR1cm4ge30gYW55dGhpbmcgcmV0dXJuZWQgYnkgaGFuZGxlciBmdW5jdGlvblxuICAqL1xuICBmaXJlRXZlbnQgKGVsLCB0eXBlLCBldmVudCwgZG9tQ2hhbmdlcywgb3B0aW9ucykge1xuICAgIGlmICghZWwpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBldmVudCA9IGV2ZW50IHx8IHt9XG4gICAgZXZlbnQudHlwZSA9IGV2ZW50LnR5cGUgfHwgdHlwZVxuICAgIGV2ZW50LnRhcmdldCA9IGVsXG4gICAgZXZlbnQuY3VycmVudFRhcmdldCA9IGVsXG4gICAgZXZlbnQudGltZXN0YW1wID0gRGF0ZS5ub3coKVxuICAgIGlmIChkb21DaGFuZ2VzKSB7XG4gICAgICB1cGRhdGVFbGVtZW50KGVsLCBkb21DaGFuZ2VzKVxuICAgIH1cbiAgICBjb25zdCBpc0J1YmJsZSA9IHRoaXMuZ2V0UmVmKCdfcm9vdCcpLmF0dHJbJ2J1YmJsZSddID09PSAndHJ1ZSdcbiAgICByZXR1cm4gZWwuZmlyZUV2ZW50KHR5cGUsIGV2ZW50LCBpc0J1YmJsZSwgb3B0aW9ucylcbiAgfVxuXG4gIC8qKlxuICAqIERlc3Ryb3kgY3VycmVudCBkb2N1bWVudCwgYW5kIHJlbW92ZSBpdHNlbGYgZm9ybSBkb2NNYXAuXG4gICovXG4gIGRlc3Ryb3kgKCkge1xuICAgIHRoaXMudGFza0NlbnRlci5kZXN0cm95Q2FsbGJhY2soKVxuICAgIGRlbGV0ZSB0aGlzLmxpc3RlbmVyXG4gICAgZGVsZXRlIHRoaXMubm9kZU1hcFxuICAgIGRlbGV0ZSB0aGlzLnRhc2tDZW50ZXJcbiAgICByZW1vdmVEb2ModGhpcy5pZClcbiAgfVxufVxuXG4vLyBkZWZhdWx0IHRhc2sgaGFuZGxlclxuRG9jdW1lbnQuaGFuZGxlciA9IG51bGxcbiIsIi8qXG4gKiBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lXG4gKiBvciBtb3JlIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGVcbiAqIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uXG4gKiByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlXG4gKiB0byB5b3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlXG4gKiBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqIHdpdGggdGhlIExpY2Vuc2UuICBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZyxcbiAqIHNvZnR3YXJlIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuXG4gKiBcIkFTIElTXCIgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxuICogS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlXG4gKiBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25zXG4gKiB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgRG9jdW1lbnQgZnJvbSAnLi4vdmRvbS9Eb2N1bWVudCdcbmltcG9ydCB7IGlzUmVnaXN0ZXJlZE1vZHVsZSwgZ2V0TW9kdWxlRGVzY3JpcHRpb24gfSBmcm9tICcuL21vZHVsZSdcbmltcG9ydCB7IGlzUmVnaXN0ZXJlZENvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50J1xuaW1wb3J0IHsgZ2V0VGFza0NlbnRlciB9IGZyb20gJy4uL3Zkb20vb3BlcmF0aW9uJ1xuXG5jb25zdCBtb2R1bGVQcm94aWVzID0ge31cblxuZnVuY3Rpb24gc2V0SWQgKHdlZXgsIGlkKSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3ZWV4LCAnW1tDdXJyZW50SW5zdGFuY2VJZF1dJywgeyB2YWx1ZTogaWQgfSlcbn1cblxuZnVuY3Rpb24gZ2V0SWQgKHdlZXgpIHtcbiAgcmV0dXJuIHdlZXhbJ1tbQ3VycmVudEluc3RhbmNlSWRdXSddXG59XG5cbmZ1bmN0aW9uIG1vZHVsZUdldHRlciAoaWQsIG1vZHVsZSwgbWV0aG9kKSB7XG4gIGNvbnN0IHRhc2tDZW50ZXIgPSBnZXRUYXNrQ2VudGVyKGlkKVxuICBpZiAoIXRhc2tDZW50ZXIgfHwgdHlwZW9mIHRhc2tDZW50ZXIuc2VuZCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIGNvbnNvbGUuZXJyb3IoYFtKUyBGcmFtZXdvcmtdIEZhaWxlZCB0byBmaW5kIHRhc2tDZW50ZXIgKCR7aWR9KS5gKVxuICAgIHJldHVybiBudWxsXG4gIH1cbiAgcmV0dXJuICguLi5hcmdzKSA9PiB0YXNrQ2VudGVyLnNlbmQoJ21vZHVsZScsIHsgbW9kdWxlLCBtZXRob2QgfSwgYXJncylcbn1cblxuZnVuY3Rpb24gbW9kdWxlU2V0dGVyIChpZCwgbW9kdWxlLCBtZXRob2QsIGZuKSB7XG4gIGNvbnN0IHRhc2tDZW50ZXIgPSBnZXRUYXNrQ2VudGVyKGlkKVxuICBpZiAoIXRhc2tDZW50ZXIgfHwgdHlwZW9mIHRhc2tDZW50ZXIuc2VuZCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIGNvbnNvbGUuZXJyb3IoYFtKUyBGcmFtZXdvcmtdIEZhaWxlZCB0byBmaW5kIHRhc2tDZW50ZXIgKCR7aWR9KS5gKVxuICAgIHJldHVybiBudWxsXG4gIH1cbiAgaWYgKHR5cGVvZiBmbiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIGNvbnNvbGUuZXJyb3IoYFtKUyBGcmFtZXdvcmtdICR7bW9kdWxlfS4ke21ldGhvZH0gbXVzdCBiZSBhc3NpZ25lZCBhcyBhIGZ1bmN0aW9uLmApXG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICByZXR1cm4gZm4gPT4gdGFza0NlbnRlci5zZW5kKCdtb2R1bGUnLCB7IG1vZHVsZSwgbWV0aG9kIH0sIFtmbl0pXG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFdlZXhJbnN0YW5jZSB7XG4gIGNvbnN0cnVjdG9yIChpZCwgY29uZmlnKSB7XG4gICAgc2V0SWQodGhpcywgU3RyaW5nKGlkKSlcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZyB8fCB7fVxuICAgIHRoaXMuZG9jdW1lbnQgPSBuZXcgRG9jdW1lbnQoaWQsIHRoaXMuY29uZmlnLmJ1bmRsZVVybClcbiAgICB0aGlzLnJlcXVpcmVNb2R1bGUgPSB0aGlzLnJlcXVpcmVNb2R1bGUuYmluZCh0aGlzKVxuICAgIHRoaXMuaXNSZWdpc3RlcmVkTW9kdWxlID0gaXNSZWdpc3RlcmVkTW9kdWxlXG4gICAgdGhpcy5pc1JlZ2lzdGVyZWRDb21wb25lbnQgPSBpc1JlZ2lzdGVyZWRDb21wb25lbnRcbiAgfVxuXG4gIHJlcXVpcmVNb2R1bGUgKG1vZHVsZU5hbWUpIHtcbiAgICBjb25zdCBpZCA9IGdldElkKHRoaXMpXG4gICAgaWYgKCEoaWQgJiYgdGhpcy5kb2N1bWVudCAmJiB0aGlzLmRvY3VtZW50LnRhc2tDZW50ZXIpKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBbSlMgRnJhbWV3b3JrXSBGYWlsZWQgdG8gcmVxdWlyZU1vZHVsZShcIiR7bW9kdWxlTmFtZX1cIiksIGBcbiAgICAgICAgKyBgaW5zdGFuY2UgKCR7aWR9KSBkb2Vzbid0IGV4aXN0IGFueW1vcmUuYClcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIC8vIHdhcm4gZm9yIHVua25vd24gbW9kdWxlXG4gICAgaWYgKCFpc1JlZ2lzdGVyZWRNb2R1bGUobW9kdWxlTmFtZSkpIHtcbiAgICAgIGNvbnNvbGUud2FybihgW0pTIEZyYW1ld29ya10gdXNpbmcgdW5yZWdpc3RlcmVkIHdlZXggbW9kdWxlIFwiJHttb2R1bGVOYW1lfVwiYClcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIC8vIGNyZWF0ZSBuZXcgbW9kdWxlIHByb3h5XG4gICAgY29uc3QgcHJveHlOYW1lID0gYCR7bW9kdWxlTmFtZX0jJHtpZH1gXG4gICAgaWYgKCFtb2R1bGVQcm94aWVzW3Byb3h5TmFtZV0pIHtcbiAgICAgIC8vIGNyZWF0ZSByZWdpc3RlcmVkIG1vZHVsZSBhcGlzXG4gICAgICBjb25zdCBtb2R1bGVEZWZpbmUgPSBnZXRNb2R1bGVEZXNjcmlwdGlvbihtb2R1bGVOYW1lKVxuICAgICAgY29uc3QgbW9kdWxlQXBpcyA9IHt9XG4gICAgICBmb3IgKGNvbnN0IG1ldGhvZE5hbWUgaW4gbW9kdWxlRGVmaW5lKSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2R1bGVBcGlzLCBtZXRob2ROYW1lLCB7XG4gICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgICAgZ2V0OiAoKSA9PiBtb2R1bGVHZXR0ZXIoaWQsIG1vZHVsZU5hbWUsIG1ldGhvZE5hbWUpLFxuICAgICAgICAgIHNldDogZm4gPT4gbW9kdWxlU2V0dGVyKGlkLCBtb2R1bGVOYW1lLCBtZXRob2ROYW1lLCBmbilcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgLy8gY3JlYXRlIG1vZHVsZSBQcm94eVxuICAgICAgaWYgKHR5cGVvZiBQcm94eSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBtb2R1bGVQcm94aWVzW3Byb3h5TmFtZV0gPSBuZXcgUHJveHkobW9kdWxlQXBpcywge1xuICAgICAgICAgIGdldCAodGFyZ2V0LCBtZXRob2ROYW1lKSB7XG4gICAgICAgICAgICBpZiAobWV0aG9kTmFtZSBpbiB0YXJnZXQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRhcmdldFttZXRob2ROYW1lXVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc29sZS53YXJuKGBbSlMgRnJhbWV3b3JrXSB1c2luZyB1bnJlZ2lzdGVyZWQgbWV0aG9kIFwiJHttb2R1bGVOYW1lfS4ke21ldGhvZE5hbWV9XCJgKVxuICAgICAgICAgICAgcmV0dXJuIG1vZHVsZUdldHRlcihpZCwgbW9kdWxlTmFtZSwgbWV0aG9kTmFtZSlcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgbW9kdWxlUHJveGllc1twcm94eU5hbWVdID0gbW9kdWxlQXBpc1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBtb2R1bGVQcm94aWVzW3Byb3h5TmFtZV1cbiAgfVxuXG4gIHN1cHBvcnRzIChjb25kaXRpb24pIHtcbiAgICBpZiAodHlwZW9mIGNvbmRpdGlvbiAhPT0gJ3N0cmluZycpIHJldHVybiBudWxsXG5cbiAgICBjb25zdCByZXMgPSBjb25kaXRpb24ubWF0Y2goL15AKFxcdyspXFwvKFxcdyspKFxcLihcXHcrKSk/JC9pKVxuICAgIGlmIChyZXMpIHtcbiAgICAgIGNvbnN0IHR5cGUgPSByZXNbMV1cbiAgICAgIGNvbnN0IG5hbWUgPSByZXNbMl1cbiAgICAgIGNvbnN0IG1ldGhvZCA9IHJlc1s0XVxuICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgIGNhc2UgJ21vZHVsZSc6IHJldHVybiBpc1JlZ2lzdGVyZWRNb2R1bGUobmFtZSwgbWV0aG9kKVxuICAgICAgICBjYXNlICdjb21wb25lbnQnOiByZXR1cm4gaXNSZWdpc3RlcmVkQ29tcG9uZW50KG5hbWUpXG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIC8vIHJlZ2lzdGVyU3R5bGVTaGVldCAoc3R5bGVzKSB7XG4gIC8vICAgaWYgKHRoaXMuZG9jdW1lbnQpIHtcbiAgLy8gICAgIHRoaXMuZG9jdW1lbnQucmVnaXN0ZXJTdHlsZVNoZWV0KHN0eWxlcylcbiAgLy8gICB9XG4gIC8vIH1cbn1cbiIsIi8qXG4gKiBMaWNlbnNlZCB0byB0aGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKEFTRikgdW5kZXIgb25lXG4gKiBvciBtb3JlIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGVcbiAqIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyB3b3JrIGZvciBhZGRpdGlvbmFsIGluZm9ybWF0aW9uXG4gKiByZWdhcmRpbmcgY29weXJpZ2h0IG93bmVyc2hpcC4gIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlXG4gKiB0byB5b3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlXG4gKiBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqIHdpdGggdGhlIExpY2Vuc2UuICBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZyxcbiAqIHNvZnR3YXJlIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuXG4gKiBcIkFTIElTXCIgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxuICogS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlXG4gKiBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kIGxpbWl0YXRpb25zXG4gKiB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBpbml0IGFzIGluaXRUYXNrSGFuZGxlciB9IGZyb20gJy4uL2JyaWRnZS9UYXNrQ2VudGVyJ1xuaW1wb3J0IHsgcmVjZWl2ZVRhc2tzIH0gZnJvbSAnLi4vYnJpZGdlL3JlY2VpdmVyJ1xuaW1wb3J0IHsgcmVnaXN0ZXJNb2R1bGVzIH0gZnJvbSAnLi9tb2R1bGUnXG5pbXBvcnQgeyByZWdpc3RlckNvbXBvbmVudHMgfSBmcm9tICcuL2NvbXBvbmVudCdcbmltcG9ydCB7IHNlcnZpY2VzLCByZWdpc3RlciwgdW5yZWdpc3RlciB9IGZyb20gJy4vc2VydmljZSdcbmltcG9ydCB7IHRyYWNrIH0gZnJvbSAnLi4vYnJpZGdlL2RlYnVnJ1xuaW1wb3J0IFdlZXhJbnN0YW5jZSBmcm9tICcuL1dlZXhJbnN0YW5jZSdcbmltcG9ydCB7IGdldERvYyB9IGZyb20gJy4uL3Zkb20vb3BlcmF0aW9uJ1xuXG5sZXQgZnJhbWV3b3Jrc1xubGV0IHJ1bnRpbWVDb25maWdcblxuY29uc3QgdmVyc2lvblJlZ0V4cCA9IC9eXFxzKlxcL1xcLyAqKFxce1tefV0qXFx9KSAqXFxyP1xcbi9cblxuLyoqXG4gKiBEZXRlY3QgYSBKUyBCdW5kbGUgY29kZSBhbmQgbWFrZSBzdXJlIHdoaWNoIGZyYW1ld29yayBpdCdzIGJhc2VkIHRvLiBFYWNoIEpTXG4gKiBCdW5kbGUgc2hvdWxkIG1ha2Ugc3VyZSB0aGF0IGl0IHN0YXJ0cyB3aXRoIGEgbGluZSBvZiBKU09OIGNvbW1lbnQgYW5kIGlzXG4gKiBtb3JlIHRoYXQgb25lIGxpbmUuXG4gKiBAcGFyYW0gIHtzdHJpbmd9IGNvZGVcbiAqIEByZXR1cm4ge29iamVjdH1cbiAqL1xuZnVuY3Rpb24gZ2V0QnVuZGxlVHlwZSAoY29kZSkge1xuICBjb25zdCByZXN1bHQgPSB2ZXJzaW9uUmVnRXhwLmV4ZWMoY29kZSlcbiAgaWYgKHJlc3VsdCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBpbmZvID0gSlNPTi5wYXJzZShyZXN1bHRbMV0pXG4gICAgICByZXR1cm4gaW5mby5mcmFtZXdvcmtcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHt9XG4gIH1cblxuICAvLyBkZWZhdWx0IGJ1bmRsZSB0eXBlXG4gIHJldHVybiAnV2VleCdcbn1cblxuZnVuY3Rpb24gY3JlYXRlU2VydmljZXMgKGlkLCBlbnYsIGNvbmZpZykge1xuICAvLyBJbml0IEphdmFTY3JpcHQgc2VydmljZXMgZm9yIHRoaXMgaW5zdGFuY2UuXG4gIGNvbnN0IHNlcnZpY2VNYXAgPSBPYmplY3QuY3JlYXRlKG51bGwpXG4gIHNlcnZpY2VNYXAuc2VydmljZSA9IE9iamVjdC5jcmVhdGUobnVsbClcbiAgc2VydmljZXMuZm9yRWFjaCgoeyBuYW1lLCBvcHRpb25zIH0pID0+IHtcbiAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdkZXZlbG9wbWVudCcpIHtcbiAgICAgIGNvbnNvbGUuZGVidWcoYFtKUyBSdW50aW1lXSBjcmVhdGUgc2VydmljZSAke25hbWV9LmApXG4gICAgfVxuICAgIGNvbnN0IGNyZWF0ZSA9IG9wdGlvbnMuY3JlYXRlXG4gICAgaWYgKGNyZWF0ZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gY3JlYXRlKGlkLCBlbnYsIGNvbmZpZylcbiAgICAgICAgT2JqZWN0LmFzc2lnbihzZXJ2aWNlTWFwLnNlcnZpY2UsIHJlc3VsdClcbiAgICAgICAgT2JqZWN0LmFzc2lnbihzZXJ2aWNlTWFwLCByZXN1bHQuaW5zdGFuY2UpXG4gICAgICB9XG4gICAgICBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBbSlMgUnVudGltZV0gRmFpbGVkIHRvIGNyZWF0ZSBzZXJ2aWNlICR7bmFtZX0uYClcbiAgICAgIH1cbiAgICB9XG4gIH0pXG4gIGRlbGV0ZSBzZXJ2aWNlTWFwLnNlcnZpY2UuaW5zdGFuY2VcbiAgT2JqZWN0LmZyZWV6ZShzZXJ2aWNlTWFwLnNlcnZpY2UpXG4gIHJldHVybiBzZXJ2aWNlTWFwXG59XG5cbmNvbnN0IGluc3RhbmNlVHlwZU1hcCA9IHt9XG5mdW5jdGlvbiBnZXRGcmFtZXdvcmtUeXBlIChpZCkge1xuICByZXR1cm4gaW5zdGFuY2VUeXBlTWFwW2lkXVxufVxuXG5mdW5jdGlvbiBjcmVhdGVJbnN0YW5jZUNvbnRleHQgKGlkLCBvcHRpb25zID0ge30sIGRhdGEpIHtcbiAgY29uc3Qgd2VleCA9IG5ldyBXZWV4SW5zdGFuY2UoaWQsIG9wdGlvbnMpXG4gIE9iamVjdC5mcmVlemUod2VleClcblxuICBjb25zdCBidW5kbGVUeXBlID0gb3B0aW9ucy5idW5kbGVUeXBlIHx8ICdWdWUnXG4gIGluc3RhbmNlVHlwZU1hcFtpZF0gPSBidW5kbGVUeXBlXG4gIGNvbnN0IGZyYW1ld29yayA9IHJ1bnRpbWVDb25maWcuZnJhbWV3b3Jrc1tidW5kbGVUeXBlXVxuICBpZiAoIWZyYW1ld29yaykge1xuICAgIHJldHVybiBuZXcgRXJyb3IoYFtKUyBGcmFtZXdvcmtdIEludmFsaWQgYnVuZGxlIHR5cGUgXCIke2J1bmRsZVR5cGV9XCIuYClcbiAgfVxuICB0cmFjayhpZCwgJ2J1bmRsZVR5cGUnLCBidW5kbGVUeXBlKVxuXG4gIC8vIHByZXBhcmUganMgc2VydmljZVxuICBjb25zdCBzZXJ2aWNlcyA9IGNyZWF0ZVNlcnZpY2VzKGlkLCB7XG4gICAgd2VleCxcbiAgICBjb25maWc6IG9wdGlvbnMsXG4gICAgY3JlYXRlZDogRGF0ZS5ub3coKSxcbiAgICBmcmFtZXdvcms6IGJ1bmRsZVR5cGUsXG4gICAgYnVuZGxlVHlwZVxuICB9LCBydW50aW1lQ29uZmlnKVxuICBPYmplY3QuZnJlZXplKHNlcnZpY2VzKVxuXG4gIC8vIHByZXBhcmUgcnVudGltZSBjb250ZXh0XG4gIGNvbnN0IHJ1bnRpbWVDb250ZXh0ID0gT2JqZWN0LmNyZWF0ZShudWxsKVxuICBPYmplY3QuYXNzaWduKHJ1bnRpbWVDb250ZXh0LCBzZXJ2aWNlcywge1xuICAgIHdlZXgsXG4gICAgc2VydmljZXMgLy8gVGVtcG9yYXJ5IGNvbXBhdGlibGUgd2l0aCBzb21lIGxlZ2FjeSBBUElzIGluIFJheFxuICB9KVxuICBPYmplY3QuZnJlZXplKHJ1bnRpbWVDb250ZXh0KVxuXG4gIC8vIHByZXBhcmUgaW5zdGFuY2UgY29udGV4dFxuICBjb25zdCBpbnN0YW5jZUNvbnRleHQgPSBPYmplY3QuYXNzaWduKHt9LCBydW50aW1lQ29udGV4dClcbiAgaWYgKHR5cGVvZiBmcmFtZXdvcmsuY3JlYXRlSW5zdGFuY2VDb250ZXh0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgT2JqZWN0LmFzc2lnbihpbnN0YW5jZUNvbnRleHQsIGZyYW1ld29yay5jcmVhdGVJbnN0YW5jZUNvbnRleHQoaWQsIHJ1bnRpbWVDb250ZXh0LCBkYXRhKSlcbiAgfVxuICBPYmplY3QuZnJlZXplKGluc3RhbmNlQ29udGV4dClcbiAgcmV0dXJuIGluc3RhbmNlQ29udGV4dFxufVxuXG4vKipcbiAqIENoZWNrIHdoaWNoIGZyYW1ld29yayBhIGNlcnRhaW4gSlMgQnVuZGxlIGNvZGUgYmFzZWQgdG8uIEFuZCBjcmVhdGUgaW5zdGFuY2VcbiAqIGJ5IHRoaXMgZnJhbWV3b3JrLlxuICogQHBhcmFtIHtzdHJpbmd9IGlkXG4gKiBAcGFyYW0ge3N0cmluZ30gY29kZVxuICogQHBhcmFtIHtvYmplY3R9IGNvbmZpZ1xuICogQHBhcmFtIHtvYmplY3R9IGRhdGFcbiAqL1xuZnVuY3Rpb24gY3JlYXRlSW5zdGFuY2UgKGlkLCBjb2RlLCBjb25maWcsIGRhdGEpIHtcbiAgaWYgKGluc3RhbmNlVHlwZU1hcFtpZF0pIHtcbiAgICByZXR1cm4gbmV3IEVycm9yKGBUaGUgaW5zdGFuY2UgaWQgXCIke2lkfVwiIGhhcyBhbHJlYWR5IGJlZW4gdXNlZCFgKVxuICB9XG5cbiAgLy8gSW5pdCBpbnN0YW5jZSBpbmZvLlxuICBjb25zdCBidW5kbGVUeXBlID0gZ2V0QnVuZGxlVHlwZShjb2RlKVxuICBpbnN0YW5jZVR5cGVNYXBbaWRdID0gYnVuZGxlVHlwZVxuXG4gIC8vIEluaXQgaW5zdGFuY2UgY29uZmlnLlxuICBjb25maWcgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGNvbmZpZyB8fCB7fSkpXG4gIGNvbmZpZy5lbnYgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGdsb2JhbC5XWEVudmlyb25tZW50IHx8IHt9KSlcbiAgY29uZmlnLmJ1bmRsZVR5cGUgPSBidW5kbGVUeXBlXG5cbiAgY29uc3QgZnJhbWV3b3JrID0gcnVudGltZUNvbmZpZy5mcmFtZXdvcmtzW2J1bmRsZVR5cGVdXG4gIGlmICghZnJhbWV3b3JrKSB7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihgW0pTIEZyYW1ld29ya10gSW52YWxpZCBidW5kbGUgdHlwZSBcIiR7YnVuZGxlVHlwZX1cIi5gKVxuICB9XG4gIGlmIChidW5kbGVUeXBlID09PSAnV2VleCcpIHtcbiAgICBjb25zb2xlLmVycm9yKGBbSlMgRnJhbWV3b3JrXSBDT01QQVRJQklMSVRZIFdBUk5JTkc6IGBcbiAgICAgICsgYFdlZXggRFNMIDEuMCAoLndlKSBmcmFtZXdvcmsgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZCEgYFxuICAgICAgKyBgSXQgd2lsbCBiZSByZW1vdmVkIGluIHRoZSBuZXh0IHZlcnNpb24gb2YgV2VleFNESywgYFxuICAgICAgKyBgeW91ciBwYWdlIHdvdWxkIGJlIGNyYXNoIGlmIHlvdSBzdGlsbCB1c2luZyB0aGUgXCIud2VcIiBmcmFtZXdvcmsuIGBcbiAgICAgICsgYFBsZWFzZSB1cGdyYWRlIGl0IHRvIFZ1ZS5qcyBvciBSYXguYClcbiAgfVxuXG4gIGNvbnN0IGluc3RhbmNlQ29udGV4dCA9IGNyZWF0ZUluc3RhbmNlQ29udGV4dChpZCwgY29uZmlnLCBkYXRhKVxuICBpZiAodHlwZW9mIGZyYW1ld29yay5jcmVhdGVJbnN0YW5jZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIC8vIFRlbXBvcmFyeSBjb21wYXRpYmxlIHdpdGggc29tZSBsZWdhY3kgQVBJcyBpbiBSYXgsXG4gICAgLy8gc29tZSBSYXggcGFnZSBpcyB1c2luZyB0aGUgbGVnYWN5IFwiLndlXCIgZnJhbWV3b3JrLlxuICAgIGlmIChidW5kbGVUeXBlID09PSAnUmF4JyB8fCBidW5kbGVUeXBlID09PSAnV2VleCcpIHtcbiAgICAgIGNvbnN0IHJheEluc3RhbmNlQ29udGV4dCA9IE9iamVjdC5hc3NpZ24oe1xuICAgICAgICBjb25maWcsXG4gICAgICAgIGNyZWF0ZWQ6IERhdGUubm93KCksXG4gICAgICAgIGZyYW1ld29yazogYnVuZGxlVHlwZVxuICAgICAgfSwgaW5zdGFuY2VDb250ZXh0KVxuICAgICAgcmV0dXJuIGZyYW1ld29yay5jcmVhdGVJbnN0YW5jZShpZCwgY29kZSwgY29uZmlnLCBkYXRhLCByYXhJbnN0YW5jZUNvbnRleHQpXG4gICAgfVxuICAgIHJldHVybiBmcmFtZXdvcmsuY3JlYXRlSW5zdGFuY2UoaWQsIGNvZGUsIGNvbmZpZywgZGF0YSwgaW5zdGFuY2VDb250ZXh0KVxuICB9XG4gIC8vIGNvbnNvbGUuZXJyb3IoYFtKUyBGcmFtZXdvcmtdIENhbid0IGZpbmQgYXZhaWxhYmxlIFwiY3JlYXRlSW5zdGFuY2VcIiBtZXRob2QgaW4gJHtidW5kbGVUeXBlfSFgKVxuICBydW5JbkNvbnRleHQoY29kZSwgaW5zdGFuY2VDb250ZXh0KVxufVxuXG4vKipcbiAqIFJ1biBqcyBjb2RlIGluIGEgc3BlY2lmaWMgY29udGV4dC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjb2RlXG4gKiBAcGFyYW0ge29iamVjdH0gY29udGV4dFxuICovXG5mdW5jdGlvbiBydW5JbkNvbnRleHQgKGNvZGUsIGNvbnRleHQpIHtcbiAgY29uc3Qga2V5cyA9IFtdXG4gIGNvbnN0IGFyZ3MgPSBbXVxuICBmb3IgKGNvbnN0IGtleSBpbiBjb250ZXh0KSB7XG4gICAga2V5cy5wdXNoKGtleSlcbiAgICBhcmdzLnB1c2goY29udGV4dFtrZXldKVxuICB9XG5cbiAgY29uc3QgYnVuZGxlID0gYFxuICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAke2NvZGV9XG4gICAgfSkoT2JqZWN0LmNyZWF0ZSh0aGlzKSlcbiAgYFxuXG4gIHJldHVybiAobmV3IEZ1bmN0aW9uKC4uLmtleXMsIGJ1bmRsZSkpKC4uLmFyZ3MpXG59XG5cbi8qKlxuICogR2V0IHRoZSBKU09OIG9iamVjdCBvZiB0aGUgcm9vdCBlbGVtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGluc3RhbmNlSWRcbiAqL1xuZnVuY3Rpb24gZ2V0Um9vdCAoaW5zdGFuY2VJZCkge1xuICBjb25zdCBkb2N1bWVudCA9IGdldERvYyhpbnN0YW5jZUlkKVxuICB0cnkge1xuICAgIGlmIChkb2N1bWVudCAmJiBkb2N1bWVudC5ib2R5KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuYm9keS50b0pTT04oKVxuICAgIH1cbiAgfVxuICBjYXRjaCAoZSkge1xuICAgIGNvbnNvbGUuZXJyb3IoYFtKUyBGcmFtZXdvcmtdIEZhaWxlZCB0byBnZXQgdGhlIHZpcnR1YWwgZG9tIHRyZWUuYClcbiAgICByZXR1cm5cbiAgfVxufVxuXG5jb25zdCBtZXRob2RzID0ge1xuICBjcmVhdGVJbnN0YW5jZSxcbiAgY3JlYXRlSW5zdGFuY2VDb250ZXh0LFxuICBnZXRSb290LFxuICBnZXREb2N1bWVudDogZ2V0RG9jLFxuICByZWdpc3RlclNlcnZpY2U6IHJlZ2lzdGVyLFxuICB1bnJlZ2lzdGVyU2VydmljZTogdW5yZWdpc3RlcixcbiAgY2FsbEpTIChpZCwgdGFza3MpIHtcbiAgICBjb25zdCBmcmFtZXdvcmsgPSBmcmFtZXdvcmtzW2dldEZyYW1ld29ya1R5cGUoaWQpXVxuICAgIGlmIChmcmFtZXdvcmsgJiYgdHlwZW9mIGZyYW1ld29yay5yZWNlaXZlVGFza3MgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiBmcmFtZXdvcmsucmVjZWl2ZVRhc2tzKGlkLCB0YXNrcylcbiAgICB9XG4gICAgcmV0dXJuIHJlY2VpdmVUYXNrcyhpZCwgdGFza3MpXG4gIH1cbn1cblxuLyoqXG4gKiBSZWdpc3RlciBtZXRob2RzIHdoaWNoIHdpbGwgYmUgY2FsbGVkIGZvciBlYWNoIGluc3RhbmNlLlxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZE5hbWVcbiAqL1xuZnVuY3Rpb24gZ2VuSW5zdGFuY2UgKG1ldGhvZE5hbWUpIHtcbiAgbWV0aG9kc1ttZXRob2ROYW1lXSA9IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgY29uc3QgaWQgPSBhcmdzWzBdXG4gICAgY29uc3QgdHlwZSA9IGdldEZyYW1ld29ya1R5cGUoaWQpXG4gICAgaWYgKHR5cGUgJiYgZnJhbWV3b3Jrc1t0eXBlXSkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gZnJhbWV3b3Jrc1t0eXBlXVttZXRob2ROYW1lXSguLi5hcmdzKVxuICAgICAgY29uc3QgaW5mbyA9IHsgZnJhbWV3b3JrOiB0eXBlIH1cblxuICAgICAgLy8gTGlmZWN5Y2xlIG1ldGhvZHNcbiAgICAgIGlmIChtZXRob2ROYW1lID09PSAncmVmcmVzaEluc3RhbmNlJykge1xuICAgICAgICBzZXJ2aWNlcy5mb3JFYWNoKHNlcnZpY2UgPT4ge1xuICAgICAgICAgIGNvbnN0IHJlZnJlc2ggPSBzZXJ2aWNlLm9wdGlvbnMucmVmcmVzaFxuICAgICAgICAgIGlmIChyZWZyZXNoKSB7XG4gICAgICAgICAgICByZWZyZXNoKGlkLCB7IGluZm8sIHJ1bnRpbWU6IHJ1bnRpbWVDb25maWcgfSlcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgICBlbHNlIGlmIChtZXRob2ROYW1lID09PSAnZGVzdHJveUluc3RhbmNlJykge1xuICAgICAgICBzZXJ2aWNlcy5mb3JFYWNoKHNlcnZpY2UgPT4ge1xuICAgICAgICAgIGNvbnN0IGRlc3Ryb3kgPSBzZXJ2aWNlLm9wdGlvbnMuZGVzdHJveVxuICAgICAgICAgIGlmIChkZXN0cm95KSB7XG4gICAgICAgICAgICBkZXN0cm95KGlkLCB7IGluZm8sIHJ1bnRpbWU6IHJ1bnRpbWVDb25maWcgfSlcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIGRlbGV0ZSBpbnN0YW5jZVR5cGVNYXBbaWRdXG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXN1bHRcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBFcnJvcihgW0pTIEZyYW1ld29ya10gVXNpbmcgaW52YWxpZCBpbnN0YW5jZSBpZCBgXG4gICAgICArIGBcIiR7aWR9XCIgd2hlbiBjYWxsaW5nICR7bWV0aG9kTmFtZX0uYClcbiAgfVxufVxuXG4vKipcbiAqIFJlZ2lzdGVyIG1ldGhvZHMgd2hpY2ggaW5pdCBlYWNoIGZyYW1ld29ya3MuXG4gKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kTmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gc2hhcmVkTWV0aG9kXG4gKi9cbmZ1bmN0aW9uIGFkYXB0TWV0aG9kIChtZXRob2ROYW1lLCBzaGFyZWRNZXRob2QpIHtcbiAgbWV0aG9kc1ttZXRob2ROYW1lXSA9IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgaWYgKHR5cGVvZiBzaGFyZWRNZXRob2QgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHNoYXJlZE1ldGhvZCguLi5hcmdzKVxuICAgIH1cblxuICAgIC8vIFRPRE86IGRlcHJlY2F0ZWRcbiAgICBmb3IgKGNvbnN0IG5hbWUgaW4gcnVudGltZUNvbmZpZy5mcmFtZXdvcmtzKSB7XG4gICAgICBjb25zdCBmcmFtZXdvcmsgPSBydW50aW1lQ29uZmlnLmZyYW1ld29ya3NbbmFtZV1cbiAgICAgIGlmIChmcmFtZXdvcmsgJiYgZnJhbWV3b3JrW21ldGhvZE5hbWVdKSB7XG4gICAgICAgIGZyYW1ld29ya1ttZXRob2ROYW1lXSguLi5hcmdzKVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBpbml0IChjb25maWcpIHtcbiAgcnVudGltZUNvbmZpZyA9IGNvbmZpZyB8fCB7fVxuICBmcmFtZXdvcmtzID0gcnVudGltZUNvbmZpZy5mcmFtZXdvcmtzIHx8IHt9XG4gIGluaXRUYXNrSGFuZGxlcigpXG5cbiAgLy8gSW5pdCBlYWNoIGZyYW1ld29yayBieSBgaW5pdGAgbWV0aG9kIGFuZCBgY29uZmlnYCB3aGljaCBjb250YWlucyB0aHJlZVxuICAvLyB2aXJ0dWFsLURPTSBDbGFzczogYERvY3VtZW50YCwgYEVsZW1lbnRgICYgYENvbW1lbnRgLCBhbmQgYSBKUyBicmlkZ2UgbWV0aG9kOlxuICAvLyBgc2VuZFRhc2tzKC4uLmFyZ3MpYC5cbiAgZm9yIChjb25zdCBuYW1lIGluIGZyYW1ld29ya3MpIHtcbiAgICBjb25zdCBmcmFtZXdvcmsgPSBmcmFtZXdvcmtzW25hbWVdXG4gICAgaWYgKHR5cGVvZiBmcmFtZXdvcmsuaW5pdCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZnJhbWV3b3JrLmluaXQoY29uZmlnKVxuICAgICAgfVxuICAgICAgY2F0Y2ggKGUpIHt9XG4gICAgfVxuICB9XG5cbiAgYWRhcHRNZXRob2QoJ3JlZ2lzdGVyQ29tcG9uZW50cycsIHJlZ2lzdGVyQ29tcG9uZW50cylcbiAgYWRhcHRNZXRob2QoJ3JlZ2lzdGVyTW9kdWxlcycsIHJlZ2lzdGVyTW9kdWxlcylcbiAgYWRhcHRNZXRob2QoJ3JlZ2lzdGVyTWV0aG9kcycpXG5cbiAgOyBbJ2Rlc3Ryb3lJbnN0YW5jZScsICdyZWZyZXNoSW5zdGFuY2UnXS5mb3JFYWNoKGdlbkluc3RhbmNlKVxuXG4gIHJldHVybiBtZXRob2RzXG59XG4iLCIvKlxuICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZVxuICogb3IgbW9yZSBjb250cmlidXRvciBsaWNlbnNlIGFncmVlbWVudHMuICBTZWUgdGhlIE5PVElDRSBmaWxlXG4gKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvblxuICogcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZVxuICogdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZVxuICogXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsXG4gKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhblxuICogXCJBUyBJU1wiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcbiAqIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZVxuICogc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9uc1xuICogdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IE5vZGUgZnJvbSAnLi9Ob2RlJ1xuaW1wb3J0IEVsZW1lbnQgZnJvbSAnLi9FbGVtZW50J1xuaW1wb3J0IENvbW1lbnQgZnJvbSAnLi9Db21tZW50J1xuaW1wb3J0IERvY3VtZW50IGZyb20gJy4vRG9jdW1lbnQnXG5cbmV4cG9ydCB7XG4gIHJlZ2lzdGVyRWxlbWVudCxcbiAgdW5yZWdpc3RlckVsZW1lbnQsXG4gIGlzV2VleEVsZW1lbnQsXG4gIGNsZWFyV2VleEVsZW1lbnRzXG59IGZyb20gJy4vV2VleEVsZW1lbnQnXG5cbmV4cG9ydCB7XG4gIERvY3VtZW50LFxuICBOb2RlLFxuICBFbGVtZW50LFxuICBDb21tZW50XG59XG4iLCIvKlxuICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZVxuICogb3IgbW9yZSBjb250cmlidXRvciBsaWNlbnNlIGFncmVlbWVudHMuICBTZWUgdGhlIE5PVElDRSBmaWxlXG4gKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvblxuICogcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZVxuICogdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZVxuICogXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsXG4gKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhblxuICogXCJBUyBJU1wiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcbiAqIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZVxuICogc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9uc1xuICogdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgRG9jdW1lbnQsIEVsZW1lbnQsIENvbW1lbnQgfSBmcm9tICcuLi92ZG9tJ1xuaW1wb3J0IExpc3RlbmVyIGZyb20gJy4uL2JyaWRnZS9MaXN0ZW5lcidcbmltcG9ydCB7IFRhc2tDZW50ZXIgfSBmcm9tICcuLi9icmlkZ2UvVGFza0NlbnRlcidcblxuY29uc3QgY29uZmlnID0ge1xuICBEb2N1bWVudCwgRWxlbWVudCwgQ29tbWVudCwgTGlzdGVuZXIsXG4gIFRhc2tDZW50ZXIsXG4gIHNlbmRUYXNrcyAoLi4uYXJncykge1xuICAgIGlmICh0eXBlb2YgY2FsbE5hdGl2ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIGNhbGxOYXRpdmUoLi4uYXJncylcbiAgICB9XG4gICAgcmV0dXJuIChnbG9iYWwuY2FsbE5hdGl2ZSB8fCAoKCkgPT4ge30pKSguLi5hcmdzKVxuICB9XG59XG5cbkRvY3VtZW50LmhhbmRsZXIgPSBjb25maWcuc2VuZFRhc2tzXG5cbmV4cG9ydCBkZWZhdWx0IGNvbmZpZ1xuIiwiLypcbiAqIExpY2Vuc2VkIHRvIHRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiAoQVNGKSB1bmRlciBvbmVcbiAqIG9yIG1vcmUgY29udHJpYnV0b3IgbGljZW5zZSBhZ3JlZW1lbnRzLiAgU2VlIHRoZSBOT1RJQ0UgZmlsZVxuICogZGlzdHJpYnV0ZWQgd2l0aCB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb25cbiAqIHJlZ2FyZGluZyBjb3B5cmlnaHQgb3duZXJzaGlwLiAgVGhlIEFTRiBsaWNlbnNlcyB0aGlzIGZpbGVcbiAqIHRvIHlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGVcbiAqIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogd2l0aCB0aGUgTGljZW5zZS4gIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLFxuICogc29mdHdhcmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW5cbiAqIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXG4gKiBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLiAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGVcbiAqIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQgbGltaXRhdGlvbnNcbiAqIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCBpbml0IGZyb20gJy4vaW5pdCdcbmltcG9ydCBjb25maWcgZnJvbSAnLi9jb25maWcnXG5pbXBvcnQgeyByZWdpc3RlciwgdW5yZWdpc3RlciwgaGFzIH0gZnJvbSAnLi9zZXJ2aWNlJ1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuZnVuY3Rpb24gZnJlZXplUHJvdG90eXBlICgpIHtcbiAgLy8gT2JqZWN0LmZyZWV6ZShjb25maWcuRWxlbWVudClcbiAgT2JqZWN0LmZyZWV6ZShjb25maWcuQ29tbWVudClcbiAgT2JqZWN0LmZyZWV6ZShjb25maWcuTGlzdGVuZXIpXG4gIE9iamVjdC5mcmVlemUoY29uZmlnLkRvY3VtZW50LnByb3RvdHlwZSlcbiAgLy8gT2JqZWN0LmZyZWV6ZShjb25maWcuRWxlbWVudC5wcm90b3R5cGUpXG4gIE9iamVjdC5mcmVlemUoY29uZmlnLkNvbW1lbnQucHJvdG90eXBlKVxuICBPYmplY3QuZnJlZXplKGNvbmZpZy5MaXN0ZW5lci5wcm90b3R5cGUpXG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgc2VydmljZTogeyByZWdpc3RlciwgdW5yZWdpc3RlciwgaGFzIH0sXG4gIGZyZWV6ZVByb3RvdHlwZSxcbiAgaW5pdCxcbiAgY29uZmlnXG59XG4iXSwibmFtZXMiOlsibGV0IiwiY29uc3QiLCJFbGVtZW50Iiwic3VwZXIiLCJ0YXNrQ2VudGVyIiwicHVyZUJlZm9yZSIsImluZGV4IiwidGhpcyIsImluaXQiLCJuYW1lIiwic2VydmljZXMiLCJpbml0VGFza0hhbmRsZXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7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 diff --git a/scripts/check-and-publish.js b/scripts/check-and-publish.js index 55bcdf60ef..05c04046e2 100644 --- a/scripts/check-and-publish.js +++ b/scripts/check-and-publish.js @@ -6,7 +6,6 @@ const { join } = require('path'); const { spawnSync } = require('child_process'); const axios = require('axios'); const semver = require('semver'); -const { IGNORE_PACKAGES } = require('./constants'); const RETRY_LIMIT = 8; const TIMEOUT = 5000; @@ -111,7 +110,6 @@ function checkVersionAndPublish() { if (ret.length > 0) { for (let i = 0; i < ret.length; i++) { const { name, workDir, local, tag } = ret[i]; - if (IGNORE_PACKAGES.includes(name)) continue; publish(name, workDir, local, tag); } } diff --git a/scripts/compile.js b/scripts/compile.js index 662524a971..7c22b5c6db 100644 --- a/scripts/compile.js +++ b/scripts/compile.js @@ -20,7 +20,6 @@ const glob = require('glob'); const minimatch = require('minimatch'); const parseArgs = require('minimist'); const chokidar = require('chokidar'); -const { IGNORE_PACKAGES } = require('./constants'); const SRC_DIR = 'src'; const JS_FILES_PATTERN = '**/*.js'; @@ -47,8 +46,6 @@ function buildPackage(packagesDir, p, isBuildEs) { const files = glob.sync(pattern, {nodir: true}); const dirName = path.basename(p); - if (IGNORE_PACKAGES.includes(dirName)) return; - process.stdout.write( fixedWidth(`${dirName}\n`) ); diff --git a/scripts/constants.js b/scripts/constants.js deleted file mode 100644 index 8128e68ac1..0000000000 --- a/scripts/constants.js +++ /dev/null @@ -1,2 +0,0 @@ -// Won't update packages -exports.IGNORE_PACKAGES = ['rax-miniapp-renderer', 'runtime-shared', 'weex-rax-framework', 'web-rax-framework', 'weex-rax-framework-api']; diff --git a/scripts/dist-core.js b/scripts/dist-core.js index ccfecdc245..90fb5534f3 100755 --- a/scripts/dist-core.js +++ b/scripts/dist-core.js @@ -12,7 +12,6 @@ const gzipSize = require('gzip-size'); const IIFE = 'iife'; const UMD = 'umd'; const ESM = 'esm'; -const CJS = 'cjs'; function transformBundleFormat({ input, name, format, entry, shouldExportDefault }) { return format === IIFE ? virtual({ @@ -132,11 +131,3 @@ buildCorePackages('rax', 'Rax'); buildCorePackages('driver-dom', 'DriverDOM'); buildCorePackages('driver-kraken', 'DriverKraken'); buildCorePackages('driver-weex', 'DriverWeex'); - -build({ package: 'driver-worker', name: 'DriverWorker' }); -build({ package: 'driver-worker', name: 'DriverWorker', format: IIFE, shouldExportDefault: true }); -build({ package: 'driver-worker', name: 'DriverWorker', format: IIFE, shouldExportDefault: true, shouldMinify: true }); -build({ package: 'driver-worker', name: 'DriverWorker', format: ESM }); - -build({ package: 'rax-miniapp-renderer', format: CJS }); -build({ package: 'rax-miniapp-renderer', format: CJS, shouldMinify: true });