Rewrite Function.bind as a builtin
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Apr 2014 18:01:54 +0000 (18:01 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Apr 2014 18:01:54 +0000 (18:01 +0000)
https://bugs.webkit.org/show_bug.cgi?id=131083

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

This change removes the existing function.bind implementation
entirely so JSBoundFunction is no more.

Instead we just return a regular JS closure with a few
private properties hanging off it that allow us to perform
the necessary bound function fakery.  While most of this is
simple, a couple of key changes:

- The parser and lexer now directly track whether they're
  parsing code for call or construct and convert the private
  name @IsConstructor into TRUETOK or FALSETOK as appropriate.
  This automatically gives us the ability to vary behaviour
  from within the builtin. It also leaves a lot of headroom
  for trivial future improvements.
- The instanceof operator now uses the prototypeForHasInstance
  private name, and we have a helper function to ensure that
  all objects that need to can update their magical 'prototype'
  property pair correctly.

* API/JSScriptRef.cpp:
(parseScript):
* JavaScriptCore.xcodeproj/project.pbxproj:
* builtins/BuiltinExecutables.cpp:
(JSC::BuiltinExecutables::createBuiltinExecutable):
* builtins/Function.prototype.js:
(bind.bindingFunction):
(bind.else.bindingFunction):
(bind):
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::generateFunctionCodeBlock):
* bytecompiler/NodesCodegen.cpp:
(JSC::InstanceOfNode::emitBytecode):
* interpreter/Interpreter.cpp:
* parser/Lexer.cpp:
(JSC::Lexer<T>::Lexer):
(JSC::Lexer<LChar>::parseIdentifier):
(JSC::Lexer<UChar>::parseIdentifier):
* parser/Lexer.h:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::parseInner):
* parser/Parser.h:
(JSC::parse):
* parser/ParserModes.h:
* runtime/CodeCache.cpp:
(JSC::CodeCache::getGlobalCodeBlock):
(JSC::CodeCache::getFunctionExecutableFromGlobalCode):
* runtime/CommonIdentifiers.h:
* runtime/Completion.cpp:
(JSC::checkSyntax):
* runtime/Executable.cpp:
(JSC::ProgramExecutable::checkSyntax):
* runtime/FunctionPrototype.cpp:
(JSC::FunctionPrototype::addFunctionProperties):
(JSC::functionProtoFuncBind): Deleted.
* runtime/JSBoundFunction.cpp: Removed.
* runtime/JSBoundFunction.h: Removed.
* runtime/JSFunction.cpp:
(JSC::RetrieveCallerFunctionFunctor::RetrieveCallerFunctionFunctor):
(JSC::RetrieveCallerFunctionFunctor::operator()):
(JSC::retrieveCallerFunction):
(JSC::JSFunction::getOwnPropertySlot):
(JSC::JSFunction::defineOwnProperty):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncSetTypeErrorAccessor):
* runtime/JSGlobalObjectFunctions.h:
* runtime/JSObject.h:
(JSC::JSObject::inlineGetOwnPropertySlot):

Source/WebCore:

Switch WebCore to use the helper functions when defining the
prototype properties on DOM constructors, and update bindings
tests accordingly.

