Skip to content
Permalink
Browse files
[Unforgeable] operations should not be writable as per Web IDL
https://bugs.webkit.org/show_bug.cgi?id=154396
<rdar://problem/24721063>

Reviewed by Ryosuke Niwa.

LayoutTests/imported/w3c:

Rebaseline now that more checks are passing.

* web-platform-tests/html/dom/interfaces-expected.txt:

Source/WebCore:

[Unforgeable] operations should not be writable as per the Web IDL specification:
http://heycam.github.io/webidl/#es-operations

They were currently non-configurable in WebKit but still writable.

No new tests, already covered by existing test.

* bindings/scripts/CodeGeneratorJS.pm:
Mark [Unforgeable] operations as ReadOnly.

* bindings/scripts/test/GObject/WebKitDOMTestObj.cpp:
* bindings/scripts/test/GObject/WebKitDOMTestObj.h:
* bindings/scripts/test/JS/JSTestObj.cpp:
* bindings/scripts/test/ObjC/DOMTestObj.h:
* bindings/scripts/test/ObjC/DOMTestObj.mm:
* bindings/scripts/test/TestObj.idl:
Add bindings test coverage for [Unforgeable].

Canonical link: https://commits.webkit.org/172524@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@196770 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
cdumez committed Feb 18, 2016
1 parent 2f006ee commit 62f0f8b46bca2e9c5173c4d4e56abca59461584b
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 16 deletions.
@@ -1,3 +1,15 @@
2016-02-18 Chris Dumez <cdumez@apple.com>

[Unforgeable] operations should not be writable as per Web IDL
https://bugs.webkit.org/show_bug.cgi?id=154396
<rdar://problem/24721063>

Reviewed by Ryosuke Niwa.

Rebaseline now that more checks are passing.

* web-platform-tests/html/dom/interfaces-expected.txt:

2016-02-18 Chris Dumez <cdumez@apple.com>

Fix behavior of reflecting unsigned long IDL attributes that are limited to only non-negative numbers greater than zero
@@ -4146,11 +4146,11 @@ PASS Location interface: window.location must have own property "port"
PASS Location interface: window.location must have own property "pathname"
PASS Location interface: window.location must have own property "search"
PASS Location interface: window.location must have own property "hash"
FAIL Location interface: window.location must have own property "assign" assert_equals: property should be writable if and only if not unforgeable expected false but got true
PASS Location interface: window.location must have own property "assign"
PASS Location interface: calling assign(USVString) on window.location with too few arguments must throw TypeError
FAIL Location interface: window.location must have own property "replace" assert_equals: property should be writable if and only if not unforgeable expected false but got true
PASS Location interface: window.location must have own property "replace"
PASS Location interface: calling replace(USVString) on window.location with too few arguments must throw TypeError
FAIL Location interface: window.location must have own property "reload" assert_equals: property should be writable if and only if not unforgeable expected false but got true
PASS Location interface: window.location must have own property "reload"
PASS Location interface: window.location must have own property "ancestorOrigins"
PASS PopStateEvent interface: existence and properties of interface object
PASS PopStateEvent interface object length
@@ -1,3 +1,29 @@
2016-02-18 Chris Dumez <cdumez@apple.com>

[Unforgeable] operations should not be writable as per Web IDL
https://bugs.webkit.org/show_bug.cgi?id=154396
<rdar://problem/24721063>

Reviewed by Ryosuke Niwa.

[Unforgeable] operations should not be writable as per the Web IDL specification:
http://heycam.github.io/webidl/#es-operations

They were currently non-configurable in WebKit but still writable.

No new tests, already covered by existing test.

* bindings/scripts/CodeGeneratorJS.pm:
Mark [Unforgeable] operations as ReadOnly.

* bindings/scripts/test/GObject/WebKitDOMTestObj.cpp:
* bindings/scripts/test/GObject/WebKitDOMTestObj.h:
* bindings/scripts/test/JS/JSTestObj.cpp:
* bindings/scripts/test/ObjC/DOMTestObj.h:
* bindings/scripts/test/ObjC/DOMTestObj.mm:
* bindings/scripts/test/TestObj.idl:
Add bindings test coverage for [Unforgeable].

2016-02-18 Chris Dumez <cdumez@apple.com>

Fix behavior of reflecting unsigned long IDL attributes that are limited to only non-negative numbers greater than zero
@@ -699,7 +699,7 @@ sub AttributeShouldBeOnInstance

# [Unforgeable] attributes should be on the instance.
# https://heycam.github.io/webidl/#Unforgeable
return 1 if $attribute->signature->extendedAttributes->{"Unforgeable"} || $interface->extendedAttributes->{"Unforgeable"};
return 1 if IsUnforgeable($interface, $attribute);

# It becomes hard to reason about attributes that require security checks if we push
# them down the prototype chain, so before we do these we'll need to carefully consider
@@ -731,7 +731,7 @@ sub OperationShouldBeOnInstance

# [Unforgeable] operations should be on the instance.
# https://heycam.github.io/webidl/#Unforgeable
return 1 if $function->signature->extendedAttributes->{"Unforgeable"} || $interface->extendedAttributes->{"Unforgeable"};
return 1 if IsUnforgeable($interface, $function);

return 0;
}
@@ -1397,8 +1397,7 @@ sub GeneratePropertiesHashTable
push(@$hashKeys, $name);

my @specials = ();
push(@specials, "DontDelete") if $attribute->signature->extendedAttributes->{"Unforgeable"}
|| $interface->extendedAttributes->{"Unforgeable"};
push(@specials, "DontDelete") if IsUnforgeable($interface, $attribute);

# As per Web IDL specification, constructor properties on the ECMAScript global object should not be enumerable.
my $is_global_constructor = $attribute->signature->type =~ /Constructor$/;
@@ -5072,14 +5071,21 @@ sub HeaderNeedsPrototypeDeclaration
return IsDOMGlobalObject($interface) || $interface->extendedAttributes->{"JSCustomNamedGetterOnPrototype"} || $interface->extendedAttributes->{"JSCustomDefineOwnPropertyOnPrototype"};
}

sub IsUnforgeable
{
my $interface = shift;
my $property = shift;

return $property->signature->extendedAttributes->{"Unforgeable"} || $interface->extendedAttributes->{"Unforgeable"};
}

