<commit_before>/* eslint-disable react/prop-types */
import {graphql} from 'react-apollo'
import React from 'react'
import Loading from './Loading'
import ErrorComponent from './Error'
import getVariables from './getVariables'
import NetworkError from './NetworkError'

export default function(query, userConfig = {}) {
  return function(ComposedComponent) {
    const defaultConfig = {
      loading: <Loading />,
      errorComponent: ErrorComponent,
      tryRefetch: 0
    }

    const config = {...defaultConfig, ...userConfig}
    class GraphQLQuery extends React.Component {
      hasData() {
        return Object.keys(this.props._data).length > 10
      }

      renderLoading() {
        if (!config.loading) return this.renderComposed()
        if (userConfig.loading) return config.loading
        // eslint-disable-next-line
        return global.apolloLoadingComponent ? <global.apolloLoadingComponent /> : config.loading
      }

      renderNetworkError() {
        if (this.hasData()) return this.renderComposed()
        if (!global.apolloNetworkErrorComponent && config.loading) return this.renderLoading()
        const GlobalComponent = global.apolloNetworkErrorComponent
        const ConfigComponent = userConfig.networkErrorComponent
        if (ConfigComponent !== null) {
          if (ConfigComponent) return <ConfigComponent />
          return GlobalComponent ? <GlobalComponent /> : <NetworkError />
        }
        return this.renderComposed()
      }

      renderError(error) {
        error = error || this.props.error
        if (error.networkError) return this.renderNetworkError()
        return global.apolloErrorComponent ? (
          // eslint-disable-next-line
          <global.apolloErrorComponent error={error} />
        ) : (
          <ErrorComponent error={error} />
        )
      }

      renderComposed() {
        try {
          return <ComposedComponent {...this.props} />
        } catch (error) {
          return this.renderError(error)
        }
      }

      render() {
        if (this.props.networkStatus === 1) {
          return this.renderLoading()
        }

        if (this.props.networkStatus < 7 && !this.hasData()) {
          return this.renderLoading()
        }

        if (this.props.error) {
          return this.renderError()
        }

        return this.renderComposed()
      }
    }

    const WithGraphQL = graphql(query, {
      ...config,
      props: ({ownProps, data}) => {
        return {
          _data: data,
          ...ownProps,
          ...data
        }
      },
      options: props => {
        const options = config.options
        const userOptions = (typeof options === 'function' ? options(props) : options) || {}
        if (userOptions.pollInterval && !userOptions.fetchPolicy) {
          userOptions.fetchPolicy = 'network-only'
        }
        return {
          fetchPolicy: 'cache-and-network', // default option
          ...userOptions,
          variables: {
            ...getVariables(query, config, props),
            ...(userOptions.variables || {})
          }
        }
      }
    })(GraphQLQuery)

    WithGraphQL.propTypes = ComposedComponent.propTypes
    WithGraphQL.defaultProps = ComposedComponent.defaultProps
    WithGraphQL.navigationOptions = ComposedComponent.navigationOptions

    return WithGraphQL
  }
}
<commit_msg>change default fetch policy<commit_after>/* eslint-disable react/prop-types */
import {graphql} from 'react-apollo'
import React from 'react'
import Loading from './Loading'
import ErrorComponent from './Error'
import getVariables from './getVariables'
import NetworkError from './NetworkError'

export default function(query, userConfig = {}) {
  return function(ComposedComponent) {
    const defaultConfig = {
      loading: <Loading />,
      errorComponent: ErrorComponent,
      tryRefetch: 0
    }

    const config = {...defaultConfig, ...userConfig}
    class GraphQLQuery extends React.Component {
      hasData() {
        return Object.keys(this.props._data).length > 10
      }

      renderLoading() {
        if (!config.loading) return this.renderComposed()
        if (userConfig.loading) return config.loading
        // eslint-disable-next-line
        return global.apolloLoadingComponent ? <global.apolloLoadingComponent /> : config.loading
      }

      renderNetworkError() {
        if (this.hasData()) return this.renderComposed()
        if (!global.apolloNetworkErrorComponent && config.loading) return this.renderLoading()
        const GlobalComponent = global.apolloNetworkErrorComponent
        const ConfigComponent = userConfig.networkErrorComponent
        if (ConfigComponent !== null) {
          if (ConfigComponent) return <ConfigComponent />
          return GlobalComponent ? <GlobalComponent /> : <NetworkError />
        }
        return this.renderComposed()
      }

      renderError(error) {
        error = error || this.props.error
        if (error.networkError) return this.renderNetworkError()
        return global.apolloErrorComponent ? (
          // eslint-disable-next-line
          <global.apolloErrorComponent error={error} />
        ) : (
          <ErrorComponent error={error} />
        )
      }

      renderComposed() {
        try {
          return <ComposedComponent {...this.props} />
        } catch (error) {
          return this.renderError(error)
        }
      }

      render() {
        const {networkStatus, error} = this.props
        if (networkStatus === 1) {
          return this.renderLoading()
        }

        if (networkStatus < 7 && !this.hasData()) {
          return this.renderLoading()
        }

        if (error) {
          return this.renderError()
        }

        return this.renderComposed()
      }
    }

    const WithGraphQL = graphql(query, {
      ...config,
      props: ({ownProps, data}) => {
        return {
          _data: data,
          ...ownProps,
          ...data
        }
      },
      options: props => {
        const options = config.options
        const userOptions = (typeof options === 'function' ? options(props) : options) || {}
        if (userOptions.pollInterval && !userOptions.fetchPolicy) {
          userOptions.fetchPolicy = 'network-only'
        }
        return {
          notifyOnNetworkStatusChange: true,
          // fetchPolicy: 'cache-and-network', // default option
          ...userOptions,
          variables: {
            ...getVariables(query, config, props),
            ...(userOptions.variables || {})
          }
        }
      }
    })(GraphQLQuery)

    WithGraphQL.propTypes = ComposedComponent.propTypes
    WithGraphQL.defaultProps = ComposedComponent.defaultProps
    WithGraphQL.navigationOptions = ComposedComponent.navigationOptions

    return WithGraphQL
  }
}
<|endoftext|>


<commit_before>(function (global, m) {

    var app = global.app = global.app || {};

    //predefine a mithril-based model for json data we're going to receive
    var Customer = function (jsonData) {
        var data = jsonData.value[0];
        this.id = m.prop(jsonData.CustomerID);
        this.name = m.prop(jsonData.ContactName);
        this.company = m.prop(jsonData.CompanyName);
        this.address = m.prop(jsonData.Address);
        this.city = m.prop(jsonData.City);
        this.postalCode = m.prop(jsonData.PostalCode);
        this.country = m.prop(jsonData.Country);
        this.phone = m.prop(jsonData.Phone);
    };

    app.Customers = function () {
        return m.request(
            {
                method: "GET",
                url: 'http://services.odata.org/Northwind/Northwind.svc/Customers?$format=json',
                //type: Customer //cast the received json payload to "Customer"
            });
    };

    //init the view model
    app.vm = {};
    app.vm.init = function () {
        this.customers = new app.Customers();
    };

}(window, Mithril));<commit_msg>'clenup'<commit_after>(function (global, m) {

    var app = global.app = global.app || {};

    //Here we use Mithrils "request" method to connect the Service and get the data.
    //Optionally we could predefine a "model class" and let Mithril process data according to its properties.
    //For example:
    //var Customer = {
    //      id: jsonData.CustomerID,
    //      name: jsonData.CustomerName,
    //      company: jsonData.CompanyName
    //  }
    //
    //then we'd call the same m.request method with an additional parameter: "type":
    //      m.request = ( method: "GET", url: "service_url", type: Customer )
    //
    //Mithril would then use this class to preprocess received data
    //
    //But in this example we will use Kendo-Framework's DataSource functionality to preprocess JSON data
    //More info here: http://docs.telerik.com/kendo-ui/api/javascript/data/datasource
    //
    app.Customers = function () {
        return m.request(
            {
                method: "GET",
                url: 'http://services.odata.org/Northwind/Northwind.svc/Customers?$format=json',
            });
    };

    //init the view model
    app.vm = {};
    app.vm.init = function () {
        this.customers = new app.Customers();
    };

}(window, Mithril));<|endoftext|>


<commit_before>import { before, beforeEach, context, describe, it } from '!mocha'
import assert from 'power-assert'
import proxyquire from 'proxyquire'
import { spy, stub } from 'sinon'