* bindings/js/JSImageConstructor.cpp:
(WebCore::JSImageConstructor::finishCreation):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateConstructorHelperMethods):
* bindings/scripts/test/JS/JSTestActiveDOMObject.cpp:
(WebCore::JSTestActiveDOMObjectConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestCustomNamedGetter.cpp:
(WebCore::JSTestCustomNamedGetterConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestEventConstructor.cpp:
(WebCore::JSTestEventConstructorConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestEventTarget.cpp:
(WebCore::JSTestEventTargetConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestException.cpp:
(WebCore::JSTestExceptionConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp:
(WebCore::JSTestGenerateIsReachableConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestInterface.cpp:
(WebCore::JSTestInterfaceConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp:
(WebCore::JSTestMediaQueryListListenerConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestNamedConstructor.cpp:
(WebCore::JSTestNamedConstructorConstructor::finishCreation):
(WebCore::JSTestNamedConstructorNamedConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestNode.cpp:
(WebCore::JSTestNodeConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestObj.cpp:
(WebCore::JSTestObjConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp:
(WebCore::JSTestOverloadedConstructorsConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp:
(WebCore::JSTestSerializedScriptValueInterfaceConstructor::finishCreation):
* bindings/scripts/test/JS/JSTestTypedefs.cpp:
(WebCore::JSTestTypedefsConstructor::finishCreation):
* bindings/scripts/test/JS/JSattribute.cpp:
(WebCore::JSattributeConstructor::finishCreation):
* bindings/scripts/test/JS/JSreadonly.cpp:
(WebCore::JSreadonlyConstructor::finishCreation):

LayoutTests:

Testing.

* js/dom/function-bind-expected.txt:
* js/regress/function-bind-expected.txt: Added.
* js/regress/function-bind.html: Added.
* js/regress/script-tests/function-bind.js: Added.
(foo):

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

75 files changed:
LayoutTests/ChangeLog
LayoutTests/js/dom/function-bind-expected.txt
LayoutTests/js/regress/function-bind-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/function-bind.html [new file with mode: 0644]
LayoutTests/js/regress/script-tests/function-bind.js [new file with mode: 0644]
Source/JavaScriptCore/API/JSObjectRef.cpp
Source/JavaScriptCore/API/JSScriptRef.cpp
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/builtins/BuiltinExecutables.cpp
Source/JavaScriptCore/builtins/Function.prototype.js
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/parser/Lexer.cpp
Source/JavaScriptCore/parser/Lexer.h
Source/JavaScriptCore/parser/Nodes.h
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/parser/ParserModes.h
Source/JavaScriptCore/runtime/ArgumentsIteratorConstructor.cpp
Source/JavaScriptCore/runtime/ArrayConstructor.cpp
Source/JavaScriptCore/runtime/BooleanConstructor.cpp
Source/JavaScriptCore/runtime/CodeCache.cpp
Source/JavaScriptCore/runtime/CommonIdentifiers.h
Source/JavaScriptCore/runtime/Completion.cpp
Source/JavaScriptCore/runtime/DateConstructor.cpp
Source/JavaScriptCore/runtime/ErrorConstructor.cpp
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/FunctionConstructor.cpp
Source/JavaScriptCore/runtime/FunctionPrototype.cpp
Source/JavaScriptCore/runtime/JSArrayBufferConstructor.cpp
Source/JavaScriptCore/runtime/JSBoundFunction.cpp [deleted file]
Source/JavaScriptCore/runtime/JSBoundFunction.h [deleted file]
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp
Source/JavaScriptCore/runtime/MapConstructor.cpp
Source/JavaScriptCore/runtime/MapIteratorConstructor.cpp
Source/JavaScriptCore/runtime/NameConstructor.cpp
Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
Source/JavaScriptCore/runtime/NumberConstructor.cpp
Source/JavaScriptCore/runtime/ObjectConstructor.cpp
Source/JavaScriptCore/runtime/RegExpConstructor.cpp
Source/JavaScriptCore/runtime/SetConstructor.cpp
Source/JavaScriptCore/runtime/SetIteratorConstructor.cpp
Source/JavaScriptCore/runtime/StringConstructor.cpp
Source/JavaScriptCore/runtime/WeakMapConstructor.cpp
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSImageConstructor.cpp
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestCustomNamedGetter.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestEventConstructor.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestEventTarget.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestException.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestNamedConstructor.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestNode.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestTypedefs.cpp
Source/WebCore/bindings/scripts/test/JS/JSattribute.cpp
Source/WebCore/bindings/scripts/test/JS/JSreadonly.cpp

index 93cad18..960e79c 100644 (file)
@@ -1,3 +1,18 @@
+2014-04-08  Oliver Hunt  <oliver@apple.com>
+
+        Rewrite Function.bind as a builtin
+        https://bugs.webkit.org/show_bug.cgi?id=131083
+
+        Reviewed by Geoffrey Garen.
+
+        Testing.
+
+        * js/dom/function-bind-expected.txt:
+        * js/regress/function-bind-expected.txt: Added.
+        * js/regress/function-bind.html: Added.
+        * js/regress/script-tests/function-bind.js: Added.
+        (foo):
+
 2014-04-13  Youenn Fablet  <youenn.fablet@crf.canon.fr>
 
         [GStreamer] No CORS support for media elements
index b3186fb..d6b7a98 100644 (file)
@@ -3,7 +3,7 @@ Tests Function.bind.
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS new (decodeURI.bind())() threw exception TypeError: function is not a constructor (evaluating 'new (decodeURI.bind())()').
+PASS new (decodeURI.bind())() threw exception TypeError: function is not a constructor.
 PASS (new (String.bind())('foo')).toString() is 'foo'
 PASS result is "[object Window] -> x:1, y:2"
 PASS result is "'a' -> x:'b', y:1"
@@ -23,9 +23,9 @@ PASS h instanceof H is true
 PASS "prototype" in F is true
 PASS "prototype" in G is false
 PASS "prototype" in H is false
-PASS Function.bind.call(undefined) threw exception TypeError: Type error.
+PASS Function.bind.call(undefined) threw exception TypeError: Cannot bind non-function object..
 PASS abcAt(1) is "b"
-PASS new abcAt(1) threw exception TypeError: function is not a constructor (evaluating 'new abcAt(1)').
+PASS new abcAt(1) threw exception TypeError: function is not a constructor.
 PASS boundFunctionPrototypeAccessed is false
 PASS Function.bind.length is 1
 PASS successfullyParsed is true
diff --git a/LayoutTests/js/regress/function-bind-expected.txt b/LayoutTests/js/regress/function-bind-expected.txt
new file mode 100644 (file)
index 0000000..cd0d915
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/function-bind
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/function-bind.html b/LayoutTests/js/regress/function-bind.html
new file mode 100644 (file)
index 0000000..6d3d232
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/function-bind.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/script-tests/function-bind.js b/LayoutTests/js/regress/script-tests/function-bind.js
new file mode 100644 (file)
index 0000000..4f360b2
--- /dev/null
@@ -0,0 +1,28 @@
+function foo(a,b) {
+    return a ^ b + arguments.length;
+}
+
+var g0 = foo.bind({});
+var g1 = foo.bind({}, 1);
+var g2 = foo.bind({}, 1, 2);
+var g3 = foo.bind({}, 1, 2, 3);
+var start = new Date;
+
+var result = 0;
+for (var i = 0; i < 100000; ++i) {
+    result *= 3;
+    result += g0(i, result);
+    result += g1();
+    result += g1(i);
+    result += g1(i, result);
+    result += g2();
+    result += g2(i);
+    result += g2(i, result);
+    result += g3();
+    result += g3(i);
+    result += g3(i, result);
+    result |= 0;
+}
+print((new Date - start))
+if (result != 1596499010)
+    throw "Bad result: " + result;
index b67c40b..8c946e8 100644 (file)
@@ -127,6 +127,7 @@ JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObje
 
     JSCallbackConstructor* constructor = JSCallbackConstructor::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
     constructor->putDirect(exec->vm(), exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
+    constructor->putDirect(exec->vm(), exec->propertyNames().prototypeForHasInstancePrivateName, jsPrototype, DontEnum | DontDelete | ReadOnly);
     return toRef(constructor);
 }
 
index 1e872c7..97566b1 100644 (file)
@@ -68,7 +68,7 @@ private:
 
 static bool parseScript(VM* vm, const SourceCode& source, ParserError& error)
 {
-    return JSC::parse<JSC::ProgramNode>(vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error);
+    return JSC::parse<JSC::ProgramNode>(vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, JSNotFunctionKind, error);
 }
 
 extern "C" {
index 13f884a..ac1f3e3 100644 (file)
@@ -394,7 +394,6 @@ set(JavaScriptCore_SOURCES
     runtime/JSArrayBufferPrototype.cpp
     runtime/JSArrayBufferView.cpp
     runtime/JSArrayIterator.cpp
-    runtime/JSBoundFunction.cpp
     runtime/JSCJSValue.cpp
     runtime/JSCell.cpp
     runtime/JSConsole.cpp
index e18d1b6..a39369c 100644 (file)
@@ -1,3 +1,81 @@
+2014-04-08  Oliver Hunt  <oliver@apple.com>
+
+        Rewrite Function.bind as a builtin
+        https://bugs.webkit.org/show_bug.cgi?id=131083
+
+        Reviewed by Geoffrey Garen.
+
+        This change removes the existing function.bind implementation
+        entirely so JSBoundFunction is no more.
+
+        Instead we just return a regular JS closure with a few
+        private properties hanging off it that allow us to perform
+        the necessary bound function fakery.  While most of this is
+        simple, a couple of key changes:
+
+        - The parser and lexer now directly track whether they're
+          parsing code for call or construct and convert the private
+          name @IsConstructor into TRUETOK or FALSETOK as appropriate.
+          This automatically gives us the ability to vary behaviour
+          from within the builtin. It also leaves a lot of headroom
+          for trivial future improvements.
+        - The instanceof operator now uses the prototypeForHasInstance
+          private name, and we have a helper function to ensure that
+          all objects that need to can update their magical 'prototype'
+          property pair correctly.
+
+        * API/JSScriptRef.cpp:
+        (parseScript):
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * builtins/BuiltinExecutables.cpp:
+        (JSC::BuiltinExecutables::createBuiltinExecutable):
+        * builtins/Function.prototype.js:
+        (bind.bindingFunction):
+        (bind.else.bindingFunction):
+        (bind):
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::generateFunctionCodeBlock):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::InstanceOfNode::emitBytecode):
+        * interpreter/Interpreter.cpp:
+        * parser/Lexer.cpp:
+        (JSC::Lexer<T>::Lexer):
+        (JSC::Lexer<LChar>::parseIdentifier):
+        (JSC::Lexer<UChar>::parseIdentifier):
+        * parser/Lexer.h:
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::Parser):
+        (JSC::Parser<LexerType>::parseInner):
+        * parser/Parser.h:
+        (JSC::parse):
+        * parser/ParserModes.h:
+        * runtime/CodeCache.cpp:
+        (JSC::CodeCache::getGlobalCodeBlock):
+        (JSC::CodeCache::getFunctionExecutableFromGlobalCode):
+        * runtime/CommonIdentifiers.h:
+        * runtime/Completion.cpp:
+        (JSC::checkSyntax):
+        * runtime/Executable.cpp:
+        (JSC::ProgramExecutable::checkSyntax):
+        * runtime/FunctionPrototype.cpp:
+        (JSC::FunctionPrototype::addFunctionProperties):
+        (JSC::functionProtoFuncBind): Deleted.
+        * runtime/JSBoundFunction.cpp: Removed.
+        * runtime/JSBoundFunction.h: Removed.
+        * runtime/JSFunction.cpp:
+        (JSC::RetrieveCallerFunctionFunctor::RetrieveCallerFunctionFunctor):
+        (JSC::RetrieveCallerFunctionFunctor::operator()):
+        (JSC::retrieveCallerFunction):
+        (JSC::JSFunction::getOwnPropertySlot):
+        (JSC::JSFunction::defineOwnProperty):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::reset):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::globalFuncSetTypeErrorAccessor):
+        * runtime/JSGlobalObjectFunctions.h:
+        * runtime/JSObject.h:
+        (JSC::JSObject::inlineGetOwnPropertySlot):
+
 2014-04-12  Filip Pizlo  <fpizlo@apple.com>
 
         Math.fround() should be an intrinsic
index 2108f94..d666ab9 100644 (file)
     <ClCompile Include="..\runtime\JSArrayBufferConstructor.cpp" />
     <ClCompile Include="..\runtime\JSArrayBufferPrototype.cpp" />
     <ClCompile Include="..\runtime\JSArrayBufferView.cpp" />
-    <ClCompile Include="..\runtime\JSBoundFunction.cpp" />
     <ClCompile Include="..\runtime\JSCJSValue.cpp" />
     <ClCompile Include="..\runtime\JSCell.cpp" />
     <ClCompile Include="..\runtime\JSConsole.cpp" />
     <ClInclude Include="..\runtime\JSArrayBufferView.h" />
     <ClInclude Include="..\runtime\JSArrayBufferViewInlines.h" />
     <ClInclude Include="..\runtime\JSArrayIterator.h" />
-    <ClInclude Include="..\runtime\JSBoundFunction.h" />
     <ClInclude Include="..\runtime\JSCInlines.h" />
     <ClInclude Include="..\runtime\JSCJSValue.h" />
     <ClInclude Include="..\runtime\JSCJSValueInlines.h" />
index 1b681d4..30a9227 100644 (file)
     <ClCompile Include="..\runtime\JSArray.cpp">
       <Filter>runtime</Filter>
     </ClCompile>
-    <ClCompile Include="..\runtime\JSBoundFunction.cpp">
-      <Filter>runtime</Filter>
-    </ClCompile>
     <ClCompile Include="..\runtime\JSCell.cpp">
       <Filter>runtime</Filter>
     </ClCompile>
     <ClInclude Include="..\runtime\JSArray.h">
       <Filter>runtime</Filter>
     </ClInclude>
-    <ClInclude Include="..\runtime\JSBoundFunction.h">
-      <Filter>runtime</Filter>
-    </ClInclude>
     <ClInclude Include="..\runtime\JSCell.h">
       <Filter>runtime</Filter>
     </ClInclude>
index 2c3f17c..52917ff 100644 (file)
                86F3EEBD168CDE930077B92A /* ObjCCallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F3EEB9168CCF750077B92A /* ObjCCallbackFunction.h */; };
                86F3EEBE168CDE930077B92A /* ObjCCallbackFunction.mm in Sources */ = {isa = PBXBuildFile; fileRef = 86F3EEBA168CCF750077B92A /* ObjCCallbackFunction.mm */; };
                86F3EEBF168CDE930077B92A /* ObjcRuntimeExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F3EEB616855A5B0077B92A /* ObjcRuntimeExtras.h */; };
-               86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */; };
-               86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */; };
                90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */; };
                90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 90213E3C123A40C200D422F3 /* MemoryStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; };
                93052C340FB792190048FDC3 /* ParserArena.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93052C320FB792190048FDC3 /* ParserArena.cpp */; };
                86F75EFB151C062F007C9BA3 /* RegExpCachedResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpCachedResult.cpp; sourceTree = "<group>"; };
                86F75EFC151C062F007C9BA3 /* RegExpCachedResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpCachedResult.h; sourceTree = "<group>"; };
                86F75EFD151C062F007C9BA3 /* RegExpMatchesArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpMatchesArray.cpp; sourceTree = "<group>"; };
-               86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBoundFunction.cpp; sourceTree = "<group>"; };
-               86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBoundFunction.h; sourceTree = "<group>"; };
                90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryStatistics.cpp; sourceTree = "<group>"; };
                90213E3C123A40C200D422F3 /* MemoryStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryStatistics.h; sourceTree = "<group>"; };
                93052C320FB792190048FDC3 /* ParserArena.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParserArena.cpp; sourceTree = "<group>"; };
                                0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
                                A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
                                A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
-                               86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
-                               86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
                                BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
                                BC1167D80E19BCC9008066DD /* JSCell.h */,
                                0F97496F1687ADE200A4FF6A /* JSCellInlines.h */,
                                A7BDAECB17F4EA1400F6140C /* JSArrayIterator.h in Headers */,
                                BC18C4180E16F5CD00B34460 /* JSBase.h in Headers */,
                                140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */,
-                               86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */,
                                BC18C4190E16F5CD00B34460 /* JSCallbackConstructor.h in Headers */,
                                BC18C41A0E16F5CD00B34460 /* JSCallbackFunction.h in Headers */,
                                BC18C41B0E16F5CD00B34460 /* JSCallbackObject.h in Headers */,
                                0F2B66E817B6B5AB00A7AE3F /* JSArrayBufferView.cpp in Sources */,
                                A7BDAECA17F4EA1400F6140C /* JSArrayIterator.cpp in Sources */,
                                1421359B0A677F4F00A8195E /* JSBase.cpp in Sources */,
-                               86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */,
                                1440F8AF0A508D200005F061 /* JSCallbackConstructor.cpp in Sources */,
                                1440F8920A508B100005F061 /* JSCallbackFunction.cpp in Sources */,
                                14ABDF600A437FEF00ECCA01 /* JSCallbackObject.cpp in Sources */,
index 43e421c..d6c6244 100644 (file)
@@ -46,7 +46,7 @@ UnlinkedFunctionExecutable* BuiltinExecutables::createBuiltinExecutable(const So
 {
     JSTextPosition positionBeforeLastNewline;
     ParserError error;
-    RefPtr<ProgramNode> program = parse<ProgramNode>(&m_vm, source, 0, Identifier(), JSParseBuiltin, JSParseProgramCode, error, &positionBeforeLastNewline);
+    RefPtr<ProgramNode> program = parse<ProgramNode>(&m_vm, source, 0, Identifier(), JSParseBuiltin, JSParseProgramCode, JSNotFunctionKind, error, &positionBeforeLastNewline);
 
     if (!program) {
         dataLog("Fatal error compiling builtin function '", name.string(), "': ", error.m_message);
@@ -71,7 +71,7 @@ UnlinkedFunctionExecutable* BuiltinExecutables::createBuiltinExecutable(const So
     RELEASE_ASSERT(body);
     for (const auto& closedVariable : program->closedVariables()) {
         if (closedVariable == m_vm.propertyNames->arguments.impl())
-        continue;
+            continue;
         
         if (closedVariable == m_vm.propertyNames->undefinedKeyword.impl())
             continue;
index 2b7540b..a6fc28d 100644 (file)
@@ -32,3 +32,166 @@ function apply(thisValue, argumentValues) {
     "use strict";
     return this.@apply(thisValue, argumentValues);
 }
+
+function bind(thisValue /*, optional arguments */)
+{
+    "use strict";
+    var boundFunction = this;
+    if (typeof boundFunction !== "function")
+        throw new @TypeError("Cannot bind non-function object.");
+    var bindingFunction;
+    var oversizedCall = undefined;
+    if (arguments.length <= 1) {
+        bindingFunction = function () {
+            if (@IsConstructor)
+                return new boundFunction(...arguments);
+            return boundFunction.@apply(thisValue, arguments);
+        }
+    } else {
+        var length = arguments.length;
+        switch (length - 1 /* skip thisValue */) {
+        case 1: {
+            var boundParameter = arguments[1];
+            bindingFunction = function () {
+                var argumentLength = arguments.length;
+                if (!argumentLength) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter);
+                    return boundFunction.@call(thisValue, boundParameter);
+                }
+                if (argumentLength == 1) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter, arguments[0]);
+                    return boundFunction.@call(thisValue, boundParameter, arguments[0]);
+                }
+                if (argumentLength == 2) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter, arguments[0], arguments[1]);
+                    return boundFunction.@call(thisValue, boundParameter, arguments[0], arguments[1]);
+                }
+                if (argumentLength == 3) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter, arguments[0], arguments[1], arguments[2]);
+                    return boundFunction.@call(thisValue, boundParameter, arguments[0], arguments[1], arguments[2]);
+                }
+                var completeArguments = [boundParameter, ...arguments];
+                if (!oversizedCall) {
+                    oversizedCall = function (isConstruct, boundFunction, thisValue, completeArguments) {
+                        if (isConstruct)
+                            return new boundFunction(...completeArguments);
+                        return boundFunction.@apply(thisValue, completeArguments);
+                    }
+                }
+                return oversizedCall(@IsConstructor, boundFunction, thisValue, completeArguments);
+            }
+            break;
+        }
+        case 2: {
+            var boundParameter1 = arguments[1];
+            var boundParameter2 = arguments[2];
+            bindingFunction = function () {
+                if (!arguments.length) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter1, boundParameter2);
+                    return boundFunction.@call(thisValue, boundParameter1, boundParameter2);
+                }
+                if (arguments.length == 1) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter1, boundParameter2, arguments[0]);
+                    return boundFunction.@call(thisValue, boundParameter1, boundParameter2, arguments[0]);
+                }
+                if (arguments.length == 2) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter1, boundParameter2, arguments[0], arguments[1]);
+                    return boundFunction.@call(thisValue, boundParameter1, boundParameter2, arguments[0], arguments[1]);
+                }
+                if (arguments.length == 3) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter1, boundParameter2, arguments[0], arguments[1], arguments[2]);
+                    return boundFunction.@call(thisValue, boundParameter1, boundParameter2, arguments[0], arguments[1], arguments[2]);
+                }
+                var completeArguments = [boundParameter1, boundParameter2, ...arguments];
+                if (!oversizedCall) {
+                    oversizedCall = function (isConstruct, boundFunction, thisValue, completeArguments) {
+                        if (isConstruct)
+                            return new boundFunction(...completeArguments);
+                        return boundFunction.@apply(thisValue, completeArguments);
+                    }
+                }
+                return oversizedCall(@IsConstructor, boundFunction, thisValue, completeArguments);
+            }
+            break;
+        }
+        case 3: {
+            var boundParameter1 = arguments[1];
+            var boundParameter2 = arguments[2];
+            var boundParameter3 = arguments[3];
+            bindingFunction = function () {
+                if (!arguments.length) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter1, boundParameter2, boundParameter3);
+                    return boundFunction.@call(thisValue, boundParameter1, boundParameter2, boundParameter3);
+                }
+                if (arguments.length == 1) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter1, boundParameter2, boundParameter3, arguments[0]);
+                    return boundFunction.@call(thisValue, boundParameter1, boundParameter2, boundParameter3, arguments[0]);
+                }
+                if (arguments.length == 2) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter1, boundParameter2, boundParameter3, arguments[0], arguments[1]);
+                    return boundFunction.@call(thisValue, boundParameter1, boundParameter2, boundParameter3, arguments[0], arguments[1]);
+                }
+                if (arguments.length == 3) {
+                    if (@IsConstructor)
+                        return new boundFunction(boundParameter1, boundParameter2, boundParameter3, arguments[0], arguments[1], arguments[2]);
+                    return boundFunction.@call(thisValue, boundParameter1, boundParameter2, boundParameter3, arguments[0], arguments[1], arguments[2]);
+                }
+                var completeArguments = [boundParameter1, boundParameter2, boundParameter3, ...arguments];
+                if (!oversizedCall) {
+                    oversizedCall = function (isConstruct, boundFunction, thisValue, completeArguments) {
+                        if (isConstruct)
+                            return new boundFunction(...completeArguments);
+                        return boundFunction.@apply(thisValue, completeArguments);
+                    }
+                }
+                return oversizedCall(@IsConstructor, boundFunction, thisValue, completeArguments);
+            }
+            break;
+        }
+        default:
+            var boundParameters = [];
+            for (var i = 1; i < length; i++)
+                boundParameters[i - 1] = arguments[i];
+            
+            bindingFunction = function () {
+                if (!arguments.length) {
+                    if (@IsConstructor)
+                        return new boundFunction(...boundParameters);
+                    return boundFunction.@apply(thisValue, boundParameters);
+                }
+                
+                var completeArguments = [];
+                var localBoundParameters = boundParameters;
+                var boundLength = localBoundParameters.length;
+                for (var i = 0; i < boundLength; i++)
+                    completeArguments[i] = localBoundParameters[i];
+                for (var i = 0; i < arguments.length; i++)
+                    completeArguments[i + boundLength] = arguments[i];
+                if (@IsConstructor)
+                    return new boundFunction(...completeArguments);
+                else
+                    return boundFunction.@apply(thisValue, completeArguments);
+            }
+        }
+    }
+    bindingFunction.@boundFunctionName = this.name;
+    bindingFunction.@boundFunction = boundFunction.@boundFunction || boundFunction;
+    var boundLength = boundFunction.length - (arguments.length - 1);
+    if (boundLength < 0)
+        boundLength = 0;
+    bindingFunction.@boundFunctionLength = boundLength;
+    @SetTypeErrorAccessor(bindingFunction, "arguments");
+    @SetTypeErrorAccessor(bindingFunction, "caller");
+    return bindingFunction;
+}
index cdad4a2..4942f48 100644 (file)
@@ -51,7 +51,7 @@ const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock
 
 static UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(VM& vm, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, UnlinkedFunctionKind functionKind, ParserError& error)
 {
-    RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(&vm, source, executable->parameters(), executable->name(), executable->toStrictness(), JSParseFunctionCode, error);
+    RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(&vm, source, executable->parameters(), executable->name(), executable->toStrictness(), JSParseFunctionCode, kind == CodeForConstruct ? JSFunctionIsConstructorKind : JSFunctionIsFunctionKind, error);
 
     if (!body) {
         ASSERT(error.m_type != ParserError::ErrorNone);
index 050f7ea..d5ce516 100644 (file)
@@ -1285,7 +1285,7 @@ RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterI
     generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
 
     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
-    generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
+    generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototypeForHasInstancePrivateName);
 
     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
@@ -1696,7 +1696,14 @@ bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, Statement
 void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
-    
+    bool constantBranch = false;
+    if (m_condition->getBooleanConstant(constantBranch)) {
+        if (constantBranch)
+            generator.emitNode(dst, m_ifBlock);
+        else if (m_elseBlock)
+            generator.emitNode(dst, m_elseBlock);
+        return;
+    }
     RefPtr<Label> beforeThen = generator.newLabel();
     RefPtr<Label> beforeElse = generator.newLabel();
     RefPtr<Label> afterElse = generator.newLabel();
index 2d87e11..d291f60 100644 (file)
@@ -44,7 +44,6 @@
 #include "GetterSetter.h"
 #include "JSActivation.h"
 #include "JSArray.h"
-#include "JSBoundFunction.h"
 #include "JSNameScope.h"
 #include "JSNotAnObject.h"
 #include "JSPropertyNameIterator.h"
index c7fc50c..8cae0fe 100644 (file)
@@ -489,10 +489,11 @@ static const LChar singleCharacterEscapeValuesForASCII[128] = {
 };
 
 template <typename T>
-Lexer<T>::Lexer(VM* vm, JSParserStrictness strictness)
+Lexer<T>::Lexer(VM* vm, JSParserStrictness strictness, JSFunctionKind functionKind)
     : m_isReparsing(false)
     , m_vm(vm)
     , m_parsingBuiltinFunction(strictness == JSParseBuiltin)
+    , m_functionKind(functionKind)
 {
 }
 
@@ -819,8 +820,13 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<LChar>::p
                 ident = m_vm->propertyNames->getPrivateName(*ident);
             else if (*ident == m_vm->propertyNames->undefinedKeyword)
                 tokenData->ident = &m_vm->propertyNames->undefinedPrivateName;
+            
             if (!ident)
                 return INVALID_PRIVATE_NAME_ERRORTOK;
+            
+            if (*ident == m_vm->propertyNames->IsConstructorPrivateName)
+                return m_functionKind == JSFunctionIsConstructorKind ? TRUETOKEN : FALSETOKEN;
+            
         }
         tokenData->ident = ident;
     } else