sub ComputeFunctionSpecial
{
my $interface = shift;
my $function = shift;

my @specials = ();
push(@specials, "DontDelete") if $function->signature->extendedAttributes->{"Unforgeable"}
|| $interface->extendedAttributes->{"Unforgeable"};
push(@specials, ("DontDelete", "ReadOnly")) if IsUnforgeable($interface, $function);
push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"NotEnumerable"};
if (IsJSBuiltin($interface, $function)) {
push(@specials, "JSC::Builtin");
@@ -91,6 +91,7 @@ enum {
PROP_STRING_ATTR,
PROP_TEST_OBJ_ATTR,
PROP_LENIENT_TEST_OBJ_ATTR,
PROP_UNFORGEABLE_ATTR,
PROP_XML_OBJ_ATTR,
PROP_CREATE,
PROP_REFLECTED_STRING_ATTR,
@@ -303,6 +304,9 @@ static void webkit_dom_test_obj_get_property(GObject* object, guint propertyId,
case PROP_LENIENT_TEST_OBJ_ATTR:
g_value_set_object(value, webkit_dom_test_obj_get_lenient_test_obj_attr(self));
break;
case PROP_UNFORGEABLE_ATTR:
g_value_take_string(value, webkit_dom_test_obj_get_unforgeable_attr(self));
break;
case PROP_XML_OBJ_ATTR:
g_value_set_object(value, webkit_dom_test_obj_get_xml_obj_attr(self));
break;
@@ -606,6 +610,16 @@ static void webkit_dom_test_obj_class_init(WebKitDOMTestObjClass* requestClass)
WEBKIT_DOM_TYPE_TEST_OBJ,
WEBKIT_PARAM_READABLE));

g_object_class_install_property(
gobjectClass,
PROP_UNFORGEABLE_ATTR,
g_param_spec_string(
"unforgeable-attr",
"TestObj:unforgeable-attr",
"read-only gchar* TestObj:unforgeable-attr",
"",
WEBKIT_PARAM_READABLE));

g_object_class_install_property(
gobjectClass,
PROP_XML_OBJ_ATTR,
@@ -1212,6 +1226,15 @@ WebKitDOMTestObj* webkit_dom_test_obj_obj_method_with_args(WebKitDOMTestObj* sel
return WebKit::kit(gobjectResult.get());
}

glong webkit_dom_test_obj_unforgeable_method(WebKitDOMTestObj* self)
{
WebCore::JSMainThreadNullState state;
g_return_val_if_fail(WEBKIT_DOM_IS_TEST_OBJ(self), 0);
WebCore::TestObj* item = WebKit::core(self);
glong result = item->unforgeableMethod();
return result;
}

void webkit_dom_test_obj_method_with_enum_arg(WebKitDOMTestObj* self, WebKitDOMTestEnumType* enumArg)
{
WebCore::JSMainThreadNullState state;
@@ -1844,6 +1867,15 @@ void webkit_dom_test_obj_set_lenient_test_obj_attr(WebKitDOMTestObj* self, WebKi
item->setLenientTestObjAttr(convertedValue);
}

gchar* webkit_dom_test_obj_get_unforgeable_attr(WebKitDOMTestObj* self)
{
WebCore::JSMainThreadNullState state;
g_return_val_if_fail(WEBKIT_DOM_IS_TEST_OBJ(self), 0);
WebCore::TestObj* item = WebKit::core(self);
gchar* result = convertToUTF8String(item->unforgeableAttr());
return result;
}

WebKitDOMTestObj* webkit_dom_test_obj_get_xml_obj_attr(WebKitDOMTestObj* self)
{
WebCore::JSMainThreadNullState state;
@@ -235,6 +235,17 @@ webkit_dom_test_obj_obj_method(WebKitDOMTestObj* self);
WEBKIT_API WebKitDOMTestObj*
webkit_dom_test_obj_obj_method_with_args(WebKitDOMTestObj* self, glong longArg, const gchar* strArg, WebKitDOMTestObj* objArg);

/**
* webkit_dom_test_obj_unforgeable_method:
* @self: A #WebKitDOMTestObj
*
* Returns: A #glong
*
* Stability: Unstable
**/
WEBKIT_API glong
webkit_dom_test_obj_unforgeable_method(WebKitDOMTestObj* self);

/**
* webkit_dom_test_obj_method_with_enum_arg:
* @self: A #WebKitDOMTestObj
@@ -891,6 +902,17 @@ webkit_dom_test_obj_get_lenient_test_obj_attr(WebKitDOMTestObj* self);
WEBKIT_API void
webkit_dom_test_obj_set_lenient_test_obj_attr(WebKitDOMTestObj* self, WebKitDOMTestObj* value);

/**
* webkit_dom_test_obj_get_unforgeable_attr:
* @self: A #WebKitDOMTestObj
*
* Returns: A #gchar
*
* Stability: Unstable
**/
WEBKIT_API gchar*
webkit_dom_test_obj_get_unforgeable_attr(WebKitDOMTestObj* self);

/**
* webkit_dom_test_obj_get_xml_obj_attr:
* @self: A #WebKitDOMTestObj
@@ -97,6 +97,7 @@ JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionLongMethod(JSC::Exec
JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionLongMethodWithArgs(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionObjMethod(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionObjMethodWithArgs(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsTestObjInstanceFunctionUnforgeableMethod(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithSequenceArg(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodReturningSequence(JSC::ExecState*);
JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithEnumArg(JSC::ExecState*);
@@ -212,6 +213,7 @@ JSC::EncodedJSValue jsTestObjTestObjAttr(JSC::ExecState*, JSC::EncodedJSValue, J
void setJSTestObjTestObjAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
JSC::EncodedJSValue jsTestObjLenientTestObjAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
void setJSTestObjLenientTestObjAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
JSC::EncodedJSValue jsTestObjUnforgeableAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
JSC::EncodedJSValue jsTestObjXMLObjAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
void setJSTestObjXMLObjAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);
JSC::EncodedJSValue jsTestObjCreate(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
@@ -365,29 +367,30 @@ typedef JSDOMConstructor<JSTestObj> JSTestObjConstructor;
/* Hash table */

static const struct CompactHashIndex JSTestObjTableIndex[17] = {
{ 4, -1 },
{ -1, -1 },
{ 5, -1 },
{ -1, -1 },
{ 6, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ 3, -1 },
{ -1, -1 },
{ 4, -1 },
{ -1, -1 },
{ 1, -1 },
{ 2, -1 },
{ 0, 16 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ 2, -1 },
{ 3, -1 },
};


static const HashTableValue JSTestObjTableValues[] =
{
{ "TestSubObjEnabledBySetting", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjTestSubObjEnabledBySettingConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjTestSubObjEnabledBySettingConstructor) } },
{ "unforgeableAttr", DontDelete | ReadOnly | CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjUnforgeableAttr), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } },
#if ENABLE(Condition1)
{ "conditionalAttr4", DontEnum, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjConditionalAttr4Constructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSTestObjConditionalAttr4Constructor) } },
#else
@@ -404,9 +407,10 @@ static const HashTableValue JSTestObjTableValues[] =
{ 0, 0, NoIntrinsic, { 0, 0 } },
#endif
{ "contentDocument", ReadOnly | CustomAccessor, NoIntrinsic, { (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjContentDocument), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } },
{ "unforgeableMethod", DontDelete | ReadOnly | JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjInstanceFunctionUnforgeableMethod), (intptr_t) (0) } },
};

static const HashTable JSTestObjTable = { 5, 15, true, JSTestObjTableValues, JSTestObjTableIndex };
static const HashTable JSTestObjTable = { 7, 15, true, JSTestObjTableValues, JSTestObjTableIndex };
/* Hash table for constructor */

static const HashTableValue JSTestObjConstructorTableValues[] =
@@ -744,7 +748,7 @@ bool JSTestObj::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyN
{
auto* thisObject = jsCast<JSTestObj*>(object);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
if (getStaticValueSlot<JSTestObj, Base>(state, JSTestObjTable, thisObject, propertyName, slot))
if (getStaticPropertySlot<JSTestObj, Base>(state, JSTestObjTable, thisObject, propertyName, slot))
return true;
return false;
}
@@ -1008,6 +1012,21 @@ EncodedJSValue jsTestObjLenientTestObjAttr(ExecState* state, EncodedJSValue this
}


EncodedJSValue jsTestObjUnforgeableAttr(ExecState* state, EncodedJSValue thisValue, PropertyName)
{
UNUSED_PARAM(state);
UNUSED_PARAM(thisValue);
JSValue decodedThisValue = JSValue::decode(thisValue);
auto* castedThis = jsDynamicCast<JSTestObj*>(decodedThisValue);
if (UNLIKELY(!castedThis)) {
return throwGetterTypeError(*state, "TestObj", "unforgeableAttr");
}
auto& impl = castedThis->wrapped();
JSValue result = jsStringWithCache(state, impl.unforgeableAttr());
return JSValue::encode(result);
}