describe('expose-events', () => {
  before(ctx => {
    ctx.process = stub({ nextTick () {} })
    ctx.exposeEvents = proxyquire.noCallThru()('../lib/expose-events', {
      './process': ctx.process
    })['default']
  })

  beforeEach(ctx => {
    ctx.process.nextTick.reset()
  })

  describe('exposeEvents (target)', () => {
    it('correctly defines on, once and removeListener on target', ctx => {
      const target = {}
      ctx.exposeEvents(target)

      for (const prop of ['on', 'once', 'removeListener']) {
        const { value, configurable, enumerable, writable } = Object.getOwnPropertyDescriptor(target, prop)
        assert(typeof value === 'function', prop)
        assert(configurable, prop)
        assert(!enumerable, prop)
        assert(writable, prop)
      }
    })

    it('returns an emitter', ctx => {
      const emitter = ctx.exposeEvents({})
      assert(typeof emitter.emit === 'function')
    })

    ;['on', 'once', 'removeListener'].forEach(method => {
      describe(`target.${method} (event, listener)`, ctx => {
        beforeEach(ctx => {
          ctx.target = {}
          ctx.emitter = ctx.exposeEvents(ctx.target)
          stub(ctx.emitter, method)
        })

        it('propagates the arguments to the emitter', ctx => {
          const args = [Symbol(), Symbol()]
          ctx.target[method](...args)

          assert(ctx.emitter[method].calledOnce)
          const { args: propagated } = ctx.emitter[method].firstCall
          assert.deepStrictEqual(propagated, args)
        })

        it('returns the thisArg', ctx => {
          const thisArg = Symbol()
          assert(ctx.target[method].call(thisArg) === thisArg)
        })
      })
    })
  })

  describe('the emitter returned by exposeEvents(target)', () => {
    const makeEmitter = ctx => {
      ctx.target = {}
      ctx.emitter = ctx.exposeEvents(ctx.target)
    }

    beforeEach(makeEmitter)

    ;['on', 'once'].forEach(method => {
      describe(`emitter.${method} (event, listener)`, () => {
        beforeEach(ctx => {
          ctx.event = Symbol
          ctx.listener = spy()
          ctx.emitter[method](ctx.event, ctx.listener)
        })

        context('listener is not a function', () => {
          it('throws a TypeError', ctx => {
            assert.throws(
              () => ctx.emitter[method](ctx.event),
              TypeError, "Parameter 'listener' must be a function, not undefined")
          })
        })

        it('registers the listener for the event', ctx => {
          ctx.emitter.emit(ctx.event)
          assert(ctx.listener.calledOnce)
        })

        describe('the listener', () => {
          it('is called with the target as the thisArg', ctx => {
            ctx.emitter.emit(ctx.event)
            const { thisValue: target } = ctx.listener.firstCall
            assert(target === ctx.target)
          })

          context('is registered more than once for the same event', () => {
            beforeEach(ctx => ctx.emitter[method](ctx.event, ctx.listener))

            it('is called once per emitted event', ctx => {
              ctx.emitter.emit(ctx.event)
              assert(ctx.listener.calledOnce)
            })
          })

          context('is registered for different events', () => {
            beforeEach(ctx => {
              ctx.event2 = Symbol()
              ctx.emitter[method](ctx.event2, ctx.listener)
            })

            it('is called for each event', ctx => {
              const [first, second] = [Symbol(), Symbol()]

              ctx.emitter.emit(ctx.event, first)
              ctx.emitter.emit(ctx.event2, second)

              const { args: [[firstValue], [secondValue]] } = ctx.listener
              assert(firstValue === first)
              assert(secondValue === second)
            })
          })
        })

        context('the event is emitted multiple times', () => {
          const eachTime = () => {
            describe('the listener', () => {
              it('is called each time', ctx => {
                [Symbol(), Symbol(), Symbol()].forEach((arg, n) => {
                  ctx.emitter.emit(ctx.event, arg)
                  assert(ctx.listener.callCount === n + 1)
                  const { args: [value] } = ctx.listener.getCall(n)
                  assert(value === arg)
                })
              })
            })
          }
          const oneTime = () => {
            describe('the listener', () => {
              it('is called only once', ctx => {
                const first = Symbol()
                ;[first, Symbol(), Symbol()].forEach((arg, n) => {
                  ctx.emitter.emit(ctx.event, arg)
                  assert(ctx.listener.calledOnce)
                  const { args: [value] } = ctx.listener.firstCall
                  assert(value === first)
                })
              })
            })
          }

          if (method === 'on') {
            eachTime()
          } else {
            oneTime()
          }

          context(`the listener was previously registered for the same event using emitter.${method === 'on' ? 'once' : 'on'}()`, () => {
            beforeEach(ctx => {
              makeEmitter(ctx)
              if (method === 'on') {
                ctx.emitter.once(ctx.event, ctx.listener)
              } else {
                ctx.emitter.on(ctx.event, ctx.listener)
              }
              ctx.emitter[method](ctx.event, ctx.listener)
            })

            eachTime()
          })
        })

        if (method === 'once') {
          context('another listener was registered after the once listener', () => {
            describe('the second listener', () => {
              it('is called after the first', ctx => {
                const listener2 = spy()
                ctx.emitter.on(ctx.event, listener2)

                ctx.emitter.emit(ctx.event)
                assert(ctx.listener.calledBefore(listener2))
              })
            })
          })
        }
      })
    })

    describe(`emitter.removeListener (event, listener)`, () => {
      beforeEach(ctx => {
        ctx.event = Symbol
        ctx.listener = spy()
      })

      context('listener is not a function', () => {
        it('throws a TypeError', ctx => {
          assert.throws(
            () => ctx.emitter.removeListener(ctx.event),
            TypeError, "Parameter 'listener' must be a function, not undefined")
        })
      })

      ;['on', 'once'].forEach(method => {
        context(`the listener was previously registered using emitter.${method}(event, listener)`, () => {
          it('is removed', ctx => {
            ctx.emitter[method](ctx.event, ctx.listener)
            ctx.emitter.removeListener(ctx.event, ctx.listener)

            ctx.emitter.emit(ctx.event)
            assert(ctx.listener.notCalled)
          })
        })
      })

      // Test added for code coverage completeness.
      context('the listener was not registered previously', () => {
        it('is OK', ctx => {
          assert.doesNotThrow(() => ctx.emitter.removeListener(ctx.event, ctx.listener))
        })
      })

      // Test added for code coverage completeness.
      context('another listener was also registered for the same event', () => {
        it('is not removed', ctx => {
          const listener2 = spy()
          ctx.emitter.on(ctx.event, ctx.listener)
          ctx.emitter.on(ctx.event, listener2)
          ctx.emitter.removeListener(ctx.event, ctx.listener)

          ctx.emitter.emit(ctx.event)
          assert(ctx.listener.notCalled)
          assert(listener2.calledOnce)
        })
      })
    })

    describe(`emitter.emit (event, ...params)`, () => {
      beforeEach(ctx => ctx.listener = spy())

      it('calls listeners synchronously', ctx => {
        ctx.emitter.on(ctx.event, ctx.listener)

        ctx.emitter.emit(ctx.event)
        assert(ctx.listener.calledOnce)
      })

      context('listers are only added after emitting', () => {
        it('does not call them', ctx => {
          ctx.emitter.emit(ctx.event)
          ctx.emitter.on(ctx.event, ctx.listener)
          assert(ctx.listener.notCalled)
        })
      })

      context('a listener throws', () => {
        beforeEach(ctx => {
          ctx.err = Symbol()
          ctx.emitter.on(ctx.event, () => { throw ctx.err })
          ctx.emitter.on(ctx.event, ctx.listener)
        })

        describe('the next listener', () => {
          it('is not called', ctx => {
            ctx.emitter.emit(ctx.event)
            assert(ctx.listener.notCalled)
          })
        })

        describe('the error', () => {
          it('is rethrown asynchronously', ctx => {
            ctx.emitter.emit(ctx.event)

            assert(ctx.process.nextTick.calledOnce)
            try {
              ctx.process.nextTick.yield()
              assert(false, 'nextTick should throw')
            } catch (err) {
              assert(err === ctx.err)
            }
          })
        })
      })

      it('calls the listeners with all params', ctx => {
        const params = [Symbol(), Symbol(), Symbol()]
        ctx.emitter.on(ctx.event, ctx.listener)

        ctx.emitter.emit(ctx.event, ...params)
        const { args: allParams } = ctx.listener.firstCall
        assert.deepStrictEqual(allParams, params)
      })
    })
  })
})
<commit_msg>clarify behavior when adding/removing listeners from inside a listener<commit_after>import { before, beforeEach, context, describe, it } from '!mocha'
import assert from 'power-assert'
import proxyquire from 'proxyquire'
import { spy, stub } from 'sinon'