@@ -896,6 +902,11 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p
                 ident = m_vm->propertyNames->getPrivateName(*ident);
             else if (*ident == m_vm->propertyNames->undefinedKeyword)
                 tokenData->ident = &m_vm->propertyNames->undefinedPrivateName;
+            if (m_functionKind == JSFunctionIsConstructorKind) {
+                if (*ident == m_vm->propertyNames->IsConstructorPrivateName)
+                    return TRUETOKEN;
+                return FALSETOKEN;
+            }
             if (!ident)
                 return INVALID_PRIVATE_NAME_ERRORTOK;
         }
index 07241ae..f5af77d 100644 (file)
@@ -71,7 +71,7 @@ class Lexer {
     WTF_MAKE_FAST_ALLOCATED;
 
 public:
-    Lexer(VM*, JSParserStrictness);
+    Lexer(VM*, JSParserStrictness, JSFunctionKind);
     ~Lexer();
 
     // Character manipulation functions.
@@ -238,6 +238,7 @@ private:
 
     VM* m_vm;
     bool m_parsingBuiltinFunction;
+    JSFunctionKind m_functionKind;
 };
 
 template <>
index 2500fb3..cdb263c 100644 (file)
@@ -164,6 +164,7 @@ namespace JSC {
         virtual bool isSubtract() const { return false; }
         virtual bool isBoolean() const { return false; }
         virtual bool isSpreadExpression() const { return false; }
+        virtual bool getBooleanConstant(bool&) const { return false; }
 
         virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, FallThroughMode);
 
@@ -213,6 +214,13 @@ namespace JSC {
         NullNode(const JSTokenLocation&);
 
     private:
+        
+        bool getBooleanConstant(bool& value) const override
+        {
+            value = false;
+            return true;
+        }
+        
         virtual bool isNull() const override { return true; }
         virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNull(); }
     };
@@ -221,8 +229,14 @@ namespace JSC {
     public:
         BooleanNode(const JSTokenLocation&, bool value);
         bool value() { return m_value; }
-
+        
     private:
+        bool getBooleanConstant(bool& value) const override
+        {
+            value = m_value;
+            return true;
+        }
+
         virtual bool isBoolean() const override { return true; }
         virtual JSValue jsValue(BytecodeGenerator&) const override { return jsBoolean(m_value); }
 
@@ -236,6 +250,11 @@ namespace JSC {
         void setValue(double value) { m_value = value; }
 
     private:
+        bool getBooleanConstant(bool& value) const override
+        {
+            value = (bool)m_value;
+            return true;
+        }
         virtual bool isNumber() const override { return true; }
         virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNumber(m_value); }
 
index 7dec9bf..9f0ced0 100644 (file)
@@ -192,7 +192,7 @@ void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B
 }
 
 template <typename LexerType>
-Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode)
+Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, JSFunctionKind functionKind)
     : m_vm(vm)
     , m_source(&source)
     , m_hasStackOverflow(false)
@@ -207,7 +207,7 @@ Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters*
     , m_sourceElements(0)
     , m_parsingBuiltin(strictness == JSParseBuiltin)
 {
-    m_lexer = adoptPtr(new LexerType(vm, strictness));
+    m_lexer = adoptPtr(new LexerType(vm, strictness, functionKind));
     m_arena = m_vm->parserArena.get();
     m_lexer->setCode(source, m_arena);
     m_token.m_location.line = source.firstLine();
@@ -283,7 +283,6 @@ String Parser<LexerType>::parseInner()
     
     Vector<RefPtr<StringImpl>> closedVariables;
     if (m_parsingBuiltin) {
-        RELEASE_ASSERT(!capturedVariables.size());
         IdentifierSet usedVariables;
         scope->getUsedVariables(usedVariables);
         for (const auto& variable : usedVariables) {
@@ -294,6 +293,16 @@ String Parser<LexerType>::parseInner()
                 continue;
             closedVariables.append(variable);
         }
+        if (!capturedVariables.isEmpty()) {
+            for (const auto& capturedVariable : capturedVariables) {
+                if (scope->hasDeclaredVariable(Identifier(m_vm, capturedVariable.get())))
+                    continue;
+                
+                if (scope->hasDeclaredParameter(Identifier(m_vm, capturedVariable.get())))
+                    continue;
+                RELEASE_ASSERT_NOT_REACHED();
+            }
+        }
     }
     didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
         context.numConstants(), capturedVariables, std::move(closedVariables));
index d6988e7..397926d 100644 (file)
@@ -411,7 +411,7 @@ class Parser {
     WTF_MAKE_FAST_ALLOCATED;
 
 public:
-    Parser(VM*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode);
+    Parser(VM*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode, JSFunctionKind);
     ~Parser();
 
     template <class ParsedNode>
@@ -954,13 +954,13 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error)
 }
 
 template <class ParsedNode>
-PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error, JSTextPosition* positionBeforeLastNewline = 0)
+PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, JSFunctionKind functionKind, ParserError& error, JSTextPosition* positionBeforeLastNewline = 0)
 {
     SamplingRegion samplingRegion("Parsing");
 
     ASSERT(!source.provider()->source().isNull());
     if (source.provider()->source().is8Bit()) {
-        Parser<Lexer<LChar>> parser(vm, source, parameters, name, strictness, parserMode);
+        Parser<Lexer<LChar>> parser(vm, source, parameters, name, strictness, parserMode, functionKind);
         RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error);
         if (positionBeforeLastNewline)
             *positionBeforeLastNewline = parser.positionBeforeLastNewline();
@@ -972,7 +972,7 @@ PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameter
         }
         return result.release();
     }
-    Parser<Lexer<UChar>> parser(vm, source, parameters, name, strictness, parserMode);
+    Parser<Lexer<UChar>> parser(vm, source, parameters, name, strictness, parserMode, functionKind);
     RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error);
     if (positionBeforeLastNewline)
         *positionBeforeLastNewline = parser.positionBeforeLastNewline();
index 9314b19..79627c0 100644 (file)
@@ -33,7 +33,8 @@ namespace JSC {
 
 enum JSParserStrictness { JSParseNormal, JSParseBuiltin, JSParseStrict };
 enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
-
+enum JSFunctionKind { JSNotFunctionKind, JSFunctionIsFunctionKind, JSFunctionIsConstructorKind };
+    
 enum ProfilerMode { ProfilerOff, ProfilerOn };
 enum DebuggerMode { DebuggerOff, DebuggerOn };
 
index afb5979..a7d5337 100644 (file)
@@ -39,7 +39,7 @@ const ClassInfo ArgumentsIteratorConstructor::s_info = { "ArgumentsIterator", &B
 void ArgumentsIteratorConstructor::finishCreation(VM& vm, ArgumentsIteratorPrototype* prototype)
 {
     Base::finishCreation(vm);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
 }
 
 }
index 4442930..862061f 100644 (file)
@@ -62,7 +62,7 @@ ArrayConstructor::ArrayConstructor(VM& vm, Structure* structure)
 void ArrayConstructor::finishCreation(VM& vm, ArrayPrototype* arrayPrototype)
 {
     Base::finishCreation(vm, arrayPrototype->classInfo()->className);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, arrayPrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
 
index b316be1..7e88dc8 100644 (file)
@@ -39,7 +39,7 @@ BooleanConstructor::BooleanConstructor(VM& vm, Structure* structure)
 void BooleanConstructor::finishCreation(VM& vm, BooleanPrototype* booleanPrototype)
 {
     Base::finishCreation(vm, booleanPrototype->classInfo()->className);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, booleanPrototype, DontEnum | DontDelete | ReadOnly);
 
     // no. of arguments for constructor
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
index 6de1044..980f2b3 100644 (file)
@@ -92,7 +92,7 @@ UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* exe
     }
 
     typedef typename CacheTypes<UnlinkedCodeBlockType>::RootNode RootNode;
-    RefPtr<RootNode> rootNode = parse<RootNode>(&vm, source, 0, Identifier(), strictness, JSParseProgramCode, error);
+    RefPtr<RootNode> rootNode = parse<RootNode>(&vm, source, 0, Identifier(), strictness, JSParseProgramCode, JSNotFunctionKind, error);
     if (!rootNode) {
         m_sourceCode.remove(addResult.iterator);
         return 0;
@@ -142,7 +142,7 @@ UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& v
         return jsCast<UnlinkedFunctionExecutable*>(addResult.iterator->value.cell.get());
 
     JSTextPosition positionBeforeLastNewline;
-    RefPtr<ProgramNode> program = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error, &positionBeforeLastNewline);
+    RefPtr<ProgramNode> program = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, JSNotFunctionKind, error, &positionBeforeLastNewline);
     if (!program) {
         RELEASE_ASSERT(error.m_type != ParserError::ErrorNone);
         m_sourceCode.remove(addResult.iterator);
index 4eb241e..456f73e 100644 (file)
     macro(Object) \
     macro(TypeError) \
     macro(undefined) \
-    macro(BuiltinLog)
+    macro(BuiltinLog) \
+    macro(IsConstructor) \
+    macro(boundFunctionName) \
+    macro(boundFunctionParameters) \
+    macro(boundFunction) \
+    macro(boundFunctionLength) \
+    macro(prototypeForHasInstance) \
+    macro(SetTypeErrorAccessor)
 
 namespace JSC {
     
index c414570..f2cc732 100644 (file)
@@ -55,7 +55,7 @@ bool checkSyntax(VM& vm, const SourceCode& source, ParserError& error)
 {
     JSLockHolder lock(vm);
     RELEASE_ASSERT(vm.atomicStringTable() == wtfThreadData().atomicStringTable());
-    RefPtr<ProgramNode> programNode = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error);
+    RefPtr<ProgramNode> programNode = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, JSNotFunctionKind, error);
     return programNode;
 }
 
