All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.scalajs.LinkingInfo.scala Maven / Gradle / Ivy

/*
 * Scala.js (https://www.scala-js.org/)
 *
 * Copyright EPFL.
 *
 * Licensed under Apache License 2.0
 * (https://www.apache.org/licenses/LICENSE-2.0).
 *
 * See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 */

package scala.scalajs

object LinkingInfo {

  import scala.scalajs.runtime.linkingInfo

  /** Returns true if we are linking for production, false otherwise.
   *
   *  `productionMode` is always equal to `!developmentMode`.
   *
   *  This ends up being constant-folded to a constant at link-time. So
   *  constant-folding, inlining, and other local optimizations can be
   *  leveraged with this "constant" to write code that should only be
   *  executed in production mode or development mode.
   *
   *  A typical usage of this method is:
   *  {{{
   *  val warningsLogger =
   *    if (productionMode) new NullLogger
   *    else new ConsoleLogger
   *  }}}
   *
   *  At link-time, `productionMode` will either be a constant true, in which
   *  case the above snippet folds into
   *  {{{
   *  val warningsLogger = new NullLogger
   *  }}}
   *  or a constant false, in which case it folds into
   *  {{{
   *  val warningsLogger = new ConsoleLogger.
   *  }}}
   *
   *  @see [[developmentMode]]
   */
  @inline
  def productionMode: Boolean =
    linkingInfo.productionMode

  /** Returns true if we are linking for development, false otherwise.
   *
   *  `developmentMode` is always equal to `!productionMode`.
   *
   *  This ends up being constant-folded to a constant at link-time. So
   *  constant-folding, inlining, and other local optimizations can be
   *  leveraged with this "constant" to write code that should only be
   *  executed in production mode or development mode.
   *
   *  A typical usage of this method is:
   *  {{{
   *  if (developmentMode) {
   *    performExpensiveSanityChecks()
   *  }
   *  }}}
   *
   *  At link-time, `developmentMode` will either be a constant true, in which
   *  case the above snippet folds into
   *  {{{
   *  performExpensiveSanityChecks()
   *  }}}
   *  or a constant false, in which case it is dead-code-eliminated away,
   *  yielding maximum performance in production.
   *
   *  @see [[productionMode]]
   */
  @inline
  def developmentMode: Boolean =
    !productionMode

  /** Version (edition) of the ECMAScript Language Specification that is
   *  assumed to be supported by the runtime.
   *
   *  This is an integer that represents the *edition* of the ECMAScript
   *  Language Specification. For example, ECMAScript 2015 is represented with
   *  the value `6`.
   *
   *  As an exception, ECMAScript 5.1 is represented with the value `5`.
   *
   *  This value can be used to:
   *
   *  - avoid feature tests and dead-code-eliminate polyfills (see below), or
   *  - conditionally offer library features that depend on underlying
   *    ECMAScript support.
   *
   *  ---
   *
   *  This ends up being constant-folded to a constant at link-time. So
   *  constant-folding, inlining, and other local optimizations can be
   *  leveraged with this "constant" to write polyfills that can be
   *  dead-code-eliminated.
   *
   *  A typical usage of this method is:
   *  {{{
   *  if (esVersion >= ESVersion.ES2018 || featureTest())
   *    useES2018Feature()
   *  else
   *    usePolyfill()
   *  }}}
   *
   *  At link-time, `esVersion` will either be a constant less than
   *  `ESVersion.ES2018`, in which case the above snippet folds into
   *  {{{
   *  if (featureTest())
   *    useES2018Feature()
   *  else
   *    usePolyfill()
   *  }}}
   *  or a constant greater or equal to `ESVersion.ES2018`, in which case it
   *  folds into
   *  {{{
   *  useES2018Feature()
   *  }}}
   */
  @inline
  def esVersion: Int =
    linkingInfo.esVersion

  /** Returns true if we are assuming that the target platform supports
   *  ECMAScript 6, false otherwise.
   *
   *  This is `true` if and only if `esVersion >= ESVersion.ES2015`.
   *
   *  ---
   *
   *  This ends up being constant-folded to a constant at link-time. So
   *  constant-folding, inlining, and other local optimizations can be
   *  leveraged with this "constant" to write polyfills that can be
   *  dead-code-eliminated.
   *
   *  A typical usage of this method is:
   *  {{{
   *  if (assumingES6 || featureTest())
   *    useES6Feature()
   *  else
   *    usePolyfill()
   *  }}}
   *
   *  At link-time, `assumingES6` will either be a constant false, in which
   *  case the above snippet folds into
   *  {{{
   *  if (featureTest())
   *    useES6Feature()
   *  else
   *    usePolyfill()
   *  }}}
   *  or a constant true, in which case it folds into
   *  {{{
   *  useES6Feature()
   *  }}}
   */
  @deprecated("use esVersion >= ESVersion.ES2015 instead", "1.6.0")
  @inline
  def assumingES6: Boolean =
    esVersion >= ESVersion.ES2015