describe('expose-events', () => {
  before(ctx => {
    ctx.process = stub({ nextTick () {} })
    ctx.exposeEvents = proxyquire.noCallThru()('../lib/expose-events', {
      './process': ctx.process
    })['default']
  })

  beforeEach(ctx => {
    ctx.process.nextTick.reset()
  })

  describe('exposeEvents (target)', () => {
    it('correctly defines on, once and removeListener on target', ctx => {
      const target = {}
      ctx.exposeEvents(target)

      for (const prop of ['on', 'once', 'removeListener']) {
        const { value, configurable, enumerable, writable } = Object.getOwnPropertyDescriptor(target, prop)
        assert(typeof value === 'function', prop)
        assert(configurable, prop)
        assert(!enumerable, prop)
        assert(writable, prop)
      }
    })

    it('returns an emitter', ctx => {
      const emitter = ctx.exposeEvents({})
      assert(typeof emitter.emit === 'function')
    })

    ;['on', 'once', 'removeListener'].forEach(method => {
      describe(`target.${method} (event, listener)`, ctx => {
        beforeEach(ctx => {
          ctx.target = {}
          ctx.emitter = ctx.exposeEvents(ctx.target)
          stub(ctx.emitter, method)
        })

        it('propagates the arguments to the emitter', ctx => {
          const args = [Symbol(), Symbol()]
          ctx.target[method](...args)

          assert(ctx.emitter[method].calledOnce)
          const { args: propagated } = ctx.emitter[method].firstCall
          assert.deepStrictEqual(propagated, args)
        })

        it('returns the thisArg', ctx => {
          const thisArg = Symbol()
          assert(ctx.target[method].call(thisArg) === thisArg)
        })
      })
    })
  })

  describe('the emitter returned by exposeEvents(target)', () => {
    const makeEmitter = ctx => {
      ctx.target = {}
      ctx.emitter = ctx.exposeEvents(ctx.target)
    }

    beforeEach(makeEmitter)

    ;['on', 'once'].forEach(method => {
      describe(`emitter.${method} (event, listener)`, () => {
        beforeEach(ctx => {
          ctx.event = Symbol
          ctx.listener = spy()
          ctx.emitter[method](ctx.event, ctx.listener)
        })

        context('listener is not a function', () => {
          it('throws a TypeError', ctx => {
            assert.throws(
              () => ctx.emitter[method](ctx.event),
              TypeError, "Parameter 'listener' must be a function, not undefined")
          })
        })

        it('registers the listener for the event', ctx => {
          ctx.emitter.emit(ctx.event)
          assert(ctx.listener.calledOnce)
        })

        describe('the listener', () => {
          it('is called with the target as the thisArg', ctx => {
            ctx.emitter.emit(ctx.event)
            const { thisValue: target } = ctx.listener.firstCall
            assert(target === ctx.target)
          })

          context('is registered more than once for the same event', () => {
            beforeEach(ctx => ctx.emitter[method](ctx.event, ctx.listener))

            it('is called once per emitted event', ctx => {
              ctx.emitter.emit(ctx.event)
              assert(ctx.listener.calledOnce)
            })
          })

          context('is registered for different events', () => {
            beforeEach(ctx => {
              ctx.event2 = Symbol()
              ctx.emitter[method](ctx.event2, ctx.listener)
            })

            it('is called for each event', ctx => {
              const [first, second] = [Symbol(), Symbol()]

              ctx.emitter.emit(ctx.event, first)
              ctx.emitter.emit(ctx.event2, second)

              const { args: [[firstValue], [secondValue]] } = ctx.listener
              assert(firstValue === first)
              assert(secondValue === second)
            })
          })
        })

        context('the event is emitted multiple times', () => {
          const eachTime = () => {
            describe('the listener', () => {
              it('is called each time', ctx => {
                [Symbol(), Symbol(), Symbol()].forEach((arg, n) => {
                  ctx.emitter.emit(ctx.event, arg)
                  assert(ctx.listener.callCount === n + 1)
                  const { args: [value] } = ctx.listener.getCall(n)
                  assert(value === arg)
                })
              })
            })
          }
          const oneTime = () => {
            describe('the listener', () => {
              it('is called only once', ctx => {
                const first = Symbol()
                ;[first, Symbol(), Symbol()].forEach((arg, n) => {
                  ctx.emitter.emit(ctx.event, arg)
                  assert(ctx.listener.calledOnce)
                  const { args: [value] } = ctx.listener.firstCall
                  assert(value === first)
                })
              })
            })
          }

          if (method === 'on') {
            eachTime()
          } else {
            oneTime()
          }

          context(`the listener was previously registered for the same event using emitter.${method === 'on' ? 'once' : 'on'}()`, () => {
            beforeEach(ctx => {
              makeEmitter(ctx)
              if (method === 'on') {
                ctx.emitter.once(ctx.event, ctx.listener)
              } else {
                ctx.emitter.on(ctx.event, ctx.listener)
              }
              ctx.emitter[method](ctx.event, ctx.listener)
            })

            eachTime()
          })
        })

        if (method === 'once') {
          context('another listener was registered after the once listener', () => {
            describe('the second listener', () => {
              it('is called after the first', ctx => {
                const listener2 = spy()
                ctx.emitter.on(ctx.event, listener2)

                ctx.emitter.emit(ctx.event)
                assert(ctx.listener.calledBefore(listener2))
              })
            })
          })
        }
      })
    })

    describe(`emitter.removeListener (event, listener)`, () => {
      beforeEach(ctx => {
        ctx.event = Symbol
        ctx.listener = spy()
      })

      context('listener is not a function', () => {
        it('throws a TypeError', ctx => {
          assert.throws(
            () => ctx.emitter.removeListener(ctx.event),
            TypeError, "Parameter 'listener' must be a function, not undefined")
        })
      })

      ;['on', 'once'].forEach(method => {
        context(`the listener was previously registered using emitter.${method}(event, listener)`, () => {
          it('is removed', ctx => {
            ctx.emitter[method](ctx.event, ctx.listener)
            ctx.emitter.removeListener(ctx.event, ctx.listener)

            ctx.emitter.emit(ctx.event)
            assert(ctx.listener.notCalled)
          })
        })
      })

      // Test added for code coverage completeness.
      context('the listener was not registered previously', () => {
        it('is OK', ctx => {
          assert.doesNotThrow(() => ctx.emitter.removeListener(ctx.event, ctx.listener))
        })
      })

      // Test added for code coverage completeness.
      context('another listener was also registered for the same event', () => {
        it('is not removed', ctx => {
          const listener2 = spy()
          ctx.emitter.on(ctx.event, ctx.listener)
          ctx.emitter.on(ctx.event, listener2)
          ctx.emitter.removeListener(ctx.event, ctx.listener)

          ctx.emitter.emit(ctx.event)
          assert(ctx.listener.notCalled)
          assert(listener2.calledOnce)
        })
      })
    })

    describe(`emitter.emit (event, ...params)`, () => {
      beforeEach(ctx => ctx.listener = spy())

      it('calls listeners synchronously', ctx => {
        ctx.emitter.on(ctx.event, ctx.listener)

        ctx.emitter.emit(ctx.event)
        assert(ctx.listener.calledOnce)
      })

      context('listers are only added after emitting', () => {
        it('does not call them', ctx => {
          ctx.emitter.emit(ctx.event)
          ctx.emitter.on(ctx.event, ctx.listener)
          assert(ctx.listener.notCalled)
        })
      })

      context('listers are added while emitting', () => {
        it('calls them', ctx => {
          ctx.emitter.on(ctx.event, () => {
            ctx.emitter.on(ctx.event, ctx.listener)
          })

          ctx.emitter.emit(ctx.event)
          assert(ctx.listener.calledOnce)
        })
      })

      context('listers are removed while emitting', () => {
        it('does not call them', ctx => {
          ctx.emitter.on(ctx.event, () => {
            ctx.emitter.removeListener(ctx.event, ctx.listener)
          })
          ctx.emitter.on(ctx.event, ctx.listener)

          ctx.emitter.emit(ctx.event)
          assert(ctx.listener.notCalled)
        })
      })

      context('a listener throws', () => {
        beforeEach(ctx => {
          ctx.err = Symbol()
          ctx.emitter.on(ctx.event, () => { throw ctx.err })
          ctx.emitter.on(ctx.event, ctx.listener)
        })

        describe('the next listener', () => {
          it('is not called', ctx => {
            ctx.emitter.emit(ctx.event)
            assert(ctx.listener.notCalled)
          })
        })

        describe('the error', () => {
          it('is rethrown asynchronously', ctx => {
            ctx.emitter.emit(ctx.event)

            assert(ctx.process.nextTick.calledOnce)
            try {
              ctx.process.nextTick.yield()
              assert(false, 'nextTick should throw')
            } catch (err) {
              assert(err === ctx.err)
            }
          })
        })
      })

      it('calls the listeners with all params', ctx => {
        const params = [Symbol(), Symbol(), Symbol()]
        ctx.emitter.on(ctx.event, ctx.listener)

        ctx.emitter.emit(ctx.event, ...params)
        const { args: allParams } = ctx.listener.firstCall
        assert.deepStrictEqual(allParams, params)
      })
    })
  })
})
<|endoftext|>


<commit_before>(function () {
  var VALID_KEYS = [
    'dropdownVisible',

    // XXX consider replacing these with one key that has an enum for values.
    'inSignupFlow',
    'inForgotPasswordFlow',
    'inChangePasswordFlow',
    'inMessageOnlyFlow',

    'errorMessage',
    'infoMessage',

    'resetPasswordToken',
    'enrollAccountToken',
    'justVerifiedEmail',

    'configureLoginServiceDialogVisible',
    'configureLoginServiceDialogServiceName',
    'configureLoginServiceDialogSaveDisabled'
  ];

  var validateKey = function (key) {
    if (!_.contains(VALID_KEYS, key))
      throw new Error("Invalid key in loginButtonsSession: " + key);
  };

  var KEY_PREFIX = "Meteor.loginButtons.";

  // XXX we should have a better pattern for code private to a package like this one
  Accounts._loginButtonsSession = {
    set: function(key, value) {
      validateKey(key);
      if (_.contains(['errorMessage', 'infoMessage'], key))
        throw new Error("Don't set errorMessage or infoMessage directly. Instead, use errorMessage() or infoMessage().");

      this._set(key, value);
    },

    _set: function(key, value) {
      Session.set(KEY_PREFIX + key, value);
    },

    get: function(key) {
      validateKey(key);
      return Session.get(KEY_PREFIX + key);
    },

    closeDropdown: function () {
      this.set('inSignupFlow', false);
      this.set('inForgotPasswordFlow', false);
      this.set('inChangePasswordFlow', false);
      this.set('inMessageOnlyFlow', false);
      this.set('dropdownVisible', false);
      this.resetMessages();
    },

    infoMessage: function(message) {
      this._set("errorMessage", null);
      this._set("infoMessage", message);
      this.set("dropdownVisible", true); // See #OpenDropdownForMessage
    },

    errorMessage: function(message) {
      this._set("errorMessage", message);
      this._set("infoMessage", null);

      // #OpenDropdownForMessage
      // for the case that you're taking some action in the dropdown, and then you
      // get an error or message. notably has no effect in the single button case.
      this.set("dropdownVisible", true);
    },

    resetMessages: function () {
      this._set("errorMessage", null);
      this._set("infoMessage", null);
    },

    configureService: function (name) {
      this.set('configureLoginServiceDialogVisible', true);
      this.set('configureLoginServiceDialogServiceName', name);
      this.set('configureLoginServiceDialogSaveDisabled', true);
    }
  };
}) ();
<commit_msg>accounts-ui: don't display message twice<commit_after>(function () {
  var VALID_KEYS = [
    'dropdownVisible',

    // XXX consider replacing these with one key that has an enum for values.
    'inSignupFlow',
    'inForgotPasswordFlow',
    'inChangePasswordFlow',
    'inMessageOnlyFlow',

    'errorMessage',
    'infoMessage',

    // dialogs with messages (info and error)
    'resetPasswordToken',
    'enrollAccountToken',
    'justVerifiedEmail',

    'configureLoginServiceDialogVisible',
    'configureLoginServiceDialogServiceName',
    'configureLoginServiceDialogSaveDisabled'
  ];

  var validateKey = function (key) {
    if (!_.contains(VALID_KEYS, key))
      throw new Error("Invalid key in loginButtonsSession: " + key);
  };

  var KEY_PREFIX = "Meteor.loginButtons.";

  // XXX we should have a better pattern for code private to a package like this one
  Accounts._loginButtonsSession = {
    set: function(key, value) {
      validateKey(key);
      if (_.contains(['errorMessage', 'infoMessage'], key))
        throw new Error("Don't set errorMessage or infoMessage directly. Instead, use errorMessage() or infoMessage().");

      this._set(key, value);
    },

    _set: function(key, value) {
      Session.set(KEY_PREFIX + key, value);
    },

    get: function(key) {
      validateKey(key);
      return Session.get(KEY_PREFIX + key);
    },

    closeDropdown: function () {
      this.set('inSignupFlow', false);
      this.set('inForgotPasswordFlow', false);
      this.set('inChangePasswordFlow', false);
      this.set('inMessageOnlyFlow', false);
      this.set('dropdownVisible', false);
      this.resetMessages();
    },

    infoMessage: function(message) {
      this._set("errorMessage", null);
      this._set("infoMessage", message);
      this.ensureMessageVisible();
    },

    errorMessage: function(message) {
      this._set("errorMessage", message);
      this._set("infoMessage", null);
      this.ensureMessageVisible();
    },

    // is there a visible dialog that shows messages (info and error)
    isMessageDialogVisible: function () {
      return this.get('resetPasswordToken') ||
        this.get('enrollAccountToken') ||
        this.get('justVerifiedEmail');
    },

    // ensure that somethings displaying a message (info or error) is
    // visible.  if a dialog with messages is open, do nothing;
    // otherwise open the dropdown.
    //
    // notably this doesn't matter when only displaying a single login
    // button since then we have an explicit message dialog
    // (_loginButtonsMessageDialog), and dropdownVisible is ignored in
    // this case.
    ensureMessageVisible: function () {
      if (!this.isMessageDialogVisible())
        this.set("dropdownVisible", true);
    },

    resetMessages: function () {
      this._set("errorMessage", null);
      this._set("infoMessage", null);
    },

    configureService: function (name) {
      this.set('configureLoginServiceDialogVisible', true);
      this.set('configureLoginServiceDialogServiceName', name);
      this.set('configureLoginServiceDialogSaveDisabled', true);
    }
  };
}) ();
<|endoftext|>


<commit_before>vde.Vis.Pipeline = (function() {
  var pipeline = function(source) {
    this.name = 'pipeline_' + (vg.keys(vde.Vis.pipelines).length+1);
    this.displayName = this.name;

    this.source = source;
    this.transforms = [];

    this.forkName = null;
    this.forkIdx  = null;

    this.scales = {};

    vde.Vis.pipelines[this.name] = this;

    return this;
  };

  var prototype = pipeline.prototype;

  prototype.spec = function() {
    var self = this;
    var specs = [{
      name: this.name,
      source: this.source,
      transform: []
    }];

    vde.Vis.Callback.run('pipeline.pre_spec', this, {spec: specs});

    var spec = 0;
    this.transforms.forEach(function(t, i) {
      if(t.forkPipeline) {
        spec++;
        self.forkName || (self.forkName = self.name + '_' + t.type);
        self.forkIdx = i;

        specs.push({
          name: self.forkName,
          source: self.source,
          transform: vg.duplicate(specs[spec-1].transform || [])
        });
      }

      var s = t.spec();
      if(s) specs[spec].transform.push(s);
    });

    vde.Vis.Callback.run('pipeline.post_spec', this, {spec: specs});

    return specs;
  };

  prototype.values = function(sliceBeg, sliceEnd) {
    var values = vg.duplicate(vde.Vis._data[this.source].values).map(vg.data.ingest);
    this.transforms.slice(sliceBeg, sliceEnd).forEach(function(t) {
      if(t.isVisual) return;

      values = t.transform(values);
    });

    return values;
  };

  prototype.schema = function(sliceBeg, sliceEnd) {
    var self = this,
        fields = [], seenFields = {};
    var values = vg.duplicate(vde.Vis._data[this.source].values).map(vg.data.ingest);

    var buildFields = function(pipeline) {
      [(values[0] || {}).data, values[0], (values.values || [])[0]].forEach(function(v, i) {
        vg.keys(v).forEach(function(k) {
          if(i != 0 && ['data', 'values', 'keys'].indexOf(k) != -1) return;
          if(seenFields[k]) return;

          var field = new vde.Vis.Field(k);
          field.raw = (i == 0);
          field.pipelineName = pipeline;
          field.type = vg.isNumber(v[k]) ? 'linear' : 'ordinal';

          fields.push(field);
          seenFields[k] = true;
        });
      });
    };

    // Build fields once before we apply any transforms
    buildFields(this.name);

    var pipelineName = this.name;
    this.transforms.slice(sliceBeg, sliceEnd).forEach(function(t) {
      if(t.forkPipeline) pipelineName = self.forkName;
      if(t.isVisual) return;

      values = t.transform(values);
      buildFields(pipelineName);
    });

    return [fields, values];
  };

  // Given a spec, find a pre-existing scale that matches,
  // or if none do, build a new scale.
  prototype.scale = function(spec, defaultSpec, displayName) {
    for(var scaleName in this.scales) {
      if(this.scales[scaleName].equals(spec))
        return this.scales[scaleName];
    }

    for(var k in defaultSpec)
      spec[k] = defaultSpec[k];

    return new vde.Vis.Scale('', this, spec, displayName);
  };

  // Figure out where to add the transform:
  // If the transform requires a fork, add it to the end
  // otherwise, assume look at properties to see where to
  // add it
  prototype.addTransform = function(t) {
    if(t.forkPipeline || t.requiresFork) this.transforms.push(t);
    else {
      var pipelineName = this.name;
      vg.keys(t.properties).some(function(k) {
        if(t.properties[k] instanceof vde.Vis.Field) {
          pipelineName = t.properties[k].pipelineName;
          return true;
        }
      });

      if(pipelineName == this.forkName) this.transforms.push(t);
      else this.transforms.splice(this.forkIdx-1, 0, t);
    }
  };

  return pipeline;
})();<commit_msg>Use data parsings, if available, to determine field.type<commit_after>vde.Vis.Pipeline = (function() {
  var pipeline = function(source) {
    this.name = 'pipeline_' + (vg.keys(vde.Vis.pipelines).length+1);
    this.displayName = this.name;

    this.source = source;
    this.transforms = [];

    this.forkName = null;
    this.forkIdx  = null;

    this.scales = {};

    vde.Vis.pipelines[this.name] = this;

    return this;
  };

  var prototype = pipeline.prototype;

  prototype.spec = function() {
    var self = this;
    var specs = [{
      name: this.name,
      source: this.source,
      transform: []
    }];

    vde.Vis.Callback.run('pipeline.pre_spec', this, {spec: specs});

    var spec = 0;
    this.transforms.forEach(function(t, i) {
      if(t.forkPipeline) {
        spec++;
        self.forkName || (self.forkName = self.name + '_' + t.type);
        self.forkIdx = i;

        specs.push({
          name: self.forkName,
          source: self.source,
          transform: vg.duplicate(specs[spec-1].transform || [])
        });
      }

      var s = t.spec();
      if(s) specs[spec].transform.push(s);
    });

    vde.Vis.Callback.run('pipeline.post_spec', this, {spec: specs});

    return specs;
  };

  prototype.values = function(sliceBeg, sliceEnd) {
    var values = vg.duplicate(vde.Vis._data[this.source].values).map(vg.data.ingest);
    this.transforms.slice(sliceBeg, sliceEnd).forEach(function(t) {
      if(t.isVisual) return;

      values = t.transform(values);
    });

    return values;
  };

  prototype.schema = function(sliceBeg, sliceEnd) {
    var self = this,
        fields = [], seenFields = {};
    var values = vg.duplicate(vde.Vis._data[this.source].values).map(vg.data.ingest);

    var buildFields = function(pipeline) {
      var parse = vde.Vis._data[self.source].format.parse;
      [(values[0] || {}).data, values[0], (values.values || [])[0]].forEach(function(v, i) {
        vg.keys(v).forEach(function(k) {
          if(i != 0 && ['data', 'values', 'keys'].indexOf(k) != -1) return;
          if(seenFields[k]) return;

          var field = new vde.Vis.Field(k);
          field.raw = (i == 0);
          field.pipelineName = pipeline;
          if(parse[k]) field.type = (parse[k] == 'date') ? 'time' : (parse[k] == 'number') ? 'linear' : 'ordinal';
          else field.type = vg.isNumber(v[k]) ? 'linear' : 'ordinal';

          fields.push(field);
          seenFields[k] = true;
        });
      });
    };

    // Build fields once before we apply any transforms
    buildFields(this.name);

    var pipelineName = this.name;
    this.transforms.slice(sliceBeg, sliceEnd).forEach(function(t) {
      if(t.forkPipeline) pipelineName = self.forkName;
      if(t.isVisual) return;

      values = t.transform(values);
      buildFields(pipelineName);
    });

    return [fields, values];
  };

  // Given a spec, find a pre-existing scale that matches,
  // or if none do, build a new scale.
  prototype.scale = function(spec, defaultSpec, displayName) {
    for(var scaleName in this.scales) {
      if(this.scales[scaleName].equals(spec))
        return this.scales[scaleName];
    }

    for(var k in defaultSpec)
      spec[k] = defaultSpec[k];

    return new vde.Vis.Scale('', this, spec, displayName);
  };

  // Figure out where to add the transform:
  // If the transform requires a fork, add it to the end
  // otherwise, assume look at properties to see where to
  // add it
  prototype.addTransform = function(t) {
    if(t.forkPipeline || t.requiresFork) this.transforms.push(t);
    else {
      var pipelineName = this.name;
      vg.keys(t.properties).some(function(k) {
        if(t.properties[k] instanceof vde.Vis.Field) {
          pipelineName = t.properties[k].pipelineName;
          return true;
        }
      });

      if(pipelineName == this.forkName) this.transforms.push(t);
      else this.transforms.splice(this.forkIdx-1, 0, t);
    }
  };

  return pipeline;
})();<|endoftext|>


<commit_before>'use strict'

angular.module('antismash.db.ui.genome', [])
  .controller('GenomeCtrl', function ($scope, GenomeSvc) {
    var vm = this;
    vm.currentGenome = null;
    vm.getMibigUrl = getMibigUrl;
    vm.showCluster = showCluster;
    vm.pending = false;

    if (vm.genomeId){
      vm.pending = true;
      GenomeSvc.getGenome(vm.genomeId).then(
        function (result) {
          vm.pending = false;
          vm.currentGenome = result.data;
        }
      );
    }

    $scope.$on("genomeSelected", function(event, args){
      if (vm.currentGenome &&
          vm.currentGenome.length > 0 &&
          vm.currentGenome[0].acc.toLowerCase() == args.toLowerCase()){
        return;
      }
      vm.pending = true;
      vm.currentGenome = null;
      GenomeSvc.getGenome(args).then(function(result){
        vm.pending = false;
        vm.currentGenome = result.data;
      })
    })

    function showCluster(entry) {
      var cluster_acc = entry.acc + '_c' + entry.cluster_number;
      window.open('/output/' + entry.acc + '/index.html#cluster-' + entry.cluster_number, '_new');
      //$state.go('show.cluster', {id: cluster_acc});
    };

    function getMibigUrl(accession) {
      if (!accession) {
        return '';
      }
      var acc = accession.split(/_/)[0];
      return "http://mibig.secondarymetabolites.org/repository/" + acc + "/index.html#cluster-1";
    };
  })
  .factory('GenomeSvc', function ($http) {
    var getGenome = function(genomeId) {
      return $http.get('/api/v1.0/genome/' + genomeId);
    };

    return {
      getGenome: getGenome
    };
  })
  .directive('asGenome', function () {
    return {
      scope: {},
      bindToController: {
        genomeId: "@"
      },
      templateUrl: 'genome/genome.html',
      controller: 'GenomeCtrl',
      controllerAs: 'ctrl'
    }
  });
<commit_msg>genome: remove unused code<commit_after>'use strict'