index 2bbdd39..953ab4f 100644 (file)
@@ -108,7 +108,7 @@ DateConstructor::DateConstructor(VM& vm, Structure* structure)
 void DateConstructor::finishCreation(VM& vm, DatePrototype* datePrototype)
 {
     Base::finishCreation(vm, datePrototype->classInfo()->className);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, datePrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, datePrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(7), ReadOnly | DontEnum | DontDelete);
 }
 
index 9acbc4c..b70f708 100644 (file)
@@ -42,7 +42,7 @@ void ErrorConstructor::finishCreation(VM& vm, ErrorPrototype* errorPrototype)
 {
     Base::finishCreation(vm, errorPrototype->classInfo()->className);
     // ECMA 15.11.3.1 Error.prototype
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, errorPrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
 }
 
index f809f08..6279d91 100644 (file)
@@ -447,7 +447,7 @@ JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
     ParserError error;
     VM* vm = &exec->vm();
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
-    RefPtr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
+    RefPtr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, JSNotFunctionKind, error);
     if (programNode)
         return 0;
     ASSERT(error.m_type != ParserError::ErrorNone);
index 3fc7242..da315da 100644 (file)
@@ -47,7 +47,7 @@ FunctionConstructor::FunctionConstructor(VM& vm, Structure* structure)
 void FunctionConstructor::finishCreation(VM& vm, FunctionPrototype* functionPrototype)
 {
     Base::finishCreation(vm, functionPrototype->classInfo()->className);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, functionPrototype, DontEnum | DontDelete | ReadOnly);
 
     // Number of arguments for constructor
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
index eb57840..8db3da9 100644 (file)
@@ -25,7 +25,6 @@
 #include "BuiltinExecutables.h"
 #include "BuiltinNames.h"
 #include "JSArray.h"
-#include "JSBoundFunction.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSStringBuilder.h"
@@ -40,7 +39,6 @@ STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(FunctionPrototype);
 const ClassInfo FunctionPrototype::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionPrototype) };
 
 static EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*);
-static EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState*);
 
 FunctionPrototype::FunctionPrototype(VM& vm, Structure* structure)
     : InternalFunction(vm, structure)
@@ -62,9 +60,8 @@ void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* g
 
     *applyFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().applyPublicName(), functionPrototypeApplyCodeGenerator(vm), DontEnum);
     *callFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().callPublicName(), functionPrototypeCallCodeGenerator(vm), DontEnum);
-
-    JSFunction* bindFunction = JSFunction::create(vm, globalObject, 1, vm.propertyNames->bind.string(), functionProtoFuncBind);
-    putDirectWithoutTransition(vm, vm.propertyNames->bind, bindFunction, DontEnum);
+    
+    putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().bindPublicName(), functionPrototypeBindCodeGenerator(vm), DontEnum);
 }
 
 static EncodedJSValue JSC_HOST_CALL callFunctionPrototype(ExecState*)
@@ -121,47 +118,4 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
     return throwVMTypeError(exec);
 }
 
-// 15.3.4.5 Function.prototype.bind (thisArg [, arg1 [, arg2, ...]])
-EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec)
-{
-    JSGlobalObject* globalObject = exec->callee()->globalObject();
-
-    // Let Target be the this value.
-    JSValue target = exec->thisValue();
-
-    // If IsCallable(Target) is false, throw a TypeError exception.
-    CallData callData;
-    CallType callType = getCallData(target, callData);
-    if (callType == CallTypeNone)
-        return throwVMTypeError(exec);
-    // Primitive values are not callable.
-    ASSERT(target.isObject());
-    JSObject* targetObject = asObject(target);
-    VM& vm = exec->vm();
-
-    // Let A be a new (possibly empty) internal list of all of the argument values provided after thisArg (arg1, arg2 etc), in order.
-    size_t numBoundArgs = exec->argumentCount() > 1 ? exec->argumentCount() - 1 : 0;
-    JSArray* boundArgs = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), numBoundArgs);
-    if (!boundArgs)
-        return JSValue::encode(throwOutOfMemoryError(exec));
-
-    for (size_t i = 0; i < numBoundArgs; ++i)
-        boundArgs->initializeIndex(vm, i, exec->argument(i + 1));
-
-    // If the [[Class]] internal property of Target is "Function", then ...
-    // Else set the length own property of F to 0.
-    unsigned length = 0;
-    if (targetObject->inherits(JSFunction::info())) {
-        ASSERT(target.get(exec, exec->propertyNames().length).isNumber());
-        // a. Let L be the length property of Target minus the length of A.
-        // b. Set the length own property of F to either 0 or L, whichever is larger.
-        unsigned targetLength = (unsigned)target.get(exec, exec->propertyNames().length).asNumber();
-        if (targetLength > numBoundArgs)
-            length = targetLength - numBoundArgs;
-    }
-
-    JSString* name = target.get(exec, exec->propertyNames().name).toString(exec);
-    return JSValue::encode(JSBoundFunction::create(vm, globalObject, targetObject, exec->argument(0), boundArgs, length, name->value(exec)));
-}
-
 } // namespace JSC
index 22f79c8..6649dec 100644 (file)
@@ -50,7 +50,7 @@ JSArrayBufferConstructor::JSArrayBufferConstructor(VM& vm, Structure* structure)
 void JSArrayBufferConstructor::finishCreation(VM& vm, JSArrayBufferPrototype* prototype)
 {
     Base::finishCreation(vm, "ArrayBuffer");
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), DontEnum | DontDelete | ReadOnly);
 
     JSGlobalObject* globalObject = this->globalObject();
diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
deleted file mode 100644 (file)
index ef79c42..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "JSBoundFunction.h"
-
-#include "GetterSetter.h"
-#include "JSGlobalObject.h"
-#include "JSCInlines.h"
-
-namespace JSC {
-
-const ClassInfo JSBoundFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSBoundFunction) };
-
-EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState* exec)
-{
-    JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee());
-
-    ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true!
-    JSArray* boundArgs = asArray(boundFunction->boundArgs());
-
-    MarkedArgumentBuffer args;
-    for (unsigned i = 0; i < boundArgs->length(); ++i)
-        args.append(boundArgs->getIndexQuickly(i));
-    for (unsigned i = 0; i < exec->argumentCount(); ++i)
-        args.append(exec->uncheckedArgument(i));
-
-    JSObject* targetFunction = boundFunction->targetFunction();
-    CallData callData;
-    CallType callType = getCallData(targetFunction, callData);
-    ASSERT(callType != CallTypeNone);
-    return JSValue::encode(call(exec, targetFunction, callType, callData, boundFunction->boundThis(), args));
-}
-
-EncodedJSValue JSC_HOST_CALL boundFunctionConstruct(ExecState* exec)
-{
-    JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee());
-
-    ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true!
-    JSArray* boundArgs = asArray(boundFunction->boundArgs());
-
-    MarkedArgumentBuffer args;
-    for (unsigned i = 0; i < boundArgs->length(); ++i)
-        args.append(boundArgs->getIndexQuickly(i));
-    for (unsigned i = 0; i < exec->argumentCount(); ++i)
-        args.append(exec->uncheckedArgument(i));
-
-    JSObject* targetFunction = boundFunction->targetFunction();
-    ConstructData constructData;
-    ConstructType constructType = getConstructData(targetFunction, constructData);
-    ASSERT(constructType != ConstructTypeNone);
-    return JSValue::encode(construct(exec, targetFunction, constructType, constructData, args));
-}
-
-JSBoundFunction* JSBoundFunction::create(VM& vm, JSGlobalObject* globalObject, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int length, const String& name)
-{
-    ConstructData constructData;
-    ConstructType constructType = JSC::getConstructData(targetFunction, constructData);
-    bool canConstruct = constructType != ConstructTypeNone;
-    NativeExecutable* executable = vm.getHostFunction(boundFunctionCall, canConstruct ? boundFunctionConstruct : callHostFunctionAsConstructor);
-    JSBoundFunction* function = new (NotNull, allocateCell<JSBoundFunction>(vm.heap)) JSBoundFunction(vm, globalObject, globalObject->boundFunctionStructure(), targetFunction, boundThis, boundArgs);
-
-    function->finishCreation(vm, executable, length, name);
-    return function;
-}
-
-void JSBoundFunction::destroy(JSCell* cell)
-{
-    static_cast<JSBoundFunction*>(cell)->JSBoundFunction::~JSBoundFunction();
-}
-
-bool JSBoundFunction::customHasInstance(JSObject* object, ExecState* exec, JSValue value)
-{
-    return jsCast<JSBoundFunction*>(object)->m_targetFunction->hasInstance(exec, value);
-}
-
-JSBoundFunction::JSBoundFunction(VM& vm, JSGlobalObject* globalObject, Structure* structure, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs)
-    : Base(vm, globalObject, structure)
-    , m_targetFunction(vm, this, targetFunction)
-    , m_boundThis(vm, this, boundThis)
-    , m_boundArgs(vm, this, boundArgs)
-{
-}
-
-void JSBoundFunction::finishCreation(VM& vm, NativeExecutable* executable, int length, const String& name)
-{
-    Base::finishCreation(vm, executable, length, name);
-    ASSERT(inherits(info()));
-
-    putDirectNonIndexAccessor(vm, vm.propertyNames->arguments, globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor);
-    putDirectNonIndexAccessor(vm, vm.propertyNames->caller, globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor);
-}
-
-void JSBoundFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
-{
-    JSBoundFunction* thisObject = jsCast<JSBoundFunction*>(cell);
-    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
-    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
-    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
-    Base::visitChildren(thisObject, visitor);
-
-    visitor.append(&thisObject->m_targetFunction);
-    visitor.append(&thisObject->m_boundThis);
-    visitor.append(&thisObject->m_boundArgs);
-}
-
-} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.h b/Source/JavaScriptCore/runtime/JSBoundFunction.h
deleted file mode 100644 (file)
index 7852f78..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#ifndef JSBoundFunction_h
-#define JSBoundFunction_h
-
-#include "JSFunction.h"
-
-namespace JSC {
-
-EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState*);
-EncodedJSValue JSC_HOST_CALL boundFunctionConstruct(ExecState*);
-
-class JSBoundFunction : public JSFunction {
-public:
-    typedef JSFunction Base;
-
-    static JSBoundFunction* create(VM&, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const String&);
-    
-    static void destroy(JSCell*);
-
-    static bool customHasInstance(JSObject*, ExecState*, JSValue);
-
-    JSObject* targetFunction() { return m_targetFunction.get(); }
-    JSValue boundThis() { return m_boundThis.get(); }
-    JSValue boundArgs() { return m_boundArgs.get(); }
-
-    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 
-    {
-        ASSERT(globalObject);
-        return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info()); 
-    }
-
-    DECLARE_INFO;
-
-protected:
-    const static unsigned StructureFlags = OverridesHasInstance | OverridesVisitChildren | Base::StructureFlags;
-
-    static void visitChildren(JSCell*, SlotVisitor&);
-
-private:
-    JSBoundFunction(VM&, JSGlobalObject*, Structure*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs);
-    
-    void finishCreation(VM&, NativeExecutable*, int, const String&);
-
-    WriteBarrier<JSObject> m_targetFunction;
-    WriteBarrier<Unknown> m_boundThis;
-    WriteBarrier<Unknown> m_boundArgs;
-};
-
-} // namespace JSC
-
-#endif // JSFunction_h
index f9f889a..c3f54df 100644 (file)
@@ -33,7 +33,6 @@
 #include "FunctionPrototype.h"
 #include "GetterSetter.h"
 #include "JSArray.h"
