Improve Proxy/construct coverage (#2159)

This commit is contained in:
Aleksey Shvayka 2019-05-29 22:49:41 +03:00 committed by Leo Balter
parent 465d0b587e
commit 1265a60017
24 changed files with 413 additions and 101 deletions

View File

@ -1,6 +1,7 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved. // Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
es6id: 9.5.14 es6id: 9.5.14
description: > description: >
trap is called with handler object as its context, and parameters are: trap is called with handler object as its context, and parameters are:

View File

@ -1,6 +1,7 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved. // Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
es6id: 9.5.14 es6id: 9.5.14
description: > description: >
Return the result from the trap method. Return the result from the trap method.
@ -11,16 +12,14 @@ info: |
features: [Proxy] features: [Proxy]
---*/ ---*/
function Target(a, b) { var P = new Proxy(function() {
this.sum = a + b; throw new Test262Error('target should not be called');
}; }, {
var handler = {
construct: function(t, c, args) { construct: function(t, c, args) {
return { return {
sum: 42 sum: 42
}; };
} }
}; });
var P = new Proxy(Target, handler);
assert.sameValue((new P(1, 2)).sum, 42); assert.sameValue((new P(1, 2)).sum, 42);

View File

@ -0,0 +1,20 @@
// Copyright (C) 2019 Aleksey Shvayka. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
description: >
[[Construct]] (argumentsList, newTarget)
1. Let handler be O.[[ProxyHandler]].
2. If handler is null, throw a TypeError exception.
features: [cross-realm, Proxy]
---*/
var OProxy = $262.createRealm().global.Proxy;
var p = OProxy.revocable(function() {}, {});
p.revoke();
assert.throws(TypeError, function() {
new p.proxy();
});

View File

@ -1,6 +1,7 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved. // Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
es6id: 9.5.14 es6id: 9.5.14
description: > description: >
[[Construct]] ( argumentsList, newTarget) [[Construct]] ( argumentsList, newTarget)

View File

@ -1,6 +1,7 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved. // Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
es6id: 9.5.14 es6id: 9.5.14
description: > description: >
Return abrupt from constructor call. Return abrupt from constructor call.

View File

@ -0,0 +1,27 @@
// Copyright (C) 2019 Aleksey Shvayka. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
description: >
Throws a TypeError if trap result is not an Object: Boolean
(honoring the Realm of the current execution context)
info: |
[[Construct]] (argumentsList, newTarget)
[...]
11. If Type(newObj) is not Object, throw a TypeError exception.
features: [cross-realm, Proxy]
---*/
var OProxy = $262.createRealm().global.Proxy;
var P = new OProxy(function() {
throw new Test262Error('target should not be called');
}, {
construct: function() {
return true;
},
});
assert.throws(TypeError, function() {
new P();
});

View File

@ -1,6 +1,7 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved. // Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
es6id: 9.5.14 es6id: 9.5.14
description: > description: >
Throws a TypeError if trap result is not an Object: Boolean Throws a TypeError if trap result is not an Object: Boolean
@ -11,10 +12,9 @@ info: |
features: [Proxy] features: [Proxy]
---*/ ---*/
function Target() { var P = new Proxy(function() {
this.attr = "done"; throw new Test262Error('target should not be called');
}; }, {
var P = new Proxy(Target, {
construct: function() { construct: function() {
return true; return true;
} }

View File

@ -0,0 +1,27 @@
// Copyright (C) 2019 Aleksey Shvayka. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
description: >
Throws a TypeError if trap result is not an Object: null
(honoring the Realm of the current execution context)
info: |
[[Construct]] (argumentsList, newTarget)
[...]
11. If Type(newObj) is not Object, throw a TypeError exception.
features: [cross-realm, Proxy]
---*/
var OProxy = $262.createRealm().global.Proxy;
var P = new OProxy(function() {
throw new Test262Error('target should not be called');
}, {
construct: function() {
return null;
},
});
assert.throws(TypeError, function() {
new P();
});

View File

@ -0,0 +1,25 @@
// Copyright (C) 2019 Aleksey Shvayka. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
description: >
Throws a TypeError if trap result is not an Object: null
info: |
[[Construct]] (argumentsList, newTarget)
[...]
11. If Type(newObj) is not Object, throw a TypeError exception.
features: [Proxy]
---*/
var P = new Proxy(function() {
throw new Test262Error('target should not be called');
}, {
construct: function() {
return null;
},
});
assert.throws(TypeError, function() {
new P();
});

View File

@ -0,0 +1,27 @@
// Copyright (C) 2019 Aleksey Shvayka. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
description: >
Throws a TypeError if trap result is not an Object: Number
(honoring the Realm of the current execution context)
info: |
[[Construct]] (argumentsList, newTarget)
[...]
11. If Type(newObj) is not Object, throw a TypeError exception.
features: [cross-realm, Proxy]
---*/
var OProxy = $262.createRealm().global.Proxy;
var P = new OProxy(function() {
throw new Test262Error('target should not be called');
}, {
construct: function() {
return 1;
},
});
assert.throws(TypeError, function() {
new P();
});

View File

@ -1,6 +1,7 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved. // Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
es6id: 9.5.14 es6id: 9.5.14
description: > description: >
Throws a TypeError if trap result is not an Object: Number Throws a TypeError if trap result is not an Object: Number
@ -11,10 +12,11 @@ info: |
features: [Proxy] features: [Proxy]
---*/ ---*/
function Target() { function Target() {}
this.attr = "done";
}; var P = new Proxy(function() {
var P = new Proxy(Target, { throw new Test262Error('target should not be called');
}, {
construct: function() { construct: function() {
return 0; return 0;
} }

View File

@ -0,0 +1,27 @@
// Copyright (C) 2019 Aleksey Shvayka. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
description: >
Throws a TypeError if trap result is not an Object: String
(honoring the Realm of the current execution context)
info: |
[[Construct]] (argumentsList, newTarget)
[...]
11. If Type(newObj) is not Object, throw a TypeError exception.
features: [cross-realm, Proxy]
---*/
var OProxy = $262.createRealm().global.Proxy;
var P = new OProxy(function() {
throw new Test262Error('target should not be called');
}, {
construct: function() {
return '';
},
});
assert.throws(TypeError, function() {
new P();
});

View File

@ -1,6 +1,7 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved. // Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
es6id: 9.5.14 es6id: 9.5.14
description: > description: >
Throws a TypeError if trap result is not an Object: String Throws a TypeError if trap result is not an Object: String
@ -11,10 +12,11 @@ info: |
features: [Proxy] features: [Proxy]
---*/ ---*/
function Target() { function Target() {}
this.attr = "done";
}; var P = new Proxy(function() {
var P = new Proxy(Target, { throw new Test262Error('target should not be called');
}, {
construct: function() { construct: function() {
return ""; return "";
} }

View File

@ -0,0 +1,27 @@
// Copyright (C) 2019 Aleksey Shvayka. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
description: >
Throws a TypeError if trap result is not an Object: Symbol
(honoring the Realm of the current execution context)
info: |
[[Construct]] (argumentsList, newTarget)
[...]
11. If Type(newObj) is not Object, throw a TypeError exception.
features: [cross-realm, Proxy]
---*/
var OProxy = $262.createRealm().global.Proxy;
var P = new OProxy(function() {
throw new Test262Error('target should not be called');
}, {
construct: function() {
return Symbol();
},
});
assert.throws(TypeError, function() {
new P();
});

View File

@ -1,6 +1,7 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved. // Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
es6id: 9.5.14 es6id: 9.5.14
description: > description: >
Throws a TypeError if trap result is not an Object: Symbol Throws a TypeError if trap result is not an Object: Symbol
@ -11,10 +12,11 @@ info: |
features: [Proxy, Symbol] features: [Proxy, Symbol]
---*/ ---*/
function Target() { function Target() {}
this.attr = "done";
}; var P = new Proxy(function() {
var P = new Proxy(Target, { throw new Test262Error('target should not be called');
}, {
construct: function() { construct: function() {
return Symbol(); return Symbol();
} }

View File

@ -0,0 +1,25 @@
// Copyright (C) 2019 Aleksey Shvayka. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
description: >
Throws a TypeError if trap result is not an Object: undefined
(honoring the Realm of the current execution context)
info: |
[[Construct]] (argumentsList, newTarget)
[...]
11. If Type(newObj) is not Object, throw a TypeError exception.
features: [cross-realm, Proxy]
---*/
var OProxy = $262.createRealm().global.Proxy;
var P = new OProxy(function() {
throw new Test262Error('target should not be called');
}, {
construct: function() {},
});
assert.throws(TypeError, function() {
new P();
});

View File

@ -1,6 +1,7 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved. // Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
es6id: 9.5.14 es6id: 9.5.14
description: > description: >
Throws a TypeError if trap result is not an Object: undefined Throws a TypeError if trap result is not an Object: undefined
@ -11,13 +12,10 @@ info: |
features: [Proxy] features: [Proxy]
---*/ ---*/
function Target() { var P = new Proxy(function() {
this.attr = "done"; throw new Test262Error('target should not be called');
}; }, {
var P = new Proxy(Target, { construct: function() {}
construct: function() {
return undefined;
}
}); });
assert.throws(TypeError, function() { assert.throws(TypeError, function() {

View File

@ -1,6 +1,7 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved. // Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
es6id: 9.5.14 es6id: 9.5.14
description: > description: >
Throws if trap is not callable. Throws if trap is not callable.

View File

@ -21,24 +21,31 @@ info: |
... ...
3. If func is either undefined or null, return undefined. 3. If func is either undefined or null, return undefined.
... ...
features: [new.target, Proxy, Reflect, Reflect.construct] features: [Proxy, Reflect, Reflect.construct]
---*/ ---*/
var calls = 0; var calls = 0;
var _NewTarget;
function NewTarget() {} var Target = new Proxy(function() {
throw new Test262Error('target should not be called');
function Target(a, b) { }, {
assert.sameValue(new.target, NewTarget); construct: function(_Target, args, NewTarget) {
calls += 1; calls += 1;
_NewTarget = NewTarget;
return { return {
sum: a + b sum: args[0] + args[1]
}; };
} }
})
var P = new Proxy(Target, { var P = new Proxy(Target, {
construct: null construct: null
}); });
var NewTarget = function() {};
var obj = Reflect.construct(P, [3, 4], NewTarget); var obj = Reflect.construct(P, [3, 4], NewTarget);
assert.sameValue(obj.sum, 7, "`construct` trap is `null`");
assert.sameValue(calls, 1, "target is called once"); assert.sameValue(calls, 1, "construct is null: [[Construct]] is invoked once");
assert.sameValue(_NewTarget, NewTarget, "construct is null: NewTarget is passed to [[Construct]]");
assert.sameValue(obj.sum, 7, "construct is null: result of [[Construct]] is returned");

View File

@ -8,24 +8,40 @@ description: >
info: | info: |
[[Construct]] (argumentsList, newTarget) [[Construct]] (argumentsList, newTarget)
7. If trap is undefined, then ...
b. Return Construct(target, argumentsList, newTarget). 5. Let trap be ? GetMethod(handler, "construct").
features: [new.target, Proxy, Reflect, Reflect.construct] 6. If trap is undefined, then
a. Assert: target has a [[Construct]] internal method.
b. Return ? Construct(target, argumentsList, newTarget).
...
GetMethod ( V, P )
...
3. If func is either undefined or null, return undefined.
...
features: [Proxy, Reflect, Reflect.construct]
---*/ ---*/
var calls = 0; var calls = 0;
var _NewTarget;
function NewTarget() {} var Target = new Proxy(function() {
throw new Test262Error('target should not be called');
function Target(a, b) { }, {
assert.sameValue(new.target, NewTarget); construct: function(_Target, args, NewTarget) {
calls += 1; calls += 1;
_NewTarget = NewTarget;
return { return {
sum: a + b sum: args[0] + args[1]
}; };
} }
})
var P = new Proxy(Target, {}); var P = new Proxy(Target, {});
var obj = Reflect.construct(P, [1, 2], NewTarget); var NewTarget = function() {};
assert.sameValue(obj.sum, 3, "`construct` trap is missing"); var obj = Reflect.construct(P, [3, 4], NewTarget);
assert.sameValue(calls, 1, "target is called once");
assert.sameValue(calls, 1, "construct is missing: [[Construct]] is invoked once");
assert.sameValue(_NewTarget, NewTarget, "construct is missing: NewTarget is passed to [[Construct]]");
assert.sameValue(obj.sum, 7, "construct is missing: result of [[Construct]] is returned");

View File

@ -0,0 +1,47 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
description: >
If trap is undefined, propagate [[Construct]] to target,
passing correct newTarget parameter
info: |
[[Construct]] ( argumentsList, newTarget )
[...]
7. If trap is undefined, then
b. Return ? Construct(target, argumentsList, newTarget).
Construct ( F [ , argumentsList [ , newTarget ] ] )
[...]
5. Return ? F.[[Construct]](argumentsList, newTarget).
[[Construct]] ( argumentsList, newTarget )
[...]
5. If kind is "base", then
a. Let thisArgument be ? OrdinaryCreateFromConstructor(newTarget, "%ObjectPrototype%").
OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )
[...]
2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto).
3. Return ObjectCreate(proto, internalSlotsList).
GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )
[...]
3. Let proto be ? Get(constructor, "prototype").
[...]
5. Return proto.
features: [cross-realm, Proxy, Reflect, Reflect.construct]
---*/
var other = $262.createRealm().global;
var C = new other.Function();
var P = new Proxy(function() {}, {});
var p = Reflect.construct(P, [], C);
assert.sameValue(Object.getPrototypeOf(p), C.prototype);

View File

@ -1,33 +0,0 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
es6id: 9.5.14
description: >
If trap is undefined, propagate the construct to the target object,
honoring the Realm of the newTarget value
info: |
[[Construct]] ( argumentsList, newTarget)
7. If trap is undefined, then
b. Return Construct(target, argumentsList, newTarget).
9.1.14 GetPrototypeFromConstructor
[...]
3. Let proto be ? Get(constructor, "prototype").
4. If Type(proto) is not Object, then
a. Let realm be ? GetFunctionRealm(constructor).
b. Let proto be realm's intrinsic object named intrinsicDefaultProto.
[...]
features: [cross-realm, Proxy, Reflect, Reflect.construct]
---*/
var other = $262.createRealm().global;
var C = new other.Function();
var P = new Proxy(function() {}, {});
var p = Reflect.construct(P, [], C);
assert.sameValue(Object.getPrototypeOf(Object.getPrototypeOf(p)), other.Object.prototype);

View File

@ -0,0 +1,56 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
description: >
If trap is undefined, propagate [[Construct]] to target,
passing correct newTarget parameter
info: |
[[Construct]] ( argumentsList, newTarget )
[...]
7. If trap is undefined, then
b. Return ? Construct(target, argumentsList, newTarget).
Construct ( F [ , argumentsList [ , newTarget ] ] )
[...]
5. Return ? F.[[Construct]](argumentsList, newTarget).
[[Construct]] ( argumentsList, newTarget )
[...]
5. If kind is "base", then
a. Let thisArgument be ? OrdinaryCreateFromConstructor(newTarget, "%ObjectPrototype%").
OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )
[...]
2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto).
3. Return ObjectCreate(proto, internalSlotsList).
GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )
[...]
3. Let proto be ? Get(constructor, "prototype").
4. If Type(proto) is not Object, then
a. Let realm be ? GetFunctionRealm(constructor).
b. Set proto to realm's intrinsic object named intrinsicDefaultProto.
5. Return proto.
GetFunctionRealm ( obj )
[...]
2. If obj has a [[Realm]] internal slot, then
a. Return obj.[[Realm]].
features: [cross-realm, Proxy, Reflect, Reflect.construct]
---*/
var other = $262.createRealm().global;
var C = new other.Function();
C.prototype = null;
var P = new Proxy(function() {}, {});
var p = Reflect.construct(P, [], C);
assert.sameValue(Object.getPrototypeOf(p), other.Object.prototype);

View File

@ -21,24 +21,31 @@ info: |
... ...
3. If func is either undefined or null, return undefined. 3. If func is either undefined or null, return undefined.
... ...
features: [new.target, Proxy, Reflect, Reflect.construct] features: [Proxy, Reflect, Reflect.construct]
---*/ ---*/
var calls = 0; var calls = 0;
var _NewTarget;
function NewTarget() {} var Target = new Proxy(function() {
throw new Test262Error('target should not be called');
function Target(a, b) { }, {
assert.sameValue(new.target, NewTarget); construct: function(_Target, args, NewTarget) {
calls += 1; calls += 1;
_NewTarget = NewTarget;
return { return {
sum: a + b sum: args[0] + args[1]
}; };
} },
});
var P = new Proxy(Target, { var P = new Proxy(Target, {
construct: undefined construct: undefined
}); });
var NewTarget = function() {};
var obj = Reflect.construct(P, [3, 4], NewTarget); var obj = Reflect.construct(P, [3, 4], NewTarget);
assert.sameValue(obj.sum, 7, "`construct` trap is `undefined`");
assert.sameValue(calls, 1, "target is called once"); assert.sameValue(calls, 1, "construct is undefined: [[Construct]] is invoked once");
assert.sameValue(_NewTarget, NewTarget, "construct is undefined: NewTarget is passed to [[Construct]]");
assert.sameValue(obj.sum, 7, "construct is undefined: result of [[Construct]] is returned");