<commit_before>import keys from '../util/keys'
import platform from '../util/platform'
import startsWith from '../util/startsWith'
import parseKeyEvent from '../util/parseKeyEvent'
import { getDOMRangeFromEvent } from '../util/windowUtils'
import DefaultDOMElement from '../dom/DefaultDOMElement'
import Component from './Component'
import Clipboard from './Clipboard'
import UnsupportedNode from './UnsupportedNodeComponent'

const BROWSER_DELAY = platform.isFF ? 1 : 0

/**
   Abstract interface for editing components.
   Dances with contenteditable, so you don't have to.
*/
export default class Surface extends Component {
  constructor (...args) {
    super(...args)

    this._initialize()
  }

  _initialize () {
    // EditorSession instance must be provided either as a prop
    // or via dependency-injection
    this.editorSession = this.props.editorSession || this.context.editorSession
    if (!this.editorSession) {
      throw new Error('No EditorSession provided')
    }
    this.name = this.props.name
    if (!this.name) {
      throw new Error('Surface must have a name.')
    }
    if (this.name.indexOf('/') > -1) {
      // because we are using '/' to deal with nested surfaces (isolated nodes)
      throw new Error("Surface.name must not contain '/'")
    }
    // this path is an identifier unique for this surface
    // considering nesting in IsolatedNodes
    this._surfaceId = Surface.createSurfaceId(this)

    this.clipboard = new Clipboard(this.editorSession)

    this.domSelection = this.context.domSelection
    if (!this.domSelection) throw new Error('DOMSelection instance must be provided via context.')

    this._state = {
      // true if the document session's selection is addressing this surface
      skipNextFocusEvent: false
    }
  }

  getChildContext () {
    return {
      surface: this,
      parentSurfaceId: this.getId(),<commit_msg>Make Surface more robust w.r.t missing DOMSelection.<commit_after>import keys from '../util/keys'
import platform from '../util/platform'
import startsWith from '../util/startsWith'
import parseKeyEvent from '../util/parseKeyEvent'
import { getDOMRangeFromEvent } from '../util/windowUtils'
import DefaultDOMElement from '../dom/DefaultDOMElement'
import Component from './Component'
import Clipboard from './Clipboard'
import DOMSelection from './DOMSelection'
import UnsupportedNode from './UnsupportedNodeComponent'

const BROWSER_DELAY = platform.isFF ? 1 : 0

/**
   Abstract interface for editing components.
   Dances with contenteditable, so you don't have to.
*/
export default class Surface extends Component {
  constructor (...args) {
    super(...args)

    this._initialize()
  }

  _initialize () {
    // EditorSession instance must be provided either as a prop
    // or via dependency-injection
    this.editorSession = this.props.editorSession || this.context.editorSession
    if (!this.editorSession) {
      throw new Error('No EditorSession provided')
    }
    this.name = this.props.name
    if (!this.name) {
      throw new Error('Surface must have a name.')
    }
    if (this.name.indexOf('/') > -1) {
      // because we are using '/' to deal with nested surfaces (isolated nodes)
      throw new Error("Surface.name must not contain '/'")
    }
    // this path is an identifier unique for this surface
    // considering nesting in IsolatedNodes
    this._surfaceId = Surface.createSurfaceId(this)

    this.clipboard = new Clipboard(this.editorSession)

    this.domSelection = this.context.domSelection || new DOMSelection(this)

    this._state = {
      // true if the document session's selection is addressing this surface
      skipNextFocusEvent: false
    }
  }

  getChildContext () {
    return {
      surface: this,
      parentSurfaceId: this.getId(),
{'fraction_non_alphanumeric': 0.10512414157422081, 'fraction_numerical': 0.001584786053882726, 'mean_word_length': 3.2265625, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '4282260', 'n_tokens_mistral': 1043, 'n_tokens_neox': 1004, 'n_words': 336}