EncodedJSValue jsTestObjXMLObjAttr(ExecState* state, EncodedJSValue thisValue, PropertyName)
{
UNUSED_PARAM(state);
@@ -3190,6 +3209,18 @@ EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionObjMethodWithArgs(ExecSta
return JSValue::encode(result);
}

EncodedJSValue JSC_HOST_CALL jsTestObjInstanceFunctionUnforgeableMethod(ExecState* state)
{
JSValue thisValue = state->thisValue();
auto castedThis = jsDynamicCast<JSTestObj*>(thisValue);
if (UNLIKELY(!castedThis))
return throwThisTypeError(*state, "TestObj", "unforgeableMethod");
ASSERT_GC_OBJECT_INHERITS(castedThis, JSTestObj::info());
auto& impl = castedThis->wrapped();
JSValue result = jsNumber(impl.unforgeableMethod());
return JSValue::encode(result);
}

EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithSequenceArg(ExecState* state)
{
JSValue thisValue = state->thisValue();
@@ -74,6 +74,7 @@ WEBCORE_EXPORT @interface DOMTestObj : DOMObject
@property (copy) NSString *stringAttr;
@property (strong) DOMTestObj *testObjAttr;
@property (strong) DOMTestObj *lenientTestObjAttr;
@property (readonly, copy) NSString *unforgeableAttr;
@property (strong) DOMTestObj *XMLObjAttr;
@property BOOL create;
@property (copy) NSString *reflectedStringAttr;
@@ -140,6 +141,7 @@ WEBCORE_EXPORT @interface DOMTestObj : DOMObject
- (int)longMethodWithArgs:(int)longArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg;
- (DOMTestObj *)objMethod;
- (DOMTestObj *)objMethodWithArgs:(int)longArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg;
- (int)unforgeableMethod;
- (void)methodWithEnumArg:(DOMTestEnumType *)enumArg;
- (void)methodWithOptionalEnumArgAndDefaultValue:(DOMTestEnumType *)enumArg;
- (DOMTestObj *)methodThatRequiresAllArgsAndThrows:(NSString *)strArg objArg:(DOMTestObj *)objArg;
@@ -239,6 +239,12 @@ - (void)setLenientTestObjAttr:(DOMTestObj *)newLenientTestObjAttr
IMPL->setLenientTestObjAttr(core(newLenientTestObjAttr));
}

- (NSString *)unforgeableAttr
{
WebCore::JSMainThreadNullState state;
return IMPL->unforgeableAttr();
}

- (DOMTestObj *)XMLObjAttr
{
WebCore::JSMainThreadNullState state;
@@ -957,6 +963,12 @@ - (DOMTestObj *)objMethodWithArgs:(int)longArg strArg:(NSString *)strArg objArg:
return kit(WTF::getPtr(IMPL->objMethodWithArgs(longArg, strArg, core(objArg))));
}

- (int)unforgeableMethod
{
WebCore::JSMainThreadNullState state;
return IMPL->unforgeableMethod();
}

- (void)methodWithEnumArg:(DOMTestEnumType *)enumArg
{
WebCore::JSMainThreadNullState state;
@@ -58,6 +58,7 @@ enum _optional { "", "OptionalValue1", "OptionalValue2", "OptionalValue3" };
attribute DOMString stringAttr;
attribute TestObj testObjAttr;
[LenientThis] attribute TestObj lenientTestObjAttr;
[Unforgeable] readonly attribute DOMString unforgeableAttr;

// WK_ucfirst, WK_lcfirst exceptional cases.
attribute TestObj XMLObjAttr;
@@ -92,6 +93,7 @@ enum _optional { "", "OptionalValue1", "OptionalValue2", "OptionalValue3" };
long longMethodWithArgs(long longArg, DOMString strArg, TestObj objArg);
TestObj objMethod();
TestObj objMethodWithArgs(long longArg, DOMString strArg, TestObj objArg);
[Unforgeable] long unforgeableMethod();

void methodWithSequenceArg(sequence<ScriptProfile> sequenceArg);
sequence<ScriptProfile> methodReturningSequence(long longArg);

0 comments on commit 62f0f8b

Please sign in to comment.