Javascript  |  354行  |  7.95 KB

// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Flags: --harmony-proxies


// Helper.

function TestWithProxies(test, x, y, z) {
  test(function(h) { return new Proxy({}, h) }, x, y, z)
  test(function(h) {
      return new Proxy(function() {}, h)
  }, x, y, z)
}



// Getting.

function TestWithGet(handler) {
  TestWithProxies(TestWithGet2, handler)
}

var c = "global"
var key = ""

function TestWithGet2(create, handler) {
  var b = "local"

  var p = create(handler);
  assertEquals("onproxy", p.a);
  assertEquals(undefined, p.b);
  assertEquals(undefined, p.c);

  with (p) {
    assertEquals("onproxy", a);
    assertEquals("local", b);
    assertEquals("global", c);
  }

  var o = Object.create(p, {d: {value: "own"}})
  with (o) {
    assertEquals("onproxy", a)
    assertEquals("local", b);
    assertEquals("global", c)
    assertEquals("own", d)
  }
}

TestWithGet({
  get(target, k) {
    key = k;
    return k === "a" ? "onproxy" : undefined
  },
  has(target, k) { return k === 'a' }
})

TestWithGet({
  get: function(r, k) { return this.get2(r, k) },
  get2: function(r, k) { key = k; return k === "a" ? "onproxy" : undefined },
  has(target, k) { return k === 'a' }
})




// Invoking.

function TestWithGetCall(handler) {
  TestWithProxies(TestWithGetCall2, handler)
}

var receiver = null
var c = function() { return "global" }

function TestWithGetCall2(create, handler) {
  var b = function() { return "local" }

  var p = create(handler)
  with (p) {
    receiver = null
    assertEquals("onproxy", a())
    assertSame(p, receiver)
    assertEquals("local", b())
    assertEquals("global", c())
  }

  var o = Object.create(p, {d: {value: function() { return "own" }}})
  with (o) {
    receiver = null
    assertEquals("onproxy", a())
    assertSame(o, receiver)
    assertEquals("local", b())
    assertEquals("global", c())
    assertEquals("own", d())
  }
}

function onproxy() { receiver = this; return "onproxy" }

TestWithGetCall({
  get: function(r, k) { key = k; return k === "a" ? onproxy : undefined },
  has: function(t, k) {
    key = k;
    return k === "a";
  }
})

TestWithGetCall({
  get: function(r, k) { return this.get2(r, k) },
  get2: function(r, k) { key = k; return k === "a" ? onproxy : undefined },
  has: function(t, k) {
    key = k;
    return k === "a";
  }
})

TestWithGetCall({
  get: function(r, k) { key = k; return k === "a" ? onproxy : undefined },
  has: function(t, k) {
    return this.has2(k)
  },
  has2: function(k) {
    key = k;
    return k === "a";
  }
})

TestWithGetCall({
  get: function(r, k) { key = k; return k === "a" ? onproxy : undefined },
  has: function(t, k) {
    key = k;
    return k === "a";
  }
})


function TestWithGetCallThrow(handler) {
  TestWithProxies(TestWithGetCallThrow2, handler)
}

function TestWithGetCallThrow2(create, handler) {
  var b = function() { return "local" }

  var p = create(handler)
  with (p) {
    assertThrowsEquals(function(){ a() }, "myexn")
    assertEquals("local", b())
    assertEquals("global", c())
  }

  var o = Object.create(p, {d: {value: function() { return "own" }}})
  with (o) {
    assertThrowsEquals(function(){ a() }, "myexn")
    assertEquals("local", b())
    assertEquals("global", c())
    assertEquals("own", d())
  }
}

function onproxythrow() { throw "myexn" }

TestWithGetCallThrow({
  has: function(r, k) { return k === "a"; },
  get: function(r, k) { key = k; return k === "a" ? onproxythrow : undefined },
})

TestWithGetCallThrow({
  has: function(r, k) { return k === "a"; },
  get: function(r, k) { return this.get2(r, k) },
  get2: function(r, k) { key = k; return k === "a" ? onproxythrow : undefined },
})



// Setting.

var key
var val

function TestWithSet(handler, hasSetter) {
  TestWithProxies(TestWithSet2, handler, hasSetter)
}

var c = "global"

function TestWithSet2(create, handler, hasSetter) {
  var b = "local"

  var p = create(handler)
  key = val = undefined
  with (p) {
    a = "set"
    assertEquals("a", key)
    assertEquals("set", val)
    assertEquals("local", b)
    assertEquals("global", c)
    b = "local"
    c = "global"
    assertEquals("a", key)
    assertEquals("set", val)
  }

  if (!hasSetter) return

  var o = Object.create(p, {d: {value: "own"}})
  key = val = undefined
  with (o) {
    a = "set"
    assertEquals("a", key)
    assertEquals("set", val)
    assertEquals("local", b)
    assertEquals("global", c)
    assertEquals("own", d)
    b = "local"
    c = "global"
    d = "own"
    assertEquals("a", key)
    assertEquals("set", val)
  }
}

TestWithSet({
  set: function(r, k, v) { key = k; val = v; return true },
  has: function(t, k) {
    return k === "a"
  }
})

TestWithSet({
  set: function(r, k, v) { return this.set2(r, k, v) },
  set2: function(r, k, v) { key = k; val = v; return true },
  has: function(t, k) {
    return k === "a"
  }
})

TestWithSet({
  has: function(t, k) {
    return k === "a"
  },
  defineProperty: function(t, k, desc) { key = k; val = desc.value }
})

TestWithSet({
  has: function(t, k) {
    return this.has2(k)
  },
  has2: function(k) {
    return k === "a"
  },
  defineProperty: function(t, k, desc) { this.defineProperty2(k, desc) },
  defineProperty2: function(k, desc) { key = k; val = desc.value }
})

TestWithSet({
  has: function(t, k) {
    return k === "a"
  },
  defineProperty: function(t, k, desc) { key = k; val = desc.value }
})

TestWithSet({
  has: function(t, k) {
    return this.has2(k) },
  has2: function(k) {
    return k === "a"
  },
  set: function(t, k, v) { key = k; val = v; return true }
}, true)

TestWithSet({
  has: function(t, k) {
    return k === "a"
  },
  defineProperty: function(t, k, desc) { key = k; val = desc.value }
})


function TestWithSetThrow(handler, hasSetter) {
  TestWithProxies(TestWithSetThrow2, handler, hasSetter)
}

function TestWithSetThrow2(create, handler, hasSetter) {
  var p = create(handler)
  assertThrowsEquals(function(){
    with (p) {
      a = 1
    }
  }, "myexn")

  if (!hasSetter) return

  var o = Object.create(p, {})
  assertThrowsEquals(function(){
    with (o) {
      a = 1
    }
  }, "myexn")
}

TestWithSetThrow({
  set: function() { throw "myexn" },
  has: function(t, k) {
    return k === "a"
  }
})

TestWithSetThrow({
  has: function() { throw "myexn" },
})

TestWithSetThrow({
  has: function() { throw "myexn" },
})

TestWithSetThrow({
  has: function(t, k) {
    return k === "a"
  },
  defineProperty: function() { throw "myexn" }
})

TestWithSetThrow({
  has: function(t, k) {
    return k === "a"
  },
  set: function() { throw "myexn" }
}, true)