<commit_before>import { ComponentRef, ElementRef, EventEmitter, Output, Renderer } from '@angular/core';

import { Footer, Header } from '../components/toolbar/toolbar';
import { isPresent, merge } from '../util/util';
import { Navbar } from '../components/navbar/navbar';
import { NavControllerBase } from './nav-controller-base';
import { NavOptions, ViewState } from './nav-util';
import { NavParams } from './nav-params';


/**
 * @name ViewController
 * @description
 * Access various features and information about the current view.
 * @usage
 *  ```ts
 * import { Component } from '@angular/core';
 * import { ViewController } from 'ionic-angular';
 *
 * @Component({...})
 * export class MyPage{
 *
 *   constructor(public viewCtrl: ViewController) {}
 *
 * }
 * ```
 */
export class ViewController {
  private _cntDir: any;
  private _cntRef: ElementRef;
  private _hdrDir: Header;
  private _ftrDir: Footer;
  private _isHidden: boolean = false;
  private _leavingOpts: NavOptions;
  private _nb: Navbar;
  private _onDidDismiss: Function;
  private _onWillDismiss: Function;
  private _detached: boolean;

  /**
   * Observable to be subscribed to when the current component will become active
   * @returns {Observable} Returns an observable
   */
  willEnter: EventEmitter<any>;

  /**
   * Observable to be subscribed to when the current component has become active
   * @returns {Observable} Returns an observable
   */
  didEnter: EventEmitter<any>;

  /**
   * Observable to be subscribed to when the current component will no longer be active
   * @returns {Observable} Returns an observable
   */
  willLeave: EventEmitter<any>;

  /**
   * Observable to be subscribed to when the current component is no long active
   * @returns {Observable} Returns an observable
   */
  didLeave: EventEmitter<any>;

  /**
   * Observable to be subscribed to when the current component has been destroyed
   * @returns {Observable} Returns an observable
   */
  willUnload: EventEmitter<any>;

  /** @private */
  data: any;

  /** @private */
  instance: any;

  /** @private */
  id: string;

  /** @private */
  isOverlay: boolean = false;

  /** @private */
  _cmp: ComponentRef<any>;

  /** @private */
  _nav: NavControllerBase;

  /** @private */
  _zIndex: number;

  /** @private */
  _state: ViewState;

  /** @private */
  _cssClass: string;

  /** @private */
  @Output() private _emitter: EventEmitter<any> = new EventEmitter();

  constructor(public component?: any, data?: any, rootCssClass: string = DEFAULT_CSS_CLASS) {
    // passed in data could be NavParams, but all we care about is its data object
    this.data = (data instanceof NavParams ? data.data : (isPresent(data) ? data : {}));

    this._cssClass = rootCssClass;

    this.willEnter = new EventEmitter();
    this.didEnter = new EventEmitter();
    this.willLeave = new EventEmitter();
    this.didLeave = new EventEmitter();
    this.willUnload = new EventEmitter();
  }

  /**
   * @private
   */
  init(componentRef: ComponentRef<any>) {
    this._cmp = componentRef;
    this.instance = this.instance || componentRef.instance;
    this._detached = false;
  }

  /**
   * @private
   */
  _setNav(navCtrl: NavControllerBase) {
    this._nav = navCtrl;
  }

  /**
   * @private
   */
  _setInstance(instance: any) {
    this.instance = instance;
  }

  /**
   * @private
   */
  subscribe(generatorOrNext?: any): any {
    return this._emitter.subscribe(generatorOrNext);
  }

  /**
   * @private
   */
  emit(data?: any) {
    this._emitter.emit(data);
  }

  /**
   * @private
   * onDismiss(..) has been deprecated. Please use onDidDismiss(..) instead
   */
  onDismiss(callback: Function) {
    // deprecated warning: added beta.11 2016-06-30
    console.warn('onDismiss(..) has been deprecated. Please use onDidDismiss(..) instead');
    this.onDidDismiss(callback);
  }

  /**
   * Called when the current viewController has be successfully dismissed
   */
  onDidDismiss(callback: Function) {
    this._onDidDismiss = callback;
  }

  /**
   * Called when the current viewController will be dismissed
   */
  onWillDismiss(callback: Function) {
    this._onWillDismiss = callback;
  }

  /**
   * Dismiss the current viewController
   * @param {any} [data] Data that you want to return when the viewController is dismissed.
   * @param {any} [role ]
   * @param {NavOptions} NavOptions Options for the dismiss navigation.
   * @returns {any} data Returns the data passed in, if any.
   *
   */
  dismiss(data?: any, role?: any, navOptions: NavOptions = {}) {
    if (!this._nav) {
      return Promise.resolve(false);
    }

    let options = merge({}, this._leavingOpts, navOptions);
    this._onWillDismiss && this._onWillDismiss(data, role);
    return this._nav.remove(this._nav.indexOf(this), 1, options).then(() => {
      this._onDidDismiss && this._onDidDismiss(data, role);
      this._onDidDismiss = null;
      return data;
    });
  }

  /**
   * @private
   */
  getNav() {
    return this._nav;
  }

  /**
   * @private
   */
  getTransitionName(direction: string): string {
    return this._nav && this._nav.config.get('pageTransition');
  }

  /**
   * @private
   */
  getNavParams(): NavParams {
    return new NavParams(this.data);
  }
<commit_msg>fix(ViewController): avoid deep copy in dismiss() that can turn into an infinite loop<commit_after>import { ComponentRef, ElementRef, EventEmitter, Output, Renderer } from '@angular/core';

import { Footer, Header } from '../components/toolbar/toolbar';
import { isPresent, assign } from '../util/util';
import { Navbar } from '../components/navbar/navbar';
import { NavControllerBase } from './nav-controller-base';
import { NavOptions, ViewState } from './nav-util';
import { NavParams } from './nav-params';


/**
 * @name ViewController
 * @description
 * Access various features and information about the current view.
 * @usage
 *  ```ts
 * import { Component } from '@angular/core';
 * import { ViewController } from 'ionic-angular';
 *
 * @Component({...})
 * export class MyPage{
 *
 *   constructor(public viewCtrl: ViewController) {}
 *
 * }
 * ```
 */
export class ViewController {
  private _cntDir: any;
  private _cntRef: ElementRef;
  private _hdrDir: Header;
  private _ftrDir: Footer;
  private _isHidden: boolean = false;
  private _leavingOpts: NavOptions;
  private _nb: Navbar;
  private _onDidDismiss: Function;
  private _onWillDismiss: Function;
  private _detached: boolean;

  /**
   * Observable to be subscribed to when the current component will become active
   * @returns {Observable} Returns an observable
   */
  willEnter: EventEmitter<any>;

  /**
   * Observable to be subscribed to when the current component has become active
   * @returns {Observable} Returns an observable
   */
  didEnter: EventEmitter<any>;

  /**
   * Observable to be subscribed to when the current component will no longer be active
   * @returns {Observable} Returns an observable
   */
  willLeave: EventEmitter<any>;

  /**
   * Observable to be subscribed to when the current component is no long active
   * @returns {Observable} Returns an observable
   */
  didLeave: EventEmitter<any>;

  /**
   * Observable to be subscribed to when the current component has been destroyed
   * @returns {Observable} Returns an observable
   */
  willUnload: EventEmitter<any>;

  /** @private */
  data: any;

  /** @private */
  instance: any;

  /** @private */
  id: string;

  /** @private */
  isOverlay: boolean = false;

  /** @private */
  _cmp: ComponentRef<any>;

  /** @private */
  _nav: NavControllerBase;

  /** @private */
  _zIndex: number;

  /** @private */
  _state: ViewState;

  /** @private */
  _cssClass: string;

  /** @private */
  @Output() private _emitter: EventEmitter<any> = new EventEmitter();

  constructor(public component?: any, data?: any, rootCssClass: string = DEFAULT_CSS_CLASS) {
    // passed in data could be NavParams, but all we care about is its data object
    this.data = (data instanceof NavParams ? data.data : (isPresent(data) ? data : {}));

    this._cssClass = rootCssClass;

    this.willEnter = new EventEmitter();
    this.didEnter = new EventEmitter();
    this.willLeave = new EventEmitter();
    this.didLeave = new EventEmitter();
    this.willUnload = new EventEmitter();
  }

  /**
   * @private
   */
  init(componentRef: ComponentRef<any>) {
    this._cmp = componentRef;
    this.instance = this.instance || componentRef.instance;
    this._detached = false;
  }

  /**
   * @private
   */
  _setNav(navCtrl: NavControllerBase) {
    this._nav = navCtrl;
  }

  /**
   * @private
   */
  _setInstance(instance: any) {
    this.instance = instance;
  }

  /**
   * @private
   */
  subscribe(generatorOrNext?: any): any {
    return this._emitter.subscribe(generatorOrNext);
  }

  /**
   * @private
   */
  emit(data?: any) {
    this._emitter.emit(data);
  }

  /**
   * @private
   * onDismiss(..) has been deprecated. Please use onDidDismiss(..) instead
   */
  onDismiss(callback: Function) {
    // deprecated warning: added beta.11 2016-06-30
    console.warn('onDismiss(..) has been deprecated. Please use onDidDismiss(..) instead');
    this.onDidDismiss(callback);
  }

  /**
   * Called when the current viewController has be successfully dismissed
   */
  onDidDismiss(callback: Function) {
    this._onDidDismiss = callback;
  }

  /**
   * Called when the current viewController will be dismissed
   */
  onWillDismiss(callback: Function) {
    this._onWillDismiss = callback;
  }

  /**
   * Dismiss the current viewController
   * @param {any} [data] Data that you want to return when the viewController is dismissed.
   * @param {any} [role ]
   * @param {NavOptions} NavOptions Options for the dismiss navigation.
   * @returns {any} data Returns the data passed in, if any.
   *
   */
  dismiss(data?: any, role?: any, navOptions: NavOptions = {}) {
    if (!this._nav) {
      return Promise.resolve(false);
    }

    let options = assign({}, this._leavingOpts, navOptions);
    this._onWillDismiss && this._onWillDismiss(data, role);
    return this._nav.remove(this._nav.indexOf(this), 1, options).then(() => {
      this._onDidDismiss && this._onDidDismiss(data, role);
      this._onDidDismiss = null;
      return data;
    });
  }

  /**
   * @private
   */
  getNav() {
    return this._nav;
  }

  /**
   * @private
   */
  getTransitionName(direction: string): string {
    return this._nav && this._nav.config.get('pageTransition');
  }

  /**
   * @private
   */
  getNavParams(): NavParams {
    return new NavParams(this.data);
  }

{'fraction_non_alphanumeric': 0.13195623467270326, 'fraction_numerical': 0.00207508017355216, 'mean_word_length': 3.179345683878597, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2471008', 'n_tokens_mistral': 3278, 'n_tokens_neox': 3198, 'n_words': 898}