-#include "JSBoundFunction.h"
 #include "JSFunctionInlines.h"
 #include "JSGlobalObject.h"
 #include "JSNameScope.h" 
@@ -251,8 +250,9 @@ EncodedJSValue JSFunction::argumentsGetter(ExecState* exec, JSObject* slotBase,
 
 class RetrieveCallerFunctionFunctor {
 public:
-    RetrieveCallerFunctionFunctor(JSFunction* functionObj)
-        : m_targetCallee(jsDynamicCast<JSObject*>(functionObj))
+    RetrieveCallerFunctionFunctor(ExecState* exec, JSFunction* functionObj)
+        : m_exec(exec)
+        , m_targetCallee(jsDynamicCast<JSObject*>(functionObj))
         , m_hasFoundFrame(false)
         , m_hasSkippedToCallerFrame(false)
         , m_result(jsNull())
@@ -265,7 +265,7 @@ public:
     {
         JSObject* callee = visitor->callee();
 
-        if (callee && callee->inherits(JSBoundFunction::info()))
+        if (callee && callee->hasOwnProperty(m_exec, m_exec->propertyNames().boundFunctionNamePrivateName))
             return StackVisitor::Continue;
 
         if (!m_hasFoundFrame && (callee != m_targetCallee))
@@ -283,6 +283,7 @@ public:
     }
 
 private:
+    ExecState* m_exec;
     JSObject* m_targetCallee;
     bool m_hasFoundFrame;
     bool m_hasSkippedToCallerFrame;
@@ -291,7 +292,7 @@ private:
 
 static JSValue retrieveCallerFunction(ExecState* exec, JSFunction* functionObj)
 {
-    RetrieveCallerFunctionFunctor functor(functionObj);
+    RetrieveCallerFunctionFunctor functor(exec, functionObj);
     exec->iterate(functor);
     return functor.result();
 }
@@ -328,17 +329,59 @@ EncodedJSValue JSFunction::nameGetter(ExecState*, JSObject* slotBase, EncodedJSV
 bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
 {
     JSFunction* thisObject = jsCast<JSFunction*>(object);
-    if (thisObject->isHostOrBuiltinFunction())
+    if (thisObject->isHostFunction())
         return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
-
-    if (propertyName == exec->propertyNames().prototype) {
+    if (thisObject->isBuiltinFunction()) {
+        if (propertyName == exec->propertyNames().caller) {
+            if (thisObject->jsExecutable()->isStrictMode()) {
+                bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+                if (!result) {
+                    thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
+                    result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+                    ASSERT(result);
+                }
+                return result;
+            }
+            slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, callerGetter);
+            return true;
+        }
+        if (propertyName == exec->propertyNames().prototypeForHasInstancePrivateName) {
+            PropertySlot boundFunctionSlot(thisObject);
+            if (Base::getOwnPropertySlot(thisObject, exec, exec->propertyNames().boundFunctionPrivateName, boundFunctionSlot)) {
+                JSValue boundFunction = boundFunctionSlot.getValue(exec, exec->propertyNames().boundFunctionPrivateName);
+                PropertySlot boundPrototypeSlot(asObject(boundFunction));
+                if (asObject(boundFunction)->getPropertySlot(exec, propertyName, boundPrototypeSlot)) {
+                    slot.setValue(boundPrototypeSlot.slotBase(), boundPrototypeSlot.attributes(), boundPrototypeSlot.getValue(exec, propertyName));
+                    return true;
+                }
+            }
+        }
+        if (propertyName == exec->propertyNames().name) {
+            PropertySlot nameSlot(thisObject);
+            if (Base::getOwnPropertySlot(thisObject, exec, exec->vm().propertyNames->boundFunctionNamePrivateName, nameSlot)) {
+                slot.setValue(thisObject, DontEnum | DontDelete | ReadOnly, nameSlot.getValue(exec, exec->vm().propertyNames->boundFunctionNamePrivateName));
+                return true;
+            }
+        }
+        if (propertyName == exec->propertyNames().length) {
+            PropertySlot lengthSlot(thisObject);
+            if (Base::getOwnPropertySlot(thisObject, exec, exec->vm().propertyNames->boundFunctionLengthPrivateName, lengthSlot)) {
+                slot.setValue(thisObject, DontEnum | DontDelete | ReadOnly, lengthSlot.getValue(exec, exec->vm().propertyNames->boundFunctionLengthPrivateName));
+                return true;
+            }
+        }
+            
+        return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+    }
+    
+    if (propertyName == exec->propertyNames().prototype || propertyName == exec->propertyNames().prototypeForHasInstancePrivateName) {
         VM& vm = exec->vm();
         unsigned attributes;
         PropertyOffset offset = thisObject->getDirectOffset(vm, propertyName, attributes);
         if (!isValidOffset(offset)) {
             JSObject* prototype = constructEmptyObject(exec);
             prototype->putDirect(vm, exec->propertyNames().constructor, thisObject, DontEnum);
-            thisObject->putDirect(vm, exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
+            thisObject->putDirectPrototypeProperty(vm, prototype, DontDelete | DontEnum);
             offset = thisObject->getDirectOffset(vm, exec->propertyNames().prototype, attributes);
             ASSERT(isValidOffset(offset));
         }
@@ -390,16 +433,23 @@ bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyN
 void JSFunction::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     JSFunction* thisObject = jsCast<JSFunction*>(object);
-    if (!thisObject->isHostOrBuiltinFunction() && (mode == IncludeDontEnumProperties)) {
-        VM& vm = exec->vm();
-        // Make sure prototype has been reified.
-        PropertySlot slot(thisObject);
-        thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, vm.propertyNames->prototype, slot);
+    if (mode == IncludeDontEnumProperties) {
+        bool shouldIncludeJSFunctionProperties = !thisObject->isHostOrBuiltinFunction();
+        if (!shouldIncludeJSFunctionProperties && thisObject->isBuiltinFunction()) {
+            PropertySlot boundFunctionSlot(thisObject);
+            shouldIncludeJSFunctionProperties = Base::getOwnPropertySlot(thisObject, exec, exec->propertyNames().boundFunctionPrivateName, boundFunctionSlot);
+        }
+        if (shouldIncludeJSFunctionProperties) {
+            VM& vm = exec->vm();
+            // Make sure prototype has been reified.
+            PropertySlot slot(thisObject);
+            thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, vm.propertyNames->prototype, slot);
 
-        propertyNames.add(vm.propertyNames->arguments);
-        propertyNames.add(vm.propertyNames->caller);
-        propertyNames.add(vm.propertyNames->length);
-        propertyNames.add(vm.propertyNames->name);
+            propertyNames.add(vm.propertyNames->arguments);
+            propertyNames.add(vm.propertyNames->caller);
+            propertyNames.add(vm.propertyNames->length);
+            propertyNames.add(vm.propertyNames->name);
+        }
     }
     Base::getOwnNonIndexPropertyNames(thisObject, exec, propertyNames, mode);
 }
@@ -419,8 +469,10 @@ void JSFunction::put(JSCell* cell, ExecState* exec, PropertyName propertyName, J
         thisObject->m_allocationProfile.clear();
         thisObject->m_allocationProfileWatchpoint.fireAll();
         // Don't allow this to be cached, since a [[Put]] must clear m_allocationProfile.
-        PutPropertySlot dontCache(thisObject);
-        Base::put(thisObject, exec, propertyName, value, dontCache);
+        PutPropertySlot dontCachePrototype(thisObject);
+        Base::put(thisObject, exec, propertyName, value, dontCachePrototype);
+        PutPropertySlot dontCachePrototypeForHasInstance(thisObject);
+        Base::put(thisObject, exec, exec->propertyNames().prototypeForHasInstancePrivateName, value, dontCachePrototypeForHasInstance);
         return;
     }
     if (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
@@ -465,7 +517,10 @@ bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyNa
         thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot);
         thisObject->m_allocationProfile.clear();
         thisObject->m_allocationProfileWatchpoint.fireAll();
-        return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+        if (!Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException))
+            return false;
+        Base::defineOwnProperty(object, exec, exec->propertyNames().prototypeForHasInstancePrivateName, descriptor, throwException);
+        return true;
     }
 
     bool valueCheck;
index 2ddc29f..fa6f7fa 100644 (file)
@@ -43,7 +43,7 @@ template<typename ViewClass>
 void JSGenericTypedArrayViewConstructor<ViewClass>::finishCreation(VM& vm, JSObject* prototype, const String& name)
 {
     Base::finishCreation(vm, name);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(3), DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->BYTES_PER_ELEMENT, jsNumber(ViewClass::elementSize), DontEnum | ReadOnly | DontDelete);
 }
index 49d86a7..6200808 100644 (file)
@@ -60,7 +60,6 @@
 #include "JSArrayBufferConstructor.h"
 #include "JSArrayBufferPrototype.h"
 #include "JSArrayIterator.h"
-#include "JSBoundFunction.h"
 #include "JSCInlines.h"
 #include "JSCallbackConstructor.h"
 #include "JSCallbackFunction.h"
@@ -278,7 +277,6 @@ void JSGlobalObject::reset(JSValue prototype)
 
     m_functionPrototype.set(vm, this, FunctionPrototype::create(vm, FunctionPrototype::createStructure(vm, this, jsNull()))); // The real prototype will be set once ObjectPrototype is created.
     m_functionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
-    m_boundFunctionStructure.set(vm, this, JSBoundFunction::createStructure(vm, this, m_functionPrototype.get()));
     m_namedFunctionStructure.set(vm, this, Structure::addPropertyTransition(vm, m_functionStructure.get(), vm.propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset));
     m_internalFunctionStructure.set(vm, this, InternalFunction::createStructure(vm, this, m_functionPrototype.get()));
     JSFunction* callFunction = 0;
@@ -453,6 +451,7 @@ void JSGlobalObject::reset(JSValue prototype)
     }
     
     JSFunction* builtinLog = JSFunction::create(vm, this, 1, vm.propertyNames->emptyIdentifier.string(), globalFuncBuiltinLog);