angular.module('antismash.db.ui.genome', [])
  .controller('GenomeCtrl', function ($scope, GenomeSvc) {
    var vm = this;
    vm.currentGenome = null;
    vm.getMibigUrl = getMibigUrl;
    vm.showCluster = showCluster;
    vm.pending = false;

    if (vm.genomeId){
      vm.pending = true;
      GenomeSvc.getGenome(vm.genomeId).then(
        function (result) {
          vm.pending = false;
          vm.currentGenome = result.data;
        }
      );
    }

    $scope.$on("genomeSelected", function(event, args){
      if (vm.currentGenome &&
          vm.currentGenome.length > 0 &&
          vm.currentGenome[0].acc.toLowerCase() == args.toLowerCase()){
        return;
      }
      vm.pending = true;
      vm.currentGenome = null;
      GenomeSvc.getGenome(args).then(function(result){
        vm.pending = false;
        vm.currentGenome = result.data;
      })
    })

    function showCluster(entry) {
      var cluster_acc = entry.acc + '_c' + entry.cluster_number;
      window.open('/output/' + entry.acc + '/index.html#cluster-' + entry.cluster_number, '_new');
    };

    function getMibigUrl(accession) {
      if (!accession) {
        return '';
      }
      var acc = accession.split(/_/)[0];
      return "http://mibig.secondarymetabolites.org/repository/" + acc + "/index.html#cluster-1";
    };
  })
  .factory('GenomeSvc', function ($http) {
    var getGenome = function(genomeId) {
      return $http.get('/api/v1.0/genome/' + genomeId);
    };

    return {
      getGenome: getGenome
    };
  })
  .directive('asGenome', function () {
    return {
      scope: {},
      bindToController: {
        genomeId: "@"
      },
      templateUrl: 'genome/genome.html',
      controller: 'GenomeCtrl',
      controllerAs: 'ctrl'
    }
  });
<|endoftext|>


<commit_before>    var GSSolver = require('../solver/GSSolver').GSSolver,
        NaiveBroadphase = require('../collision/NaiveBroadphase').NaiveBroadphase,
        glMatrix = require('gl-matrix'),
        vec2 = glMatrix.vec2,
        Circle = require('../objects/Shape').Circle,
        Plane = require('../objects/Shape').Plane,
        Particle = require('../objects/Shape').Particle,
        bp = require('../collision/Broadphase'),
        Broadphase = bp.Broadphase;

    exports.World = World;

    function now(){
        if(performance.now)
            return performance.now();
        else if(performance.webkitNow)
            return performance.webkitNow();
        else
            return new Date().getTime();
    }

    /**
     * The dynamics world, where all bodies and constraints lives.
     *
     * @class
     * @param {Object} [options]
     * @param {p2.Solver} options.solver Default: p2.GSSolver
     * @param {vec2} options.gravity Default: [0,-9.78]
     * @param {p2.Broadphase} options.broadphase Default: p2.NaiveBroadphase
     */
    function World(options){
        options = options || {};

        /**
         * All springs in the world.
         * @member {Array}
         * @memberof World
         */
        this.springs = [];

        /**
         * All bodies in the world.
         * @member {Array}
         * @memberof World
         */
        this.bodies = [];

        /**
         * The solver used to satisfy constraints and contacts.
         * @member {p2.Solver}
         * @memberof World
         */
        this.solver = options.solver || new GSSolver();

        /**
         * The contacts in the world that were generated during the last step().
         * @member {Array}
         * @memberof World
         */
        this.contacts = [];

        this.oldContacts = [];
        this.collidingBodies = [];

        /**
         * Gravity in the world. This is applied on all bodies in the beginning of each step().
         * @member {vec2}
         * @memberof World
         */
        this.gravity = options.gravity || vec2.fromValues(0, -9.78);

        /**
         * Whether to do timing measurements during the step() or not.
         * @member {bool}
         * @memberof World
         */
        this.doProfiling = options.doProfiling || false;

        /**
         * How many millisecconds the last step() took. This is updated each step if .doProfiling is set to true.
         * @member {number}
         * @memberof World
         */
        this.lastStepTime = 0.0;

        /**
         * The broadphase algorithm to use.
         * @member {p2.Broadphase}
         * @memberof World
         */
        this.broadphase = options.broadphase || new NaiveBroadphase();

        /**
         * User-added constraints.
         * @member {Array}
         * @memberof World
         */
        this.constraints = [];

        // Id counters
        this._constraintIdCounter = 0;
        this._bodyIdCounter = 0;
    };

    /**
     * Add a constraint to the simulation.
     * @memberof World
     * @param {p2.Constraint} c
     */
    World.prototype.addConstraint = function(c){
        this.constraints.push(c);
        c.id = this._constraintIdCounter++;
    };

    /**
     * Removes a constraint
     * @memberof World
     * @param {p2.Constraint} c
     */
    World.prototype.removeConstraint = function(c){
        var idx = this.constraints.indexOf(c);
        if(idx!==-1){
            this.constraints.splice(idx,1);
        }
    };

    var step_r = vec2.create();
    var step_runit = vec2.create();
    var step_u = vec2.create();
    var step_f = vec2.create();
    var step_fhMinv = vec2.create();
    var step_velodt = vec2.create();

    /**
     * Step the physics world forward in time.
     *
     * @method
     * @memberof World
     * @param {number} dt The time step size to use.
     */
    World.prototype.step = function(dt,callback){
        var that = this,
            doProfiling = this.doProfiling,
            Nsprings = this.springs.length,
            springs = this.springs,
            bodies = this.bodies,
            collidingBodies=this.collidingBodies,
            g = this.gravity,
            solver = this.solver,
            Nbodies = this.bodies.length,
            broadphase = this.broadphase,
            constraints = this.constraints,
            t0, t1;

        if(doProfiling){
            t0 = now();
        }

        // add gravity to bodies
        for(var i=0; i!==Nbodies; i++){
            var fi = bodies[i].force;
            vec2.add(fi,fi,g);
        }

        // Calculate all new spring forces
        for(var i=0; i!==Nsprings; i++){
            var s = springs[i];
            var k = s.stiffness;
            var d = s.damping;
            var l = s.restLength;
            var bodyA = s.bodyA;
            var bodyB = s.bodyB;
            var r = step_r;
            var r_unit = step_runit;
            var u = step_u;
            var f = step_f;

            vec2.sub(r,bodyA.position,bodyB.position);
            vec2.sub(u,bodyA.velocity,bodyB.velocity);
            var rlen = vec2.len(r);
            vec2.normalize(r_unit,r);
            vec2.scale(f, r_unit, k*(rlen-l) + d*vec2.dot(u,r_unit));
            vec2.sub( bodyA.force,bodyA.force, f);
            vec2.add( bodyB.force,bodyB.force, f);
        }

        // Broadphase
        var result = broadphase.getCollisionPairs(this);

        // Nearphase
        var oldContacts = this.contacts.concat(this.oldContacts);
        var contacts = this.contacts = [];
        for(var i=0, Nresults=result.length; i!==Nresults; i+=2){
            var bi = result[i];
            var bj = result[i+1];
            var si = bi.shape;
            var sj = bj.shape;
            if(si instanceof Circle){
                     if(sj instanceof Circle)   bp.nearphaseCircleCircle  (bi,bj,contacts,oldContacts);
                else if(sj instanceof Particle) bp.nearphaseCircleParticle(bi,bj,contacts,oldContacts);
                else if(sj instanceof Plane)    bp.nearphaseCirclePlane   (bi,bj,contacts,oldContacts);
            } else if(si instanceof Particle){
                     if(sj instanceof Circle)   bp.nearphaseCircleParticle(bj,bi,contacts,oldContacts);
            } else if(si instanceof Plane){
                     if(sj instanceof Circle)   bp.nearphaseCirclePlane   (bj,bi,contacts,oldContacts);
            }
        }
        this.oldContacts = oldContacts;

        // Add equations to solver
        for(var i=0, Ncontacts=contacts.length; i!==Ncontacts; i++){
            solver.addEquation(contacts[i]);
        }
        // Add user-defined constraint equations
        var Nconstraints = constraints.length;
        for(i=0; i!==Nconstraints; i++){
            var c = constraints[i];
            c.update();
            for(var j=0, Neq=c.equations.length; j!==Neq; j++){
                var eq = c.equations[j];
                solver.addEquation(eq);
            }
        }
        solver.solve(dt,this,function(){
            solver.removeAllEquations();

            // Step forward
            var fhMinv = step_fhMinv;
            var velodt = step_velodt;
            for(var i=0; i!==Nbodies; i++){
                var body = bodies[i];
                if(body.mass>0){
                    var minv = 1.0 / body.mass,
                        f = body.force,
                        pos = body.position,
                        velo = body.velocity;

                    // Angular step
                    body.angularVelocity += body.angularForce * body.invInertia * dt;
                    body.angle += body.angularVelocity * dt;

                    // Linear step
                    vec2.scale(fhMinv,f,dt*minv);
                    vec2.add(velo,fhMinv,velo);
                    vec2.scale(velodt,velo,dt);
                    vec2.add(pos,pos,velodt);
                }
            }

            // Reset force
            for(var i=0; i!==Nbodies; i++){
                var bi = bodies[i];
                vec2.set(bi.force,0.0,0.0);
                bi.angularForce = 0.0;
            }

            if(doProfiling){
                t1 = now();
                that.lastStepTime = t1-t0;
            }

            callback();
        });
    };

    /**
     * Add a spring to the simulation
     *
     * @method
     * @memberof World
     * @param {p2.Spring} s
     */
    World.prototype.addSpring = function(s){
        this.springs.push(s);
    };

    /**
     * Remove a spring
     *
     * @method
     * @memberof World
     * @param {p2.Spring} s
     */
    World.prototype.removeSpring = function(s){
        var idx = this.springs.indexOf(s);
        if(idx===-1)
            this.springs.splice(idx,1);
    };

    /**
     * Add a body to the simulation
     *
     * @method
     * @memberof World
     * @param {p2.Body} body
     */
    World.prototype.addBody = function(body){
        this.bodies.push(body);
        this.collidingBodies.push(body);
    };

    /**
     * Remove a body from the simulation
     *
     * @method
     * @memberof World
     * @param {p2.Body} body
     */
    World.prototype.removeBody = function(body){
        var idx = this.bodies.indexOf(body);
        if(idx===-1)
            this.bodies.splice(idx,1);
    };

<commit_msg>indent fix<commit_after>var GSSolver = require('../solver/GSSolver').GSSolver,
    NaiveBroadphase = require('../collision/NaiveBroadphase').NaiveBroadphase,
    glMatrix = require('gl-matrix'),
    vec2 = glMatrix.vec2,
    Circle = require('../objects/Shape').Circle,
    Plane = require('../objects/Shape').Plane,
    Particle = require('../objects/Shape').Particle,
    bp = require('../collision/Broadphase'),
    Broadphase = bp.Broadphase;

exports.World = World;

function now(){
    if(performance.now)
        return performance.now();
    else if(performance.webkitNow)
        return performance.webkitNow();
    else
        return new Date().getTime();
}

/**
 * The dynamics world, where all bodies and constraints lives.
 *
 * @class
 * @param {Object} [options]
 * @param {p2.Solver} options.solver Default: p2.GSSolver
 * @param {vec2} options.gravity Default: [0,-9.78]
 * @param {p2.Broadphase} options.broadphase Default: p2.NaiveBroadphase
 */
