Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: src/v8natives.js

Issue 7623011: Implement function proxies (except for their use as constructors). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed second round of comments. Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/string.js ('k') | src/x64/builtins-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 return %IsPropertyEnumerable(ToObject(this), P); 261 return %IsPropertyEnumerable(ToObject(this), P);
262 } 262 }
263 263
264 264
265 // Extensions for providing property getters and setters. 265 // Extensions for providing property getters and setters.
266 function ObjectDefineGetter(name, fun) { 266 function ObjectDefineGetter(name, fun) {
267 var receiver = this; 267 var receiver = this;
268 if (receiver == null && !IS_UNDETECTABLE(receiver)) { 268 if (receiver == null && !IS_UNDETECTABLE(receiver)) {
269 receiver = %GlobalReceiver(global); 269 receiver = %GlobalReceiver(global);
270 } 270 }
271 if (!IS_FUNCTION(fun)) { 271 if (!IS_SPEC_FUNCTION(fun)) {
272 throw new $TypeError('Object.prototype.__defineGetter__: Expecting function' ); 272 throw new $TypeError('Object.prototype.__defineGetter__: Expecting function' );
273 } 273 }
274 var desc = new PropertyDescriptor(); 274 var desc = new PropertyDescriptor();
275 desc.setGet(fun); 275 desc.setGet(fun);
276 desc.setEnumerable(true); 276 desc.setEnumerable(true);
277 desc.setConfigurable(true); 277 desc.setConfigurable(true);
278 DefineOwnProperty(ToObject(receiver), ToString(name), desc, false); 278 DefineOwnProperty(ToObject(receiver), ToString(name), desc, false);
279 } 279 }
280 280
281 281
282 function ObjectLookupGetter(name) { 282 function ObjectLookupGetter(name) {
283 var receiver = this; 283 var receiver = this;
284 if (receiver == null && !IS_UNDETECTABLE(receiver)) { 284 if (receiver == null && !IS_UNDETECTABLE(receiver)) {
285 receiver = %GlobalReceiver(global); 285 receiver = %GlobalReceiver(global);
286 } 286 }
287 return %LookupAccessor(ToObject(receiver), ToString(name), GETTER); 287 return %LookupAccessor(ToObject(receiver), ToString(name), GETTER);
288 } 288 }
289 289
290 290
291 function ObjectDefineSetter(name, fun) { 291 function ObjectDefineSetter(name, fun) {
292 var receiver = this; 292 var receiver = this;
293 if (receiver == null && !IS_UNDETECTABLE(receiver)) { 293 if (receiver == null && !IS_UNDETECTABLE(receiver)) {
294 receiver = %GlobalReceiver(global); 294 receiver = %GlobalReceiver(global);
295 } 295 }
296 if (!IS_FUNCTION(fun)) { 296 if (!IS_SPEC_FUNCTION(fun)) {
297 throw new $TypeError( 297 throw new $TypeError(
298 'Object.prototype.__defineSetter__: Expecting function'); 298 'Object.prototype.__defineSetter__: Expecting function');
299 } 299 }
300 var desc = new PropertyDescriptor(); 300 var desc = new PropertyDescriptor();
301 desc.setSet(fun); 301 desc.setSet(fun);
302 desc.setEnumerable(true); 302 desc.setEnumerable(true);
303 desc.setConfigurable(true); 303 desc.setConfigurable(true);
304 DefineOwnProperty(ToObject(receiver), ToString(name), desc, false); 304 DefineOwnProperty(ToObject(receiver), ToString(name), desc, false);
305 } 305 }
306 306
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 if ("value" in obj) { 399 if ("value" in obj) {
400 desc.setValue(obj.value); 400 desc.setValue(obj.value);
401 } 401 }
402 402
403 if ("writable" in obj) { 403 if ("writable" in obj) {
404 desc.setWritable(ToBoolean(obj.writable)); 404 desc.setWritable(ToBoolean(obj.writable));
405 } 405 }
406 406
407 if ("get" in obj) { 407 if ("get" in obj) {
408 var get = obj.get; 408 var get = obj.get;
409 if (!IS_UNDEFINED(get) && !IS_FUNCTION(get)) { 409 if (!IS_UNDEFINED(get) && !IS_SPEC_FUNCTION(get)) {
410 throw MakeTypeError("getter_must_be_callable", [get]); 410 throw MakeTypeError("getter_must_be_callable", [get]);
411 } 411 }
412 desc.setGet(get); 412 desc.setGet(get);
413 } 413 }
414 414
415 if ("set" in obj) { 415 if ("set" in obj) {
416 var set = obj.set; 416 var set = obj.set;
417 if (!IS_UNDEFINED(set) && !IS_FUNCTION(set)) { 417 if (!IS_UNDEFINED(set) && !IS_SPEC_FUNCTION(set)) {
418 throw MakeTypeError("setter_must_be_callable", [set]); 418 throw MakeTypeError("setter_must_be_callable", [set]);
419 } 419 }
420 desc.setSet(set); 420 desc.setSet(set);
421 } 421 }
422 422
423 if (IsInconsistentDescriptor(desc)) { 423 if (IsInconsistentDescriptor(desc)) {
424 throw MakeTypeError("value_and_accessor", [obj]); 424 throw MakeTypeError("value_and_accessor", [obj]);
425 } 425 }
426 return desc; 426 return desc;
427 } 427 }
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 591
592 592
593 // For Harmony proxies. 593 // For Harmony proxies.
594 function GetTrap(handler, name, defaultTrap) { 594 function GetTrap(handler, name, defaultTrap) {
595 var trap = handler[name]; 595 var trap = handler[name];
596 if (IS_UNDEFINED(trap)) { 596 if (IS_UNDEFINED(trap)) {
597 if (IS_UNDEFINED(defaultTrap)) { 597 if (IS_UNDEFINED(defaultTrap)) {
598 throw MakeTypeError("handler_trap_missing", [handler, name]); 598 throw MakeTypeError("handler_trap_missing", [handler, name]);
599 } 599 }
600 trap = defaultTrap; 600 trap = defaultTrap;
601 } else if (!IS_FUNCTION(trap)) { 601 } else if (!IS_SPEC_FUNCTION(trap)) {
602 throw MakeTypeError("handler_trap_must_be_callable", [handler, name]); 602 throw MakeTypeError("handler_trap_must_be_callable", [handler, name]);
603 } 603 }
604 return trap; 604 return trap;
605 } 605 }
606 606
607 607
608 function CallTrap0(handler, name, defaultTrap) { 608 function CallTrap0(handler, name, defaultTrap) {
609 return %_CallFunction(handler, GetTrap(handler, name, defaultTrap)); 609 return %_CallFunction(handler, GetTrap(handler, name, defaultTrap));
610 } 610 }
611 611
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 // ES5 section 15.2.3.6. 977 // ES5 section 15.2.3.6.
978 function ObjectDefineProperty(obj, p, attributes) { 978 function ObjectDefineProperty(obj, p, attributes) {
979 if (!IS_SPEC_OBJECT(obj)) { 979 if (!IS_SPEC_OBJECT(obj)) {
980 throw MakeTypeError("obj_ctor_property_non_object", ["defineProperty"]); 980 throw MakeTypeError("obj_ctor_property_non_object", ["defineProperty"]);
981 } 981 }
982 var name = ToString(p); 982 var name = ToString(p);
983 if (%IsJSProxy(obj)) { 983 if (%IsJSProxy(obj)) {
984 // Clone the attributes object for protection. 984 // Clone the attributes object for protection.
985 // TODO(rossberg): not spec'ed yet, so not sure if this should involve 985 // TODO(rossberg): not spec'ed yet, so not sure if this should involve
986 // non-own properties as it does (or non-enumerable ones, as it doesn't?). 986 // non-own properties as it does (or non-enumerable ones, as it doesn't?).
987 var attributesClone = {} 987 var attributesClone = {};
988 for (var a in attributes) { 988 for (var a in attributes) {
989 attributesClone[a] = attributes[a]; 989 attributesClone[a] = attributes[a];
990 } 990 }
991 DefineProxyProperty(obj, name, attributesClone, true); 991 DefineProxyProperty(obj, name, attributesClone, true);
992 // The following would implement the spec as in the current proposal, 992 // The following would implement the spec as in the current proposal,
993 // but after recent comments on es-discuss, is most likely obsolete. 993 // but after recent comments on es-discuss, is most likely obsolete.
994 /* 994 /*
995 var defineObj = FromGenericPropertyDescriptor(desc); 995 var defineObj = FromGenericPropertyDescriptor(desc);
996 var names = ObjectGetOwnPropertyNames(attributes); 996 var names = ObjectGetOwnPropertyNames(attributes);
997 var standardNames = 997 var standardNames =
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1038 } 1038 }
1039 1039
1040 1040
1041 // Harmony proxies. 1041 // Harmony proxies.
1042 function ProxyFix(obj) { 1042 function ProxyFix(obj) {
1043 var handler = %GetHandler(obj); 1043 var handler = %GetHandler(obj);
1044 var props = CallTrap0(handler, "fix", void 0); 1044 var props = CallTrap0(handler, "fix", void 0);
1045 if (IS_UNDEFINED(props)) { 1045 if (IS_UNDEFINED(props)) {
1046 throw MakeTypeError("handler_returned_undefined", [handler, "fix"]); 1046 throw MakeTypeError("handler_returned_undefined", [handler, "fix"]);
1047 } 1047 }
1048 %Fix(obj); 1048
1049 if (IS_SPEC_FUNCTION(obj)) {
1050 var callTrap = %GetCallTrap(obj);
1051 var constructTrap = %GetConstructTrap(obj);
1052 var code = DelegateCallAndConstruct(callTrap, constructTrap);
1053 %Fix(obj); // becomes a regular function
1054 %SetCode(obj, code);
1055 } else {
1056 %Fix(obj);
1057 }
1049 ObjectDefineProperties(obj, props); 1058 ObjectDefineProperties(obj, props);
1050 } 1059 }
1051 1060
1052 1061
1053 // ES5 section 15.2.3.8. 1062 // ES5 section 15.2.3.8.
1054 function ObjectSeal(obj) { 1063 function ObjectSeal(obj) {
1055 if (!IS_SPEC_OBJECT(obj)) { 1064 if (!IS_SPEC_OBJECT(obj)) {
1056 throw MakeTypeError("obj_ctor_property_non_object", ["seal"]); 1065 throw MakeTypeError("obj_ctor_property_non_object", ["seal"]);
1057 } 1066 }
1058 if (%IsJSProxy(obj)) { 1067 if (%IsJSProxy(obj)) {
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
1406 1415
1407 SetupNumber(); 1416 SetupNumber();
1408 1417
1409 1418
1410 // ---------------------------------------------------------------------------- 1419 // ----------------------------------------------------------------------------
1411 // Function 1420 // Function
1412 1421
1413 $Function.prototype.constructor = $Function; 1422 $Function.prototype.constructor = $Function;
1414 1423
1415 function FunctionSourceString(func) { 1424 function FunctionSourceString(func) {
1425 while (%IsJSFunctionProxy(func)) {
1426 func = %GetCallTrap(func);
1427 }
1428
1416 if (!IS_FUNCTION(func)) { 1429 if (!IS_FUNCTION(func)) {
1417 throw new $TypeError('Function.prototype.toString is not generic'); 1430 throw new $TypeError('Function.prototype.toString is not generic');
1418 } 1431 }
1419 1432
1420 var source = %FunctionGetSourceCode(func); 1433 var source = %FunctionGetSourceCode(func);
1421 if (!IS_STRING(source) || %FunctionIsBuiltin(func)) { 1434 if (!IS_STRING(source) || %FunctionIsBuiltin(func)) {
1422 var name = %FunctionGetName(func); 1435 var name = %FunctionGetName(func);
1423 if (name) { 1436 if (name) {
1424 // Mimic what KJS does. 1437 // Mimic what KJS does.
1425 return 'function ' + name + '() { [native code] }'; 1438 return 'function ' + name + '() { [native code] }';
1426 } else { 1439 } else {
1427 return 'function () { [native code] }'; 1440 return 'function () { [native code] }';
1428 } 1441 }
1429 } 1442 }
1430 1443
1431 var name = %FunctionNameShouldPrintAsAnonymous(func) 1444 var name = %FunctionNameShouldPrintAsAnonymous(func)
1432 ? 'anonymous' 1445 ? 'anonymous'
1433 : %FunctionGetName(func); 1446 : %FunctionGetName(func);
1434 return 'function ' + name + source; 1447 return 'function ' + name + source;
1435 } 1448 }
1436 1449
1437 1450
1438 function FunctionToString() { 1451 function FunctionToString() {
1439 return FunctionSourceString(this); 1452 return FunctionSourceString(this);
1440 } 1453 }
1441 1454
1442 1455
1443 // ES5 15.3.4.5 1456 // ES5 15.3.4.5
1444 function FunctionBind(this_arg) { // Length is 1. 1457 function FunctionBind(this_arg) { // Length is 1.
1445 if (!IS_FUNCTION(this)) { 1458 if (!IS_SPEC_FUNCTION(this)) {
1446 throw new $TypeError('Bind must be called on a function'); 1459 throw new $TypeError('Bind must be called on a function');
1447 } 1460 }
1448 // this_arg is not an argument that should be bound. 1461 // this_arg is not an argument that should be bound.
1449 var argc_bound = (%_ArgumentsLength() || 1) - 1; 1462 var argc_bound = (%_ArgumentsLength() || 1) - 1;
1450 var fn = this; 1463 var fn = this;
1464
1451 if (argc_bound == 0) { 1465 if (argc_bound == 0) {
1452 var result = function() { 1466 var result = function() {
1453 if (%_IsConstructCall()) { 1467 if (%_IsConstructCall()) {
1454 // %NewObjectFromBound implicitly uses arguments passed to this 1468 // %NewObjectFromBound implicitly uses arguments passed to this
1455 // function. We do not pass the arguments object explicitly to avoid 1469 // function. We do not pass the arguments object explicitly to avoid
1456 // materializing it and guarantee that this function will be optimized. 1470 // materializing it and guarantee that this function will be optimized.
1457 return %NewObjectFromBound(fn, null); 1471 return %NewObjectFromBound(fn, null);
1458 } 1472 }
1459 1473 return %Apply(fn, this_arg, arguments, 0, %_ArgumentsLength());
1460 return fn.apply(this_arg, arguments);
1461 }; 1474 };
1462 } else { 1475 } else {
1463 var bound_args = new InternalArray(argc_bound); 1476 var bound_args = new InternalArray(argc_bound);
1464 for(var i = 0; i < argc_bound; i++) { 1477 for(var i = 0; i < argc_bound; i++) {
1465 bound_args[i] = %_Arguments(i+1); 1478 bound_args[i] = %_Arguments(i+1);
1466 } 1479 }
1467 1480
1468 var result = function() { 1481 var result = function() {
1469 // If this is a construct call we use a special runtime method 1482 // If this is a construct call we use a special runtime method
1470 // to generate the actual object using the bound function. 1483 // to generate the actual object using the bound function.
1471 if (%_IsConstructCall()) { 1484 if (%_IsConstructCall()) {
1472 // %NewObjectFromBound implicitly uses arguments passed to this 1485 // %NewObjectFromBound implicitly uses arguments passed to this
1473 // function. We do not pass the arguments object explicitly to avoid 1486 // function. We do not pass the arguments object explicitly to avoid
1474 // materializing it and guarantee that this function will be optimized. 1487 // materializing it and guarantee that this function will be optimized.
1475 return %NewObjectFromBound(fn, bound_args); 1488 return %NewObjectFromBound(fn, bound_args);
1476 } 1489 }
1477 1490
1478 // Combine the args we got from the bind call with the args 1491 // Combine the args we got from the bind call with the args
1479 // given as argument to the invocation. 1492 // given as argument to the invocation.
1480 var argc = %_ArgumentsLength(); 1493 var argc = %_ArgumentsLength();
1481 var args = new InternalArray(argc + argc_bound); 1494 var args = new InternalArray(argc + argc_bound);
1482 // Add bound arguments. 1495 // Add bound arguments.
1483 for (var i = 0; i < argc_bound; i++) { 1496 for (var i = 0; i < argc_bound; i++) {
1484 args[i] = bound_args[i]; 1497 args[i] = bound_args[i];
1485 } 1498 }
1486 // Add arguments from call. 1499 // Add arguments from call.
1487 for (var i = 0; i < argc; i++) { 1500 for (var i = 0; i < argc; i++) {
1488 args[argc_bound + i] = %_Arguments(i); 1501 args[argc_bound + i] = %_Arguments(i);
1489 } 1502 }
1490 return fn.apply(this_arg, args); 1503 return %Apply(fn, this_arg, args, 0, argc + argc_bound);
1491 }; 1504 };
1492 } 1505 }
1493 1506
1494 // We already have caller and arguments properties on functions, 1507 // We already have caller and arguments properties on functions,
1495 // which are non-configurable. It therefore makes no sence to 1508 // which are non-configurable. It therefore makes no sence to
1496 // try to redefine these as defined by the spec. The spec says 1509 // try to redefine these as defined by the spec. The spec says
1497 // that bind should make these throw a TypeError if get or set 1510 // that bind should make these throw a TypeError if get or set
1498 // is called and make them non-enumerable and non-configurable. 1511 // is called and make them non-enumerable and non-configurable.
1499 // To be consistent with our normal functions we leave this as it is. 1512 // To be consistent with our normal functions we leave this as it is.
1500 1513
1501 // Set the correct length.
1502 var length = (this.length - argc_bound) > 0 ? this.length - argc_bound : 0;
1503 %FunctionRemovePrototype(result); 1514 %FunctionRemovePrototype(result);
1504 %FunctionSetBound(result); 1515 %FunctionSetBound(result);
1505 %BoundFunctionSetLength(result, length); 1516 // Set the correct length. If this is a function proxy, this.length might
1517 // throw, or return a bogus result. Leave length alone in that case.
1518 // TODO(rossberg): This is underspecified in the current proxy proposal.
1519 try {
1520 var old_length = ToInteger(this.length);
1521 var length = (old_length - argc_bound) > 0 ? old_length - argc_bound : 0;
1522 %BoundFunctionSetLength(result, length);
1523 } catch(x) {}
1506 return result; 1524 return result;
1507 } 1525 }
1508 1526
1509 1527
1510 function NewFunction(arg1) { // length == 1 1528 function NewFunction(arg1) { // length == 1
1511 var n = %_ArgumentsLength(); 1529 var n = %_ArgumentsLength();
1512 var p = ''; 1530 var p = '';
1513 if (n > 1) { 1531 if (n > 1) {
1514 p = new InternalArray(n - 1); 1532 p = new InternalArray(n - 1);
1515 for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i); 1533 for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i);
(...skipping 18 matching lines...) Expand all
1534 // ---------------------------------------------------------------------------- 1552 // ----------------------------------------------------------------------------
1535 1553
1536 function SetupFunction() { 1554 function SetupFunction() {
1537 InstallFunctions($Function.prototype, DONT_ENUM, $Array( 1555 InstallFunctions($Function.prototype, DONT_ENUM, $Array(
1538 "bind", FunctionBind, 1556 "bind", FunctionBind,
1539 "toString", FunctionToString 1557 "toString", FunctionToString
1540 )); 1558 ));
1541 } 1559 }
1542 1560
1543 SetupFunction(); 1561 SetupFunction();
OLDNEW
« no previous file with comments | « src/string.js ('k') | src/x64/builtins-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698