+    JSFunction* setTypeErrorAccessor = JSFunction::create(vm, this, 2, vm.propertyNames->emptyIdentifier.string(), globalFuncSetTypeErrorAccessor);
     GlobalPropertyInfo staticGlobals[] = {
         GlobalPropertyInfo(vm.propertyNames->NaN, jsNaN(), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->Infinity, jsNumber(std::numeric_limits<double>::infinity()), DontEnum | DontDelete | ReadOnly),
@@ -460,7 +459,8 @@ void JSGlobalObject::reset(JSValue prototype)
         GlobalPropertyInfo(vm.propertyNames->undefinedPrivateName, jsUndefined(), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->ObjectPrivateName, objectConstructor, DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->TypeErrorPrivateName, m_typeErrorConstructor.get(), DontEnum | DontDelete | ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->BuiltinLogPrivateName, builtinLog, DontEnum | DontDelete | ReadOnly)
+        GlobalPropertyInfo(vm.propertyNames->BuiltinLogPrivateName, builtinLog, DontEnum | DontDelete | ReadOnly),
+        GlobalPropertyInfo(vm.propertyNames->SetTypeErrorAccessorPrivateName, setTypeErrorAccessor, DontEnum | DontDelete | ReadOnly)
     };
     addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
     
index c52e938..a492f85 100644 (file)
@@ -26,6 +26,7 @@
 #include "JSGlobalObjectFunctions.h"
 
 #include "CallFrame.h"
+#include "GetterSetter.h"
 #include "Interpreter.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
@@ -812,4 +813,19 @@ EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState* exec)
     return JSValue::encode(jsUndefined());
 }
 
+    
+EncodedJSValue JSC_HOST_CALL globalFuncSetTypeErrorAccessor(ExecState* exec)
+{
+    JSObject* target = jsDynamicCast<JSObject*>(exec->argument(0));
+    JSValue propertyName = exec->argument(1);
+    
+    // Setting __proto__ of a primitive should have no effect.
+    if (!target || !propertyName.isString())
+        return JSValue::encode(jsUndefined());
+    VM& vm = exec->vm();
+    Identifier property(exec, asString(propertyName)->getString(exec));
+    target->putDirectNonIndexAccessor(vm, vm.propertyNames->arguments, target->globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor);
+    return JSValue::encode(jsUndefined());
+}
+    
 } // namespace JSC
index 2922d61..881b9c8 100644 (file)
@@ -53,6 +53,8 @@ EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState*);
 EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*);
 EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState*);
     
+EncodedJSValue JSC_HOST_CALL globalFuncSetTypeErrorAccessor(ExecState*);
+    
 static const double mantissaOverflowLowerBound = 9007199254740992.0;
 double parseIntOverflow(const LChar*, unsigned length, int radix);
 bool isStrWhiteSpace(UChar);
index e303e79..6ade670 100644 (file)
@@ -2668,5 +2668,17 @@ JSObject* throwTypeError(ExecState* exec, const String& message)
 {
     return exec->vm().throwException(exec, createTypeError(exec, message));
 }
-
+    
+void JSObject::putDirectPrototypeProperty(VM& vm, JSValue value, int attributes)
+{
+    putDirect(vm, vm.propertyNames->prototype, value, attributes);
+    putDirect(vm, vm.propertyNames->prototypeForHasInstancePrivateName, value, attributes);
+}
+    
+void JSObject::putDirectPrototypePropertyWithoutTransitions(VM& vm, JSValue value, int attributes)
+{
+    putDirectWithoutTransition(vm, vm.propertyNames->prototype, value, attributes);
+    putDirectWithoutTransition(vm, vm.propertyNames->prototypeForHasInstancePrivateName, value, attributes);
+}
+    
 } // namespace JSC
index 521b5f4..0fea9b9 100644 (file)
@@ -932,6 +932,9 @@ protected:
         }
     }
 
+    JS_EXPORT_PRIVATE void putDirectPrototypeProperty(VM&, JSValue, int);
+    void putDirectPrototypePropertyWithoutTransitions(VM&, JSValue, int);
+    
 private:
     friend class LLIntOffsetsExtractor;
         
index 4026196..b92061d 100644 (file)
@@ -86,7 +86,7 @@ JSPromiseConstructor::JSPromiseConstructor(VM& vm, Structure* structure)
 void JSPromiseConstructor::finishCreation(VM& vm, JSPromisePrototype* promisePrototype)
 {
     Base::finishCreation(vm, "Promise");
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, promisePrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, promisePrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
 
index 9e3a4bf..c0b23a3 100644 (file)
@@ -40,7 +40,7 @@ const ClassInfo MapConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREA
 void MapConstructor::finishCreation(VM& vm, MapPrototype* mapPrototype)
 {
     Base::finishCreation(vm, mapPrototype->classInfo()->className);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, mapPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, mapPrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum | DontDelete);
 }
 
index fbc6c8b..d97e8a6 100644 (file)
@@ -39,7 +39,7 @@ const ClassInfo MapIteratorConstructor::s_info = { "MapIterator Iterator", &Base
 void MapIteratorConstructor::finishCreation(VM& vm, MapIteratorPrototype* prototype)
 {
     Base::finishCreation(vm);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
 }
 
 }
index 3926883..6c8256e 100644 (file)
@@ -44,7 +44,7 @@ NameConstructor::NameConstructor(VM& vm, Structure* structure)
 void NameConstructor::finishCreation(VM& vm, NamePrototype* prototype)
 {
     Base::finishCreation(vm, prototype->classInfo()->className);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
 }
 
index 6260055..be51813 100644 (file)
@@ -46,7 +46,7 @@ void NativeErrorConstructor::finishCreation(VM& vm, JSGlobalObject* globalObject
     NativeErrorPrototype* prototype = NativeErrorPrototype::create(vm, globalObject, prototypeStructure, name, this);
     
     putDirect(vm, vm.propertyNames->length, jsNumber(1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
-    putDirect(vm, vm.propertyNames->prototype, prototype, DontDelete | ReadOnly | DontEnum);
+    putDirectPrototypeProperty(vm, prototype, DontDelete | ReadOnly | DontEnum);
     m_errorStructure.set(vm, this, ErrorInstance::createStructure(vm, globalObject, prototype));
     ASSERT(m_errorStructure);
     ASSERT(m_errorStructure->isObject());
index 04c5098..78708bf 100644 (file)
@@ -66,7 +66,7 @@ void NumberConstructor::finishCreation(VM& vm, NumberPrototype* numberPrototype)
     ASSERT(inherits(info()));
 
     // Number.Prototype
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, numberPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, numberPrototype, DontEnum | DontDelete | ReadOnly);
 
     // no. of arguments for constructor
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
index a3c1927..8793d8e 100644 (file)
@@ -88,7 +88,7 @@ void ObjectConstructor::finishCreation(VM& vm, ObjectPrototype* objectPrototype)
 {
     Base::finishCreation(vm, Identifier(&vm, "Object").string());
     // ECMA 15.2.3.1
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, objectPrototype, DontEnum | DontDelete | ReadOnly);
     // no. of arguments for constructor
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
index 0c6bf48..e00c07f 100644 (file)
@@ -95,7 +95,7 @@ void RegExpConstructor::finishCreation(VM& vm, RegExpPrototype* regExpPrototype)
     ASSERT(inherits(info()));
 
     // ECMA 15.10.5.1 RegExp.prototype
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, regExpPrototype, DontEnum | DontDelete | ReadOnly);
 
     // no. of arguments for constructor
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
index b203888..fc1a38a 100644 (file)
@@ -41,7 +41,7 @@ const ClassInfo SetConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREA
 void SetConstructor::finishCreation(VM& vm, SetPrototype* setPrototype)
 {
     Base::finishCreation(vm, setPrototype->classInfo()->className);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, setPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, setPrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum | DontDelete);
 }
 
index c16ff9b..e898b73 100644 (file)
@@ -39,7 +39,7 @@ const ClassInfo SetIteratorConstructor::s_info = { "Set Iterator", &Base::s_info
 void SetIteratorConstructor::finishCreation(VM& vm, SetIteratorPrototype* prototype)
 {
     Base::finishCreation(vm);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
 }
 
 }