function World(options){
    options = options || {};

    /**
     * All springs in the world.
     * @member {Array}
     * @memberof World
     */
    this.springs = [];

    /**
     * All bodies in the world.
     * @member {Array}
     * @memberof World
     */
    this.bodies = [];

    /**
     * The solver used to satisfy constraints and contacts.
     * @member {p2.Solver}
     * @memberof World
     */
    this.solver = options.solver || new GSSolver();

    /**
     * The contacts in the world that were generated during the last step().
     * @member {Array}
     * @memberof World
     */
    this.contacts = [];

    this.oldContacts = [];
    this.collidingBodies = [];

    /**
     * Gravity in the world. This is applied on all bodies in the beginning of each step().
     * @member {vec2}
     * @memberof World
     */
    this.gravity = options.gravity || vec2.fromValues(0, -9.78);

    /**
     * Whether to do timing measurements during the step() or not.
     * @member {bool}
     * @memberof World
     */
    this.doProfiling = options.doProfiling || false;

    /**
     * How many millisecconds the last step() took. This is updated each step if .doProfiling is set to true.
     * @member {number}
     * @memberof World
     */
    this.lastStepTime = 0.0;

    /**
     * The broadphase algorithm to use.
     * @member {p2.Broadphase}
     * @memberof World
     */
    this.broadphase = options.broadphase || new NaiveBroadphase();

    /**
     * User-added constraints.
     * @member {Array}
     * @memberof World
     */
    this.constraints = [];

    // Id counters
    this._constraintIdCounter = 0;
    this._bodyIdCounter = 0;
};

/**
 * Add a constraint to the simulation.
 * @memberof World
 * @param {p2.Constraint} c
 */
World.prototype.addConstraint = function(c){
    this.constraints.push(c);
    c.id = this._constraintIdCounter++;
};

/**
 * Removes a constraint
 * @memberof World
 * @param {p2.Constraint} c
 */
World.prototype.removeConstraint = function(c){
    var idx = this.constraints.indexOf(c);
    if(idx!==-1){
        this.constraints.splice(idx,1);
    }
};

var step_r = vec2.create();
var step_runit = vec2.create();
var step_u = vec2.create();
var step_f = vec2.create();
var step_fhMinv = vec2.create();
var step_velodt = vec2.create();

/**
 * Step the physics world forward in time.
 *
 * @method
 * @memberof World
 * @param {number} dt The time step size to use.
 */
World.prototype.step = function(dt,callback){
    var that = this,
        doProfiling = this.doProfiling,
        Nsprings = this.springs.length,
        springs = this.springs,
        bodies = this.bodies,
        collidingBodies=this.collidingBodies,
        g = this.gravity,
        solver = this.solver,
        Nbodies = this.bodies.length,
        broadphase = this.broadphase,
        constraints = this.constraints,
        t0, t1;

    if(doProfiling){
        t0 = now();
    }

    // add gravity to bodies
    for(var i=0; i!==Nbodies; i++){
        var fi = bodies[i].force;
        vec2.add(fi,fi,g);
    }

    // Calculate all new spring forces
    for(var i=0; i!==Nsprings; i++){
        var s = springs[i];
        var k = s.stiffness;
        var d = s.damping;
        var l = s.restLength;
        var bodyA = s.bodyA;
        var bodyB = s.bodyB;
        var r = step_r;
        var r_unit = step_runit;
        var u = step_u;
        var f = step_f;

        vec2.sub(r,bodyA.position,bodyB.position);
        vec2.sub(u,bodyA.velocity,bodyB.velocity);
        var rlen = vec2.len(r);
        vec2.normalize(r_unit,r);
        vec2.scale(f, r_unit, k*(rlen-l) + d*vec2.dot(u,r_unit));
        vec2.sub( bodyA.force,bodyA.force, f);
        vec2.add( bodyB.force,bodyB.force, f);
    }

    // Broadphase
    var result = broadphase.getCollisionPairs(this);

    // Nearphase
    var oldContacts = this.contacts.concat(this.oldContacts);
    var contacts = this.contacts = [];
    for(var i=0, Nresults=result.length; i!==Nresults; i+=2){
        var bi = result[i];
        var bj = result[i+1];
        var si = bi.shape;
        var sj = bj.shape;
        if(si instanceof Circle){
                 if(sj instanceof Circle)   bp.nearphaseCircleCircle  (bi,bj,contacts,oldContacts);
            else if(sj instanceof Particle) bp.nearphaseCircleParticle(bi,bj,contacts,oldContacts);
            else if(sj instanceof Plane)    bp.nearphaseCirclePlane   (bi,bj,contacts,oldContacts);
        } else if(si instanceof Particle){
                 if(sj instanceof Circle)   bp.nearphaseCircleParticle(bj,bi,contacts,oldContacts);
        } else if(si instanceof Plane){
                 if(sj instanceof Circle)   bp.nearphaseCirclePlane   (bj,bi,contacts,oldContacts);
        }
    }
    this.oldContacts = oldContacts;

    // Add equations to solver
    for(var i=0, Ncontacts=contacts.length; i!==Ncontacts; i++){
        solver.addEquation(contacts[i]);
    }
    // Add user-defined constraint equations
    var Nconstraints = constraints.length;
    for(i=0; i!==Nconstraints; i++){
        var c = constraints[i];
        c.update();
        for(var j=0, Neq=c.equations.length; j!==Neq; j++){
            var eq = c.equations[j];
            solver.addEquation(eq);
        }
    }
    solver.solve(dt,this,function(){
        solver.removeAllEquations();

        // Step forward
        var fhMinv = step_fhMinv;
        var velodt = step_velodt;
        for(var i=0; i!==Nbodies; i++){
            var body = bodies[i];
            if(body.mass>0){
                var minv = 1.0 / body.mass,
                    f = body.force,
                    pos = body.position,
                    velo = body.velocity;

                // Angular step
                body.angularVelocity += body.angularForce * body.invInertia * dt;
                body.angle += body.angularVelocity * dt;

                // Linear step
                vec2.scale(fhMinv,f,dt*minv);
                vec2.add(velo,fhMinv,velo);
                vec2.scale(velodt,velo,dt);
                vec2.add(pos,pos,velodt);
            }
        }

        // Reset force
        for(var i=0; i!==Nbodies; i++){
            var bi = bodies[i];
            vec2.set(bi.force,0.0,0.0);
            bi.angularForce = 0.0;
        }

        if(doProfiling){
            t1 = now();
            that.lastStepTime = t1-t0;
        }

        callback();
    });
};

/**
 * Add a spring to the simulation
 *
 * @method
 * @memberof World
 * @param {p2.Spring} s
 */
World.prototype.addSpring = function(s){
    this.springs.push(s);
};

/**
 * Remove a spring
 *
 * @method
 * @memberof World
 * @param {p2.Spring} s
 */
World.prototype.removeSpring = function(s){
    var idx = this.springs.indexOf(s);
    if(idx===-1)
        this.springs.splice(idx,1);
};

/**
 * Add a body to the simulation
 *
 * @method
 * @memberof World
 * @param {p2.Body} body
 */
World.prototype.addBody = function(body){
    this.bodies.push(body);
    this.collidingBodies.push(body);
};

/**
 * Remove a body from the simulation
 *
 * @method
 * @memberof World
 * @param {p2.Body} body
 */
World.prototype.removeBody = function(body){
    var idx = this.bodies.indexOf(body);
    if(idx===-1)
        this.bodies.splice(idx,1);
};

<|endoftext|>


<commit_before>define(function () {
  return function (ParsleyForm, Parsley) {
    describe('ParsleyForm', function () {
      it('should be a function', function () {
        expect(ParsleyForm).to.be.a('function');
      });
      it('should throw an error if no element given', function () {
        expect(ParsleyForm).to.throwException();
      });
      it('should bind parsleyFields children', function () {
        $('body').append(
          '<form id="element">'                 +
            '<input id="field1" type="text"/>'  +
            '

'           +
            '<textarea id="field2"></textarea>' +
          '</form>');
        var parsleyForm = new Parsley($('#element'));
        expect(parsleyForm.fields.length).to.be(2);
      });
      it('should bind parsleyFields children, and not excluded ones', function () {
        $('body').append(
          '<form id="element">'                 +
            '<input id="field1" type="text"/>'  +
            '

'           +
            '<textarea id="field2"></textarea>' +
            '

' + // ParsleyForm, not a valid child
            '<input id="field3" disabled />'    + // Disabled, excluded buy custom options below
            '<input type="submit"/>'            + // Excluded field, not valid
          '</form>');
        var parsleyForm = new Parsley($('#element'), { excluded: '[disabled], input[type=button], input[type=submit], input[type=reset]' });
        expect(parsleyForm.fields.length).to.be(2);
      });
      it('should properly bind options for form and children fields', function () {
        $('body').append(
          '<form id="element" data-parsley-trigger="change">'                 +
            '<input id="field1" type="text" data-parsley-required="true" />'  +
            '

'                                         +
            '<textarea id="field3" data-parsley-notblank="true"></textarea>'  +
          '</form>');
        var parsleyForm = new Parsley($('#element'));
        expect(parsleyForm.fields.length).to.be(2);
        expect(new Parsley('#field1').options.trigger).to.be('change');
        expect(new Parsley('#field1').options).to.have.key('required');
        expect(new Parsley('#field1').options).to.not.have.key('notblank');
        expect(new Parsley('#field3').options).to.have.key('notblank');
        expect(new Parsley('#field3').options).to.not.have.key('required');
      });
      it('should properly store validation state after `validate()`', function () {
        $('body').append(
          '<form id="element" data-parsley-trigger="change">'                 +
            '<input id="field1" type="text" data-parsley-required="true" />'  +
            '

'                                         +
            '<textarea id="field3" data-parsley-notblank="true"></textarea>'  +
          '</form>');
          var parsleyForm = new Parsley($('#element'));
          parsleyForm.validate();
          expect(parsleyForm.validationResult).to.be(false);
          $('#field1').val('foo');
          $('#field3').val('foo');
          expect(parsleyForm.validate()).to.be(true);
      });
      it('should handle group validation', function () {
        $('body').append(
          '<form id="element">'                                                                        +
            '<input id="field1" type="text" data-parsley-group="foo" data-parsley-required="true" />'  +
            '

'                                                                  +
            '<textarea id="field3" data-parsley-group="bar" data-parsley-required="true"></textarea>'  +
          '</form>');
          var parsleyForm = new Parsley($('#element'));
          expect(parsleyForm.isValid()).to.be(false);
          $('#field1').val('value');
          expect(parsleyForm.isValid()).to.be(false);
          expect(parsleyForm.isValid('foo')).to.be(true);
          expect(parsleyForm.isValid('bar')).to.be(false);
      });
      it('should handle group validation with controls with multiple group names', function () {
        $('body').append(
          '<form id="element">'                                                                        +
            '<input id="field1" type="text" data-parsley-group=\'["foo", "baz"]\' data-parsley-required="true" />'  +
            '

'                                                                  +
            '<textarea id="field3" data-parsley-group="bar" data-parsley-required="true"></textarea>'  +
          '</form>');
          var parsleyForm = new Parsley($('#element'));
          expect(parsleyForm.isValid()).to.be(false);
          $('#field1').val('value');
          expect(parsleyForm.isValid()).to.be(false);
          expect(parsleyForm.isValid('foo')).to.be(true);
          expect(parsleyForm.isValid('baz')).to.be(true);
          expect(parsleyForm.isValid('bar')).to.be(false);
      });
      it('should handle `onFormSubmit` validation', function () {
        $('body').append(
          '<form id="element" data-parsley-trigger="change">'                 +
            '<input id="field1" type="text" data-parsley-required="true" />'  +
            '

'                                         +
            '<textarea id="field3" data-parsley-notblank="true"></textarea>'  +
          '</form>');
          var parsleyForm = new Parsley($('#element'));

          // parsley.remote hack because if valid, parsley remote re-send form
          parsleyForm.subscribe('parsley:form:validate', function (formInstance) {
            if (formInstance.asyncSupport)
              formInstance.submitEvent._originalPreventDefault();
          });

          var event = $.Event();
          // parsley.remote hack
          event._originalPreventDefault = event.preventDefault;
          event.preventDefault = sinon.spy();
          parsleyForm.onSubmitValidate(event);
          expect(event.preventDefault.called).to.be(true);

          $('#field1').val('foo');
          $('#field3').val('foo');

          event = $.Event();
          // parsley.remote hack
          event._originalPreventDefault = event.preventDefault;
          event.preventDefault = sinon.spy();
          parsleyForm.onSubmitValidate(event);

          if (!parsleyForm.asyncSupport)
            expect(event.preventDefault.called).to.be(false);
          else
            expect(event.preventDefault.called).to.be(true);
      });
      it('should have a force option for validate and isValid methods', function () {
        $('body').append(
          '<form id="element">'                                   +
            '<input id="field1" type="email" />'                  +
            '<input id="field3" data-parsley-notblank="true" />'  +
          '</form>');
        expect($('#element').parsley().isValid()).to.be(true);
        expect($('#element').parsley().isValid(undefined, true)).to.be(false);
        expect($('#element').parsley().validate()).to.be(true);
        expect($('#element').parsley().validate(undefined, true)).to.be(false);
      });
      it('should properly bind dynamically added fields', function () {
        $('body').append('<form id="element" data-parsley-trigger="change"></form>');
        $('#element').append('<input type="email" id="email" required />');
        var fieldInstance = $('#email').psly();
        expect(fieldInstance.__class__).to.be('ParsleyField');
        var formInstance = $('#element').psly();
        // form corectly have its field, and field have finaly its parent form
        expect(formInstance.fields[0].$element.attr('id')).to.be('email');
        expect(fieldInstance.parent.__class__).to.be('ParsleyForm');
      });
      it('should stop event propagation on form submit', function (done) {
        $('body').append('<form id="element"><input type="text" required/></form>');
        var parsleyInstance = $('#element').parsley();

        $('#element').on('submit', function () {
          // It sould never pass here!
          expect(true).to.be(false);
        });

        parsleyInstance.subscribe('parsley:form:validated', function () {
          done();
        });

        $('#element').submit();
      });
      afterEach(function () {
        if ($('#element').length)
          $('#element').remove();
      });
    });
  };
});
<commit_msg>Update test case for multiple group name validation<commit_after>define(function () {
  return function (ParsleyForm, Parsley) {
    describe('ParsleyForm', function () {
      it('should be a function', function () {
        expect(ParsleyForm).to.be.a('function');
      });
      it('should throw an error if no element given', function () {
        expect(ParsleyForm).to.throwException();
      });
      it('should bind parsleyFields children', function () {
        $('body').append(
          '<form id="element">'                 +
            '<input id="field1" type="text"/>'  +
            '

'           +
            '<textarea id="field2"></textarea>' +
          '</form>');
        var parsleyForm = new Parsley($('#element'));
        expect(parsleyForm.fields.length).to.be(2);
      });
      it('should bind parsleyFields children, and not excluded ones', function () {
        $('body').append(
          '<form id="element">'                 +
            '<input id="field1" type="text"/>'  +
            '

'           +
            '<textarea id="field2"></textarea>' +
            '

' + // ParsleyForm, not a valid child
            '<input id="field3" disabled />'    + // Disabled, excluded buy custom options below
            '<input type="submit"/>'            + // Excluded field, not valid
          '</form>');
        var parsleyForm = new Parsley($('#element'), { excluded: '[disabled], input[type=button], input[type=submit], input[type=reset]' });
        expect(parsleyForm.fields.length).to.be(2);
      });
      it('should properly bind options for form and children fields', function () {
        $('body').append(
          '<form id="element" data-parsley-trigger="change">'                 +
            '<input id="field1" type="text" data-parsley-required="true" />'  +
            '

'                                         +
            '<textarea id="field3" data-parsley-notblank="true"></textarea>'  +
          '</form>');
        var parsleyForm = new Parsley($('#element'));
        expect(parsleyForm.fields.length).to.be(2);
        expect(new Parsley('#field1').options.trigger).to.be('change');
        expect(new Parsley('#field1').options).to.have.key('required');
        expect(new Parsley('#field1').options).to.not.have.key('notblank');
        expect(new Parsley('#field3').options).to.have.key('notblank');
        expect(new Parsley('#field3').options).to.not.have.key('required');
      });
      it('should properly store validation state after `validate()`', function () {
        $('body').append(
          '<form id="element" data-parsley-trigger="change">'                 +
            '<input id="field1" type="text" data-parsley-required="true" />'  +
            '

'                                         +
            '<textarea id="field3" data-parsley-notblank="true"></textarea>'  +
          '</form>');
          var parsleyForm = new Parsley($('#element'));
          parsleyForm.validate();
          expect(parsleyForm.validationResult).to.be(false);
          $('#field1').val('foo');
          $('#field3').val('foo');
          expect(parsleyForm.validate()).to.be(true);
      });
      it('should handle group validation', function () {
        $('body').append(
          '<form id="element">'                                                                        +
            '<input id="field1" type="text" data-parsley-group="foo" data-parsley-required="true" />'  +
            '

'                                                                  +
            '<textarea id="field3" data-parsley-group="bar" data-parsley-required="true"></textarea>'  +
          '</form>');
          var parsleyForm = new Parsley($('#element'));
          expect(parsleyForm.isValid()).to.be(false);
          $('#field1').val('value');
          expect(parsleyForm.isValid()).to.be(false);
          expect(parsleyForm.isValid('foo')).to.be(true);
          expect(parsleyForm.isValid('bar')).to.be(false);
      });
      it('should handle group validation with controls with multiple group names', function () {
        $('body').append(
          '<form id="element">'                                                                        +
            '<input id="field1" type="text" data-parsley-group=\'["foo", "bar"]\' data-parsley-required="true" />'  +
            '<input id="field2" type="text" data-parsley-group=\'["bar", "baz"]\' data-parsley-required="true" />'  +
            '<textarea id="field3" data-parsley-group=\'["baz", "qux"]\' data-parsley-required="true"></textarea>'  +
          '</form>');
          var parsleyForm = new Parsley($('#element'));
          expect(parsleyForm.isValid()).to.be(false);
          $('#field1').val('value');
          $('#field2').val('value');
          expect(parsleyForm.isValid()).to.be(false);
          // group name only on one required field, with value
          expect(parsleyForm.isValid('foo')).to.be(true);
          // group name on multiple required fields, all with values
          expect(parsleyForm.isValid('bar')).to.be(true);
          // group name on multiple required fields, one missing a value
          expect(parsleyForm.isValid('baz')).to.be(false);
          // group name on single required field, without value
          expect(parsleyForm.isValid('qux')).to.be(false);
      });
      it('should handle `onFormSubmit` validation', function () {
        $('body').append(
          '<form id="element" data-parsley-trigger="change">'                 +
            '<input id="field1" type="text" data-parsley-required="true" />'  +
            '

'                                         +
            '<textarea id="field3" data-parsley-notblank="true"></textarea>'  +
          '</form>');
          var parsleyForm = new Parsley($('#element'));

          // parsley.remote hack because if valid, parsley remote re-send form
          parsleyForm.subscribe('parsley:form:validate', function (formInstance) {
            if (formInstance.asyncSupport)
              formInstance.submitEvent._originalPreventDefault();
          });

          var event = $.Event();
          // parsley.remote hack
          event._originalPreventDefault = event.preventDefault;
          event.preventDefault = sinon.spy();
          parsleyForm.onSubmitValidate(event);
          expect(event.preventDefault.called).to.be(true);

          $('#field1').val('foo');
          $('#field3').val('foo');

          event = $.Event();
          // parsley.remote hack
          event._originalPreventDefault = event.preventDefault;
          event.preventDefault = sinon.spy();
          parsleyForm.onSubmitValidate(event);

          if (!parsleyForm.asyncSupport)
            expect(event.preventDefault.called).to.be(false);
          else
            expect(event.preventDefault.called).to.be(true);
      });
      it('should have a force option for validate and isValid methods', function () {
        $('body').append(
          '<form id="element">'                                   +
            '<input id="field1" type="email" />'                  +
            '<input id="field3" data-parsley-notblank="true" />'  +
          '</form>');
        expect($('#element').parsley().isValid()).to.be(true);
        expect($('#element').parsley().isValid(undefined, true)).to.be(false);
        expect($('#element').parsley().validate()).to.be(true);
        expect($('#element').parsley().validate(undefined, true)).to.be(false);
      });
      it('should properly bind dynamically added fields', function () {
        $('body').append('<form id="element" data-parsley-trigger="change"></form>');
        $('#element').append('<input type="email" id="email" required />');
        var fieldInstance = $('#email').psly();
        expect(fieldInstance.__class__).to.be('ParsleyField');
        var formInstance = $('#element').psly();
        // form corectly have its field, and field have finaly its parent form
        expect(formInstance.fields[0].$element.attr('id')).to.be('email');
        expect(fieldInstance.parent.__class__).to.be('ParsleyForm');
      });
      it('should stop event propagation on form submit', function (done) {
        $('body').append('<form id="element"><input type="text" required/></form>');
        var parsleyInstance = $('#element').parsley();

        $('#element').on('submit', function () {
          // It sould never pass here!
          expect(true).to.be(false);
        });

        parsleyInstance.subscribe('parsley:form:validated', function () {
          done();
        });

        $('#element').submit();
      });
      afterEach(function () {
        if ($('#element').length)
          $('#element').remove();
      });
    });
  };
});
<|endoftext|>