  /** Whether Scala.js language features use ECMAScript 2015 (edition 6)
   *  semantics or not.
   *
   *  When `true`, the following semantics apply:
   *
   *  - JavaScript classes are true `class`'es, therefore a) they can extend
   *    native JavaScript `class`'es and b) they inherit static members from
   *    their parent class.
   *  - Lambdas for `js.Function`s that are not also `js.ThisFunction`s are
   *    JavaScript arrow functions (`=>`). Lambdas for `js.ThisFunction`s are
   *    `function` functions.
   *  - Throwable classes are proper JavaScript error classes, recognized as
   *    such by debuggers.
   *  - In Script (`NoModule`) mode, top-level exports are defined as `let`s.
   *
   *  When `false`, the following semantics apply:
   *
   *  - All classes defined in Scala.js are `function`s instead of `class`'es.
   *    Non-native JS classes cannot extend native JS `class`'es and they do
   *    not inherit static members from their parent class.
   *  - All lambdas for `js.Function`s are `function`s.
   *  - Throwable classes have JavaScript's `Error.prototype` in their
   *    prototype chain, but they are not considered proper error classes.
   *  - In Script (`NoModule`) mode, top-level exports are defined as `var`s.
   *
   *  Prefer reading this value instead of `esVersion` to determine which
   *  semantics apply.
   *
   *  For example, it can be used in tests whose results depend on which
   *  semantics are used.
   *
   *  ---
   *
   *  This ends up being constant-folded to a constant at link-time. So
   *  constant-folding, inlining, and other local optimizations can be
   *  leveraged with this "constant" to write alternatives that can be
   *  dead-code-eliminated.
   *
   *  A typical usage of this method is:
   *  {{{
   *  if (useECMAScript2015Semantics)
   *    implementationWithES2015Semantics()
   *  else
   *    implementationWithoutES2015Semantics()
   *  }}}
   *
   *  At link-time, `useECMAScript2015Semantics` will either be a constant
   *  true, in which case the above snippet folds into
   *  {{{
   *  implementationWithES2015Semantics()
   *  }}}
   *  or a constant false, in which case it folds into
   *  {{{
   *  implementationWithoutES2015Semantics()
   *  }}}
   */
  @inline
  def useECMAScript2015Semantics: Boolean =
    linkingInfo.assumingES6 // name mismatch for historical reasons

  /** Whether we are linking to WebAssembly.
   *
   *  This property can be used to delegate to different code paths optimized
   *  for WebAssembly rather than for JavaScript.
   *
   *  ---
   *
   *  This ends up being constant-folded to a constant at link-time. So
   *  constant-folding, inlining, and other local optimizations can be
   *  leveraged with this "constant" to write alternatives that can be
   *  dead-code-eliminated.
   *
   *  A typical usage of this method is:
   *  {{{
   *  if (isWebAssembly)
   *    implementationOptimizedForWebAssembly()
   *  else
   *    implementationOptimizedForJavaScript()
   *  }}}
   *
   *  At link-time, `isWebAssembly` will either be a constant
   *  true, in which case the above snippet folds into
   *  {{{
   *  implementationOptimizedForWebAssembly()
   *  }}}
   *  or a constant false, in which case it folds into
   *  {{{
   *  implementationOptimizedForJavaScript()
   *  }}}
   */
  @inline
  def isWebAssembly: Boolean =
    linkingInfo.isWebAssembly

  /** Constants for the value of `esVersion`. */
  object ESVersion {
    /** ECMAScrîpt 5.1. */
    final val ES5_1 = 5

    /** ECMAScript 2015 (6th edition). */
    final val ES2015 = 6

    /** ECMAScript 2016 (7th edition).
     *
     *  Contains the following notable features:
     *
     *  - The `**` operator for numbers
     *  - `async`/`await`
     */
    final val ES2016 = 7

    /** ECMAScript 2017 (8th edition).
     *
     *  Contains the following notable features:
     *
     *  - Async functions
     *  - Shared Memory and Atomics (via `SharedArrayBuffer`)
     *  - `Object.values`, `Object.entries`, and `Object.getOwnPropertyDescriptors`
     */
    final val ES2017 = 8

    /** ECMAScript 2018 (9th edition).
     *
     *  Contains the following notable features:
     *
     *  - Asynchronous iteration via the `AsyncIterator` protocol and async generators
     *  - Regular expression features: the dotAll flag `'s'`, named capture groups,
     *    Unicode property escapes (`\p{}` and `\P{}`) and look-behind assertions
     *  - Rest parameter and spread operator support for object properties
     */
    final val ES2018 = 9

    /** ECMAScript 2019 (10th edition).
     *
     *  Contains the following notable features:
     *
     *  - Minor additions to the built-in library functions
     */
    final val ES2019 = 10

    /** ECMAScript 2020 (11th edition).
     *
     *  Contains the following notable features:
     *
     *  - Dynamic `import()` calls
     *  - `BigInt`
     *  - `globalThis`
     *  - `export * as ns from 'module'`
     *  - `import.meta`
     */
    final val ES2020 = 11

    /** ECMAScript 2021 (12th edition).
     *
     *  Contains the following notable features:
     *
     *  - `WeakRef` and `FinalizationRegistry`
     *  - `AggregateError`
     *  - Separators for numeric literals (e.g., `1_000`)
     */
    final val ES2021 = 12
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy