/*
 * Copyright 2017 Google Inc. All Rights Reserved.
 * Licensed 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.
 */

import EventTarget from '../lib/EventTarget';

export const PRIVATE = Symbol('@@webxr-polyfill/XR');

export const XRSessionModes = ['inline', 'immersive-vr', 'immersive-ar'];

const POLYFILL_REQUEST_SESSION_ERROR = 
`Polyfill Error: Must call navigator.xr.supportsSession() with any XRSessionMode
or navigator.xr.requestSession('inline') prior to requesting an immersive
session. This is a limitation specific to the WebXR Polyfill and does not apply
to native implementations of the API.`

export default class XR extends EventTarget {
  /**
   * Receives a promise of an XRDevice, so that the polyfill
   * can pass in some initial checks to asynchronously provide XRDevices
   * if content immediately requests `requestDevice()`.
   *
   * @param {Promise<XRDevice>} devicePromise
   */
  constructor(devicePromise) {
    super();
    this[PRIVATE] = {
      device: null,
      devicePromise,
      immersiveSession: null,
      inlineSessions: new Set(),
    };

    devicePromise.then((device) => { this[PRIVATE].device = device; });
  }

  /**
   * @param {XRSessionMode} mode
   * @return {Promise<null>}
   */
  async supportsSession(mode) {
    // Always ensure that we wait for the device promise to resolve.
    if (!this[PRIVATE].device) {
      await this[PRIVATE].devicePromise;
    }

    // 'inline' is always guaranteed to be supported.
    if (mode != 'inline') {
      if (!this[PRIVATE].device.supportsSession(mode)) {
        return Promise.reject(null);
      }
    } 

    return Promise.resolve(null);
  }

  /**
   * @param {XRSessionMode} mode
   * @return {Promise<XRSession>}
   */
  async requestSession(mode) {
    // If the device hasn't resolved yet, wait for it and try again.
    if (!this[PRIVATE].device) {
      if (mode != 'inline') {
        // Because requesting immersive modes requires a user gesture, we can't
        // wait for a promise to resolve before making the real session request.
        // For that reason, we'll throw a polyfill-specific error here.
        throw new Error(POLYFILL_REQUEST_SESSION_ERROR);
      } else {
        await this[PRIVATE].devicePromise;
      }
    }

    // Call device's requestSession, which does some initialization (1.1 
    // fallback calls `vrDisplay.requestPresent()` for example). Could throw 
    // due to missing user gesture.
    const sessionId = await this[PRIVATE].device.requestSession(mode);
    const session = new XRSession(this[PRIVATE].device, mode, sessionId);

    if (mode == 'inline') {
      this[PRIVATE].inlineSessions.add(session);
    } else {
      this[PRIVATE].immersiveSession = session;
    }

    const onSessionEnd = () => {
      if (mode == 'inline') {
        this[PRIVATE].inlineSessions.delete(session);
      } else {
        this[PRIVATE].immersiveSession = null;
      }
      session.removeEventListener('end', onSessionEnd);
    };
    session.addEventListener('end', onSessionEnd);

    return session;
  }
}

@@ -2079,19 +2079,88 @@
 reject(n
-ull
+ew DOMException('The specified session configuration is not supported.')
 );%0A     
@@ -2197,20 +2197,16 @@
 resolve(
-null
 );%0A  %7D%0A%0A

Fix return values from XR.supportsSession()