Git Product home page Git Product logo

proposal-object-freeze-seal-syntax's Introduction

Object.freeze and Object.seal syntax

Rationale

Object.freeze and Object.seal are both useful functions, but they aren't particularly ergonomic to use, especially when dealing with deeply nested objects or trying to do complex things like create a superset of a frozen object. Also even frozen objects can be modified via their prototype chain:

> const x = Object.freeze({});
undefined
> x.foo
undefined
> Object.prototype.foo = 3;
3
> x.foo
3

To prevent this you can use Object.freeze({ __proto__: null }) or Object.freeze(Object.assign(Object.create(null), {})) to ensure that frozen objects cannot be modified via their prototype chain.

> const x = Object.freeze({ __proto__: null });
undefined
> x.foo
undefined
> Object.prototype.foo = 3;
3
> x.foo
undefined

In addition, it would be useful to have these syntaxes in other places. It'd be useful to seal a destructuring expression, or freeze function arguments to create immutable bindings.

Sketches

Basic freezing of an object

const foo = {#
  a: {#
    b: {#
      c: {#
        d: {#
          e: [# "some string!" #]
        #}
      #}
    #}
  #}
#}
Click here to see the desugared version
const foo = Object.freeze({
  __proto__: null,
  a: Object.freeze({
    __proto__: null,
    b: Object.freeze({
      __proto__: null,
      c: Object.freeze({
        __proto__: null,
        d: Object.freeze({
          __proto__: null,
          e: Object.freeze([ "some string!" ])
        })
      })
    })
  })
})

Basic sealing of an object

const foo = {|
  a: {|
    b: {|
      c: {|
        d: {|
          e: [| "some string!" |]
        |}
      |}
    |}
  |}
|}
Click here to see the desugared version
const foo = Object.seal({
  __proto__: null,
  a: Object.seal({
    __proto__: null,
    b: Object.seal({
      __proto__: null,
      c: Object.seal({
        __proto__: null,
        d: Object.seal({
          __proto__: null,
          e: Object.seal(["some string!"])
        })
      })
    })
  })
})

Sealing a functions destructured options bag

function ajax({| url, headers, onSuccess |}) {
  fetch(url, { headers }).then(onSuccess)
}
ajax({ url: 'http://example.com', onsuccess: console.log })
// throws TypeError('cannot define property `onsuccess`. Object is not extensible')
Click here to see the desugared version
function ajax(_ref1) {
  const _ref2 = Object.seal({ url: undefined, headers: undefined, onSuccess: undefined })
  Object.assign(_ref2, _ref1)
  let url = _ref2.url
  let headers = _ref2.headers
  let onSuccess = _ref2.onSuccess

  fetch(url, { headers }).then(onSuccess)
}
ajax({ url: 'http://example.com', onsuccess: console.log })
// throws TypeError('cannot define property `onsuccess`. Object is not extensible')

Freezing a functions destructured options bag

function ajax({# url, headers, onSuccess #}) {
  url = new URL(url) // throws TypeError('cannot assign to const `url`')
  fetch(url, { headers }).then(onSuccess)
}
ajax({ url: 'http://example.com', onSuccess: console.log })
Click here to see the desugared version
function ajax(_ref1) {
  const _ref2 = Object.seal({ url: undefined, headers: undefined, onSuccess: undefined }) // seal now, const later
  Object.assign(_ref2, _ref1)
  const url = _ref2.url
  const headers = _ref2.headers
  const onSuccess = _ref2.onSuccess

  url = new URL(url) // throws TypeError('cannot assign to const `url`')
  fetch(url, { headers }).then(onSuccess)
}
ajax({ url: 'http://example.com', onSuccess: console.log })

Potential extensions - sketches

Sealed function param bindings

function add(| a, b |) {
  return a + b
}
add(2, 2, 2) === 6
// throws TypeError('invalid third parameter, expected 2`)
Click here to see the desugared version
function add(_1, _2) {
  if (arguments.length > 2) {
    throws TypeError('invalid third parameter, expected 2')
  }
  let a = arguments[0]
  let b = arguments[1]

  return a + b
}
add(2, 2, 2) === 6
// throws TypeError('invalid third parameter, expected 2`)

Frozen function param bindings

function add1(# a #) {
  a += 1 // throws TypeError `invalid assignment...`
  return a
}
add1(1) === 2
Click here to see the desugared version
function add1(_1) {
  if (arguments.length > 1) {
    throws TypeError('invalid second parameter, expected 1')
  }
  const a = arguments[0]

  a += 1 // throws TypeError `invalid assignment...`
  return a
}
add1(1) === 2

Extending syntax to general destructing for better type safety

const foo = { a: 1, b: 2 }
const {| a, b, c |} = foo
// Throws TypeError 'invalid assignment to unknown property c'
Click here to see the desugared version
const foo = { a: 1, b: 2 }
if (!('a' in foo)) throw new TypeError('invalid assignment to unknown property a')
const a = foo.a
if (!('b' in foo)) throw new TypeError('invalid assignment to unknown property b')
const b = foo.b
if (!('c' in foo)) throw new TypeError('invalid assignment to unknown property c')
const c = foo.c
// Throws TypeError 'invalid assignment to unknown property c'

proposal-object-freeze-seal-syntax's People

Contributors

deltaevo avatar graingert avatar keithamus avatar morkro avatar msegado avatar uzitech avatar xtuc avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.