<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#ffffff" text="#000000">
    I'd like to follow up on this message from last month.  Has any
    decision been made about how a defineProperty() trap should reject
    the property definition attempt?  §4.6.4 of the latest WebIDL draft
    specifies a [[DefineOwnProperty]] algorithm with a Reject step that
    is dependent on the Throw argument.  And right now it can't really
    be implemented with a Proxy in a way that will work correctly when
    the proxy is used in non-strict code. <br>
    <br>
    Tom suggested that defineProperty could return false or throw a
    TypeError to reject.  I assume that the proxy implementation would
    then do the right thing (return false or throw TypeError) based on
    the value of the Throw argument.<br>
    <br>
        David<br>
    <br>
    On 5/26/11 6:36 AM, Tom Van Cutsem wrote:
    <blockquote
      cite="mid:BANLkTi=0MQBJ2Yqmg-QP-aGgdQriXRu4qA@mail.gmail.com"
      type="cite">
      <div>Hi David,</div>
      <div><br>
      </div>
      <div>The short answer: if you also define a 'set' trap, throwing a
        TypeError from defineProperty() to signal rejection is
        appropriate.</div>
      <div><br>
      </div>
      <div>The longer answer:</div>
      <div><br>
      </div>
      <div>defineProperty() is based on [[DefineOwnProperty]] (ES5
        section 8.12.9) whose rejection behavior depends on an explicit
        'Throw' parameter, just like [[Put]] and [[Delete]]. Why then,
        do set() and delete() return a boolean success flag to determine
        their rejection behavior, while defineProperty() does not?</div>
      <div><br>
      </div>
      <div>I believe that, until now, we were convinced that in the case
        of proxies, defineProperty() actually does _not_ depend on
        strict mode, because the built-in Object.defineProperty and
        Object.defineProperties methods (ES5 section 15.2.3.6-7) call
        the built-in [[DefineOwnProperty]] method with its 3rd argument
        'Throw' set unconditionally to 'true', meaning it should never
        reject silently, independent of the strictness of the code.<br>
      </div>
      <div><br>
      </div>
      <div>However, checking other parts of the spec where
        [[DefineOwnProperty]] is invoked, I now notice it's also invoked
        by [[Put]], which passes its own 'Throw' argument to
        [[DefineOwnProperty]], and this time, the 'Throw' argument is
        dependent on strict mode. This complicates matters because of
        derived traps.</div>
      <div><br>
      </div>
      <div>If a proxy handler does _not_ define a 'set' trap (which is
        derived), the proxy implementation will fall back on the
        fundamental defineProperty() trap, whose rejection behavior in
        that context now _should_ depend on strict mode. However, the
        current defineProperty() API doesn't allow the programmer to
        express this.</div>
      <div><br>
      </div>
      <div>I see two options here:</div>
      <div>1) modify the defineProperty() trap such that it also returns
        a boolean flag to indicate rejection, like set() and delete().
        This is still possible as defineProperty() currently has no
        useful return value.</div>
      <div><br>
      </div>
      <div>2) specify unambiguously that defineProperty() on proxies
        should always reject explicitly by throwing a TypeError, even if
        the defineProperty() trap was called as part of the default
        'set' trap.</div>
      <div>This can be justified if we specify that the default 'set'
        trap invokes the 'defineProperty' trap as if by calling
        "Object.defineProperty", which is specified to never reject
        silently.</div>
      <div><br>
      </div>
      <div>Option #1 would most closely follow the current ES5 spec, but
        would disallow the default 'set' trap behavior from being
        written in Javascript itself, since it's impossible to specify
        the value of the 'Throw' parameter in Javascript.</div>
      <div><br>
      </div>
      <div>Option #2 is in line with how the current default 'set'
        behavior is specified at <<a moz-do-not-send="true"
href="http://wiki.ecmascript.org/doku.php?id=harmony:proxies#trap_defaults">http://wiki.ecmascript.org/doku.php?id=harmony:proxies#trap_defaults</a>>.</div>
      <div><br>
      </div>
      <div>Cheers,</div>
      <div>Tom</div>
      <div><br>
      </div>
      <div>
        <div class="gmail_quote">2011/5/25 David Flanagan <span
            dir="ltr"><<a moz-do-not-send="true"
              href="mailto:dflanagan@mozilla.com">dflanagan@mozilla.com</a>></span><br>
          <blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt
            0.8ex; border-left: 1px solid rgb(204, 204, 204);
            padding-left: 1ex;">
            I'm using a proxy to implement the DOM NodeList interface.
             A NodeList object is array-like and has read-only,
            non-configurable array index properties.<br>
            <br>
            In my handler's set() and delete() methods, I just return
            false if an attempt is made to set or delete an indexed
            property.<br>
            <br>
            The defineProperty() method is not parallel to set() and
            delete(), however.  I can't just return false, since the
            return value is ignored.  And I can't tell from the proposal
            whether I am allowed to throw a TypeError from this method.
            In getOwnPropertyDescriptor() I know that I have to lie and
            return a descriptor with configurable:true for the indexed
            properties. So in defineProperty() should I just silently
            ignore any attempts to set an indexed property, or should I
            actively reject those attempts with a TypeError?<br>
            <br>
            _______________________________________________<br>
            es-discuss mailing list<br>
            <a moz-do-not-send="true"
              href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
            <a moz-do-not-send="true"
              href="https://mail.mozilla.org/listinfo/es-discuss"
              target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
          </blockquote>
        </div>
        <br>
      </div>
    </blockquote>
    <br>
  </body>
</html>