Best JavaScript code snippet using wpt
webxr-test.js
Source:webxr-test.js  
...138  requestSession(sessionOptions) {139    const requests = [];140    // Request a session from all the runtimes.141    for (let i = 0; i < this.runtimes_.length; i++) {142      requests[i] = this.runtimes_[i]._requestRuntimeSession(sessionOptions);143    }144    return Promise.all(requests).then((results) => {145      // Find and return the first successful result.146      for (let i = 0; i < results.length; i++) {147        if (results[i].session) {148          // Construct a dummy metrics recorder149          const metricsRecorderPtr = new vrMojom.XRSessionMetricsRecorderRemote();150          metricsRecorderPtr.$.bindNewPipeAndPassReceiver().handle.close();151          const success = {152            session: results[i].session,153            metricsRecorder: metricsRecorderPtr,154          };155          return {result: {success}};156        }157      }158      // If there were no successful results, returns a null session.159      return {160        result: {failureReason: vrMojom.RequestSessionError.NO_RUNTIME_FOUND}161      };162    });163  }164  supportsSession(sessionOptions) {165    const requests = [];166    // Check supports on all the runtimes.167    for (let i = 0; i < this.runtimes_.length; i++) {168      requests[i] = this.runtimes_[i]._runtimeSupportsSession(sessionOptions);169    }170    return Promise.all(requests).then((results) => {171      // Find and return the first successful result.172      for (let i = 0; i < results.length; i++) {173        if (results[i].supportsSession) {174          return results[i];175        }176      }177      // If there were no successful results, returns false.178      return {supportsSession: false};179    });180  }181  exitPresent() {182    return Promise.resolve();183  }184  setFramesThrottled(throttled) {185    this.setFramesThrottledImpl(throttled);186  }187  // We cannot override the mojom interceptors via the prototype; so this method188  // and the above indirection exist to allow overrides by internal code.189  setFramesThrottledImpl(throttled) {}190  // Only handles asynchronous calls to makeXrCompatible. Synchronous calls are191  // not supported in Javascript.192  makeXrCompatible() {193    if (this.runtimes_.length == 0) {194      return {195        xrCompatibleResult: vrMojom.XrCompatibleResult.kNoDeviceAvailable196      };197    }198    return {xrCompatibleResult: vrMojom.XrCompatibleResult.kAlreadyCompatible};199  }200}201class FakeXRAnchorController {202  constructor() {203    // Private properties.204    this.device_ = null;205    this.id_ = null;206    this.dirty_ = true;207    // Properties backing up public attributes / methods.208    this.deleted_ = false;209    this.paused_ = false;210    this.anchorOrigin_ = XRMathHelper.identity();211  }212  // WebXR Test API (Anchors Extension)213  get deleted() {214    return this.deleted_;215  }216  pauseTracking() {217    if(!this.paused_) {218      this.paused_ = true;219      this.dirty_ = true;220    }221  }222  resumeTracking() {223    if(this.paused_) {224      this.paused_ = false;225      this.dirty_ = true;226    }227  }228  stopTracking() {229    if(!this.deleted_) {230      this.device_._deleteAnchorController(this.id_);231      this.deleted_ = true;232      this.dirty_ = true;233    }234  }235  setAnchorOrigin(anchorOrigin) {236    this.anchorOrigin_ = getMatrixFromTransform(anchorOrigin);237    this.dirty_ = true;238  }239  // Internal implementation:240  set id(value) {241    this.id_ = value;242  }243  set device(value) {244    this.device_ = value;245  }246  get dirty() {247    return this.dirty_;248  }249  get paused() {250    return this.paused_;251  }252  _markProcessed() {253    this.dirty_ = false;254  }255  _getAnchorOrigin() {256    return this.anchorOrigin_;257  }258}259// Implements XRFrameDataProvider and XRPresentationProvider. Maintains a mock260// for XRPresentationProvider. Implements FakeXRDevice test API.261class MockRuntime {262  // Mapping from string feature names to the corresponding mojo types.263  // This is exposed as a member for extensibility.264  static _featureToMojoMap = {265    'viewer': vrMojom.XRSessionFeature.REF_SPACE_VIEWER,266    'local': vrMojom.XRSessionFeature.REF_SPACE_LOCAL,267    'local-floor': vrMojom.XRSessionFeature.REF_SPACE_LOCAL_FLOOR,268    'bounded-floor': vrMojom.XRSessionFeature.REF_SPACE_BOUNDED_FLOOR,269    'unbounded': vrMojom.XRSessionFeature.REF_SPACE_UNBOUNDED,270    'hit-test': vrMojom.XRSessionFeature.HIT_TEST,271    'dom-overlay': vrMojom.XRSessionFeature.DOM_OVERLAY,272    'light-estimation': vrMojom.XRSessionFeature.LIGHT_ESTIMATION,273    'anchors': vrMojom.XRSessionFeature.ANCHORS,274    'depth-sensing': vrMojom.XRSessionFeature.DEPTH,275    'secondary-views': vrMojom.XRSessionFeature.SECONDARY_VIEWS,276  };277  static _sessionModeToMojoMap = {278    "inline": vrMojom.XRSessionMode.kInline,279    "immersive-vr": vrMojom.XRSessionMode.kImmersiveVr,280    "immersive-ar": vrMojom.XRSessionMode.kImmersiveAr,281  };282  static _environmentBlendModeToMojoMap = {283    "opaque": vrMojom.XREnvironmentBlendMode.kOpaque,284    "alpha-blend": vrMojom.XREnvironmentBlendMode.kAlphaBlend,285    "additive": vrMojom.XREnvironmentBlendMode.kAdditive,286  };287  static _interactionModeToMojoMap = {288    "screen-space": vrMojom.XRInteractionMode.kScreenSpace,289    "world-space": vrMojom.XRInteractionMode.kWorldSpace,290  };291  constructor(fakeDeviceInit, service) {292    this.sessionClient_ = null;293    this.presentation_provider_ = new MockXRPresentationProvider();294    this.pose_ = null;295    this.next_frame_id_ = 0;296    this.bounds_ = null;297    this.send_mojo_space_reset_ = false;298    this.stageParameters_ = null;299    this.stageParametersId_ = 1;300    this.service_ = service;301    this.framesOfReference = {};302    this.input_sources_ = new Map();303    this.next_input_source_index_ = 1;304    // Currently active hit test subscriptons.305    this.hitTestSubscriptions_ = new Map();306    // Currently active transient hit test subscriptions.307    this.transientHitTestSubscriptions_ = new Map();308    // ID of the next subscription to be assigned.309    this.next_hit_test_id_ = 1n;310    this.anchor_controllers_ = new Map();311    // ID of the next anchor to be assigned.312    this.next_anchor_id_ = 1n;313    // Anchor creation callback (initially null, can be set by tests).314    this.anchor_creation_callback_ = null;315    this.depthSensingData_ = null;316    this.depthSensingDataDirty_ = false;317    let supportedModes = [];318    if (fakeDeviceInit.supportedModes) {319      supportedModes = fakeDeviceInit.supportedModes.slice();320      if (fakeDeviceInit.supportedModes.length === 0) {321        supportedModes = ["inline"];322      }323    } else {324      // Back-compat mode.325      console.warn("Please use `supportedModes` to signal which modes are supported by this device.");326      if (fakeDeviceInit.supportsImmersive == null) {327        throw new TypeError("'supportsImmersive' must be set");328      }329      supportedModes = ["inline"];330      if (fakeDeviceInit.supportsImmersive) {331        supportedModes.push("immersive-vr");332      }333    }334    this.supportedModes_ = this._convertModesToEnum(supportedModes);335    // Initialize DisplayInfo first to set the defaults, then override with336    // anything from the deviceInit337    if (this.supportedModes_.includes(vrMojom.XRSessionMode.kImmersiveVr) ||338        this.supportedModes_.includes(vrMojom.XRSessionMode.kImmersiveAr)) {339      this.displayInfo_ = this._getImmersiveDisplayInfo();340    } else if (this.supportedModes_.includes(vrMojom.XRSessionMode.kInline)) {341      this.displayInfo_ = this._getNonImmersiveDisplayInfo();342    } else {343      // This should never happen!344      console.error("Device has empty supported modes array!");345      throw new InvalidStateError();346    }347    if (fakeDeviceInit.viewerOrigin != null) {348      this.setViewerOrigin(fakeDeviceInit.viewerOrigin);349    }350    if (fakeDeviceInit.floorOrigin != null) {351      this.setFloorOrigin(fakeDeviceInit.floorOrigin);352    }353    if (fakeDeviceInit.world) {354      this.setWorld(fakeDeviceInit.world);355    }356    if (fakeDeviceInit.depthSensingData) {357      this.setDepthSensingData(fakeDeviceInit.depthSensingData);358    }359    this.defaultFramebufferScale_ = default_framebuffer_scale;360    this.enviromentBlendMode_ = this._convertBlendModeToEnum(fakeDeviceInit.environmentBlendMode);361    this.interactionMode_ = this._convertInteractionModeToEnum(fakeDeviceInit.interactionMode);362    // This appropriately handles if the coordinates are null363    this.setBoundsGeometry(fakeDeviceInit.boundsCoordinates);364    this.setViews(fakeDeviceInit.views, fakeDeviceInit.secondaryViews);365    // Need to support webVR which doesn't have a notion of features366    this._setFeatures(fakeDeviceInit.supportedFeatures || []);367  }368  // WebXR Test API369  setViews(primaryViews, secondaryViews) {370    this.primaryViews_ = [];371    this.secondaryViews_ = [];372    let xOffset = 0;373    if (primaryViews) {374      this.primaryViews_ = [];375      xOffset = this._setViews(primaryViews, xOffset, this.primaryViews_);376    }377    if (secondaryViews) {378      this.secondaryViews_ = [];379      this._setViews(secondaryViews, xOffset, this.secondaryViews_);380    }381    // Do not include secondary views here because they are only exposed to382    // WebXR if requested by the session. getFrameData() will send back the383    // secondary views when enabled.384    this.displayInfo_.views = this.primaryViews_;385    if (this.sessionClient_) {386      this.sessionClient_.onChanged(this.displayInfo_);387    }388  }389  disconnect() {390    this.service_._removeRuntime(this);391    this.presentation_provider_._close();392    if (this.sessionClient_) {393      this.sessionClient_.$.close();394      this.sessionClient_ = null;395    }396    return Promise.resolve();397  }398  setViewerOrigin(origin, emulatedPosition = false) {399    const p = origin.position;400    const q = origin.orientation;401    this.pose_ = {402      orientation: { x: q[0], y: q[1], z: q[2], w: q[3] },403      position: { x: p[0], y: p[1], z: p[2] },404      emulatedPosition: emulatedPosition,405      angularVelocity: null,406      linearVelocity: null,407      angularAcceleration: null,408      linearAcceleration: null,409      inputState: null,410      poseIndex: 0411    };412  }413  clearViewerOrigin() {414    this.pose_ = null;415  }416  setFloorOrigin(floorOrigin) {417    if (!this.stageParameters_) {418      this.stageParameters_ = default_stage_parameters;419      this.stageParameters_.bounds = this.bounds_;420    }421    // floorOrigin is passed in as mojoFromFloor.422    this.stageParameters_.mojoFromFloor =423        {matrix: getMatrixFromTransform(floorOrigin)};424    this._onStageParametersUpdated();425  }426  clearFloorOrigin() {427    if (this.stageParameters_) {428      this.stageParameters_ = null;429      this._onStageParametersUpdated();430    }431  }432  setBoundsGeometry(bounds) {433    if (bounds == null) {434      this.bounds_ = null;435    } else if (bounds.length < 3) {436      throw new Error("Bounds must have a length of at least 3");437    } else {438      this.bounds_ = bounds;439    }440    // We can only set bounds if we have stageParameters set; otherwise, we441    // don't know the transform from local space to bounds space.442    // We'll cache the bounds so that they can be set in the future if the443    // floorLevel transform is set, but we won't update them just yet.444    if (this.stageParameters_) {445      this.stageParameters_.bounds = this.bounds_;446      this._onStageParametersUpdated();447    }448  }449  simulateResetPose() {450    this.send_mojo_space_reset_ = true;451  }452  simulateVisibilityChange(visibilityState) {453    let mojoState = null;454    switch (visibilityState) {455      case "visible":456        mojoState = vrMojom.XRVisibilityState.VISIBLE;457        break;458      case "visible-blurred":459        mojoState = vrMojom.XRVisibilityState.VISIBLE_BLURRED;460        break;461      case "hidden":462        mojoState = vrMojom.XRVisibilityState.HIDDEN;463        break;464    }465    if (mojoState && this.sessionClient_) {466      this.sessionClient_.onVisibilityStateChanged(mojoState);467    }468  }469  simulateInputSourceConnection(fakeInputSourceInit) {470    const index = this.next_input_source_index_;471    this.next_input_source_index_++;472    const source = new MockXRInputSource(fakeInputSourceInit, index, this);473    this.input_sources_.set(index, source);474    return source;475  }476  // WebXR Test API Hit Test extensions477  setWorld(world) {478    this.world_ = world;479  }480  clearWorld() {481    this.world_ = null;482  }483  // WebXR Test API Anchor extensions484  setAnchorCreationCallback(callback) {485    this.anchor_creation_callback_ = callback;486  }487  setHitTestSourceCreationCallback(callback) {488    this.hit_test_source_creation_callback_ = callback;489  }490  // WebXR Test API Lighting estimation extensions491  setLightEstimate(fakeXrLightEstimateInit) {492    if (!fakeXrLightEstimateInit.sphericalHarmonicsCoefficients) {493      throw new TypeError("sphericalHarmonicsCoefficients must be set");494    }495    if (fakeXrLightEstimateInit.sphericalHarmonicsCoefficients.length != 27) {496      throw new TypeError("Must supply all 27 sphericalHarmonicsCoefficients");497    }498    if (fakeXrLightEstimateInit.primaryLightDirection && fakeXrLightEstimateInit.primaryLightDirection.w != 0) {499      throw new TypeError("W component of primaryLightDirection must be 0");500    }501    if (fakeXrLightEstimateInit.primaryLightIntensity && fakeXrLightEstimateInit.primaryLightIntensity.w != 1) {502      throw new TypeError("W component of primaryLightIntensity must be 1");503    }504    // If the primaryLightDirection or primaryLightIntensity aren't set, we need to set them505    // to the defaults that the spec expects. ArCore will either give us everything or nothing,506    // so these aren't nullable on the mojom.507    if (!fakeXrLightEstimateInit.primaryLightDirection) {508      fakeXrLightEstimateInit.primaryLightDirection = { x: 0.0, y: 1.0, z: 0.0, w: 0.0 };509    }510    if (!fakeXrLightEstimateInit.primaryLightIntensity) {511      fakeXrLightEstimateInit.primaryLightIntensity = { x: 0.0, y: 0.0, z: 0.0, w: 1.0 };512    }513    let c = fakeXrLightEstimateInit.sphericalHarmonicsCoefficients;514    this.light_estimate_ = {515      lightProbe: {516        // XRSphereicalHarmonics517        sphericalHarmonics: {518          coefficients: [519            { red: c[0],  green: c[1],  blue: c[2] },520            { red: c[3],  green: c[4],  blue: c[5] },521            { red: c[6],  green: c[7],  blue: c[8] },522            { red: c[9],  green: c[10], blue: c[11] },523            { red: c[12], green: c[13], blue: c[14] },524            { red: c[15], green: c[16], blue: c[17] },525            { red: c[18], green: c[19], blue: c[20] },526            { red: c[21], green: c[22], blue: c[23] },527            { red: c[24], green: c[25], blue: c[26] }528          ]529        },530        // Vector3dF531        mainLightDirection: {532          x: fakeXrLightEstimateInit.primaryLightDirection.x,533          y: fakeXrLightEstimateInit.primaryLightDirection.y,534          z: fakeXrLightEstimateInit.primaryLightDirection.z535        },536        // RgbTupleF32537        mainLightIntensity: {538          red:   fakeXrLightEstimateInit.primaryLightIntensity.x,539          green: fakeXrLightEstimateInit.primaryLightIntensity.y,540          blue:  fakeXrLightEstimateInit.primaryLightIntensity.z541        }542      }543    }544  }545  // WebXR Test API depth Sensing Extensions546  setDepthSensingData(depthSensingData) {547    for(const key of ["depthData", "normDepthBufferFromNormView", "rawValueToMeters", "width", "height"]) {548      if(!(key in depthSensingData)) {549        throw new TypeError("Required key not present. Key: " + key);550      }551    }552    if(depthSensingData.depthData != null) {553      // Create new object w/ properties based on the depthSensingData, but554      // convert the FakeXRRigidTransformInit into a transformation matrix object.555      this.depthSensingData_ = Object.assign({},556        depthSensingData, {557          normDepthBufferFromNormView: composeGFXTransform(depthSensingData.normDepthBufferFromNormView),558        });559    } else {560      throw new TypeError("`depthData` is not set");561    }562    this.depthSensingDataDirty_ = true;563  }564  clearDepthSensingData() {565    this.depthSensingData_ = null;566    this.depthSensingDataDirty_ = true;567  }568  // Internal Implementation/Helper Methods569  _convertModeToEnum(sessionMode) {570    if (sessionMode in MockRuntime._sessionModeToMojoMap) {571      return MockRuntime._sessionModeToMojoMap[sessionMode];572    }573    throw new TypeError("Unrecognized value for XRSessionMode enum: " + sessionMode);574  }575  _convertModesToEnum(sessionModes) {576    return sessionModes.map(mode => this._convertModeToEnum(mode));577  }578  _convertBlendModeToEnum(blendMode) {579    if (blendMode in MockRuntime._environmentBlendModeToMojoMap) {580      return MockRuntime._environmentBlendModeToMojoMap[blendMode];581    } else {582      if (this.supportedModes_.includes(vrMojom.XRSessionMode.kImmersiveAr)) {583        return vrMojom.XREnvironmentBlendMode.kAdditive;584      } else if (this.supportedModes_.includes(585            vrMojom.XRSessionMode.kImmersiveVr)) {586        return vrMojom.XREnvironmentBlendMode.kOpaque;587      }588    }589  }590  _convertInteractionModeToEnum(interactionMode) {591    if (interactionMode in MockRuntime._interactionModeToMojoMap) {592      return MockRuntime._interactionModeToMojoMap[interactionMode];593    } else {594      return vrMojom.XRInteractionMode.kWorldSpace;595    }596  }597  _setViews(deviceViews, xOffset, views) {598    for (let i = 0; i < deviceViews.length; i++) {599      views[i] = this._getView(deviceViews[i], xOffset);600      xOffset += deviceViews[i].resolution.width;601    }602    return xOffset;603  }604  _onStageParametersUpdated() {605    // Indicate for the frame loop that the stage parameters have been updated.606    this.stageParametersId_++;607  }608  _getNonImmersiveDisplayInfo() {609    const displayInfo = this._getImmersiveDisplayInfo();610    displayInfo.capabilities.canPresent = false;611    displayInfo.views = [];612    return displayInfo;613  }614  // Function to generate some valid display information for the device.615  _getImmersiveDisplayInfo() {616    const viewport_size = 20;617    return {618      displayName: 'FakeDevice',619      capabilities: {620        hasPosition: false,621        hasExternalDisplay: false,622        canPresent: true,623        maxLayers: 1624      },625      stageParameters: null,626      views: [{627        eye: vrMojom.XREye.kLeft,628        fieldOfView: {629          upDegrees: 48.316,630          downDegrees: 50.099,631          leftDegrees: 50.899,632          rightDegrees: 35.197633        },634        mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform({635          position: [-0.032, 0, 0],636          orientation: [0, 0, 0, 1]637        })),638        viewport: { x: 0, y: 0, width: viewport_size, height: viewport_size }639      },640      {641        eye: vrMojom.XREye.kRight,642        fieldOfView: {643          upDegrees: 48.316,644          downDegrees: 50.099,645          leftDegrees: 50.899,646          rightDegrees: 35.197647        },648        mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform({649          position: [0.032, 0, 0],650          orientation: [0, 0, 0, 1]651        })),652        viewport: { x: viewport_size, y: 0, width: viewport_size, height: viewport_size }653      }]654    };655  }656  // This function converts between the matrix provided by the WebXR test API657  // and the internal data representation.658  _getView(fakeXRViewInit, xOffset) {659    let fov = null;660    if (fakeXRViewInit.fieldOfView) {661      fov = {662        upDegrees: fakeXRViewInit.fieldOfView.upDegrees,663        downDegrees: fakeXRViewInit.fieldOfView.downDegrees,664        leftDegrees: fakeXRViewInit.fieldOfView.leftDegrees,665        rightDegrees: fakeXRViewInit.fieldOfView.rightDegrees666      };667    } else {668      const m = fakeXRViewInit.projectionMatrix;669      function toDegrees(tan) {670        return Math.atan(tan) * 180 / Math.PI;671      }672      const leftTan = (1 - m[8]) / m[0];673      const rightTan = (1 + m[8]) / m[0];674      const upTan = (1 + m[9]) / m[5];675      const downTan = (1 - m[9]) / m[5];676      fov = {677        upDegrees: toDegrees(upTan),678        downDegrees: toDegrees(downTan),679        leftDegrees: toDegrees(leftTan),680        rightDegrees: toDegrees(rightTan)681      };682    }683    let viewEye = vrMojom.XREye.kNone;684    // The eye passed in corresponds to the values in the WebXR spec, which are685    // the strings "none", "left", and "right". They should be converted to the686    // corresponding values of XREye in vr_service.mojom.687    switch(fakeXRViewInit.eye) {688      case "none":689        viewEye = vrMojom.XREye.kNone;690        break;691      case "left":692        viewEye = vrMojom.XREye.kLeft;693        break;694      case "right":695        viewEye = vrMojom.XREye.kRight;696        break;697    }698    return {699      eye: viewEye,700      fieldOfView: fov,701      mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform(fakeXRViewInit.viewOffset)),702      viewport: {703        x: xOffset,704        y: 0,705        width: fakeXRViewInit.resolution.width,706        height: fakeXRViewInit.resolution.height707      },708      isFirstPersonObserver: fakeXRViewInit.isFirstPersonObserver ? true : false,709      viewOffset: composeGFXTransform(fakeXRViewInit.viewOffset)710    };711  }712  _setFeatures(supportedFeatures) {713    function convertFeatureToMojom(feature) {714      if (feature in MockRuntime._featureToMojoMap) {715        return MockRuntime._featureToMojoMap[feature];716      } else {717        return vrMojom.XRSessionFeature.INVALID;718      }719    }720    this.supportedFeatures_ = [];721    for (let i = 0; i < supportedFeatures.length; i++) {722      const feature = convertFeatureToMojom(supportedFeatures[i]);723      if (feature !== vrMojom.XRSessionFeature.INVALID) {724        this.supportedFeatures_.push(feature);725      }726    }727  }728  // These methods are intended to be used by MockXRInputSource only.729  _addInputSource(source) {730    if (!this.input_sources_.has(source.source_id_)) {731      this.input_sources_.set(source.source_id_, source);732    }733  }734  _removeInputSource(source) {735    this.input_sources_.delete(source.source_id_);736  }737  // These methods are intended to be used by FakeXRAnchorController only.738  _deleteAnchorController(controllerId) {739    this.anchor_controllers_.delete(controllerId);740  }741  // Extension point for non-standard modules.742  _injectAdditionalFrameData(options, frameData) {743  }744  // Mojo function implementations.745  // XRFrameDataProvider implementation.746  getFrameData(options) {747    return new Promise((resolve) => {748      const populatePose = () => {749        const mojo_space_reset = this.send_mojo_space_reset_;750        this.send_mojo_space_reset_ = false;751        if (this.pose_) {752          this.pose_.poseIndex++;753        }754        // Setting the input_state to null tests a slightly different path than755        // the browser tests where if the last input source is removed, the device756        // code always sends up an empty array, but it's also valid mojom to send757        // up a null array.758        let input_state = null;759        if (this.input_sources_.size > 0) {760          input_state = [];761          for (const input_source of this.input_sources_.values()) {762            input_state.push(input_source._getInputSourceState());763          }764        }765        let frame_views = this.primaryViews_;766        for (let i = 0; i < this.primaryViews_.length; i++) {767          this.primaryViews_[i].mojoFromView =768            this._getMojoFromViewerWithOffset(this.primaryViews_[i].viewOffset);769        }770        if (this.enabledFeatures_.includes(vrMojom.XRSessionFeature.SECONDARY_VIEWS)) {771          for (let i = 0; i < this.secondaryViews_.length; i++) {772            this.secondaryViews_[i].mojoFromView =773              this._getMojoFromViewerWithOffset(this.secondaryViews_[i].viewOffset);774          }775          frame_views = frame_views.concat(this.secondaryViews_);776        }777        const frameData = {778          mojoFromViewer: this.pose_,779          views: frame_views,780          mojoSpaceReset: mojo_space_reset,781          inputState: input_state,782          timeDelta: {783            // window.performance.now() is in milliseconds, so convert to microseconds.784            microseconds: BigInt(Math.floor(window.performance.now() * 1000)),785          },786          frameId: this.next_frame_id_,787          bufferHolder: null,788          bufferSize: {},789          renderingTimeRatio: 0,790          stageParameters: this.stageParameters_,791          stageParametersId: this.stageParametersId_,792          lightEstimationData: this.light_estimate_793        };794        this.next_frame_id_++;795        this._calculateHitTestResults(frameData);796        this._calculateAnchorInformation(frameData);797        this._calculateDepthInformation(frameData);798        this._injectAdditionalFrameData(options, frameData);799        resolve({frameData});800      };801      if(this.sessionOptions_.mode == vrMojom.XRSessionMode.kInline) {802        // Inline sessions should not have a delay introduced since it causes them803        // to miss a vsync blink-side and delays propagation of changes that happened804        // within a rAFcb by one frame (e.g. setViewerOrigin() calls would take 2 frames805        // to propagate).806        populatePose();807      } else {808        // For immerive sessions, add additional delay to allow for anchor creation809        // promises to run.810        setTimeout(populatePose, 3);  // note: according to MDN, the timeout is not exact811      }812    });813  }814  getEnvironmentIntegrationProvider(environmentProviderRequest) {815    if (this.environmentProviderReceiver_) {816      this.environmentProviderReceiver_.$.close();817    }818    this.environmentProviderReceiver_ =819        new vrMojom.XREnvironmentIntegrationProviderReceiver(this);820    this.environmentProviderReceiver_.$.bindHandle(821        environmentProviderRequest.handle);822  }823  setInputSourceButtonListener(listener) { listener.$.close(); }824  // XREnvironmentIntegrationProvider implementation:825  subscribeToHitTest(nativeOriginInformation, entityTypes, ray) {826    if (!this.supportedModes_.includes(vrMojom.XRSessionMode.kImmersiveAr)) {827      // Reject outside of AR.828      return Promise.resolve({829        result : vrMojom.SubscribeToHitTestResult.FAILURE_GENERIC,830        subscriptionId : 0n831      });832    }833    if (!this._nativeOriginKnown(nativeOriginInformation)) {834      return Promise.resolve({835        result : vrMojom.SubscribeToHitTestResult.FAILURE_GENERIC,836        subscriptionId : 0n837      });838    }839    // Reserve the id for hit test source:840    const id = this.next_hit_test_id_++;841    const hitTestParameters = { isTransient: false, profileName: null };842    const controller = new FakeXRHitTestSourceController(id);843    return this._shouldHitTestSourceCreationSucceed(hitTestParameters, controller)844      .then((succeeded) => {845        if(succeeded) {846          // Store the subscription information as-is (including controller):847          this.hitTestSubscriptions_.set(id, { nativeOriginInformation, entityTypes, ray, controller });848          return Promise.resolve({849            result : vrMojom.SubscribeToHitTestResult.SUCCESS,850            subscriptionId : id851          });852        } else {853          return Promise.resolve({854            result : vrMojom.SubscribeToHitTestResult.FAILURE_GENERIC,855            subscriptionId : 0n856          });857        }858      });859  }860  subscribeToHitTestForTransientInput(profileName, entityTypes, ray){861    if (!this.supportedModes_.includes(vrMojom.XRSessionMode.kImmersiveAr)) {862      // Reject outside of AR.863      return Promise.resolve({864        result : vrMojom.SubscribeToHitTestResult.FAILURE_GENERIC,865        subscriptionId : 0n866      });867    }868    const id = this.next_hit_test_id_++;869    const hitTestParameters = { isTransient: true, profileName: profileName };870    const controller = new FakeXRHitTestSourceController(id);871    // Check if we have hit test source creation callback.872    // If yes, ask it if the hit test source creation should succeed.873    // If no, for back-compat, assume the hit test source creation succeeded.874    return this._shouldHitTestSourceCreationSucceed(hitTestParameters, controller)875      .then((succeeded) => {876        if(succeeded) {877          // Store the subscription information as-is (including controller):878          this.transientHitTestSubscriptions_.set(id, { profileName, entityTypes, ray, controller });879          return Promise.resolve({880            result : vrMojom.SubscribeToHitTestResult.SUCCESS,881            subscriptionId : id882          });883        } else {884          return Promise.resolve({885            result : vrMojom.SubscribeToHitTestResult.FAILURE_GENERIC,886            subscriptionId : 0n887          });888        }889      });890  }891  unsubscribeFromHitTest(subscriptionId) {892    let controller = null;893    if(this.transientHitTestSubscriptions_.has(subscriptionId)){894      controller = this.transientHitTestSubscriptions_.get(subscriptionId).controller;895      this.transientHitTestSubscriptions_.delete(subscriptionId);896    } else if(this.hitTestSubscriptions_.has(subscriptionId)){897      controller = this.hitTestSubscriptions_.get(subscriptionId).controller;898      this.hitTestSubscriptions_.delete(subscriptionId);899    }900    if(controller) {901      controller.deleted = true;902    }903  }904  createAnchor(nativeOriginInformation, nativeOriginFromAnchor) {905    return new Promise((resolve) => {906      if(this.anchor_creation_callback_ == null) {907        resolve({908          result : vrMojom.CreateAnchorResult.FAILURE,909          anchorId : 0n910        });911        return;912      }913      const mojoFromNativeOrigin = this._getMojoFromNativeOrigin(nativeOriginInformation);914      if(mojoFromNativeOrigin == null) {915        resolve({916          result : vrMojom.CreateAnchorResult.FAILURE,917          anchorId : 0n918        });919        return;920      }921      const mojoFromAnchor = XRMathHelper.mul4x4(mojoFromNativeOrigin, nativeOriginFromAnchor);922      const anchorCreationParameters = {923        requestedAnchorOrigin: mojoFromAnchor,924        isAttachedToEntity: false,925      };926      const anchorController = new FakeXRAnchorController();927      this.anchor_creation_callback_(anchorCreationParameters, anchorController)928            .then((result) => {929              if(result) {930                // If the test allowed the anchor creation,931                // store the anchor controller & return success.932                const anchor_id = this.next_anchor_id_;933                this.next_anchor_id_++;934                this.anchor_controllers_.set(anchor_id, anchorController);935                anchorController.device = this;936                anchorController.id = anchor_id;937                resolve({938                  result : vrMojom.CreateAnchorResult.SUCCESS,939                  anchorId : anchor_id940                });941              } else {942                // The test has rejected anchor creation.943                resolve({944                  result : vrMojom.CreateAnchorResult.FAILURE,945                  anchorId : 0n946                });947              }948            })949            .catch(() => {950              // The test threw an error, treat anchor creation as failed.951              resolve({952                result : vrMojom.CreateAnchorResult.FAILURE,953                anchorId : 0n954              });955            });956    });957  }958  createPlaneAnchor(planeFromAnchor, planeId) {959    return new Promise((resolve) => {960      // Not supported yet.961      resolve({962        result : vrMojom.CreateAnchorResult.FAILURE,963        anchorId : 0n,964      });965    });966  }967  detachAnchor(anchorId) {}968  // Utility function969  _requestRuntimeSession(sessionOptions) {970    return this._runtimeSupportsSession(sessionOptions).then((result) => {971      // The JavaScript bindings convert c_style_names to camelCase names.972      const options = {973        transportMethod:974            vrMojom.XRPresentationTransportMethod.SUBMIT_AS_MAILBOX_HOLDER,975        waitForTransferNotification: true,976        waitForRenderNotification: true,977        waitForGpuFence: false,978      };979      let submit_frame_sink;980      if (result.supportsSession) {981        submit_frame_sink = {982          clientReceiver: this.presentation_provider_._getClientReceiver(),983          provider: this.presentation_provider_._bindProvider(sessionOptions),...Using AI Code Generation
1var wpt = require('webpagetest');2var wpt = new WebPageTest('www.webpagetest.org');3wpt.runTest('www.example.com', { runs: 3, firstViewOnly: true }, function(err, data) {4  if (err) console.log('Error: ' + err);5  else {6    wpt.getTestStatus(data.data.testId, function(err, data) {7      if (err) console.log('Error: ' + err);8      else {9        wpt.getTestResults(data.data.testId, function(err, data) {10          if (err) console.log('Error: ' + err);11          else console.log(data);12        });13      }14    });15  }16});17{ statusCode: 400,18   { statusCode: 400,19     data: 'Missing required parameter: testId' } }20var wpt = new WebPageTest('www.webpagetest.org/api/runtest.php');21wpt.runTest('www.example.com', { runs: 3, firstViewOnly: true }, function(err, data) {22  if (err) console.log('Error: ' + err);23  else {24    wpt.getTestStatus(data.data.testId, function(err, data) {25      if (err) console.log('Error: ' + err);26      else {27        wpt.getTestResults(data.data.testId, function(err, data) {28          if (err) console.log('Error: ' + err);29          else console.log(data);30        });31      }32    });33  }34});35var wpt = require('webpagetest');36var wpt = new WebPageTest('www.webpagetest.org');37wpt.runTest('www.example.com', { runs: 3, firstViewOnly: true }, function(err, data) {38  if (err) console.log('Error: ' + err);39  else {40    wpt.getTestStatus(data.data.testId, function(err, data) {Using AI Code Generation
1var wpt = require('wpt');2var wpt = new WebPageTest('www.webpagetest.org');3wpt._requestRuntimeSession(function(err, data){4  if (err) {5    console.log(err);6  } else {7    console.log(data);8  }9});10{ statusCode: 200,11  data: '{"statusCode":200,"statusText":"OK","data":{"id":"a5a8b8f7b1c5d1d9b9c5e8e2a5b1c1d1","owner":"anonymous","created":"2014-09-12T06:01:24.000Z","updated":"2014-09-12T06:01:24.000Z","state":"running","location":"Dulles:Chrome","ip":"Using AI Code Generation
1var wpt = require('webpagetest');2var webpagetest = new wpt('www.webpagetest.org');3    if (err) {4        console.log(err);5    } else {6        console.log(data);7    }8});9{ [Error: Request failed with status code 404]10   { method: 'get',11     headers: { Accept: 'application/json, text/plain, */*' } },12   { status: 404,13      { 'content-type': 'text/html',14        server: 'Apache/2.2.22 (Ubuntu)',15        connection: 'close' },16      { method: 'get',17        maxContentLength: -1 },18      { domain: null,19     data: undefined } }Using AI Code Generation
1const wpt = require('webpagetest');2const client = wpt('www.webpagetest.org');3client.runTest(url, { location: 'ec2-us-west-1' }, (err, data) => {4    if (err) {5        return console.log(err);6    }7    console.log(data);8});9client._requestRuntimeSession(url, { location: 'ec2-us-west-1' }, (err, data) => {10    if (err) {11        return console.log(err);12    }13    console.log(data);14});15const wpt = require('webpagetest');16const client = wpt('www.webpagetest.org');17client._requestRuntimeSession(url, { location: 'ec2-us-west-1' }, (err, data) => {18    if (err) {19        return console.log(err);20    }21    console.log(data);22    client.getTestStatus(data.data.testId, (err, data) => {23        if (err) {24            return console.log(err);25        }26        console.log(data);27    });28});29{ statusCode: 400,30const wpt = require('webpagetest');31const client = wpt('www.webpagetest.org');32client._requestRuntimeSession(url, { location: 'ec2-us-west-1' }, (err, data) => {33    if (err) {34        return console.log(err);35    }36    console.log(data);37});38{ statusCode: 400,Using AI Code Generation
1const wpt = require('webpagetest');2const wptClient = wpt('www.webpagetest.org', 'A.1e2d3f4g5h6i7j8k9l0m1n2o3p4q5r6s7t8u9v0w1x2y3z4a5b6c7d8e9f0g1h2i3j4k5l6m7n8o9p0q1r2s3t4u5v6w7x8y9z0');3  console.log(data);4});5const wpt = require('webpagetest');6const wptClient = wpt('www.webpagetest.org', 'A.1e2d3f4g5h6i7j8k9l0m1n2o3p4q5r6s7t8u9v0w1x2y3z4a5b6c7d8e9f0g1h2i3j4k5l6m7n8o9p0q1r2s3t4u5v6w7x8y9z0');7wptClient._getRuntimeStatus('1234567890', (err, data) => {8  console.log(data);9});Using AI Code Generation
1var wpt = require('wpt');2wpt._requestRuntimeSession(function(err, data) {3  console.log(data);4});5{ [Error: connect ECONNREFUSED]6  syscall: 'connect' }Using AI Code Generation
1var wpt = require('wpt-hook');2var wptHook = new wpt.WPTHook();3  if(err) {4    console.log('Error: ', err);5  } else {6    console.log('Data: ', data);7  }8});9var wpt = require('wpt-hook');10var wptHook = new wpt.WPTHook();11  if(err) {12    console.log('Error: ', err);13  } else {14    console.log('Data: ', data);15  }16});17var wpt = require('wpt-hook');18var wptHook = new wpt.WPTHook();19  if(err) {20    console.log('Error: ', err);21  } else {22    console.log('Data: ', data);23  }24});25var wpt = require('wpt-hook');26var wptHook = new wpt.WPTHook();27  if(err) {28    console.log('Error: ', err);29  } else {30    console.log('Data: ', data);31  }32});33var wpt = require('wpt-hook');34var wptHook = new wpt.WPTHook();35  if(err) {36    console.log('Error: ', err);37  } else {38    console.log('Data: ', data);39  }40});Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
