Attachment #640061: Part 7 - Implement getOwnPropertyDescriptorTrap for bug #703537

View | Details | Raw Unified | Return to bug 703537
Collapse All | Expand All

(-)a/js/src/js.msg (+5 lines)
Line     Link Here 
 Lines 347-354   MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LI Link Here 
347
MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND, 294, 0, JSEXN_TYPEERR, "variable not found in environment")
347
MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND, 294, 0, JSEXN_TYPEERR, "variable not found in environment")
348
MSG_DEF(JSMSG_PARAMETER_AFTER_REST,   295, 0, JSEXN_SYNTAXERR, "parameter after rest parameter")
348
MSG_DEF(JSMSG_PARAMETER_AFTER_REST,   295, 0, JSEXN_SYNTAXERR, "parameter after rest parameter")
349
MSG_DEF(JSMSG_NO_REST_NAME,           296, 0, JSEXN_SYNTAXERR, "no parameter name after ...")
349
MSG_DEF(JSMSG_NO_REST_NAME,           296, 0, JSEXN_SYNTAXERR, "no parameter name after ...")
350
MSG_DEF(JSMSG_ARGUMENTS_AND_REST,     297, 0, JSEXN_SYNTAXERR, "'arguments' object may not be used in conjunction with a rest parameter")
350
MSG_DEF(JSMSG_ARGUMENTS_AND_REST,     297, 0, JSEXN_SYNTAXERR, "'arguments' object may not be used in conjunction with a rest parameter")
351
MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 298, 0, JSEXN_ERR, "the 'arguments' property of a function with a rest parameter may not be used")
351
MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 298, 0, JSEXN_ERR, "the 'arguments' property of a function with a rest parameter may not be used")
352
MSG_DEF(JSMSG_REST_WITH_DEFAULT,      299, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
352
MSG_DEF(JSMSG_REST_WITH_DEFAULT,      299, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
353
MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 300, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default")
353
MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 300, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default")
354
MSG_DEF(JSMSG_YIELD_IN_DEFAULT,       301, 0, JSEXN_SYNTAXERR, "yield in default expression")
354
MSG_DEF(JSMSG_YIELD_IN_DEFAULT,       301, 0, JSEXN_SYNTAXERR, "yield in default expression")
355
MSG_DEF(JSMSG_CANT_REPORT_NC_AS_NE,   302, 0, JSEXN_TYPEERR, "can't report a non-configurable own property as non-existent")
356
MSG_DEF(JSMSG_CANT_REPORT_E_AS_NE,    303, 0, JSEXN_TYPEERR, "can't report an existing own property as non-existent on a non-extensible object")
357
MSG_DEF(JSMSG_CANT_REPORT_NEW,        304, 0, JSEXN_TYPEERR, "can't report a new property on a non-extensible object")
358
MSG_DEF(JSMSG_CANT_REPORT_INVALID,    305, 0, JSEXN_TYPEERR, "can't report an incompatible property descriptor")
359
MSG_DEF(JSMSG_CANT_REPORT_NE_AS_NC,   306, 0, JSEXN_TYPEERR, "can't report a non-existent property as non-configurable")
(-)a/js/src/jsproxy.cpp (-31 / +479 lines)
Line     Link Here 
 Lines 361-377   bool Link Here 
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, &current))
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(&current)) ||
1185
        (!IsDataDescriptor(desc) && IsDataDescriptor(&current))) {
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(&current)) {
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
}

Return to bug 703537