Commit 07469fa5 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Make function proxies work as constructors.

R=kmillikin@chromium.org
BUG=v8:1543
TEST=

Review URL: http://codereview.chromium.org/7628021

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9310 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ab30559f
...@@ -619,12 +619,12 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { ...@@ -619,12 +619,12 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// -- sp[...]: constructor arguments // -- sp[...]: constructor arguments
// ----------------------------------- // -----------------------------------
Label non_function_call; Label slow, non_function_call;
// Check that the function is not a smi. // Check that the function is not a smi.
__ JumpIfSmi(r1, &non_function_call); __ JumpIfSmi(r1, &non_function_call);
// Check that the function is a JSFunction. // Check that the function is a JSFunction.
__ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
__ b(ne, &non_function_call); __ b(ne, &slow);
// Jump to the function-specific construct stub. // Jump to the function-specific construct stub.
__ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
...@@ -633,10 +633,19 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { ...@@ -633,10 +633,19 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// r0: number of arguments // r0: number of arguments
// r1: called object // r1: called object
// r2: object type
Label do_call;
__ bind(&slow);
__ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE));
__ b(ne, &non_function_call);
__ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
__ jmp(&do_call);
__ bind(&non_function_call); __ bind(&non_function_call);
__ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
__ bind(&do_call);
// Set expected number of arguments to zero (not changing r0). // Set expected number of arguments to zero (not changing r0).
__ mov(r2, Operand(0, RelocInfo::NONE)); __ mov(r2, Operand(0, RelocInfo::NONE));
__ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
__ SetCallKind(r5, CALL_AS_METHOD); __ SetCallKind(r5, CALL_AS_METHOD);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
......
...@@ -3634,6 +3634,7 @@ MaybeObject* Heap::ReinitializeJSReceiver( ...@@ -3634,6 +3634,7 @@ MaybeObject* Heap::ReinitializeJSReceiver(
// Functions require some minimal initialization. // Functions require some minimal initialization.
if (type == JS_FUNCTION_TYPE) { if (type == JS_FUNCTION_TYPE) {
map->set_function_with_prototype(true);
String* name; String* name;
MaybeObject* maybe_name = LookupAsciiSymbol("<freezing call trap>"); MaybeObject* maybe_name = LookupAsciiSymbol("<freezing call trap>");
if (!maybe_name->To<String>(&name)) return maybe_name; if (!maybe_name->To<String>(&name)) return maybe_name;
......
...@@ -80,12 +80,12 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { ...@@ -80,12 +80,12 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// -- edi: constructor function // -- edi: constructor function
// ----------------------------------- // -----------------------------------
Label non_function_call; Label slow, non_function_call;
// Check that function is not a smi. // Check that function is not a smi.
__ JumpIfSmi(edi, &non_function_call); __ JumpIfSmi(edi, &non_function_call);
// Check that function is a JSFunction. // Check that function is a JSFunction.
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
__ j(not_equal, &non_function_call); __ j(not_equal, &slow);
// Jump to the function-specific construct stub. // Jump to the function-specific construct stub.
__ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
...@@ -95,10 +95,19 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { ...@@ -95,10 +95,19 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// edi: called object // edi: called object
// eax: number of arguments // eax: number of arguments
// ecx: object map
Label do_call;
__ bind(&slow);
__ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
__ j(not_equal, &non_function_call);
__ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
__ jmp(&do_call);
__ bind(&non_function_call); __ bind(&non_function_call);
__ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
__ bind(&do_call);
// Set expected number of arguments to zero (not changing eax). // Set expected number of arguments to zero (not changing eax).
__ Set(ebx, Immediate(0)); __ Set(ebx, Immediate(0));
__ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
Handle<Code> arguments_adaptor = Handle<Code> arguments_adaptor =
masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
__ SetCallKind(ecx, CALL_AS_METHOD); __ SetCallKind(ecx, CALL_AS_METHOD);
...@@ -751,7 +760,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { ...@@ -751,7 +760,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
static const int kArgumentsOffset = 2 * kPointerSize; static const int kArgumentsOffset = 2 * kPointerSize;
static const int kReceiverOffset = 3 * kPointerSize; static const int kReceiverOffset = 3 * kPointerSize;
static const int kFunctionOffset = 4 * kPointerSize; static const int kFunctionOffset = 4 * kPointerSize;
{ {
FrameScope frame_scope(masm, StackFrame::INTERNAL); FrameScope frame_scope(masm, StackFrame::INTERNAL);
__ push(Operand(ebp, kFunctionOffset)); // push this __ push(Operand(ebp, kFunctionOffset)); // push this
...@@ -900,7 +909,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { ...@@ -900,7 +909,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
// Leave internal frame. // Leave internal frame.
} }
__ ret(3 * kPointerSize); // remove this, receiver, and arguments __ ret(3 * kPointerSize); // remove this, receiver, and arguments
} }
......
...@@ -41,14 +41,20 @@ $Proxy.createFunction = function(handler, callTrap, constructTrap) { ...@@ -41,14 +41,20 @@ $Proxy.createFunction = function(handler, callTrap, constructTrap) {
throw MakeTypeError("handler_non_object", ["create"]) throw MakeTypeError("handler_non_object", ["create"])
if (!IS_SPEC_FUNCTION(callTrap)) if (!IS_SPEC_FUNCTION(callTrap))
throw MakeTypeError("trap_function_expected", ["createFunction", "call"]) throw MakeTypeError("trap_function_expected", ["createFunction", "call"])
var construct
if (IS_UNDEFINED(constructTrap)) { if (IS_UNDEFINED(constructTrap)) {
constructTrap = callTrap construct = DerivedConstructTrap(callTrap)
} else if (!IS_SPEC_FUNCTION(constructTrap)) { } else if (IS_SPEC_FUNCTION(constructTrap)) {
construct = function() {
// Make sure the trap receives 'undefined' as this.
return $Function.prototype.apply.call(constructTrap, void 0, arguments)
}
} else {
throw MakeTypeError("trap_function_expected", throw MakeTypeError("trap_function_expected",
["createFunction", "construct"]) ["createFunction", "construct"])
} }
return %CreateJSFunctionProxy( return %CreateJSFunctionProxy(
handler, callTrap, constructTrap, $Function.prototype) handler, callTrap, construct, $Function.prototype)
} }
...@@ -57,6 +63,17 @@ $Proxy.createFunction = function(handler, callTrap, constructTrap) { ...@@ -57,6 +63,17 @@ $Proxy.createFunction = function(handler, callTrap, constructTrap) {
// Builtins // Builtins
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
function DerivedConstructTrap(callTrap) {
return function() {
var proto = this.prototype
if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
var obj = new $Object()
obj.__proto__ = proto
var result = $Function.prototype.apply.call(callTrap, obj, arguments)
return IS_SPEC_OBJECT(result) ? result : obj
}
}
function DelegateCallAndConstruct(callTrap, constructTrap) { function DelegateCallAndConstruct(callTrap, constructTrap) {
return function() { return function() {
return %Apply(%_IsConstructCall() ? constructTrap : callTrap, return %Apply(%_IsConstructCall() ? constructTrap : callTrap,
......
...@@ -429,20 +429,10 @@ function CALL_FUNCTION_PROXY() { ...@@ -429,20 +429,10 @@ function CALL_FUNCTION_PROXY() {
} }
function CALL_FUNCTION_PROXY_AS_CONSTRUCTOR(proxy) { function CALL_FUNCTION_PROXY_AS_CONSTRUCTOR() {
var arity = %_ArgumentsLength() - 1; var proxy = this;
var trap = %GetConstructTrap(proxy); var trap = %GetConstructTrap(proxy);
var receiver = void 0; return %Apply(trap, this, arguments, 0, %_ArgumentsLength());
if (!IS_UNDEFINED(trap)) {
trap = %GetCallTrap(proxy);
var proto = proxy.prototype;
if (!IS_SPEC_OBJECT(proto) && proto !== null) {
throw MakeTypeError("proto_object_or_null", [proto]);
}
receiver = new global.Object();
receiver.__proto__ = proto;
}
return %Apply(trap, this, arguments, 1, arity);
} }
......
...@@ -1049,6 +1049,15 @@ function ProxyFix(obj) { ...@@ -1049,6 +1049,15 @@ function ProxyFix(obj) {
var code = DelegateCallAndConstruct(callTrap, constructTrap); var code = DelegateCallAndConstruct(callTrap, constructTrap);
%Fix(obj); // becomes a regular function %Fix(obj); // becomes a regular function
%SetCode(obj, code); %SetCode(obj, code);
// TODO(rossberg): What about length and other properties? Not specified.
// We just put in some half-reasonable defaults for now.
var prototype = new $Object();
$Object.defineProperty(prototype, "constructor",
{value: obj, writable: true, enumerable: false, configrable: true});
$Object.defineProperty(obj, "prototype",
{value: prototype, writable: true, enumerable: false, configrable: false})
$Object.defineProperty(obj, "length",
{value: 0, writable: true, enumerable: false, configrable: false});
} else { } else {
%Fix(obj); %Fix(obj);
} }
......
...@@ -79,12 +79,12 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { ...@@ -79,12 +79,12 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// -- rdi: constructor function // -- rdi: constructor function
// ----------------------------------- // -----------------------------------
Label non_function_call; Label slow, non_function_call;
// Check that function is not a smi. // Check that function is not a smi.
__ JumpIfSmi(rdi, &non_function_call); __ JumpIfSmi(rdi, &non_function_call);
// Check that function is a JSFunction. // Check that function is a JSFunction.
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
__ j(not_equal, &non_function_call); __ j(not_equal, &slow);
// Jump to the function-specific construct stub. // Jump to the function-specific construct stub.
__ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
...@@ -94,10 +94,19 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { ...@@ -94,10 +94,19 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// rdi: called object // rdi: called object
// rax: number of arguments // rax: number of arguments
// rcx: object map
Label do_call;
__ bind(&slow);
__ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
__ j(not_equal, &non_function_call);
__ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
__ jmp(&do_call);
__ bind(&non_function_call); __ bind(&non_function_call);
__ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
__ bind(&do_call);
// Set expected number of arguments to zero (not changing rax). // Set expected number of arguments to zero (not changing rax).
__ Set(rbx, 0); __ Set(rbx, 0);
__ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
__ SetCallKind(rcx, CALL_AS_METHOD); __ SetCallKind(rcx, CALL_AS_METHOD);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
......
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
// TODO(rossberg): for-in for proxies not implemented. // TODO(rossberg): for-in for proxies not implemented.
// TODO(rossberg): inheritance from proxies not implemented. // TODO(rossberg): inheritance from proxies not implemented.
// TODO(rossberg): function proxies as constructors not implemented.
// Helper. // Helper.
...@@ -1586,23 +1584,30 @@ TestIsEnumerableThrow(Proxy.create({ ...@@ -1586,23 +1584,30 @@ TestIsEnumerableThrow(Proxy.create({
// Calling (call, Function.prototype.call, Function.prototype.apply, // Calling (call, Function.prototype.call, Function.prototype.apply,
// Function.prototype.bind). // Function.prototype.bind).
var global = this var global_object = this
var receiver var receiver
function CreateFrozen(handler, callTrap, constructTrap) {
if (handler.fix === undefined) handler.fix = function() { return {} }
var f = Proxy.createFunction(handler, callTrap, constructTrap)
Object.freeze(f)
return f
}
function TestCall(isStrict, callTrap) { function TestCall(isStrict, callTrap) {
assertEquals(42, callTrap(5, 37)) assertEquals(42, callTrap(5, 37))
// TODO(rossberg): unrelated bug: this does not succeed for optimized code. // TODO(rossberg): unrelated bug: this does not succeed for optimized code.
// assertEquals(isStrict ? undefined : global, receiver) // assertEquals(isStrict ? undefined : global_object, receiver)
var f = Proxy.createFunction({fix: function() { return {} }}, callTrap) var f = Proxy.createFunction({}, callTrap)
receiver = 333 receiver = 333
assertEquals(42, f(11, 31)) assertEquals(42, f(11, 31))
assertEquals(isStrict ? undefined : global, receiver) assertEquals(isStrict ? undefined : global_object, receiver)
var o = {} var o = {}
assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) assertEquals(42, Function.prototype.call.call(f, o, 20, 22))
assertEquals(o, receiver) assertEquals(o, receiver)
assertEquals(43, Function.prototype.call.call(f, null, 20, 23)) assertEquals(43, Function.prototype.call.call(f, null, 20, 23))
assertEquals(isStrict ? null : global, receiver) assertEquals(isStrict ? null : global_object, receiver)
assertEquals(44, Function.prototype.call.call(f, 2, 21, 23)) assertEquals(44, Function.prototype.call.call(f, 2, 21, 23))
assertEquals(2, receiver.valueOf()) assertEquals(2, receiver.valueOf())
receiver = 333 receiver = 333
...@@ -1616,7 +1621,7 @@ function TestCall(isStrict, callTrap) { ...@@ -1616,7 +1621,7 @@ function TestCall(isStrict, callTrap) {
assertEquals(32, Function.prototype.apply.call(ff, {}, [20])) assertEquals(32, Function.prototype.apply.call(ff, {}, [20]))
assertEquals(o, receiver) assertEquals(o, receiver)
Object.freeze(f) var f = CreateFrozen({}, callTrap)
receiver = 333 receiver = 333
assertEquals(42, f(11, 31)) assertEquals(42, f(11, 31))
// TODO(rossberg): unrelated bug: this does not succeed for optimized code. // TODO(rossberg): unrelated bug: this does not succeed for optimized code.
...@@ -1653,21 +1658,18 @@ TestCall(true, Proxy.createFunction({}, function(x, y) { ...@@ -1653,21 +1658,18 @@ TestCall(true, Proxy.createFunction({}, function(x, y) {
receiver = this; return x + y receiver = this; return x + y
})) }))
var p = Proxy.createFunction({fix: function() {return {}}}, function(x, y) { TestCall(false, CreateFrozen({}, function(x, y) {
receiver = this; return x + y receiver = this; return x + y
}) }))
TestCall(false, p)
Object.freeze(p)
TestCall(false, p)
function TestCallThrow(callTrap) { function TestCallThrow(callTrap) {
var f = Proxy.createFunction({fix: function() {return {}}}, callTrap) var f = Proxy.createFunction({}, callTrap)
assertThrows(function(){ f(11) }, "myexn") assertThrows(function(){ f(11) }, "myexn")
assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn")
assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn")
Object.freeze(f) var f = CreateFrozen({}, callTrap)
assertThrows(function(){ f(11) }, "myexn") assertThrows(function(){ f(11) }, "myexn")
assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn")
assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn")
...@@ -1675,8 +1677,139 @@ function TestCallThrow(callTrap) { ...@@ -1675,8 +1677,139 @@ function TestCallThrow(callTrap) {
TestCallThrow(function() { throw "myexn" }) TestCallThrow(function() { throw "myexn" })
TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" })) TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" }))
TestCallThrow(CreateFrozen({}, function() { throw "myexn" }))
// Construction (new).
var prototype = {}
var receiver
var handlerWithPrototype = {
fix: function() { return {prototype: prototype} },
get: function(r, n) { assertEquals("prototype", n); return prototype }
}
var handlerSansPrototype = {
fix: function() { return {} },
get: function(r, n) { assertEquals("prototype", n); return undefined }
}
function ReturnUndef(x, y) { "use strict"; receiver = this; this.sum = x + y }
function ReturnThis(x, y) { "use strict"; receiver = this; this.sum = x + y; return this }
function ReturnNew(x, y) { "use strict"; receiver = this; return {sum: x + y} }
function ReturnNewWithProto(x, y) {
"use strict";
receiver = this;
var result = Object.create(prototype)
result.sum = x + y
return result
}
function TestConstruct(proto, constructTrap) {
TestConstruct2(proto, constructTrap, handlerWithPrototype)
TestConstruct2(proto, constructTrap, handlerSansPrototype)
}
function TestConstruct2(proto, constructTrap, handler) {
var f = Proxy.createFunction(handler, function() {}, constructTrap)
var o = new f(11, 31)
// TODO(rossberg): doesn't hold, due to unrelated bug.
// assertEquals(undefined, receiver)
assertEquals(42, o.sum)
assertSame(proto, Object.getPrototypeOf(o))
var f = CreateFrozen(handler, function() {}, constructTrap)
var o = new f(11, 32)
// TODO(rossberg): doesn't hold, due to unrelated bug.
// assertEquals(undefined, receiver)
assertEquals(43, o.sum)
assertSame(proto, Object.getPrototypeOf(o))
}
TestConstruct(Object.prototype, ReturnNew)
TestConstruct(prototype, ReturnNewWithProto)
TestConstruct(Object.prototype, Proxy.createFunction({}, ReturnNew))
TestConstruct(prototype, Proxy.createFunction({}, ReturnNewWithProto))
TestConstruct(Object.prototype, CreateFrozen({}, ReturnNew))
TestConstruct(prototype, CreateFrozen({}, ReturnNewWithProto))
function TestConstructFromCall(proto, returnsThis, callTrap) {
TestConstructFromCall2(proto, returnsThis, callTrap, handlerWithPrototype)
TestConstructFromCall2(proto, returnsThis, callTrap, handlerSansPrototype)
}
function TestConstructFromCall2(proto, returnsThis, callTrap, handler) {
var f = Proxy.createFunction(handler, callTrap)
var o = new f(11, 31)
if (returnsThis) assertEquals(o, receiver)
assertEquals(42, o.sum)
assertSame(proto, Object.getPrototypeOf(o))
var f = CreateFrozen(handler, callTrap)
var o = new f(11, 32)
if (returnsThis) assertEquals(o, receiver)
assertEquals(43, o.sum)
assertSame(proto, Object.getPrototypeOf(o))
}
TestConstructFromCall(Object.prototype, true, ReturnUndef)
TestConstructFromCall(Object.prototype, true, ReturnThis)
TestConstructFromCall(Object.prototype, false, ReturnNew)
TestConstructFromCall(prototype, false, ReturnNewWithProto)
TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnUndef))
TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnThis))
TestConstructFromCall(Object.prototype, false, Proxy.createFunction({}, ReturnNew))
TestConstructFromCall(prototype, false, Proxy.createFunction({}, ReturnNewWithProto))
TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnUndef))
TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnThis))
TestConstructFromCall(Object.prototype, false, CreateFrozen({}, ReturnNew))
TestConstructFromCall(prototype, false, CreateFrozen({}, ReturnNewWithProto))
ReturnUndef.prototype = prototype
ReturnThis.prototype = prototype
ReturnNew.prototype = prototype
ReturnNewWithProto.prototype = prototype
TestConstructFromCall(prototype, true, ReturnUndef)
TestConstructFromCall(prototype, true, ReturnThis)
TestConstructFromCall(Object.prototype, false, ReturnNew)
TestConstructFromCall(prototype, false, ReturnNewWithProto)
TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnUndef))
TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnThis))
TestConstructFromCall(Object.prototype, false, Proxy.createFunction({}, ReturnNew))
TestConstructFromCall(prototype, false, Proxy.createFunction({}, ReturnNewWithProto))
TestConstructFromCall(prototype, true, Proxy.createFunction(handlerWithPrototype, ReturnUndef))
TestConstructFromCall(prototype, true, Proxy.createFunction(handlerWithPrototype, ReturnThis))
TestConstructFromCall(Object.prototype, false, Proxy.createFunction(handlerWithPrototype, ReturnNew))
TestConstructFromCall(prototype, false, Proxy.createFunction(handlerWithPrototype, ReturnNewWithProto))
TestConstructFromCall(prototype, true, CreateFrozen(handlerWithPrototype, ReturnUndef))
TestConstructFromCall(prototype, true, CreateFrozen(handlerWithPrototype, ReturnThis))
TestConstructFromCall(Object.prototype, false, CreateFrozen(handlerWithPrototype, ReturnNew))
TestConstructFromCall(prototype, false, CreateFrozen(handlerWithPrototype, ReturnNewWithProto))
function TestConstructThrow(trap) {
TestConstructThrow2(Proxy.createFunction({fix: function() {return {}}}, trap))
TestConstructThrow2(Proxy.createFunction({fix: function() {return {}}},
function() {}, trap))
}
function TestConstructThrow2(f) {
assertThrows(function(){ new f(11) }, "myexn")
Object.freeze(f)
assertThrows(function(){ new f(11) }, "myexn")
}
var p = Proxy.createFunction( TestConstructThrow(function() { throw "myexn" })
{fix: function() {return {}}}, function() { throw "myexn" }) TestConstructThrow(Proxy.createFunction({}, function() { throw "myexn" }))
Object.freeze(p) TestConstructThrow(CreateFrozen({}, function() { throw "myexn" }))
TestCallThrow(p)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment