https://bugs.webkit.org/show_bug.cgi?id=75429
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Jan 2012 21:05:46 +0000 (21:05 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Jan 2012 21:05:46 +0000 (21:05 +0000)
ThrowTypeError should be a singleton object

Reviewed by Sam Weinig.

Source/JavaScriptCore:

Per section 13.2.3 of the spec.
We could change setAccessorDescriptor to be able to share the global
GetterSetter object, rather than storing the accessor functions and
creating a new GetterSetter in defineProperty - but this won't be a
small change to PropertyDescriptors (and would probably mean making
GetterSetter objects immutable?) - so I'll leave that for another
patch.

* JavaScriptCore.exp:
    - don't export setAccessorDescriptor
* runtime/Arguments.cpp:
(JSC::Arguments::createStrictModeCallerIfNecessary):
(JSC::Arguments::createStrictModeCalleeIfNecessary):
    - call throwTypeErrorGetterSetter instead of createTypeErrorFunction
* runtime/Error.cpp:
* runtime/Error.h:
    - remove createTypeErrorFunction
* runtime/JSFunction.cpp:
* runtime/JSFunction.h:
    - remove unused createDescriptorForThrowingProperty
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
(JSC::JSGlobalObject::visitChildren):
    - removed m_strictModeTypeErrorFunctionStructure.
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::internalFunctionStructure):
    - removed m_strictModeTypeErrorFunctionStructure.
* runtime/PropertyDescriptor.cpp:
(JSC::PropertyDescriptor::setAccessorDescriptor):
    - changed to take a GetterSetter
* runtime/PropertyDescriptor.h:
    - changed to take a GetterSetter

LayoutTests:

Per section 13.2.3 of the spec.

* fast/js/basic-strict-mode-expected.txt:
    - ThrowTypeError is a singleton, so cannot generate
      property-specific error messages.
* fast/js/script-tests/strict-throw-type-error.js: Added.
* fast/js/strict-throw-type-error-expected.txt: Added.
* fast/js/strict-throw-type-error.html: Added.
    - added test case that ThrowTypeError is a singleton

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@103958 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/js/basic-strict-mode-expected.txt
LayoutTests/fast/js/script-tests/strict-throw-type-error.js [new file with mode: 0644]
LayoutTests/fast/js/strict-throw-type-error-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/strict-throw-type-error.html [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.exp
Source/JavaScriptCore/runtime/Arguments.cpp
Source/JavaScriptCore/runtime/Error.cpp
Source/JavaScriptCore/runtime/Error.h
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSFunction.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
Source/JavaScriptCore/runtime/PropertyDescriptor.h

index a73e22b..7de768d 100644 (file)
@@ -1,3 +1,20 @@
+2012-01-03  Gavin Barraclough  <barraclough@apple.com>
+
+        https://bugs.webkit.org/show_bug.cgi?id=75429
+        ThrowTypeError should be a singleton object
+
+        Reviewed by Sam Weinig.
+
+        Per section 13.2.3 of the spec.
+
+        * fast/js/basic-strict-mode-expected.txt:
+            - ThrowTypeError is a singleton, so cannot generate
+              property-specific error messages.
+        * fast/js/script-tests/strict-throw-type-error.js: Added.
+        * fast/js/strict-throw-type-error-expected.txt: Added.
+        * fast/js/strict-throw-type-error.html: Added.
+            - added test case that ThrowTypeError is a singleton
+
 2011-12-22  Joseph Pecoraro  <pecoraro@apple.com>
 
         Implement Date and Time Input Value Sanitization
index 0c0f340..666cb70 100644 (file)
@@ -56,14 +56,14 @@ PASS (function (){var a; function f() {'use strict'; delete a;} })() threw excep
 PASS (function(){(function (){var a; function f() {'use strict'; delete a;} })()}) threw exception SyntaxError: Cannot delete unqualified property 'a' in strict mode.
 PASS (function (){'use strict'; with(1){};}) threw exception SyntaxError: 'with' statements are not valid in strict mode.
 PASS (function(){(function (){'use strict'; with(1){};})}) threw exception SyntaxError: 'with' statements are not valid in strict mode.
-PASS (function (){'use strict'; arguments.callee; })() threw exception TypeError: Unable to access callee of strict mode function.
-PASS (function (){'use strict'; arguments.caller; })() threw exception TypeError: Unable to access caller of strict mode function.
+PASS (function (){'use strict'; arguments.callee; })() threw exception TypeError: Type error.
+PASS (function (){'use strict'; arguments.caller; })() threw exception TypeError: Type error.
 PASS (function f(){'use strict'; f.arguments; })() threw exception TypeError: Type error.
 PASS (function f(){'use strict'; f.caller; })() threw exception TypeError: Type error.
 PASS (function f(){'use strict'; f.arguments=5; })() threw exception TypeError: Type error.
 PASS (function f(){'use strict'; f.caller=5; })() threw exception TypeError: Type error.
-PASS (function (arg){'use strict'; arguments.callee; })() threw exception TypeError: Unable to access callee of strict mode function.
-PASS (function (arg){'use strict'; arguments.caller; })() threw exception TypeError: Unable to access caller of strict mode function.
+PASS (function (arg){'use strict'; arguments.callee; })() threw exception TypeError: Type error.
+PASS (function (arg){'use strict'; arguments.caller; })() threw exception TypeError: Type error.
 PASS (function f(arg){'use strict'; f.arguments; })() threw exception TypeError: Type error.
 PASS (function f(arg){'use strict'; f.caller; })() threw exception TypeError: Type error.
 PASS (function f(arg){'use strict'; f.arguments=5; })() threw exception TypeError: Type error.
diff --git a/LayoutTests/fast/js/script-tests/strict-throw-type-error.js b/LayoutTests/fast/js/script-tests/strict-throw-type-error.js
new file mode 100644 (file)
index 0000000..734a690
--- /dev/null
@@ -0,0 +1,50 @@
+description("ThrowTypeError is a singleton object");
+
+function getter(object, name)
+{
+    Object.getOwnPropertyDescriptor(object, name).get;
+}
+
+function strictArgumentsFunction1()
+{
+    "use strict";
+    return arguments;
+}
+var strictArguments1 = strictArgumentsFunction1();
+var boundFunction1 = strictArgumentsFunction1.bind();
+var functionCaller1 = getter(strictArgumentsFunction1, "caller");
+var functionArguments1 = getter(strictArgumentsFunction1, "arguments");
+var argumentsCaller1 = getter(strictArguments1, "caller");
+var argumentsCallee1 = getter(strictArguments1, "callee");
+var boundCaller1 = getter(boundFunction1, "caller");
+var boundArguments1 = getter(boundFunction1, "arguments");
+
+function strictArgumentsFunction2()
+{
+    "use strict";
+    return arguments;
+}
+var strictArguments2 = strictArgumentsFunction2();
+var boundFunction2 = strictArgumentsFunction2.bind();
+var functionCaller2 = getter(strictArgumentsFunction2, "caller");
+var functionArguments2 = getter(strictArgumentsFunction2, "arguments");
+var argumentsCaller2 = getter(strictArguments2, "caller");
+var argumentsCallee2 = getter(strictArguments2, "callee");
+var boundCaller2 = getter(boundFunction2, "caller");
+var boundArguments2 = getter(boundFunction2, "arguments");
+
+shouldBeTrue('functionCaller1 === functionCaller2');
+
+shouldBeTrue('functionCaller1 === functionArguments1');
+shouldBeTrue('functionCaller1 === argumentsCaller1');
+shouldBeTrue('functionCaller1 === argumentsCallee1');
+shouldBeTrue('functionCaller1 === boundCaller1');
+shouldBeTrue('functionCaller1 === boundArguments1');
+
+shouldBeTrue('functionCaller2 === functionArguments2');
+shouldBeTrue('functionCaller2 === argumentsCaller2');
+shouldBeTrue('functionCaller2 === argumentsCallee2');
+shouldBeTrue('functionCaller2 === boundCaller2');
+shouldBeTrue('functionCaller2 === boundArguments2');
+
+successfullyParsed = true;
diff --git a/LayoutTests/fast/js/strict-throw-type-error-expected.txt b/LayoutTests/fast/js/strict-throw-type-error-expected.txt
new file mode 100644 (file)
index 0000000..3e4fc61
--- /dev/null
@@ -0,0 +1,20 @@
+ThrowTypeError is a singleton object
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS functionCaller1 === functionCaller2 is true
+PASS functionCaller1 === functionArguments1 is true
+PASS functionCaller1 === argumentsCaller1 is true
+PASS functionCaller1 === argumentsCallee1 is true
+PASS functionCaller1 === boundCaller1 is true
+PASS functionCaller1 === boundArguments1 is true
+PASS functionCaller2 === functionArguments2 is true
+PASS functionCaller2 === argumentsCaller2 is true
+PASS functionCaller2 === argumentsCallee2 is true
+PASS functionCaller2 === boundCaller2 is true
+PASS functionCaller2 === boundArguments2 is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/js/strict-throw-type-error.html b/LayoutTests/fast/js/strict-throw-type-error.html
new file mode 100644 (file)
index 0000000..15dbbcd
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/strict-throw-type-error.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>
index 68d5e17..15edef6 100644 (file)
@@ -1,3 +1,43 @@
+2012-01-03  Gavin Barraclough  <barraclough@apple.com>
+
+        https://bugs.webkit.org/show_bug.cgi?id=75429
+        ThrowTypeError should be a singleton object
+
+        Reviewed by Sam Weinig.
+
+        Per section 13.2.3 of the spec.
+        We could change setAccessorDescriptor to be able to share the global
+        GetterSetter object, rather than storing the accessor functions and
+        creating a new GetterSetter in defineProperty - but this won't be a
+        small change to PropertyDescriptors (and would probably mean making
+        GetterSetter objects immutable?) - so I'll leave that for another
+        patch.
+
+        * JavaScriptCore.exp:
+            - don't export setAccessorDescriptor
+        * runtime/Arguments.cpp:
+        (JSC::Arguments::createStrictModeCallerIfNecessary):
+        (JSC::Arguments::createStrictModeCalleeIfNecessary):
+            - call throwTypeErrorGetterSetter instead of createTypeErrorFunction
+        * runtime/Error.cpp:
+        * runtime/Error.h:
+            - remove createTypeErrorFunction
+        * runtime/JSFunction.cpp:
+        * runtime/JSFunction.h:
+            - remove unused createDescriptorForThrowingProperty
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::reset):
+        (JSC::JSGlobalObject::visitChildren):
+            - removed m_strictModeTypeErrorFunctionStructure.
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::internalFunctionStructure):
+            - removed m_strictModeTypeErrorFunctionStructure.
+        * runtime/PropertyDescriptor.cpp:
+        (JSC::PropertyDescriptor::setAccessorDescriptor):
+            - changed to take a GetterSetter
+        * runtime/PropertyDescriptor.h:
+            - changed to take a GetterSetter
+
 2012-01-02  Gavin Barraclough  <barraclough@apple.com>
 
         Check in fixes for jsc tests following bug #75455.
index 90aa42a..4c19711 100644 (file)
@@ -219,7 +219,6 @@ __ZN3JSC18PropertyDescriptor13setDescriptorENS_7JSValueEj
 __ZN3JSC18PropertyDescriptor13setEnumerableEb
 __ZN3JSC18PropertyDescriptor15setConfigurableEb
 __ZN3JSC18PropertyDescriptor17defaultAttributesE
-__ZN3JSC18PropertyDescriptor21setAccessorDescriptorENS_7JSValueES1_j
 __ZN3JSC18PropertyDescriptor9setGetterENS_7JSValueE
 __ZN3JSC18PropertyDescriptor9setSetterENS_7JSValueE
 __ZN3JSC19SourceProviderCache5clearEv
index 2ea1167..e1f3380 100644 (file)
@@ -104,8 +104,7 @@ void Arguments::createStrictModeCallerIfNecessary(ExecState* exec)
 
     d->overrodeCaller = true;
     PropertyDescriptor descriptor;
-    JSValue thrower = createTypeErrorFunction(exec, "Unable to access caller of strict mode function");
-    descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
+    descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Getter | Setter);
     methodTable()->defineOwnProperty(this, exec, exec->propertyNames().caller, descriptor, false);
 }
 
@@ -116,8 +115,7 @@ void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec)
     
     d->overrodeCallee = true;
     PropertyDescriptor descriptor;
-    JSValue thrower = createTypeErrorFunction(exec, "Unable to access callee of strict mode function");
-    descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
+    descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Getter | Setter);
     methodTable()->defineOwnProperty(this, exec, exec->propertyNames().callee, descriptor, false);
 }
 
index a5373d5..24f5da4 100644 (file)
@@ -175,10 +175,4 @@ void StrictModeTypeErrorFunction::destroy(JSCell* cell)
     jsCast<StrictModeTypeErrorFunction*>(cell)->StrictModeTypeErrorFunction::~StrictModeTypeErrorFunction();
 }
 
-JSValue createTypeErrorFunction(ExecState* exec, const UString& message)
-{
-    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
-    return StrictModeTypeErrorFunction::create(exec, globalObject, globalObject->strictModeTypeErrorFunctionStructure(), message);
-}
-
 } // namespace JSC
index 0bbc540..b807d4a 100644 (file)
@@ -72,8 +72,6 @@ namespace JSC {
     inline EncodedJSValue throwVMError(ExecState* exec, JSValue error) { return JSValue::encode(throwError(exec, error)); }
     inline EncodedJSValue throwVMTypeError(ExecState* exec) { return JSValue::encode(throwTypeError(exec)); }
 
-    JSValue createTypeErrorFunction(ExecState* exec, const UString& message);
-    
     class StrictModeTypeErrorFunction : public InternalFunction {
     private:
         StrictModeTypeErrorFunction(JSGlobalObject* globalObject, Structure* structure, const UString& message)
index 97ee59d..65470a5 100644 (file)
@@ -114,12 +114,6 @@ void JSFunction::destroy(JSCell* cell)
     thisObject->JSFunction::~JSFunction();
 }
 
-void createDescriptorForThrowingProperty(ExecState* exec, PropertyDescriptor& descriptor, const char* message)
-{
-    JSValue thrower = createTypeErrorFunction(exec, message);
-    descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
-}
-
 const UString& JSFunction::name(ExecState* exec)
 {
     return asString(getDirect(exec->globalData(), exec->globalData().propertyNames->name))->tryGetValue();
index f24455c..5118f8b 100644 (file)
@@ -42,8 +42,6 @@ namespace JSC {
 
     EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
 
-    void createDescriptorForThrowingProperty(ExecState*, PropertyDescriptor&, const char* message);
-
     class JSFunction : public JSNonFinalObject {
         friend class JIT;
         friend class DFG::SpeculativeJIT;
index c63ecf6..5ad53c2 100644 (file)
@@ -204,7 +204,6 @@ void JSGlobalObject::reset(JSValue prototype)
     m_boundFunctionStructure.set(exec->globalData(), this, JSBoundFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
     m_namedFunctionStructure.set(exec->globalData(), this, Structure::addPropertyTransition(exec->globalData(), m_functionStructure.get(), exec->globalData().propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset));
     m_internalFunctionStructure.set(exec->globalData(), this, InternalFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
-    m_strictModeTypeErrorFunctionStructure.set(exec->globalData(), this, StrictModeTypeErrorFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
     JSFunction* callFunction = 0;
     JSFunction* applyFunction = 0;
     m_functionPrototype->addFunctionProperties(exec, this, &callFunction, &applyFunction);
@@ -384,7 +383,6 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitIfNeeded(visitor, &thisObject->m_regExpStructure);
     visitIfNeeded(visitor, &thisObject->m_stringObjectStructure);
     visitIfNeeded(visitor, &thisObject->m_internalFunctionStructure);
-    visitIfNeeded(visitor, &thisObject->m_strictModeTypeErrorFunctionStructure);
 
     if (thisObject->m_registerArray) {
         // Outside the execution of global code, when our variables are torn off,
index e0ce19d..176c543 100644 (file)
@@ -132,7 +132,6 @@ namespace JSC {
         WriteBarrier<Structure> m_regExpStructure;
         WriteBarrier<Structure> m_stringObjectStructure;
         WriteBarrier<Structure> m_internalFunctionStructure;
-        WriteBarrier<Structure> m_strictModeTypeErrorFunctionStructure;
 
         Debugger* m_debugger;
 
@@ -262,7 +261,6 @@ namespace JSC {
         size_t functionNameOffset() const { return m_functionNameOffset; }
         Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); }
         Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); }
-        Structure* strictModeTypeErrorFunctionStructure() const { return m_strictModeTypeErrorFunctionStructure.get(); }
         Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); }
         Structure* regExpStructure() const { return m_regExpStructure.get(); }
         Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); }
index cf85dc7..9d62dfc 100644 (file)
@@ -108,13 +108,15 @@ void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
     }
 }
 
-void PropertyDescriptor::setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes)
+void PropertyDescriptor::setAccessorDescriptor(GetterSetter* accessor, unsigned attributes)
 {
     ASSERT(attributes & (Getter | Setter));
-    ASSERT(getter || setter);
+    ASSERT(accessor->getter() || accessor->setter());
+    ASSERT(!accessor->getter() == !(attributes & Getter));
+    ASSERT(!accessor->setter() == !(attributes & Setter));
     m_attributes = attributes;
-    m_getter = getter;
-    m_setter = setter;
+    m_getter = accessor->getter();
+    m_setter = accessor->setter();
     m_attributes &= ~ReadOnly;
     m_seenAttributes = EnumerablePresent | ConfigurablePresent;
 }
index ff9f160..bebf5e8 100644 (file)
@@ -29,6 +29,8 @@
 #include "JSValue.h"
 
 namespace JSC {
+    class GetterSetter;
+
     class PropertyDescriptor {
     public:
         PropertyDescriptor()
@@ -48,7 +50,7 @@ namespace JSC {
         JSValue setter() const;
         void setUndefined();
         void setDescriptor(JSValue value, unsigned attributes);
-        void setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes);
+        void setAccessorDescriptor(GetterSetter* accessor, unsigned attributes);
         void setWritable(bool);
         void setEnumerable(bool);
         void setConfigurable(bool);