|
|
|
|
| 361 |
IndirectProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy, |
361 |
IndirectProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy, |
| 362 |
jsid id, bool set, |
362 |
jsid id, bool set, |
| 363 |
PropertyDescriptor *desc) |
363 |
PropertyDescriptor *desc) |
| 364 |
{ |
364 |
{ |
| 365 |
return JS_GetPropertyDescriptorById(cx, GetProxyTargetObject(proxy), id, |
365 |
return JS_GetPropertyDescriptorById(cx, GetProxyTargetObject(proxy), id, |
| 366 |
JSRESOLVE_QUALIFIED, desc); |
366 |
JSRESOLVE_QUALIFIED, desc); |
| 367 |
} |
367 |
} |
| 368 |
|
368 |
|
| 369 |
static bool |
369 |
bool |
| 370 |
GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, unsigned flags, |
370 |
GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, unsigned flags, |
| 371 |
JSPropertyDescriptor *desc) |
371 |
JSPropertyDescriptor *desc) |
| 372 |
{ |
372 |
{ |
| 373 |
// If obj is a proxy, we can do better than just guessing. This is |
373 |
// If obj is a proxy, we can do better than just guessing. This is |
| 374 |
// important for certain types of wrappers that wrap other wrappers. |
374 |
// important for certain types of wrappers that wrap other wrappers. |
| 375 |
if (obj->isProxy()) |
375 |
if (obj->isProxy()) |
| 376 |
return Proxy::getOwnPropertyDescriptor(cx, obj, id, |
376 |
return Proxy::getOwnPropertyDescriptor(cx, obj, id, |
| 377 |
flags & JSRESOLVE_ASSIGNING, |
377 |
flags & JSRESOLVE_ASSIGNING, |
|
Lines 592-607
DirectProxyHandler::iterate(JSContext *c
|
Link Here
|
|---|
|
| 592 |
return GetIterator(cx, target, flags, vp); |
592 |
return GetIterator(cx, target, flags, vp); |
| 593 |
} |
593 |
} |
| 594 |
|
594 |
|
| 595 |
static bool |
595 |
static bool |
| 596 |
GetTrap(JSContext *cx, JSObject *handler, PropertyName *name, Value *fvalp) |
596 |
GetTrap(JSContext *cx, JSObject *handler, PropertyName *name, Value *fvalp) |
| 597 |
{ |
597 |
{ |
| 598 |
JS_CHECK_RECURSION(cx, return false); |
598 |
JS_CHECK_RECURSION(cx, return false); |
| 599 |
|
599 |
|
|
|
600 |
// Direct proxies allow the handler object to be NULL |
| 601 |
if (!handler) { |
| 602 |
*fvalp = UndefinedValue(); |
| 603 |
return true; |
| 604 |
} |
| 600 |
Rooted<PropertyName*> propname(cx, name); |
605 |
Rooted<PropertyName*> propname(cx, name); |
| 601 |
return handler->getProperty(cx, propname, fvalp); |
606 |
return handler->getProperty(cx, propname, fvalp); |
| 602 |
} |
607 |
} |
| 603 |
|
608 |
|
| 604 |
static bool |
609 |
static bool |
| 605 |
GetFundamentalTrap(JSContext *cx, JSObject *handler, PropertyName *name, Value *fvalp) |
610 |
GetFundamentalTrap(JSContext *cx, JSObject *handler, PropertyName *name, Value *fvalp) |
| 606 |
{ |
611 |
{ |
| 607 |
if (!GetTrap(cx, handler, name, fvalp)) |
612 |
if (!GetTrap(cx, handler, name, fvalp)) |
|
Lines 656-671
Trap2(JSContext *cx, HandleObject handle
|
Link Here
|
|---|
|
| 656 |
Value argv[2] = { *rval, v }; |
661 |
Value argv[2] = { *rval, v }; |
| 657 |
return Trap(cx, handler, fval, 2, argv, rval); |
662 |
return Trap(cx, handler, fval, 2, argv, rval); |
| 658 |
} |
663 |
} |
| 659 |
|
664 |
|
| 660 |
static bool |
665 |
static bool |
| 661 |
ParsePropertyDescriptorObject(JSContext *cx, JSObject *obj, jsid id, const Value &v, |
666 |
ParsePropertyDescriptorObject(JSContext *cx, JSObject *obj, jsid id, const Value &v, |
| 662 |
PropertyDescriptor *desc) |
667 |
PropertyDescriptor *desc) |
| 663 |
{ |
668 |
{ |
|
|
669 |
if (v.isUndefined()) { |
| 670 |
// Indicate undefined by setting the obj field to NULL |
| 671 |
desc->obj = NULL; |
| 672 |
return true; |
| 673 |
} |
| 664 |
AutoPropDescArrayRooter descs(cx); |
674 |
AutoPropDescArrayRooter descs(cx); |
| 665 |
PropDesc *d = descs.append(); |
675 |
PropDesc *d = descs.append(); |
| 666 |
if (!d || !d->initialize(cx, v)) |
676 |
if (!d || !d->initialize(cx, v)) |
| 667 |
return false; |
677 |
return false; |
| 668 |
desc->obj = obj; |
678 |
desc->obj = obj; |
| 669 |
desc->value = d->hasValue() ? d->value() : UndefinedValue(); |
679 |
desc->value = d->hasValue() ? d->value() : UndefinedValue(); |
| 670 |
JS_ASSERT(!(d->attributes() & JSPROP_SHORTID)); |
680 |
JS_ASSERT(!(d->attributes() & JSPROP_SHORTID)); |
| 671 |
desc->attrs = d->attributes(); |
681 |
desc->attrs = d->attributes(); |
|
Lines 714-733
ArrayToIdVector(JSContext *cx, const Val
|
Link Here
|
|---|
|
| 714 |
if (!props.append(id)) |
724 |
if (!props.append(id)) |
| 715 |
return false; |
725 |
return false; |
| 716 |
} |
726 |
} |
| 717 |
|
727 |
|
| 718 |
return true; |
728 |
return true; |
| 719 |
} |
729 |
} |
| 720 |
|
730 |
|
| 721 |
/* Derived class for all scripted proxy handlers. */ |
731 |
/* Derived class for all scripted proxy handlers. */ |
| 722 |
class ScriptedProxyHandler : public IndirectProxyHandler { |
732 |
class ScriptedIndirectProxyHandler : public IndirectProxyHandler { |
| 723 |
public: |
733 |
public: |
| 724 |
ScriptedProxyHandler(); |
734 |
ScriptedIndirectProxyHandler(); |
| 725 |
virtual ~ScriptedProxyHandler(); |
735 |
virtual ~ScriptedIndirectProxyHandler(); |
| 726 |
|
736 |
|
| 727 |
/* ES5 Harmony fundamental proxy traps. */ |
737 |
/* ES5 Harmony fundamental proxy traps. */ |
| 728 |
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, |
738 |
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, |
| 729 |
PropertyDescriptor *desc); |
739 |
PropertyDescriptor *desc); |
| 730 |
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, |
740 |
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, |
| 731 |
PropertyDescriptor *desc); |
741 |
PropertyDescriptor *desc); |
| 732 |
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, |
742 |
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, |
| 733 |
PropertyDescriptor *desc); |
743 |
PropertyDescriptor *desc); |
|
Lines 742-767
class ScriptedProxyHandler : public Indi
|
Link Here
|
|---|
|
| 742 |
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict, |
752 |
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict, |
| 743 |
Value *vp); |
753 |
Value *vp); |
| 744 |
virtual bool keys(JSContext *cx, JSObject *proxy, AutoIdVector &props); |
754 |
virtual bool keys(JSContext *cx, JSObject *proxy, AutoIdVector &props); |
| 745 |
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags, Value *vp); |
755 |
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags, Value *vp); |
| 746 |
|
756 |
|
| 747 |
virtual JSType typeOf(JSContext *cx, JSObject *proxy); |
757 |
virtual JSType typeOf(JSContext *cx, JSObject *proxy); |
| 748 |
virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp); |
758 |
virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp); |
| 749 |
|
759 |
|
| 750 |
static ScriptedProxyHandler singleton; |
760 |
static ScriptedIndirectProxyHandler singleton; |
| 751 |
}; |
761 |
}; |
| 752 |
|
762 |
|
| 753 |
static int sScriptedProxyHandlerFamily = 0; |
763 |
static int sScriptedIndirectProxyHandlerFamily = 0; |
| 754 |
|
764 |
|
| 755 |
ScriptedProxyHandler::ScriptedProxyHandler() : IndirectProxyHandler(&sScriptedProxyHandlerFamily) |
765 |
ScriptedIndirectProxyHandler::ScriptedIndirectProxyHandler() |
|
|
766 |
: IndirectProxyHandler(&sScriptedIndirectProxyHandlerFamily) |
| 756 |
{ |
767 |
{ |
| 757 |
} |
768 |
} |
| 758 |
|
769 |
|
| 759 |
ScriptedProxyHandler::~ScriptedProxyHandler() |
770 |
ScriptedIndirectProxyHandler::~ScriptedIndirectProxyHandler() |
| 760 |
{ |
771 |
{ |
| 761 |
} |
772 |
} |
| 762 |
|
773 |
|
| 763 |
static bool |
774 |
static bool |
| 764 |
ReturnedValueMustNotBePrimitive(JSContext *cx, JSObject *proxy, JSAtom *atom, const Value &v) |
775 |
ReturnedValueMustNotBePrimitive(JSContext *cx, JSObject *proxy, JSAtom *atom, const Value &v) |
| 765 |
{ |
776 |
{ |
| 766 |
if (v.isPrimitive()) { |
777 |
if (v.isPrimitive()) { |
| 767 |
JSAutoByteString bytes; |
778 |
JSAutoByteString bytes; |
|
Lines 777-893
ReturnedValueMustNotBePrimitive(JSContex
|
Link Here
|
|---|
|
| 777 |
static JSObject * |
788 |
static JSObject * |
| 778 |
GetProxyHandlerObject(JSContext *cx, JSObject *proxy) |
789 |
GetProxyHandlerObject(JSContext *cx, JSObject *proxy) |
| 779 |
{ |
790 |
{ |
| 780 |
JS_ASSERT(OperationInProgress(cx, proxy)); |
791 |
JS_ASSERT(OperationInProgress(cx, proxy)); |
| 781 |
return GetProxyPrivate(proxy).toObjectOrNull(); |
792 |
return GetProxyPrivate(proxy).toObjectOrNull(); |
| 782 |
} |
793 |
} |
| 783 |
|
794 |
|
| 784 |
bool |
795 |
bool |
| 785 |
ScriptedProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy_, jsid id_, bool set, |
796 |
ScriptedIndirectProxyHandler::getPropertyDescriptor(JSContext *cx, |
| 786 |
PropertyDescriptor *desc) |
797 |
JSObject *proxy_, jsid id_, |
|
|
798 |
bool set, |
| 799 |
PropertyDescriptor *desc) |
| 787 |
{ |
800 |
{ |
|
|
801 |
RootedObject proxy(cx, proxy_); |
| 788 |
RootedId id(cx, id_); |
802 |
RootedId id(cx, id_); |
| 789 |
RootedObject proxy(cx, proxy_); |
|
|
| 790 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
803 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 791 |
RootedValue fval(cx), value(cx); |
804 |
RootedValue fval(cx), value(cx); |
| 792 |
return GetFundamentalTrap(cx, handler, ATOM(getPropertyDescriptor), fval.address()) && |
805 |
return GetFundamentalTrap(cx, handler, ATOM(getPropertyDescriptor), fval.address()) && |
| 793 |
Trap1(cx, handler, fval, id, value.address()) && |
806 |
Trap1(cx, handler, fval, id, value.address()) && |
| 794 |
((value.get().isUndefined() && IndicatePropertyNotFound(cx, desc)) || |
807 |
((value.get().isUndefined() && IndicatePropertyNotFound(cx, desc)) || |
| 795 |
(ReturnedValueMustNotBePrimitive(cx, proxy, ATOM(getPropertyDescriptor), value) && |
808 |
(ReturnedValueMustNotBePrimitive(cx, proxy, ATOM(getPropertyDescriptor), value) && |
| 796 |
ParsePropertyDescriptorObject(cx, proxy, id, value, desc))); |
809 |
ParsePropertyDescriptorObject(cx, proxy, id, value, desc))); |
| 797 |
} |
810 |
} |
| 798 |
|
811 |
|
| 799 |
bool |
812 |
bool |
| 800 |
ScriptedProxyHandler::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy_, jsid id_, bool set, |
813 |
ScriptedIndirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, |
| 801 |
PropertyDescriptor *desc) |
814 |
JSObject *proxy_, jsid id_, |
|
|
815 |
bool set, |
| 816 |
PropertyDescriptor *desc) |
| 802 |
{ |
817 |
{ |
| 803 |
RootedId id(cx, id_); |
818 |
RootedId id(cx, id_); |
| 804 |
RootedObject proxy(cx, proxy_); |
819 |
RootedObject proxy(cx, proxy_); |
| 805 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
820 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 806 |
RootedValue fval(cx), value(cx); |
821 |
RootedValue fval(cx), value(cx); |
| 807 |
return GetFundamentalTrap(cx, handler, ATOM(getOwnPropertyDescriptor), fval.address()) && |
822 |
return GetFundamentalTrap(cx, handler, ATOM(getOwnPropertyDescriptor), fval.address()) && |
| 808 |
Trap1(cx, handler, fval, id, value.address()) && |
823 |
Trap1(cx, handler, fval, id, value.address()) && |
| 809 |
((value.get().isUndefined() && IndicatePropertyNotFound(cx, desc)) || |
824 |
((value.get().isUndefined() && IndicatePropertyNotFound(cx, desc)) || |
| 810 |
(ReturnedValueMustNotBePrimitive(cx, proxy, ATOM(getPropertyDescriptor), value) && |
825 |
(ReturnedValueMustNotBePrimitive(cx, proxy, ATOM(getPropertyDescriptor), value) && |
| 811 |
ParsePropertyDescriptorObject(cx, proxy, id, value, desc))); |
826 |
ParsePropertyDescriptorObject(cx, proxy, id, value, desc))); |
| 812 |
} |
827 |
} |
| 813 |
|
828 |
|
| 814 |
bool |
829 |
bool |
| 815 |
ScriptedProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id_, |
830 |
ScriptedIndirectProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, |
| 816 |
PropertyDescriptor *desc) |
831 |
jsid id_, PropertyDescriptor *desc) |
| 817 |
{ |
832 |
{ |
| 818 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
833 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 819 |
RootedValue fval(cx), value(cx); |
834 |
RootedValue fval(cx), value(cx); |
| 820 |
RootedId id(cx, id_); |
835 |
RootedId id(cx, id_); |
| 821 |
return GetFundamentalTrap(cx, handler, ATOM(defineProperty), fval.address()) && |
836 |
return GetFundamentalTrap(cx, handler, ATOM(defineProperty), fval.address()) && |
| 822 |
NewPropertyDescriptorObject(cx, desc, value.address()) && |
837 |
NewPropertyDescriptorObject(cx, desc, value.address()) && |
| 823 |
Trap2(cx, handler, fval, id, value, value.address()); |
838 |
Trap2(cx, handler, fval, id, value, value.address()); |
| 824 |
} |
839 |
} |
| 825 |
|
840 |
|
| 826 |
bool |
841 |
bool |
| 827 |
ScriptedProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) |
842 |
ScriptedIndirectProxyHandler::getOwnPropertyNames(JSContext *cx, |
|
|
843 |
JSObject *proxy, |
| 844 |
AutoIdVector &props) |
| 828 |
{ |
845 |
{ |
| 829 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
846 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 830 |
RootedValue fval(cx), value(cx); |
847 |
RootedValue fval(cx), value(cx); |
| 831 |
return GetFundamentalTrap(cx, handler, ATOM(getOwnPropertyNames), fval.address()) && |
848 |
return GetFundamentalTrap(cx, handler, ATOM(getOwnPropertyNames), fval.address()) && |
| 832 |
Trap(cx, handler, fval, 0, NULL, value.address()) && |
849 |
Trap(cx, handler, fval, 0, NULL, value.address()) && |
| 833 |
ArrayToIdVector(cx, value, props); |
850 |
ArrayToIdVector(cx, value, props); |
| 834 |
} |
851 |
} |
| 835 |
|
852 |
|
| 836 |
bool |
853 |
bool |
| 837 |
ScriptedProxyHandler::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) |
854 |
ScriptedIndirectProxyHandler::delete_(JSContext *cx, JSObject *proxy, jsid id, |
|
|
855 |
bool *bp) |
| 838 |
{ |
856 |
{ |
| 839 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
857 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 840 |
RootedValue fval(cx), value(cx); |
858 |
RootedValue fval(cx), value(cx); |
| 841 |
return GetFundamentalTrap(cx, handler, ATOM(delete), fval.address()) && |
859 |
return GetFundamentalTrap(cx, handler, ATOM(delete), fval.address()) && |
| 842 |
Trap1(cx, handler, fval, id, value.address()) && |
860 |
Trap1(cx, handler, fval, id, value.address()) && |
| 843 |
ValueToBool(cx, value, bp); |
861 |
ValueToBool(cx, value, bp); |
| 844 |
} |
862 |
} |
| 845 |
|
863 |
|
| 846 |
bool |
864 |
bool |
| 847 |
ScriptedProxyHandler::enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) |
865 |
ScriptedIndirectProxyHandler::enumerate(JSContext *cx, JSObject *proxy, |
|
|
866 |
AutoIdVector &props) |
| 848 |
{ |
867 |
{ |
| 849 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
868 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 850 |
RootedValue fval(cx), value(cx); |
869 |
RootedValue fval(cx), value(cx); |
| 851 |
return GetFundamentalTrap(cx, handler, ATOM(enumerate), fval.address()) && |
870 |
return GetFundamentalTrap(cx, handler, ATOM(enumerate), fval.address()) && |
| 852 |
Trap(cx, handler, fval, 0, NULL, value.address()) && |
871 |
Trap(cx, handler, fval, 0, NULL, value.address()) && |
| 853 |
ArrayToIdVector(cx, value, props); |
872 |
ArrayToIdVector(cx, value, props); |
| 854 |
} |
873 |
} |
| 855 |
|
874 |
|
| 856 |
bool |
875 |
bool |
| 857 |
ScriptedProxyHandler::has(JSContext *cx, JSObject *proxy_, jsid id, bool *bp) |
876 |
ScriptedIndirectProxyHandler::has(JSContext *cx, JSObject *proxy_, jsid id, |
|
|
877 |
bool *bp) |
| 858 |
{ |
878 |
{ |
| 859 |
RootedObject proxy(cx, proxy_); |
879 |
RootedObject proxy(cx, proxy_); |
| 860 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
880 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 861 |
RootedValue fval(cx), value(cx); |
881 |
RootedValue fval(cx), value(cx); |
| 862 |
if (!GetDerivedTrap(cx, handler, ATOM(has), fval.address())) |
882 |
if (!GetDerivedTrap(cx, handler, ATOM(has), fval.address())) |
| 863 |
return false; |
883 |
return false; |
| 864 |
if (!js_IsCallable(fval)) |
884 |
if (!js_IsCallable(fval)) |
| 865 |
return BaseProxyHandler::has(cx, proxy, id, bp); |
885 |
return BaseProxyHandler::has(cx, proxy, id, bp); |
| 866 |
return Trap1(cx, handler, fval, id, value.address()) && |
886 |
return Trap1(cx, handler, fval, id, value.address()) && |
| 867 |
ValueToBool(cx, value, bp); |
887 |
ValueToBool(cx, value, bp); |
| 868 |
} |
888 |
} |
| 869 |
|
889 |
|
| 870 |
bool |
890 |
bool |
| 871 |
ScriptedProxyHandler::hasOwn(JSContext *cx, JSObject *proxy_, jsid id, bool *bp) |
891 |
ScriptedIndirectProxyHandler::hasOwn(JSContext *cx, JSObject *proxy_, jsid id, |
|
|
892 |
bool *bp) |
| 872 |
{ |
893 |
{ |
| 873 |
RootedObject proxy(cx, proxy_); |
894 |
RootedObject proxy(cx, proxy_); |
| 874 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
895 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 875 |
RootedValue fval(cx), value(cx); |
896 |
RootedValue fval(cx), value(cx); |
| 876 |
if (!GetDerivedTrap(cx, handler, ATOM(hasOwn), fval.address())) |
897 |
if (!GetDerivedTrap(cx, handler, ATOM(hasOwn), fval.address())) |
| 877 |
return false; |
898 |
return false; |
| 878 |
if (!js_IsCallable(fval)) |
899 |
if (!js_IsCallable(fval)) |
| 879 |
return BaseProxyHandler::hasOwn(cx, proxy, id, bp); |
900 |
return BaseProxyHandler::hasOwn(cx, proxy, id, bp); |
| 880 |
return Trap1(cx, handler, fval, id, value.address()) && |
901 |
return Trap1(cx, handler, fval, id, value.address()) && |
| 881 |
ValueToBool(cx, value, bp); |
902 |
ValueToBool(cx, value, bp); |
| 882 |
} |
903 |
} |
| 883 |
|
904 |
|
| 884 |
bool |
905 |
bool |
| 885 |
ScriptedProxyHandler::get(JSContext *cx, JSObject *proxy_, JSObject *receiver, jsid id_, Value *vp) |
906 |
ScriptedIndirectProxyHandler::get(JSContext *cx, JSObject *proxy_, |
|
|
907 |
JSObject *receiver, jsid id_, Value *vp) |
| 886 |
{ |
908 |
{ |
| 887 |
RootedId id(cx, id_); |
909 |
RootedId id(cx, id_); |
| 888 |
RootedObject proxy(cx, proxy_); |
910 |
RootedObject proxy(cx, proxy_); |
| 889 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
911 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 890 |
JSString *str = ToString(cx, IdToValue(id)); |
912 |
JSString *str = ToString(cx, IdToValue(id)); |
| 891 |
if (!str) |
913 |
if (!str) |
| 892 |
return false; |
914 |
return false; |
| 893 |
RootedValue value(cx, StringValue(str)); |
915 |
RootedValue value(cx, StringValue(str)); |
|
Lines 896-913
ScriptedProxyHandler::get(JSContext *cx,
|
Link Here
|
|---|
|
| 896 |
if (!GetDerivedTrap(cx, handler, ATOM(get), fval.address())) |
918 |
if (!GetDerivedTrap(cx, handler, ATOM(get), fval.address())) |
| 897 |
return false; |
919 |
return false; |
| 898 |
if (!js_IsCallable(fval)) |
920 |
if (!js_IsCallable(fval)) |
| 899 |
return BaseProxyHandler::get(cx, proxy, receiver, id, vp); |
921 |
return BaseProxyHandler::get(cx, proxy, receiver, id, vp); |
| 900 |
return Trap(cx, handler, fval, 2, argv, vp); |
922 |
return Trap(cx, handler, fval, 2, argv, vp); |
| 901 |
} |
923 |
} |
| 902 |
|
924 |
|
| 903 |
bool |
925 |
bool |
| 904 |
ScriptedProxyHandler::set(JSContext *cx, JSObject *proxy_, JSObject *receiver, jsid id_, bool strict, |
926 |
ScriptedIndirectProxyHandler::set(JSContext *cx, JSObject *proxy_, |
| 905 |
Value *vp) |
927 |
JSObject *receiver, jsid id_, bool strict, |
|
|
928 |
Value *vp) |
| 906 |
{ |
929 |
{ |
| 907 |
RootedId id(cx, id_); |
930 |
RootedId id(cx, id_); |
| 908 |
RootedObject proxy(cx, proxy_); |
931 |
RootedObject proxy(cx, proxy_); |
| 909 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
932 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 910 |
JSString *str = ToString(cx, IdToValue(id)); |
933 |
JSString *str = ToString(cx, IdToValue(id)); |
| 911 |
if (!str) |
934 |
if (!str) |
| 912 |
return false; |
935 |
return false; |
| 913 |
RootedValue value(cx, StringValue(str)); |
936 |
RootedValue value(cx, StringValue(str)); |
|
Lines 916-981
ScriptedProxyHandler::set(JSContext *cx,
|
Link Here
|
|---|
|
| 916 |
if (!GetDerivedTrap(cx, handler, ATOM(set), fval.address())) |
939 |
if (!GetDerivedTrap(cx, handler, ATOM(set), fval.address())) |
| 917 |
return false; |
940 |
return false; |
| 918 |
if (!js_IsCallable(fval)) |
941 |
if (!js_IsCallable(fval)) |
| 919 |
return BaseProxyHandler::set(cx, proxy, receiver, id, strict, vp); |
942 |
return BaseProxyHandler::set(cx, proxy, receiver, id, strict, vp); |
| 920 |
return Trap(cx, handler, fval, 3, argv, value.address()); |
943 |
return Trap(cx, handler, fval, 3, argv, value.address()); |
| 921 |
} |
944 |
} |
| 922 |
|
945 |
|
| 923 |
bool |
946 |
bool |
| 924 |
ScriptedProxyHandler::keys(JSContext *cx, JSObject *proxy_, AutoIdVector &props) |
947 |
ScriptedIndirectProxyHandler::keys(JSContext *cx, JSObject *proxy_, |
|
|
948 |
AutoIdVector &props) |
| 925 |
{ |
949 |
{ |
| 926 |
RootedObject proxy(cx, proxy_); |
950 |
RootedObject proxy(cx, proxy_); |
| 927 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
951 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 928 |
RootedValue value(cx); |
952 |
RootedValue value(cx); |
| 929 |
if (!GetDerivedTrap(cx, handler, ATOM(keys), value.address())) |
953 |
if (!GetDerivedTrap(cx, handler, ATOM(keys), value.address())) |
| 930 |
return false; |
954 |
return false; |
| 931 |
if (!js_IsCallable(value)) |
955 |
if (!js_IsCallable(value)) |
| 932 |
return BaseProxyHandler::keys(cx, proxy, props); |
956 |
return BaseProxyHandler::keys(cx, proxy, props); |
| 933 |
return Trap(cx, handler, value, 0, NULL, value.address()) && |
957 |
return Trap(cx, handler, value, 0, NULL, value.address()) && |
| 934 |
ArrayToIdVector(cx, value, props); |
958 |
ArrayToIdVector(cx, value, props); |
| 935 |
} |
959 |
} |
| 936 |
|
960 |
|
| 937 |
bool |
961 |
bool |
| 938 |
ScriptedProxyHandler::iterate(JSContext *cx, JSObject *proxy_, unsigned flags, Value *vp) |
962 |
ScriptedIndirectProxyHandler::iterate(JSContext *cx, JSObject *proxy_, |
|
|
963 |
unsigned flags, Value *vp) |
| 939 |
{ |
964 |
{ |
| 940 |
RootedObject proxy(cx, proxy_); |
965 |
RootedObject proxy(cx, proxy_); |
| 941 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
966 |
RootedObject handler(cx, GetProxyHandlerObject(cx, proxy)); |
| 942 |
RootedValue value(cx); |
967 |
RootedValue value(cx); |
| 943 |
if (!GetDerivedTrap(cx, handler, ATOM(iterate), value.address())) |
968 |
if (!GetDerivedTrap(cx, handler, ATOM(iterate), value.address())) |
| 944 |
return false; |
969 |
return false; |
| 945 |
if (!js_IsCallable(value)) |
970 |
if (!js_IsCallable(value)) |
| 946 |
return BaseProxyHandler::iterate(cx, proxy, flags, vp); |
971 |
return BaseProxyHandler::iterate(cx, proxy, flags, vp); |
| 947 |
return Trap(cx, handler, value, 0, NULL, vp) && |
972 |
return Trap(cx, handler, value, 0, NULL, vp) && |
| 948 |
ReturnedValueMustNotBePrimitive(cx, proxy, ATOM(iterate), *vp); |
973 |
ReturnedValueMustNotBePrimitive(cx, proxy, ATOM(iterate), *vp); |
| 949 |
} |
974 |
} |
| 950 |
|
975 |
|
| 951 |
JSType |
976 |
JSType |
| 952 |
ScriptedProxyHandler::typeOf(JSContext *cx, JSObject *proxy) |
977 |
ScriptedIndirectProxyHandler::typeOf(JSContext *cx, JSObject *proxy) |
| 953 |
{ |
978 |
{ |
| 954 |
/* |
979 |
/* |
| 955 |
* This function is only here to prevent a regression in |
980 |
* This function is only here to prevent a regression in |
| 956 |
* js1_8_5/extensions/scripted-proxies.js. It will be removed when the |
981 |
* js1_8_5/extensions/scripted-proxies.js. It will be removed when the |
| 957 |
* direct proxy refactor is complete. |
982 |
* direct proxy refactor is complete. |
| 958 |
*/ |
983 |
*/ |
| 959 |
return BaseProxyHandler::typeOf(cx, proxy); |
984 |
return BaseProxyHandler::typeOf(cx, proxy); |
| 960 |
} |
985 |
} |
| 961 |
|
986 |
|
| 962 |
bool |
987 |
bool |
| 963 |
ScriptedProxyHandler::defaultValue(JSContext *cx, JSObject *proxy, JSType hint, |
988 |
ScriptedIndirectProxyHandler::defaultValue(JSContext *cx, JSObject *proxy, |
| 964 |
Value *vp) |
989 |
JSType hint, Value *vp) |
| 965 |
{ |
990 |
{ |
| 966 |
/* |
991 |
/* |
| 967 |
* This function is only here to prevent bug 757063. It will be removed when |
992 |
* This function is only here to prevent bug 757063. It will be removed when |
| 968 |
* the direct proxy refactor is complete. |
993 |
* the direct proxy refactor is complete. |
| 969 |
*/ |
994 |
*/ |
| 970 |
return BaseProxyHandler::defaultValue(cx, proxy, hint, vp); |
995 |
return BaseProxyHandler::defaultValue(cx, proxy, hint, vp); |
| 971 |
} |
996 |
} |
| 972 |
|
997 |
|
| 973 |
ScriptedProxyHandler ScriptedProxyHandler::singleton; |
998 |
ScriptedIndirectProxyHandler ScriptedIndirectProxyHandler::singleton; |
|
|
999 |
|
| 1000 |
class ScriptedDirectProxyHandler : public DirectProxyHandler { |
| 1001 |
public: |
| 1002 |
ScriptedDirectProxyHandler(); |
| 1003 |
|
| 1004 |
virtual ~ScriptedDirectProxyHandler(); |
| 1005 |
|
| 1006 |
/* ES5 Harmony fundamental proxy traps. */ |
| 1007 |
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, |
| 1008 |
jsid id, bool set, |
| 1009 |
PropertyDescriptor *desc); |
| 1010 |
|
| 1011 |
static ScriptedDirectProxyHandler singleton; |
| 1012 |
}; |
| 1013 |
|
| 1014 |
const uint32_t HANDLER_EXTRA = 0; |
| 1015 |
|
| 1016 |
inline JSObject * |
| 1017 |
GetProxyHandlerObject(const JSObject *obj) |
| 1018 |
{ |
| 1019 |
JS_ASSERT(IsProxy(obj)); |
| 1020 |
return GetProxyExtra(obj, HANDLER_EXTRA).toObjectOrNull(); |
| 1021 |
} |
| 1022 |
|
| 1023 |
/* |
| 1024 |
* The information in a PropertyDescriptor is effectively a subset of that in |
| 1025 |
* the corresponding PropDesc. This causes some problems, as PropertyDescriptor |
| 1026 |
* misses some fields that are present in PropDesc, and which we need in order |
| 1027 |
* to implement standard conforming behavior. |
| 1028 |
* |
| 1029 |
* In particular, the specification assumes that properties are represented as |
| 1030 |
* JavaScript objects, which allows for the possibility of missing fields. To |
| 1031 |
* keep track of missing fields, PropDesc contains several bit flags, which are |
| 1032 |
* absent in PropertyDescriptor. |
| 1033 |
* |
| 1034 |
* |
| 1035 |
*/ |
| 1036 |
|
| 1037 |
static inline bool |
| 1038 |
IsDataDescriptor(PropertyDescriptor *desc) |
| 1039 |
{ |
| 1040 |
/* 1. If Desc is undefined, then return false */ |
| 1041 |
if (!desc->obj) |
| 1042 |
return false; |
| 1043 |
|
| 1044 |
/* |
| 1045 |
* 2. If both Desc.[[Value]] and Desc.[[Set]] are absent, then return false. |
| 1046 |
*/ |
| 1047 |
|
| 1048 |
/* |
| 1049 |
* We cannot distinguish here between a property descriptor in which the |
| 1050 |
* value field is absent, or one in which the value field is undefined, so |
| 1051 |
* instead, we define IsDataDescriptor as the logical negation of |
| 1052 |
* IsAccessorDescriptor. |
| 1053 |
*/ |
| 1054 |
if ((desc->attrs & JSPROP_GETTER) || (desc->attrs & JSPROP_SETTER)) |
| 1055 |
return false; |
| 1056 |
|
| 1057 |
/* 3. Return true. */ |
| 1058 |
return true; |
| 1059 |
} |
| 1060 |
|
| 1061 |
static inline bool |
| 1062 |
IsAccessorDescriptor(PropertyDescriptor *desc) |
| 1063 |
{ |
| 1064 |
/* 1. If Desc is undefined, then return false */ |
| 1065 |
if (!desc->obj) |
| 1066 |
return false; |
| 1067 |
|
| 1068 |
/* 2. If both Desc.[[Get] and Desc.[[Set]] are absent, then return false */ |
| 1069 |
if (!(desc->attrs & JSPROP_GETTER) && !(desc->attrs & JSPROP_SETTER)) |
| 1070 |
return false; |
| 1071 |
|
| 1072 |
/* 3. Return true. */ |
| 1073 |
return true; |
| 1074 |
} |
| 1075 |
|
| 1076 |
static inline bool |
| 1077 |
IsGenericDescriptor(PropertyDescriptor *desc) |
| 1078 |
{ |
| 1079 |
/* 1. If Desc is undefined, then return false */ |
| 1080 |
if (!desc->obj) |
| 1081 |
return false; |
| 1082 |
|
| 1083 |
/* |
| 1084 |
* 2. If IsAccessorDescriptor(Desc) and IsDataDescriptor(Desc) are both |
| 1085 |
* false, then return true. |
| 1086 |
*/ |
| 1087 |
|
| 1088 |
/* |
| 1089 |
* Due to the way we've devined IsDataDescriptor (see above), this test |
| 1090 |
* always fails, and IsGenericDescriptor always returns true. |
| 1091 |
*/ |
| 1092 |
if (!IsDataDescriptor(desc) && !IsAccessorDescriptor(desc)) |
| 1093 |
return false; |
| 1094 |
|
| 1095 |
/* 3. Return true. */ |
| 1096 |
return true; |
| 1097 |
} |
| 1098 |
|
| 1099 |
/* Aux 5. ValidateProperty(O, P, Desc) */ |
| 1100 |
static inline bool |
| 1101 |
ValidateProperty(JSContext *cx, JSObject *proxy, jsid id, |
| 1102 |
PropertyDescriptor *desc, bool *bp) |
| 1103 |
{ |
| 1104 |
/* |
| 1105 |
* 1. Let current be the result of calling the [[GetOwnProperty]] internal |
| 1106 |
* method of O with property name P. |
| 1107 |
*/ |
| 1108 |
AutoPropertyDescriptorRooter current(cx); |
| 1109 |
if (!GetOwnPropertyDescriptor(cx, proxy, id, 0, ¤t)) |
| 1110 |
return false; |
| 1111 |
|
| 1112 |
/* |
| 1113 |
* 2. Let extensible be the value of the [[Extensible]] internal property of |
| 1114 |
* O. |
| 1115 |
*/ |
| 1116 |
bool extensible = proxy->isExtensible(); |
| 1117 |
|
| 1118 |
/* 3. If current is undefined and extensible is false, return false. */ |
| 1119 |
if (!current.obj && !extensible) { |
| 1120 |
*bp = false; |
| 1121 |
return true; |
| 1122 |
} |
| 1123 |
|
| 1124 |
/* 4. If current is undefined and extensible is true, return true. */ |
| 1125 |
if (!current.obj && extensible) { |
| 1126 |
*bp = true; |
| 1127 |
return true; |
| 1128 |
} |
| 1129 |
|
| 1130 |
/* 5. Return true, if every field in Desc is absent */ |
| 1131 |
|
| 1132 |
/* |
| 1133 |
* We cannot distinguish here between a property descriptor in which the |
| 1134 |
* value field is absent, or one in which the value field is undefined, so |
| 1135 |
* we are forced to ignore this step. |
| 1136 |
*/ |
| 1137 |
|
| 1138 |
/* |
| 1139 |
* 6. Return true if every field in Desc also occurs in current and the |
| 1140 |
* value of every field in Desc is the same value as the corresponding |
| 1141 |
* field in current when compared using the SameValue algorithm |
| 1142 |
*/ |
| 1143 |
if (desc->obj == current.obj && desc->attrs == current.attrs && |
| 1144 |
desc->getter == current.getter && desc->setter == current.setter) { |
| 1145 |
bool same; |
| 1146 |
if (!SameValue(cx, desc->value, current.value, &same)) |
| 1147 |
return false; |
| 1148 |
if (same) { |
| 1149 |
*bp = true; |
| 1150 |
return true; |
| 1151 |
} |
| 1152 |
} |
| 1153 |
|
| 1154 |
/* 7 If the [[Configurable]] field of current is false then */ |
| 1155 |
if (current.attrs & JSPROP_PERMANENT) { |
| 1156 |
/* a. Return false, if the [[Configurable]] field of Desc is true. */ |
| 1157 |
if (!(desc->attrs & JSPROP_PERMANENT)) { |
| 1158 |
*bp = false; |
| 1159 |
return true; |
| 1160 |
} |
| 1161 |
|
| 1162 |
/* |
| 1163 |
* b. Return false if the [[Enumerable]] field of Desc is present and |
| 1164 |
* [[Enumerable]] fields of current and Desc are the Boolean negation |
| 1165 |
* of each other. |
| 1166 |
*/ |
| 1167 |
if ((desc->attrs & JSPROP_ENUMERATE) != |
| 1168 |
(current.attrs & JSPROP_ENUMERATE)) { |
| 1169 |
*bp = false; |
| 1170 |
return true; |
| 1171 |
} |
| 1172 |
} |
| 1173 |
|
| 1174 |
/* 8. If IsGenericDescriptor(Desc) is true, return true */ |
| 1175 |
if (IsGenericDescriptor(desc)) { |
| 1176 |
*bp = true; |
| 1177 |
return true; |
| 1178 |
} |
| 1179 |
|
| 1180 |
/* |
| 1181 |
* 9. Else, if IsDataDescriptor(current) and IsDataDescriptor(desc) have |
| 1182 |
* different results, then |
| 1183 |
*/ |
| 1184 |
if ((IsDataDescriptor(desc) && !IsDataDescriptor(¤t)) || |
| 1185 |
(!IsDataDescriptor(desc) && IsDataDescriptor(¤t))) { |
| 1186 |
/* a. Return false, if the [[Configurable]] field of current is false. */ |
| 1187 |
if (current.attrs & JSPROP_PERMANENT) { |
| 1188 |
*bp = false; |
| 1189 |
return true; |
| 1190 |
} |
| 1191 |
|
| 1192 |
/* b. Return true */ |
| 1193 |
*bp = true; |
| 1194 |
return true; |
| 1195 |
} |
| 1196 |
|
| 1197 |
/* |
| 1198 |
* 10. Else, if IsDataDescriptor(current) and IsDataDescriptor(desc) are |
| 1199 |
* both true, |
| 1200 |
*/ |
| 1201 |
if (IsDataDescriptor(desc) && IsDataDescriptor(¤t)) { |
| 1202 |
/* a. If the [[Configurable]] field of current is false, then */ |
| 1203 |
if (current.attrs & JSPROP_PERMANENT) { |
| 1204 |
/* |
| 1205 |
* i. Return false, if the [[Writable] field of current is false, |
| 1206 |
* and the [[Writable]] field of Desc is true. |
| 1207 |
*/ |
| 1208 |
if (!(desc->attrs & JSPROP_READONLY) && |
| 1209 |
(current.attrs & JSPROP_READONLY)) { |
| 1210 |
*bp = true; |
| 1211 |
return true; |
| 1212 |
} |
| 1213 |
|
| 1214 |
/* ii. If the [[Writable]] field of current is false, then */ |
| 1215 |
if (current.attrs & JSPROP_READONLY) { |
| 1216 |
/* |
| 1217 |
* 1. Return false, if the [[Value]] field of desc is present |
| 1218 |
* and SameValue(Desc.[[Value]], current.[[Value]]) is |
| 1219 |
* false. |
| 1220 |
*/ |
| 1221 |
bool same; |
| 1222 |
if (!SameValue(cx, desc->value, current.value, &same)) |
| 1223 |
return false; |
| 1224 |
if (!same) { |
| 1225 |
*bp = false; |
| 1226 |
return true; |
| 1227 |
} |
| 1228 |
} |
| 1229 |
} |
| 1230 |
|
| 1231 |
/* b. Else, return true. */ |
| 1232 |
*bp = true; |
| 1233 |
return true; |
| 1234 |
} |
| 1235 |
|
| 1236 |
/* 12. Return true. */ |
| 1237 |
*bp = true; |
| 1238 |
return true; |
| 1239 |
} |
| 1240 |
|
| 1241 |
/* Aux. 6 IsSealed(O, P) */ |
| 1242 |
static inline bool |
| 1243 |
IsSealed(JSContext* cx, JSObject *obj, jsid id, bool *bp) |
| 1244 |
{ |
| 1245 |
/* 1. Let desc be the result of calling O.[[GetOwnProperty]](P) */ |
| 1246 |
AutoPropertyDescriptorRooter desc(cx); |
| 1247 |
if (!GetOwnPropertyDescriptor(cx, obj, id, 0, &desc)) |
| 1248 |
return false; |
| 1249 |
|
| 1250 |
/* 2. If desc is undefined, return false */ |
| 1251 |
if (!desc.obj) { |
| 1252 |
*bp = false; |
| 1253 |
return true; |
| 1254 |
} |
| 1255 |
|
| 1256 |
/* 3. Return the boolean negation of desc.[[Configurable]] */ |
| 1257 |
*bp = desc.attrs & JSPROP_PERMANENT; |
| 1258 |
return true; |
| 1259 |
} |
| 1260 |
|
| 1261 |
static int sScriptedDirectProxyHandlerFamily = 0; |
| 1262 |
|
| 1263 |
ScriptedDirectProxyHandler::ScriptedDirectProxyHandler() |
| 1264 |
: DirectProxyHandler(&sScriptedDirectProxyHandlerFamily) |
| 1265 |
{ |
| 1266 |
} |
| 1267 |
|
| 1268 |
ScriptedDirectProxyHandler::~ScriptedDirectProxyHandler() |
| 1269 |
{ |
| 1270 |
} |
| 1271 |
|
| 1272 |
bool |
| 1273 |
ScriptedDirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, |
| 1274 |
JSObject *proxy, jsid id, |
| 1275 |
bool set, |
| 1276 |
PropertyDescriptor *desc) |
| 1277 |
{ |
| 1278 |
/* 1. Let handler be the value of the [[Handler]] internal property of O. */ |
| 1279 |
JSObject *handler = GetProxyHandlerObject(proxy); |
| 1280 |
|
| 1281 |
/* 2. Let target be the value of the [[Target]] internal property of O. */ |
| 1282 |
JSObject *target = GetProxyTargetObject(proxy); |
| 1283 |
|
| 1284 |
/* |
| 1285 |
* 3. Let trap be the result of calling |
| 1286 |
* GetTrap(handler, "getOwnPropertyDescriptor") |
| 1287 |
*/ |
| 1288 |
AutoValueRooter fval(cx); |
| 1289 |
if (!GetTrap(cx, handler, ATOM(getOwnPropertyDescriptor), fval.addr())) |
| 1290 |
return false; |
| 1291 |
|
| 1292 |
/* 4. If trap is undefined */ |
| 1293 |
if (fval.value().isUndefined()) { |
| 1294 |
/* |
| 1295 |
* a. Return the result of calling the built-in function |
| 1296 |
* Reflect.getOwnPropertyDescriptor(target, P) |
| 1297 |
*/ |
| 1298 |
return DirectProxyHandler::getOwnPropertyDescriptor(cx, proxy, id, set, |
| 1299 |
desc); |
| 1300 |
} |
| 1301 |
|
| 1302 |
/* |
| 1303 |
* 5. Let trapResult be the result of calling the [[Call] internal method of |
| 1304 |
* trap providing handler as the this value, target as the first agument and |
| 1305 |
* P as the second argument. |
| 1306 |
*/ |
| 1307 |
JSString *name = ToString(cx, IdToValue(id)); |
| 1308 |
if (!name) |
| 1309 |
return false; |
| 1310 |
Value argv[] = { |
| 1311 |
ObjectValue(*target), |
| 1312 |
StringValue(name) |
| 1313 |
}; |
| 1314 |
AutoValueRooter rval(cx); |
| 1315 |
if (!Invoke(cx, ObjectOrNullValue(handler), fval.value(), 2, argv, rval.addr())) |
| 1316 |
return false; |
| 1317 |
|
| 1318 |
/* 6. Let desc be NormalizeAndCompletePropertyDescriptor(trapResult) */ |
| 1319 |
|
| 1320 |
/* |
| 1321 |
* Due to how PropertyDescriptors are represented, we can neither normalize |
| 1322 |
* or complete them, so we are forced to simply convert trapResult to a |
| 1323 |
* PropertyDescriptor. |
| 1324 |
*/ |
| 1325 |
if (!ParsePropertyDescriptorObject(cx, proxy, id, rval.value(), desc)) |
| 1326 |
return false; |
| 1327 |
|
| 1328 |
/* 7. If desc is undefined */ |
| 1329 |
if (!desc->obj) { |
| 1330 |
/* |
| 1331 |
* a. If IsSealed(target, P), throw a TypeError (cannot report a |
| 1332 |
* non-configurable property as non-existent) |
| 1333 |
*/ |
| 1334 |
bool sealed; |
| 1335 |
if (!IsSealed(cx, target, id, &sealed)) |
| 1336 |
return false; |
| 1337 |
if (sealed) { |
| 1338 |
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, |
| 1339 |
JSMSG_CANT_REPORT_NC_AS_NE); |
| 1340 |
return false; |
| 1341 |
} |
| 1342 |
|
| 1343 |
/* |
| 1344 |
* b. If the [[Extensible]] attribute of target is false and |
| 1345 |
* target.[[HasOwn]](P) is true then, |
| 1346 |
*/ |
| 1347 |
if (!target->isExtensible()) { |
| 1348 |
bool found; |
| 1349 |
if (!getOwnPropertyDescriptor(cx, proxy, id, false, desc)) |
| 1350 |
return false; |
| 1351 |
if (!desc->obj) |
| 1352 |
return false; |
| 1353 |
if (found) { |
| 1354 |
/* |
| 1355 |
* i. Throw a TypeError (cannot report existing own property as |
| 1356 |
* non-existent on a non-extensible object) |
| 1357 |
*/ |
| 1358 |
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, |
| 1359 |
JSMSG_CANT_REPORT_E_AS_NE); |
| 1360 |
return false; |
| 1361 |
} |
| 1362 |
} |
| 1363 |
} |
| 1364 |
|
| 1365 |
/* 8. Let isFixed be the result of calling target.[[HasOwn]].P */ |
| 1366 |
bool found; |
| 1367 |
if (!getOwnPropertyDescriptor(cx, proxy, id, false, desc)) |
| 1368 |
return false; |
| 1369 |
found = !!desc->obj; |
| 1370 |
|
| 1371 |
/* |
| 1372 |
* 9. If the [[Extensible]] attribute of target is false and isFixed is |
| 1373 |
* false then, |
| 1374 |
*/ |
| 1375 |
if (!target->isExtensible() && !found) { |
| 1376 |
/* |
| 1377 |
* a. Throw a TypeError (cannot report a new own property on a |
| 1378 |
* non-extensible object) |
| 1379 |
*/ |
| 1380 |
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, |
| 1381 |
JSMSG_CANT_REPORT_NEW); |
| 1382 |
return false; |
| 1383 |
} |
| 1384 |
|
| 1385 |
/* 10. If isFixed is true, */ |
| 1386 |
if (found) { |
| 1387 |
/* |
| 1388 |
* a. Let valid be the result of calling |
| 1389 |
* ValidateProperty(target, P, desc) |
| 1390 |
*/ |
| 1391 |
bool valid; |
| 1392 |
if (!ValidateProperty(cx, target, id, desc, &valid)) |
| 1393 |
return false; |
| 1394 |
|
| 1395 |
/* |
| 1396 |
* b. If valid is false, throw a TypeError (cannot report incompatible |
| 1397 |
* property descriptor) |
| 1398 |
*/ |
| 1399 |
if (!valid) { |
| 1400 |
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, |
| 1401 |
JSMSG_CANT_REPORT_INVALID); |
| 1402 |
return false; |
| 1403 |
} |
| 1404 |
} |
| 1405 |
|
| 1406 |
/* 11. If desc.[[Configurable]] is false and isFixed is false, */ |
| 1407 |
if (desc->attrs & JSPROP_PERMANENT && !found) { |
| 1408 |
/* |
| 1409 |
* a. Throw a TypeError (cannot report a non-configurable descriptor for |
| 1410 |
* a non-configurable descriptor for a non-existent property) |
| 1411 |
*/ |
| 1412 |
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, |
| 1413 |
JSMSG_CANT_REPORT_NE_AS_NC); |
| 1414 |
return false; |
| 1415 |
} |
| 1416 |
|
| 1417 |
/* 12. Return desc */ |
| 1418 |
return true; |
| 1419 |
} |
| 1420 |
|
| 1421 |
ScriptedDirectProxyHandler ScriptedDirectProxyHandler::singleton; |
| 974 |
|
1422 |
|
| 975 |
class AutoPendingProxyOperation { |
1423 |
class AutoPendingProxyOperation { |
| 976 |
JSRuntime *rt; |
1424 |
JSRuntime *rt; |
| 977 |
PendingProxyOperation op; |
1425 |
PendingProxyOperation op; |
| 978 |
public: |
1426 |
public: |
| 979 |
AutoPendingProxyOperation(JSContext *cx, JSObject *proxy) |
1427 |
AutoPendingProxyOperation(JSContext *cx, JSObject *proxy) |
| 980 |
: rt(cx->runtime), op(cx, proxy) |
1428 |
: rt(cx->runtime), op(cx, proxy) |
| 981 |
{ |
1429 |
{ |
|
Lines 1778-1794
proxy_create(JSContext *cx, unsigned arg
|
Link Here
|
|---|
|
| 1778 |
proto = &vp[3].toObject(); |
2226 |
proto = &vp[3].toObject(); |
| 1779 |
parent = proto->getParent(); |
2227 |
parent = proto->getParent(); |
| 1780 |
} else { |
2228 |
} else { |
| 1781 |
JS_ASSERT(IsFunctionObject(vp[0])); |
2229 |
JS_ASSERT(IsFunctionObject(vp[0])); |
| 1782 |
proto = NULL; |
2230 |
proto = NULL; |
| 1783 |
} |
2231 |
} |
| 1784 |
if (!parent) |
2232 |
if (!parent) |
| 1785 |
parent = vp[0].toObject().getParent(); |
2233 |
parent = vp[0].toObject().getParent(); |
| 1786 |
JSObject *proxy = NewProxyObject(cx, &ScriptedProxyHandler::singleton, ObjectValue(*handler), |
2234 |
JSObject *proxy = NewProxyObject(cx, &ScriptedIndirectProxyHandler::singleton, ObjectValue(*handler), |
| 1787 |
proto, parent); |
2235 |
proto, parent); |
| 1788 |
if (!proxy) |
2236 |
if (!proxy) |
| 1789 |
return false; |
2237 |
return false; |
| 1790 |
|
2238 |
|
| 1791 |
vp->setObject(*proxy); |
2239 |
vp->setObject(*proxy); |
| 1792 |
return true; |
2240 |
return true; |
| 1793 |
} |
2241 |
} |
| 1794 |
|
2242 |
|
|
Lines 1815-1831
proxy_createFunction(JSContext *cx, unsi
|
Link Here
|
|---|
|
| 1815 |
return false; |
2263 |
return false; |
| 1816 |
JSObject *construct = NULL; |
2264 |
JSObject *construct = NULL; |
| 1817 |
if (argc > 2) { |
2265 |
if (argc > 2) { |
| 1818 |
construct = ValueToCallable(cx, &vp[4]); |
2266 |
construct = ValueToCallable(cx, &vp[4]); |
| 1819 |
if (!construct) |
2267 |
if (!construct) |
| 1820 |
return false; |
2268 |
return false; |
| 1821 |
} |
2269 |
} |
| 1822 |
|
2270 |
|
| 1823 |
JSObject *proxy = NewProxyObject(cx, &ScriptedProxyHandler::singleton, |
2271 |
JSObject *proxy = NewProxyObject(cx, &ScriptedIndirectProxyHandler::singleton, |
| 1824 |
ObjectValue(*handler), |
2272 |
ObjectValue(*handler), |
| 1825 |
proto, parent, call, construct); |
2273 |
proto, parent, call, construct); |
| 1826 |
if (!proxy) |
2274 |
if (!proxy) |
| 1827 |
return false; |
2275 |
return false; |
| 1828 |
|
2276 |
|
| 1829 |
vp->setObject(*proxy); |
2277 |
vp->setObject(*proxy); |
| 1830 |
return true; |
2278 |
return true; |
| 1831 |
} |
2279 |
} |