| Index: src/v8natives.js
|
| diff --git a/src/v8natives.js b/src/v8natives.js
|
| index 88525f6b44f01de4e114175bb6253d0685deec44..0e7014467f3b0ac4f5bc414189ec3a677d071eb9 100644
|
| --- a/src/v8natives.js
|
| +++ b/src/v8natives.js
|
| @@ -268,7 +268,7 @@ function ObjectDefineGetter(name, fun) {
|
| if (receiver == null && !IS_UNDETECTABLE(receiver)) {
|
| receiver = %GlobalReceiver(global);
|
| }
|
| - if (!IS_FUNCTION(fun)) {
|
| + if (!IS_SPEC_FUNCTION(fun)) {
|
| throw new $TypeError('Object.prototype.__defineGetter__: Expecting function');
|
| }
|
| var desc = new PropertyDescriptor();
|
| @@ -293,7 +293,7 @@ function ObjectDefineSetter(name, fun) {
|
| if (receiver == null && !IS_UNDETECTABLE(receiver)) {
|
| receiver = %GlobalReceiver(global);
|
| }
|
| - if (!IS_FUNCTION(fun)) {
|
| + if (!IS_SPEC_FUNCTION(fun)) {
|
| throw new $TypeError(
|
| 'Object.prototype.__defineSetter__: Expecting function');
|
| }
|
| @@ -406,7 +406,7 @@ function ToPropertyDescriptor(obj) {
|
|
|
| if ("get" in obj) {
|
| var get = obj.get;
|
| - if (!IS_UNDEFINED(get) && !IS_FUNCTION(get)) {
|
| + if (!IS_UNDEFINED(get) && !IS_SPEC_FUNCTION(get)) {
|
| throw MakeTypeError("getter_must_be_callable", [get]);
|
| }
|
| desc.setGet(get);
|
| @@ -414,7 +414,7 @@ function ToPropertyDescriptor(obj) {
|
|
|
| if ("set" in obj) {
|
| var set = obj.set;
|
| - if (!IS_UNDEFINED(set) && !IS_FUNCTION(set)) {
|
| + if (!IS_UNDEFINED(set) && !IS_SPEC_FUNCTION(set)) {
|
| throw MakeTypeError("setter_must_be_callable", [set]);
|
| }
|
| desc.setSet(set);
|
| @@ -598,7 +598,7 @@ function GetTrap(handler, name, defaultTrap) {
|
| throw MakeTypeError("handler_trap_missing", [handler, name]);
|
| }
|
| trap = defaultTrap;
|
| - } else if (!IS_FUNCTION(trap)) {
|
| + } else if (!IS_SPEC_FUNCTION(trap)) {
|
| throw MakeTypeError("handler_trap_must_be_callable", [handler, name]);
|
| }
|
| return trap;
|
| @@ -984,7 +984,7 @@ function ObjectDefineProperty(obj, p, attributes) {
|
| // Clone the attributes object for protection.
|
| // TODO(rossberg): not spec'ed yet, so not sure if this should involve
|
| // non-own properties as it does (or non-enumerable ones, as it doesn't?).
|
| - var attributesClone = {}
|
| + var attributesClone = {};
|
| for (var a in attributes) {
|
| attributesClone[a] = attributes[a];
|
| }
|
| @@ -1045,7 +1045,16 @@ function ProxyFix(obj) {
|
| if (IS_UNDEFINED(props)) {
|
| throw MakeTypeError("handler_returned_undefined", [handler, "fix"]);
|
| }
|
| - %Fix(obj);
|
| +
|
| + if (IS_SPEC_FUNCTION(obj)) {
|
| + var callTrap = %GetCallTrap(obj);
|
| + var constructTrap = %GetConstructTrap(obj);
|
| + var code = DelegateCallAndConstruct(callTrap, constructTrap);
|
| + %Fix(obj); // becomes a regular function
|
| + %SetCode(obj, code);
|
| + } else {
|
| + %Fix(obj);
|
| + }
|
| ObjectDefineProperties(obj, props);
|
| }
|
|
|
| @@ -1413,6 +1422,10 @@ SetupNumber();
|
| $Function.prototype.constructor = $Function;
|
|
|
| function FunctionSourceString(func) {
|
| + while (%IsJSFunctionProxy(func)) {
|
| + func = %GetCallTrap(func);
|
| + }
|
| +
|
| if (!IS_FUNCTION(func)) {
|
| throw new $TypeError('Function.prototype.toString is not generic');
|
| }
|
| @@ -1442,12 +1455,13 @@ function FunctionToString() {
|
|
|
| // ES5 15.3.4.5
|
| function FunctionBind(this_arg) { // Length is 1.
|
| - if (!IS_FUNCTION(this)) {
|
| + if (!IS_SPEC_FUNCTION(this)) {
|
| throw new $TypeError('Bind must be called on a function');
|
| }
|
| // this_arg is not an argument that should be bound.
|
| var argc_bound = (%_ArgumentsLength() || 1) - 1;
|
| var fn = this;
|
| +
|
| if (argc_bound == 0) {
|
| var result = function() {
|
| if (%_IsConstructCall()) {
|
| @@ -1456,8 +1470,7 @@ function FunctionBind(this_arg) { // Length is 1.
|
| // materializing it and guarantee that this function will be optimized.
|
| return %NewObjectFromBound(fn, null);
|
| }
|
| -
|
| - return fn.apply(this_arg, arguments);
|
| + return %Apply(fn, this_arg, arguments, 0, %_ArgumentsLength());
|
| };
|
| } else {
|
| var bound_args = new InternalArray(argc_bound);
|
| @@ -1487,7 +1500,7 @@ function FunctionBind(this_arg) { // Length is 1.
|
| for (var i = 0; i < argc; i++) {
|
| args[argc_bound + i] = %_Arguments(i);
|
| }
|
| - return fn.apply(this_arg, args);
|
| + return %Apply(fn, this_arg, args, 0, argc + argc_bound);
|
| };
|
| }
|
|
|
| @@ -1498,11 +1511,16 @@ function FunctionBind(this_arg) { // Length is 1.
|
| // is called and make them non-enumerable and non-configurable.
|
| // To be consistent with our normal functions we leave this as it is.
|
|
|
| - // Set the correct length.
|
| - var length = (this.length - argc_bound) > 0 ? this.length - argc_bound : 0;
|
| %FunctionRemovePrototype(result);
|
| %FunctionSetBound(result);
|
| - %BoundFunctionSetLength(result, length);
|
| + // Set the correct length. If this is a function proxy, this.length might
|
| + // throw, or return a bogus result. Leave length alone in that case.
|
| + // TODO(rossberg): This is underspecified in the current proxy proposal.
|
| + try {
|
| + var old_length = ToInteger(this.length);
|
| + var length = (old_length - argc_bound) > 0 ? old_length - argc_bound : 0;
|
| + %BoundFunctionSetLength(result, length);
|
| + } catch(x) {}
|
| return result;
|
| }
|
|
|
|
|