<commit_before>import { Chess } from 'chess.js';

export default function chessWorker(self) {
  function forsyth(role) {
    return role === 'knight' ? 'n' : role[0];
  }

  self.onmessage = function (ev) {
    const { ply, fen, promotion, orig, dest } = ev.data;
    const promotionLetter = (dest[1] === '1' || dest[1] === '8') ?
      (promotion ? forsyth(promotion) : 'q') : null;
    const chess = new Chess(fen, 0);
    const move = chess.move({
      from: orig,
      to: dest,
      promotion: promotionLetter
    });
    const turnColor = chess.turn() === 'w' ? 'white' : 'black';
    self.postMessage({
      fen: chess.fen(),
      turnColor: turnColor,
      movable: {
        color: turnColor,
        dests: chess.dests()
      },
      check: chess.in_check(),
      finished: chess.game_over(),
      checkmate: chess.in_checkmate(),
      stalemate: chess.in_stalemate(),
      threefold: chess.in_threefold_repetition(),
      draw: chess.in_draw(),
      lastMove: [move.from, move.to],
      san: move.san,
      ply: ply,
      promotion: promotionLetter
    });
  };
}
<commit_msg>WIP on offline analysis<commit_after>import { Chess } from 'chess.js';

export default function chessWorker(self) {
  function forsyth(role) {
    return role === 'knight' ? 'n' : role[0];
  }

  self.onmessage = function (msg) {
    switch (msg.data.topic) {
      case 'getDests':
        getDests(msg.data);
        break;
      case 'addMove':
        addMove(msg.data);
        break;
    }
  };

  function getDests(data) {
    const { fen } = data;
    const chess = new Chess(fen, 0);
    self.postMessage({
      dests: chess.dests()
    });
  }

  function addMove(data) {
    const { ply, fen, promotion, orig, dest } = data;
    const promotionLetter = (dest[1] === '1' || dest[1] === '8') ?
    (promotion ? forsyth(promotion) : 'q') : null;
    const chess = new Chess(fen, 0);
    const move = chess.move({
      from: orig,
      to: dest,
      promotion: promotionLetter
    });
    const turnColor = chess.turn() === 'w' ? 'white' : 'black';
    self.postMessage({
      fen: chess.fen(),
      turnColor: turnColor,
      movable: {
        color: turnColor,
        dests: chess.dests()
      },
      check: chess.in_check(),
      finished: chess.game_over(),
      checkmate: chess.in_checkmate(),
      stalemate: chess.in_stalemate(),
      threefold: chess.in_threefold_repetition(),
      draw: chess.in_draw(),
      lastMove: [move.from, move.to],
      san: move.san,
      ply: ply,
      promotion: promotionLetter
    });
  }
}
<|endoftext|>


<commit_before>import getFunctionFromString from 'shared/getFunctionFromString';
import createReferenceResolver from 'virtualdom/items/shared/Resolvers/createReferenceResolver';
import circular from 'circular';
import eventStack from 'Ractive/prototype/shared/eventStack';
import fireEvent from 'Ractive/prototype/shared/fireEvent';
import log from 'utils/log/log';

var Fragment, getValueOptions = { args: true }, eventPattern = /^event(?:\.(.+))?/;

circular.push( function () {
	Fragment = circular.Fragment;
});

export default function EventHandler$init ( element, name, template ) {
	var action, refs, ractive, i;

	this.element = element;
	this.root = element.root;
	this.parentFragment = element.parentFragment;
	this.name = name;

	if( name.indexOf( '*' ) !== -1 ) {
		log.error({
			debug: this.root.debug,
			message: 'noElementProxyEventWildcards',
			args: {
				element: element.tagName,
				event: name
			}
		});

		this.invalid = true;
	}

	if ( template.m ) {
		refs = template.a.r;

		// This is a method call
		this.method = template.m;
		this.keypaths = [];
		this.fn = getFunctionFromString( template.a.s, refs.length );

		this.parentFragment = element.parentFragment;
		ractive = this.root;

		// Create resolvers for each reference
		this.refResolvers = [];
		for ( i = 0; i < refs.length; i++ ) {
			let match, ref = refs[i];

			// special case - the `event` object
			if ( match = eventPattern.exec( ref ) ) {
				this.keypaths[i] = {
					eventObject: true,
					refinements: match[1] ? match[1].split( '.' ) : []
				};
			}

			else {
				this.refResolvers.push( createReferenceResolver( this, ref, getCallback( this, i ) ) );
			}
		}

		this.fire = fireMethodCall;
	}

	else {
		// Get action ('foo' in 'on-click='foo')
		action = template.n || template;
		if ( typeof action !== 'string' ) {
			action = new Fragment({
				template: action,
				root: this.root,
				owner: this
			});
		}

		this.action = action;

		// Get parameters
		if ( template.d ) {
			this.dynamicParams = new Fragment({
				template: template.d,
				root: this.root,
				owner: this.element
			});

			this.fire = fireEventWithDynamicParams;
		} else if ( template.a ) {
			this.params = template.a;
			this.fire = fireEventWithParams;
		}
	}
}

function fireMethodCall ( event ) {
	var ractive, values, args;

	ractive = this.root;

	if ( typeof ractive[ this.method ] !== 'function' ) {
		throw new Error( 'Attempted to call a non-existent method ("' + this.method + '")' );
	}

	values = this.keypaths.map( function ( keypath ) {
		var value, len, i;

		if ( keypath === undefined ) {
			// not yet resolved
			return undefined;
		}

		// TODO the refinements stuff would be better handled at parse time
		if ( keypath.eventObject ) {
			value = event;

			if ( len = keypath.refinements.length ) {
				for ( i = 0; i < len; i += 1 ) {
					value = value[ keypath.refinements[i] ];
				}
			}
		} else {
			value = ractive.viewmodel.get( keypath );
		}

		return value;
	});

	eventStack.enqueue( ractive, event );

	args = this.fn.apply( null, values );
	ractive[ this.method ].apply( ractive, args );

	eventStack.dequeue( ractive );
}

function fireEventWithParams ( event ) {
	fireEvent( this.root, this.getAction(), { event: event, args: this.params } );
}

function fireEventWithDynamicParams ( event ) {
	var args = this.dynamicParams.getValue( getValueOptions );

	// need to strip [] from ends if a string!
	if ( typeof args === 'string' ) {
		args = args.substr( 1, args.length - 2 );
	}

	fireEvent( this.root, this.getAction(), { event: event, args: args } );
}

function getCallback( handler, index ) {
	return keypath => handler.resolve( index, keypath );
}
<commit_msg>even better solution to event handler reference resolver rebind issue<commit_after>import getFunctionFromString from 'shared/getFunctionFromString';
import createReferenceResolver from 'virtualdom/items/shared/Resolvers/createReferenceResolver';
import circular from 'circular';
import eventStack from 'Ractive/prototype/shared/eventStack';
import fireEvent from 'Ractive/prototype/shared/fireEvent';
import log from 'utils/log/log';

var Fragment, getValueOptions = { args: true }, eventPattern = /^event(?:\.(.+))?/;

circular.push( function () {
	Fragment = circular.Fragment;
});

export default function EventHandler$init ( element, name, template ) {
	var action, refs, ractive, i;

	this.element = element;
	this.root = element.root;
	this.parentFragment = element.parentFragment;
	this.name = name;

	if( name.indexOf( '*' ) !== -1 ) {
		log.error({
			debug: this.root.debug,
			message: 'noElementProxyEventWildcards',
			args: {
				element: element.tagName,
				event: name
			}
		});

		this.invalid = true;
	}

	if ( template.m ) {
		refs = template.a.r;

		// This is a method call
		this.method = template.m;
		this.keypaths = [];
		this.fn = getFunctionFromString( template.a.s, refs.length );

		this.parentFragment = element.parentFragment;
		ractive = this.root;

		// Create resolvers for each reference
		this.refResolvers = [];
		refs.forEach(( ref, i ) => {
			let match;

			// special case - the `event` object
			if ( match = eventPattern.exec( ref ) ) {
				this.keypaths[i] = {
					eventObject: true,
					refinements: match[1] ? match[1].split( '.' ) : []
				};
			}

			else {
				this.refResolvers.push( createReferenceResolver( this, ref, keypath => this.resolve( i, keypath ) ) );
			}
		});

		this.fire = fireMethodCall;
	}

	else {
		// Get action ('foo' in 'on-click='foo')
		action = template.n || template;
		if ( typeof action !== 'string' ) {
			action = new Fragment({
				template: action,
				root: this.root,
				owner: this
			});
		}

		this.action = action;

		// Get parameters
		if ( template.d ) {
			this.dynamicParams = new Fragment({
				template: template.d,
				root: this.root,
				owner: this.element
			});

			this.fire = fireEventWithDynamicParams;
		} else if ( template.a ) {
			this.params = template.a;
			this.fire = fireEventWithParams;
		}
	}
}

function fireMethodCall ( event ) {
	var ractive, values, args;

	ractive = this.root;

	if ( typeof ractive[ this.method ] !== 'function' ) {
		throw new Error( 'Attempted to call a non-existent method ("' + this.method + '")' );
	}

	values = this.keypaths.map( function ( keypath ) {
		var value, len, i;

		if ( keypath === undefined ) {
			// not yet resolved
			return undefined;
		}

		// TODO the refinements stuff would be better handled at parse time
		if ( keypath.eventObject ) {
			value = event;

			if ( len = keypath.refinements.length ) {
				for ( i = 0; i < len; i += 1 ) {
					value = value[ keypath.refinements[i] ];
				}
			}
		} else {
			value = ractive.viewmodel.get( keypath );
		}

		return value;
	});

	eventStack.enqueue( ractive, event );

	args = this.fn.apply( null, values );
	ractive[ this.method ].apply( ractive, args );

	eventStack.dequeue( ractive );
}

function fireEventWithParams ( event ) {
	fireEvent( this.root, this.getAction(), { event: event, args: this.params } );
}

function fireEventWithDynamicParams ( event ) {
	var args = this.dynamicParams.getValue( getValueOptions );

	// need to strip [] from ends if a string!
	if ( typeof args === 'string' ) {
		args = args.substr( 1, args.length - 2 );
	}

	fireEvent( this.root, this.getAction(), { event: event, args: args } );
}
<|endoftext|>