index f8221d7..f89d883 100644 (file)
@@ -56,7 +56,7 @@ StringConstructor::StringConstructor(VM& vm, Structure* structure)
 void StringConstructor::finishCreation(VM& vm, StringPrototype* stringPrototype)
 {
     Base::finishCreation(vm, stringPrototype->classInfo()->className);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, stringPrototype, ReadOnly | DontEnum | DontDelete);
+    putDirectPrototypePropertyWithoutTransitions(vm, stringPrototype, ReadOnly | DontEnum | DontDelete);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
 
index f3540fa..e4b3123 100644 (file)
@@ -39,7 +39,7 @@ const ClassInfo WeakMapConstructor::s_info = { "Function", &Base::s_info, 0, 0,
 void WeakMapConstructor::finishCreation(VM& vm, WeakMapPrototype* prototype)
 {
     Base::finishCreation(vm, prototype->classInfo()->className);
-    putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
+    putDirectPrototypePropertyWithoutTransitions(vm, prototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum | DontDelete);
 }
 
index f98320f..e3b4c8b 100644 (file)
@@ -1,3 +1,52 @@
+2014-04-08  Oliver Hunt  <oliver@apple.com>
+
+        Rewrite Function.bind as a builtin
+        https://bugs.webkit.org/show_bug.cgi?id=131083
+
+        Reviewed by Geoffrey Garen.
+
+        Switch WebCore to use the helper functions when defining the
+        prototype properties on DOM constructors, and update bindings
+        tests accordingly.
+
+        * bindings/js/JSImageConstructor.cpp:
+        (WebCore::JSImageConstructor::finishCreation):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateConstructorHelperMethods):
+        * bindings/scripts/test/JS/JSTestActiveDOMObject.cpp:
+        (WebCore::JSTestActiveDOMObjectConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestCustomNamedGetter.cpp:
+        (WebCore::JSTestCustomNamedGetterConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestEventConstructor.cpp:
+        (WebCore::JSTestEventConstructorConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestEventTarget.cpp:
+        (WebCore::JSTestEventTargetConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestException.cpp:
+        (WebCore::JSTestExceptionConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp:
+        (WebCore::JSTestGenerateIsReachableConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestInterface.cpp:
+        (WebCore::JSTestInterfaceConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp:
+        (WebCore::JSTestMediaQueryListListenerConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestNamedConstructor.cpp:
+        (WebCore::JSTestNamedConstructorConstructor::finishCreation):
+        (WebCore::JSTestNamedConstructorNamedConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestNode.cpp:
+        (WebCore::JSTestNodeConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestObj.cpp:
+        (WebCore::JSTestObjConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp:
+        (WebCore::JSTestOverloadedConstructorsConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp:
+        (WebCore::JSTestSerializedScriptValueInterfaceConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSTestTypedefs.cpp:
+        (WebCore::JSTestTypedefsConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSattribute.cpp:
+        (WebCore::JSattributeConstructor::finishCreation):
+        * bindings/scripts/test/JS/JSreadonly.cpp:
+        (WebCore::JSreadonlyConstructor::finishCreation):
+
 2014-04-13  Simon Fraser  <simon.fraser@apple.com>
 
         [iOS WK2] Hook up scrolling tree nodes when coming out of the page cache
index a86effd..40afca1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
+ *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2014 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -43,7 +43,7 @@ void JSImageConstructor::finishCreation(VM& vm, JSDOMGlobalObject* globalObject)
 {
     Base::finishCreation(globalObject);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSHTMLImageElementPrototype::self(vm, globalObject), None);
+    putDirectPrototypeProperty(vm, JSHTMLImageElementPrototype::self(vm, globalObject), None);
 }
 
 static EncodedJSValue JSC_HOST_CALL constructImage(ExecState* exec)
index cc7fd59..cd3be06 100644 (file)
@@ -4526,15 +4526,15 @@ sub GenerateConstructorHelperMethods
     if (IsDOMGlobalObject($interface)) {
         push(@$outputArray, "    Base::finishCreation(vm);\n");
         push(@$outputArray, "    ASSERT(inherits(info()));\n");
-        push(@$outputArray, "    putDirect(vm, vm.propertyNames->prototype, globalObject->prototype(), DontDelete | ReadOnly);\n");
+        push(@$outputArray, "    putDirectPrototypeProperty(vm, globalObject->prototype(), DontDelete | ReadOnly);\n");
     } elsif ($generatingNamedConstructor) {
         push(@$outputArray, "    Base::finishCreation(globalObject);\n");
         push(@$outputArray, "    ASSERT(inherits(info()));\n");
-        push(@$outputArray, "    putDirect(vm, vm.propertyNames->prototype, ${className}Prototype::self(vm, globalObject), None);\n");
+        push(@$outputArray, "    putDirectPrototypeProperty(vm, ${className}Prototype::self(vm, globalObject), None);\n");
     } else {
         push(@$outputArray, "    Base::finishCreation(vm);\n");
         push(@$outputArray, "    ASSERT(inherits(info()));\n");
-        push(@$outputArray, "    putDirect(vm, vm.propertyNames->prototype, ${protoClassName}::self(vm, globalObject), DontDelete | ReadOnly);\n");
+        push(@$outputArray, "    putDirectPrototypeProperty(vm, ${protoClassName}::self(vm, globalObject), DontDelete | ReadOnly);\n");
     }
     push(@$outputArray, "    putDirect(vm, vm.propertyNames->length, jsNumber(${leastConstructorLength}), ReadOnly | DontDelete | DontEnum);\n") if defined $leastConstructorLength;
     push(@$outputArray, "}\n\n");
index 77334fb..a7eaf6f 100644 (file)
@@ -74,7 +74,7 @@ void JSTestActiveDOMObjectConstructor::finishCreation(VM& vm, JSDOMGlobalObject*
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestActiveDOMObjectPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestActiveDOMObjectPrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }
 
index 44c415d..1670d88 100644 (file)
@@ -70,7 +70,7 @@ void JSTestCustomNamedGetterConstructor::finishCreation(VM& vm, JSDOMGlobalObjec
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestCustomNamedGetterPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestCustomNamedGetterPrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }
 
index 9ad9eef..0229654 100644 (file)
@@ -95,7 +95,7 @@ void JSTestEventConstructorConstructor::finishCreation(VM& vm, JSDOMGlobalObject
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestEventConstructorPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestEventConstructorPrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
 }
 
index debee97..767fb9a 100644 (file)
@@ -76,7 +76,7 @@ void JSTestEventTargetConstructor::finishCreation(VM& vm, JSDOMGlobalObject* glo
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestEventTargetPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestEventTargetPrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }
 
index 5e3a6eb..20bb920 100644 (file)
@@ -69,7 +69,7 @@ void JSTestExceptionConstructor::finishCreation(VM& vm, JSDOMGlobalObject* globa
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestExceptionPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestExceptionPrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }
 
index f8ffb69..0833fd3 100644 (file)
@@ -52,7 +52,7 @@ void JSTestGenerateIsReachableConstructor::finishCreation(VM& vm, JSDOMGlobalObj
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestGenerateIsReachablePrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestGenerateIsReachablePrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }
 
index d6c0fee..d21789b 100644 (file)
@@ -193,7 +193,7 @@ void JSTestInterfaceConstructor::finishCreation(VM& vm, JSDOMGlobalObject* globa
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestInterfacePrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestInterfacePrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
 }
 
index 8b89707..2de6dea 100644 (file)
@@ -56,7 +56,7 @@ void JSTestMediaQueryListListenerConstructor::finishCreation(VM& vm, JSDOMGlobal
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestMediaQueryListListenerPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestMediaQueryListListenerPrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }
 
index 86c3237..1d77b82 100644 (file)
@@ -55,7 +55,7 @@ void JSTestNamedConstructorConstructor::finishCreation(VM& vm, JSDOMGlobalObject
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestNamedConstructorPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestNamedConstructorPrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }
 
@@ -98,7 +98,7 @@ void JSTestNamedConstructorNamedConstructor::finishCreation(VM& vm, JSDOMGlobalO
 {
     Base::finishCreation(globalObject);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestNamedConstructorPrototype::self(vm, globalObject), None);
+    putDirectPrototypeProperty(vm, JSTestNamedConstructorPrototype::self(vm, globalObject), None);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }
 
index b070ead..edf8c9c 100644 (file)
@@ -62,7 +62,7 @@ void JSTestNodeConstructor::finishCreation(VM& vm, JSDOMGlobalObject* globalObje
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestNodePrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestNodePrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }
 
index 81b3d9f..1ceb33c 100644 (file)
@@ -242,7 +242,7 @@ void JSTestObjConstructor::finishCreation(VM& vm, JSDOMGlobalObject* globalObjec
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestObjPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestObjPrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
 }
 
index d8ca74e..5342444 100644 (file)
@@ -121,7 +121,7 @@ void JSTestOverloadedConstructorsConstructor::finishCreation(VM& vm, JSDOMGlobal
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestOverloadedConstructorsPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestOverloadedConstructorsPrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
 }
 
index fe39024..de593e5 100644 (file)
@@ -60,7 +60,7 @@ void JSTestSerializedScriptValueInterfaceConstructor::finishCreation(VM& vm, JSD
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestSerializedScriptValueInterfacePrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestSerializedScriptValueInterfacePrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }
 
index 485811e..6b0d49f 100644 (file)
@@ -97,7 +97,7 @@ void JSTestTypedefsConstructor::finishCreation(VM& vm, JSDOMGlobalObject* global
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSTestTypedefsPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSTestTypedefsPrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
 }
 
index 88324f8..e7a1eb1 100644 (file)
@@ -55,7 +55,7 @@ void JSattributeConstructor::finishCreation(VM& vm, JSDOMGlobalObject* globalObj
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSattributePrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSattributePrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }
 
index d44308a..630649a 100644 (file)
@@ -52,7 +52,7 @@ void JSreadonlyConstructor::finishCreation(VM& vm, JSDOMGlobalObject* globalObje
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    putDirect(vm, vm.propertyNames->prototype, JSreadonlyPrototype::self(vm, globalObject), DontDelete | ReadOnly);
+    putDirectPrototypeProperty(vm, JSreadonlyPrototype::self(vm, globalObject), DontDelete | ReadOnly);
     putDirect(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontDelete | DontEnum);
 }