Changeset 35016 in webkit for trunk/JavaScriptCore
- Timestamp:
- Jul 5, 2008, 4:19:36 PM (17 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 15 edited
- 10 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r35011 r35016 1 2008-07-05 Sam Weinig <[email protected]> 2 3 Rubber-stamped by Cameron Zwarich. 4 5 Split Arguments, IndexToNameMap, PrototypeFunction, GlobalEvalFunction and 6 the functions on the global object out of JSFunction.h/cpp. 7 8 * GNUmakefile.am: 9 * JavaScriptCore.pri: 10 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: 11 * JavaScriptCore.xcodeproj/project.pbxproj: 12 * JavaScriptCoreSources.bkl: 13 * VM/Machine.cpp: 14 * kjs/AllInOneFile.cpp: 15 * kjs/Arguments.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp. 16 * kjs/Arguments.h: Copied from JavaScriptCore/kjs/JSFunction.h. 17 * kjs/GlobalEvalFunction.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp. 18 * kjs/GlobalEvalFunction.h: Copied from JavaScriptCore/kjs/JSFunction.h. 19 * kjs/IndexToNameMap.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp. 20 * kjs/IndexToNameMap.h: Copied from JavaScriptCore/kjs/JSFunction.h. 21 * kjs/JSActivation.cpp: 22 * kjs/JSFunction.cpp: 23 * kjs/JSFunction.h: 24 * kjs/JSGlobalObject.cpp: 25 * kjs/JSGlobalObjectFunctions.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp. 26 * kjs/JSGlobalObjectFunctions.h: Copied from JavaScriptCore/kjs/JSFunction.h. 27 The functions on the global object should be in JSGlobalObject.cpp, but putting them there 28 was a 0.5% regression. 29 30 * kjs/PrototypeFunction.cpp: Copied from JavaScriptCore/kjs/JSFunction.cpp. 31 * kjs/PrototypeFunction.h: Copied from JavaScriptCore/kjs/JSFunction.h. 32 * kjs/Shell.cpp: 33 * kjs/lexer.cpp: 34 * kjs/ustring.cpp: 35 1 36 2008-07-04 Sam Weinig <[email protected]> 2 37 -
trunk/JavaScriptCore/GNUmakefile.am
r35007 r35016 75 75 76 76 javascriptcore_sources += \ 77 JavaScriptCore/kjs/CommonIdentifiers.cpp \ 78 JavaScriptCore/kjs/DateMath.cpp \ 79 JavaScriptCore/kjs/JSImmediate.cpp \ 80 JavaScriptCore/kjs/JSLock.cpp \ 81 JavaScriptCore/kjs/JSWrapperObject.cpp \ 82 JavaScriptCore/kjs/Parser.cpp \ 83 JavaScriptCore/kjs/PropertyNameArray.cpp \ 84 JavaScriptCore/kjs/JSArray.cpp \ 77 JavaScriptCore/kjs/Arguments.cpp \ 85 78 JavaScriptCore/kjs/ArrayConstructor.cpp \ 86 79 JavaScriptCore/kjs/ArrayPrototype.cpp \ … … 89 82 JavaScriptCore/kjs/BooleanPrototype.cpp \ 90 83 JavaScriptCore/kjs/collector.cpp \ 84 JavaScriptCore/kjs/CommonIdentifiers.cpp \ 85 JavaScriptCore/kjs/DateConstructor.cpp \ 91 86 JavaScriptCore/kjs/DateInstance.cpp \ 92 JavaScriptCore/kjs/Date Constructor.cpp \87 JavaScriptCore/kjs/DateMath.cpp \ 93 88 JavaScriptCore/kjs/DatePrototype.cpp \ 94 89 JavaScriptCore/kjs/debugger.cpp \ … … 98 93 JavaScriptCore/kjs/ErrorInstance.cpp \ 99 94 JavaScriptCore/kjs/ErrorPrototype.cpp \ 95 JavaScriptCore/kjs/FunctionConstructor.cpp \ 96 JavaScriptCore/kjs/FunctionPrototype.cpp \ 100 97 JavaScriptCore/kjs/GetterSetter.cpp \ 98 JavaScriptCore/kjs/GlobalEvalFunction.cpp \ 99 JavaScriptCore/kjs/identifier.cpp \ 100 JavaScriptCore/kjs/IndexToNameMap.cpp \ 101 JavaScriptCore/kjs/InternalFunction.cpp \ 102 JavaScriptCore/kjs/interpreter.cpp \ 103 JavaScriptCore/kjs/JSArray.cpp \ 101 104 JavaScriptCore/kjs/JSCell.cpp \ 102 105 JavaScriptCore/kjs/JSFunction.cpp \ 106 JavaScriptCore/kjs/JSGlobalObject.cpp \ 107 JavaScriptCore/kjs/JSGlobalObjectFunctions.cpp \ 108 JavaScriptCore/kjs/JSImmediate.cpp \ 109 JavaScriptCore/kjs/JSLock.cpp \ 103 110 JavaScriptCore/kjs/JSNumberCell.cpp \ 111 JavaScriptCore/kjs/JSObject.cpp \ 104 112 JavaScriptCore/kjs/JSString.cpp \ 113 JavaScriptCore/kjs/JSValue.cpp \ 105 114 JavaScriptCore/kjs/JSVariableObject.cpp \ 106 JavaScriptCore/kjs/FunctionConstructor.cpp \ 107 JavaScriptCore/kjs/FunctionPrototype.cpp \ 108 JavaScriptCore/kjs/identifier.cpp \ 109 JavaScriptCore/kjs/InternalFunction.cpp \ 110 JavaScriptCore/kjs/interpreter.cpp \ 115 JavaScriptCore/kjs/JSWrapperObject.cpp \ 111 116 JavaScriptCore/kjs/LabelStack.cpp \ 112 117 JavaScriptCore/kjs/lexer.cpp \ … … 114 119 JavaScriptCore/kjs/lookup.cpp \ 115 120 JavaScriptCore/kjs/MathObject.cpp \ 121 JavaScriptCore/kjs/NativeErrorConstructor.cpp \ 122 JavaScriptCore/kjs/NativeErrorPrototype.cpp \ 116 123 JavaScriptCore/kjs/nodes.cpp \ 117 124 JavaScriptCore/kjs/nodes2string.cpp \ 118 JavaScriptCore/kjs/NativeErrorConstructor.cpp \119 JavaScriptCore/kjs/NativeErrorPrototype.cpp \120 125 JavaScriptCore/kjs/NumberConstructor.cpp \ 121 126 JavaScriptCore/kjs/NumberObject.cpp \ 122 127 JavaScriptCore/kjs/NumberPrototype.cpp \ 123 JavaScriptCore/kjs/JSObject.cpp \124 JavaScriptCore/kjs/JSGlobalObject.cpp \125 128 JavaScriptCore/kjs/ObjectConstructor.cpp \ 126 129 JavaScriptCore/kjs/ObjectPrototype.cpp \ 127 130 JavaScriptCore/kjs/operations.cpp \ 131 JavaScriptCore/kjs/Parser.cpp \ 128 132 JavaScriptCore/kjs/PropertyMap.cpp \ 133 JavaScriptCore/kjs/PropertyNameArray.cpp \ 129 134 JavaScriptCore/kjs/PropertySlot.cpp \ 135 JavaScriptCore/kjs/PrototypeFunction.cpp \ 130 136 JavaScriptCore/kjs/regexp.cpp \ 131 137 JavaScriptCore/kjs/RegExpConstructor.cpp \ … … 137 143 JavaScriptCore/kjs/StringPrototype.cpp \ 138 144 JavaScriptCore/kjs/ustring.cpp \ 139 JavaScriptCore/kjs/JSValue.cpp \140 145 JavaScriptCore/wtf/FastMalloc.cpp \ 141 146 JavaScriptCore/wtf/TCSystemAlloc.cpp \ -
trunk/JavaScriptCore/JavaScriptCore.pri
r35007 r35016 62 62 # Other compilers may be able to do this at link time 63 63 SOURCES += \ 64 kjs/JSFunction.cpp \ 65 kjs/debugger.cpp \ 66 kjs/JSArray.cpp \ 64 kjs/Arguments.cpp \ 67 65 kjs/ArrayConstructor.cpp \ 68 66 kjs/ArrayPrototype.cpp \ … … 72 70 kjs/collector.cpp \ 73 71 kjs/CommonIdentifiers.cpp \ 72 kjs/DateConstructor.cpp \ 74 73 kjs/DateInstance.cpp \ 75 kjs/DateConstructor.cpp \76 74 kjs/DateMath.cpp \ 77 75 kjs/DatePrototype.cpp \ 76 kjs/debugger.cpp \ 78 77 kjs/DebuggerCallFrame.cpp \ 79 78 kjs/dtoa.cpp \ … … 86 85 kjs/FunctionPrototype.cpp \ 87 86 kjs/GetterSetter.cpp \ 87 kjs/GlobalEvalFunction.cpp \ 88 88 kjs/identifier.cpp \ 89 kjs/IndexToNameMap.cpp \ 89 90 kjs/InternalFunction.cpp \ 90 91 kjs/interpreter.cpp \ 92 kjs/JSArray.cpp \ 91 93 kjs/JSCell.cpp \ 94 kjs/JSFunction.cpp \ 95 kjs/JSGlobalObjectFunctions.cpp \ 92 96 kjs/JSImmediate.cpp \ 93 97 kjs/JSLock.cpp \ 94 98 kjs/JSNumberCell.cpp \ 99 kjs/JSObject.cpp \ 95 100 kjs/JSString.cpp \ 101 kjs/JSValue.cpp \ 96 102 kjs/JSWrapperObject.cpp \ 97 103 kjs/LabelStack.cpp \ … … 107 113 kjs/NumberObject.cpp \ 108 114 kjs/NumberPrototype.cpp \ 109 kjs/JSObject.cpp \110 115 kjs/ObjectConstructor.cpp \ 111 116 kjs/ObjectPrototype.cpp \ … … 113 118 kjs/Parser.cpp \ 114 119 kjs/PropertyMap.cpp \ 120 kjs/PropertyNameArray.cpp \ 115 121 kjs/PropertySlot.cpp \ 116 kjs/Pro pertyNameArray.cpp \122 kjs/PrototypeFunction.cpp \ 117 123 kjs/regexp.cpp \ 118 124 kjs/RegExpConstructor.cpp \ … … 124 130 kjs/StringPrototype.cpp \ 125 131 kjs/ustring.cpp \ 126 kjs/JSValue.cpp \132 profiler/Profile.cpp \ 127 133 profiler/ProfileNode.cpp \ 128 profiler/Profile.cpp \129 134 profiler/Profiler.cpp \ 130 135 profiler/TreeProfile.cpp \ -
trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
r35007 r35016 274 274 </File> 275 275 <File 276 RelativePath="..\..\kjs\Arguments.cpp" 277 > 278 </File> 279 <File 280 RelativePath="..\..\kjs\Arguments.h" 281 > 282 </File> 283 <File 276 284 RelativePath="..\..\kjs\ArrayConstructor.cpp" 277 285 > … … 450 458 </File> 451 459 <File 460 RelativePath="..\..\kjs\GlobalEvalFunction.cpp" 461 > 462 </File> 463 <File 464 RelativePath="..\..\kjs\GlobalEvalFunction.h" 465 > 466 </File> 467 <File 452 468 RelativePath="..\..\kjs\identifier.cpp" 453 469 > … … 458 474 </File> 459 475 <File 476 RelativePath="..\..\kjs\IndexToNameMap.cpp" 477 > 478 </File> 479 <File 480 RelativePath="..\..\kjs\IndexToNameMap.h" 481 > 482 </File> 483 <File 460 484 RelativePath="..\..\kjs\InitializeThreading.cpp" 461 485 > … … 530 554 </File> 531 555 <File 556 RelativePath="..\..\kjs\JSGlobalObjectFunctions.cpp" 557 > 558 </File> 559 <File 560 RelativePath="..\..\kjs\JSGlobalObjectFunctions.h" 561 > 562 </File> 563 <File 532 564 RelativePath="..\..\kjs\JSImmediate.cpp" 533 565 > … … 731 763 <File 732 764 RelativePath="..\..\kjs\protect.h" 765 > 766 </File> 767 <File 768 RelativePath="..\..\kjs\PrototypeFunction.cpp" 769 > 770 </File> 771 <File 772 RelativePath="..\..\kjs\PrototypeFunction.h" 733 773 > 734 774 </File> -
trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r35011 r35016 254 254 BC18C52E0E16FCE100B34460 /* lexer.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BC18C52D0E16FCE100B34460 /* lexer.lut.h */; }; 255 255 BC18C5300E16FCEB00B34460 /* grammar.h in Headers */ = {isa = PBXBuildFile; fileRef = BC18C52F0E16FCEB00B34460 /* grammar.h */; }; 256 BC257DE80E1F51C50016B6C9 /* Arguments.h in Headers */ = {isa = PBXBuildFile; fileRef = BC257DE60E1F51C50016B6C9 /* Arguments.h */; }; 257 BC257DEC0E1F52BA0016B6C9 /* IndexToNameMap.h in Headers */ = {isa = PBXBuildFile; fileRef = BC257DEA0E1F52BA0016B6C9 /* IndexToNameMap.h */; }; 258 BC257DF00E1F52ED0016B6C9 /* GlobalEvalFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = BC257DEE0E1F52ED0016B6C9 /* GlobalEvalFunction.h */; }; 259 BC257DF40E1F53740016B6C9 /* PrototypeFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = BC257DF20E1F53740016B6C9 /* PrototypeFunction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 256 260 BC3046070E1F497F003232CF /* Error.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3046060E1F497F003232CF /* Error.h */; settings = {ATTRIBUTES = (Private, ); }; }; 257 261 BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; 262 BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */; }; 258 263 BC7F8FB90E19D1C3008632C0 /* JSNumberCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7F8FB80E19D1C3008632C0 /* JSNumberCell.h */; settings = {ATTRIBUTES = (Private, ); }; }; 259 264 BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD202BE0E1706A7002C7E82 /* RegExpConstructor.h */; }; … … 634 639 BC22A3990E16E14800AF21C8 /* JSObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObject.h; sourceTree = "<group>"; }; 635 640 BC22A39A0E16E14800AF21C8 /* JSVariableObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSVariableObject.cpp; sourceTree = "<group>"; }; 641 BC257DE50E1F51C50016B6C9 /* Arguments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Arguments.cpp; sourceTree = "<group>"; }; 642 BC257DE60E1F51C50016B6C9 /* Arguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Arguments.h; sourceTree = "<group>"; }; 643 BC257DE90E1F52BA0016B6C9 /* IndexToNameMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexToNameMap.cpp; sourceTree = "<group>"; }; 644 BC257DEA0E1F52BA0016B6C9 /* IndexToNameMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexToNameMap.h; sourceTree = "<group>"; }; 645 BC257DED0E1F52ED0016B6C9 /* GlobalEvalFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GlobalEvalFunction.cpp; sourceTree = "<group>"; }; 646 BC257DEE0E1F52ED0016B6C9 /* GlobalEvalFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlobalEvalFunction.h; sourceTree = "<group>"; }; 647 BC257DF10E1F53740016B6C9 /* PrototypeFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrototypeFunction.cpp; sourceTree = "<group>"; }; 648 BC257DF20E1F53740016B6C9 /* PrototypeFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrototypeFunction.h; sourceTree = "<group>"; }; 636 649 BC2680C00E16D4E900A06E92 /* FunctionConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionConstructor.cpp; sourceTree = "<group>"; }; 637 650 BC2680C10E16D4E900A06E92 /* FunctionConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FunctionConstructor.h; sourceTree = "<group>"; }; … … 649 662 BC337BEA0E1B00CB0076918A /* Error.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Error.cpp; sourceTree = "<group>"; }; 650 663 BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassInfo.h; sourceTree = "<group>"; }; 664 BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalObjectFunctions.cpp; sourceTree = "<group>"; }; 665 BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObjectFunctions.h; sourceTree = "<group>"; }; 651 666 BC7952060E15E8A800A898AB /* ArrayConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayConstructor.cpp; sourceTree = "<group>"; }; 652 667 BC7952070E15E8A800A898AB /* ArrayConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayConstructor.h; sourceTree = "<group>"; }; … … 1050 1065 children = ( 1051 1066 659126BC0BDD1728001921FB /* AllInOneFile.cpp */, 1067 BC257DE50E1F51C50016B6C9 /* Arguments.cpp */, 1068 BC257DE60E1F51C50016B6C9 /* Arguments.h */, 1052 1069 BC7952060E15E8A800A898AB /* ArrayConstructor.cpp */, 1053 1070 BC7952070E15E8A800A898AB /* ArrayConstructor.h */, … … 1099 1116 BC02E9B80E184545000F9297 /* GetterSetter.cpp */, 1100 1117 BC337BDE0E1AF0B80076918A /* GetterSetter.h */, 1118 BC257DED0E1F52ED0016B6C9 /* GlobalEvalFunction.cpp */, 1119 BC257DEE0E1F52ED0016B6C9 /* GlobalEvalFunction.h */, 1101 1120 933A349D038AE80F008635CE /* identifier.cpp */, 1102 1121 933A349A038AE7C6008635CE /* identifier.h */, 1122 BC257DE90E1F52BA0016B6C9 /* IndexToNameMap.cpp */, 1123 BC257DEA0E1F52BA0016B6C9 /* IndexToNameMap.h */, 1103 1124 E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */, 1104 1125 E178633F0D9BEC0000D74E75 /* InitializeThreading.h */, … … 1119 1140 14DE0D680D02431400AACCA2 /* JSGlobalObject.cpp */, 1120 1141 A8E894330CD0603F00367179 /* JSGlobalObject.h */, 1142 BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */, 1143 BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */, 1121 1144 14760863099C633800437128 /* JSImmediate.cpp */, 1122 1145 1483B589099BC1950016E4F0 /* JSImmediate.h */, … … 1169 1192 65621E6B089E859700760F35 /* PropertySlot.cpp */, 1170 1193 65621E6C089E859700760F35 /* PropertySlot.h */, 1194 BC257DF10E1F53740016B6C9 /* PrototypeFunction.cpp */, 1195 BC257DF20E1F53740016B6C9 /* PrototypeFunction.h */, 1171 1196 65C02FBB0637462A003E7EE6 /* protect.h */, 1172 1197 F692A87D0255597D01FF60F7 /* regexp.cpp */, … … 1456 1481 BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */, 1457 1482 BC3046070E1F497F003232CF /* Error.h in Headers */, 1483 BC257DE80E1F51C50016B6C9 /* Arguments.h in Headers */, 1484 BC257DEC0E1F52BA0016B6C9 /* IndexToNameMap.h in Headers */, 1485 BC257DF00E1F52ED0016B6C9 /* GlobalEvalFunction.h in Headers */, 1486 BC257DF40E1F53740016B6C9 /* PrototypeFunction.h in Headers */, 1487 BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */, 1458 1488 ); 1459 1489 runOnlyForDeploymentPostprocessing = 0; -
trunk/JavaScriptCore/JavaScriptCoreSources.bkl
r35007 r35016 44 44 <set append="1" var="JSCORE_SOURCES_KJS"> 45 45 DerivedSources/JavaScriptCore/grammar.cpp 46 kjs/ JSArray.cpp46 kjs/Arguments.cpp 47 47 kjs/ArrayConstructor.cpp 48 48 kjs/ArrayPrototype.cpp … … 52 52 kjs/collector.cpp 53 53 kjs/CommonIdentifiers.cpp 54 kjs/DateConstructor.cpp 54 55 kjs/DateInstance.cpp 55 kjs/DateConstructor.cpp56 56 kjs/DateMath.cpp 57 57 kjs/DatePrototype.cpp … … 64 64 kjs/ErrorPrototype.cpp 65 65 kjs/ExecState.cpp 66 kjs/GetterSetter.cpp67 kjs/JSFunction.cpp68 66 kjs/FunctionConstructor.cpp 69 67 kjs/FunctionPrototype.cpp 68 kjs/GetterSetter.cpp 69 kjs/GlobalEvalFunction.cpp 70 70 kjs/identifier.cpp 71 kjs/IndexToNameMap.cpp 71 72 kjs/InitializeThreading.cpp 72 73 kjs/InternalFunction.cpp 73 74 kjs/interpreter.cpp 74 75 kjs/JSActivation.cpp 76 kjs/JSArray.cpp 75 77 kjs/JSCell.cpp 78 kjs/JSFunction.cpp 76 79 kjs/JSGlobalData.cpp 77 80 kjs/JSGlobalObject.cpp 78 kjs/JS VariableObject.cpp81 kjs/JSGlobalObjectFunctions.cpp 79 82 kjs/JSImmediate.cpp 80 83 kjs/JSLock.cpp 81 84 kjs/JSNotAnObject.cpp 82 85 kjs/JSNumberCell.cpp 86 kjs/JSObject.cpp 83 87 kjs/JSString.cpp 88 kjs/JSValue.cpp 89 kjs/JSVariableObject.cpp 84 90 kjs/JSWrapperObject.cpp 85 91 kjs/LabelStack.cpp … … 95 101 kjs/NumberObject.cpp 96 102 kjs/NumberPrototype.cpp 97 kjs/JSObject.cpp98 103 kjs/ObjectConstructor.cpp 99 104 kjs/ObjectPrototype.cpp … … 101 106 kjs/Parser.cpp 102 107 kjs/PropertyMap.cpp 108 kjs/PropertyNameArray.cpp 103 109 kjs/PropertySlot.cpp 104 kjs/Pro pertyNameArray.cpp110 kjs/PrototypeFunction.cpp 105 111 kjs/regexp.cpp 106 112 kjs/RegExpConstructor.cpp … … 112 118 kjs/StringPrototype.cpp 113 119 kjs/ustring.cpp 114 kjs/JSValue.cpp115 120 116 121 </set> -
trunk/JavaScriptCore/VM/Machine.cpp
r34981 r35016 35 35 #include "ExceptionHelpers.h" 36 36 #include "ExecState.h" 37 #include "GlobalEvalFunction.h" 37 38 #include "JSActivation.h" 38 39 #include "JSArray.h" -
trunk/JavaScriptCore/kjs/AllInOneFile.cpp
r35007 r35016 1 1 /* 2 * Copyright (C) 2006 Apple Inc. All rights reserved.2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 28 28 29 29 #include "JSFunction.cpp" 30 #include "IndexToNameMap.cpp" 31 #include "Arguments.cpp" 32 #include "JSGlobalObjectFunctions.cpp" 33 #include "PrototypeFunction.cpp" 34 #include "GlobalEvalFunction.cpp" 30 35 #include "debugger.cpp" 31 36 #include "JSArray.cpp" -
trunk/JavaScriptCore/kjs/Arguments.cpp
r35006 r35016 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 2 * Copyright (C) 1999-2002 Harri Porten ([email protected]) … … 25 24 26 25 #include "config.h" 26 #include "Arguments.h" 27 27 28 #include "JSFunction.h" 28 29 #include "ExecState.h" 30 #include "FunctionPrototype.h" 29 #include "JSGlobalObject.h" 31 30 #include "JSActivation.h" 32 #include "JSGlobalObject.h"33 #include "JSString.h"34 #include "Machine.h"35 #include "ObjectPrototype.h"36 #include "Parser.h"37 #include "PropertyNameArray.h"38 #include "ScopeChainMark.h"39 #include "debugger.h"40 #include "dtoa.h"41 #include "lexer.h"42 #include "nodes.h"43 #include "operations.h"44 #include <errno.h>45 #include <profiler/Profiler.h>46 #include <stdio.h>47 #include <stdlib.h>48 #include <string.h>49 #include <wtf/ASCIICType.h>50 #include <wtf/Assertions.h>51 #include <wtf/MathExtras.h>52 #include <wtf/unicode/UTF8.h>53 54 using namespace WTF;55 using namespace Unicode;56 31 57 32 namespace KJS { 58 59 // ----------------------------- JSFunction ----------------------------------60 61 const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };62 63 JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* b, ScopeChainNode* scopeChain)64 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)65 , body(b)66 , _scope(scopeChain)67 {68 }69 70 void JSFunction::mark()71 {72 InternalFunction::mark();73 body->mark();74 _scope.mark();75 }76 77 CallType JSFunction::getCallData(CallData& callData)78 {79 callData.js.functionBody = body.get();80 callData.js.scopeChain = _scope.node();81 return CallTypeJS;82 }83 84 JSValue* JSFunction::call(ExecState* exec, JSValue* thisValue, const ArgList& args)85 {86 return exec->machine()->execute(body.get(), exec, this, thisValue->toThisObject(exec), args, _scope.node(), exec->exceptionSlot());87 }88 89 JSValue* JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)90 {91 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());92 return exec->machine()->retrieveArguments(exec, thisObj);93 }94 95 JSValue* JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)96 {97 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());98 return exec->machine()->retrieveCaller(exec, thisObj);99 }100 101 JSValue* JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)102 {103 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());104 return jsNumber(exec, thisObj->body->parameters().size());105 }106 107 bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)108 {109 if (propertyName == exec->propertyNames().arguments) {110 slot.setCustom(this, argumentsGetter);111 return true;112 }113 114 if (propertyName == exec->propertyNames().length) {115 slot.setCustom(this, lengthGetter);116 return true;117 }118 119 if (propertyName == exec->propertyNames().caller) {120 slot.setCustom(this, callerGetter);121 return true;122 }123 124 return InternalFunction::getOwnPropertySlot(exec, propertyName, slot);125 }126 127 void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue* value)128 {129 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)130 return;131 InternalFunction::put(exec, propertyName, value);132 }133 134 bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)135 {136 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)137 return false;138 return InternalFunction::deleteProperty(exec, propertyName);139 }140 141 /* Returns the parameter name corresponding to the given index. eg:142 * function f1(x, y, z): getParameterName(0) --> x143 *144 * If a name appears more than once, only the last index at which145 * it appears associates with it. eg:146 * function f2(x, x): getParameterName(0) --> null147 */148 const Identifier& JSFunction::getParameterName(int index)149 {150 Vector<Identifier>& parameters = body->parameters();151 152 if (static_cast<size_t>(index) >= body->parameters().size())153 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;154 155 const Identifier& name = parameters[index];156 157 // Are there any subsequent parameters with the same name?158 size_t size = parameters.size();159 for (size_t i = index + 1; i < size; ++i)160 if (parameters[i] == name)161 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;162 163 return name;164 }165 166 // ECMA 13.2.2 [[Construct]]167 ConstructType JSFunction::getConstructData(ConstructData& constructData)168 {169 constructData.js.functionBody = body.get();170 constructData.js.scopeChain = _scope.node();171 return ConstructTypeJS;172 }173 174 JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)175 {176 JSObject* proto;177 JSValue* p = get(exec, exec->propertyNames().prototype);178 if (p->isObject())179 proto = static_cast<JSObject*>(p);180 else181 proto = exec->lexicalGlobalObject()->objectPrototype();182 183 JSObject* thisObj = new (exec) JSObject(proto);184 185 JSValue* result = exec->machine()->execute(body.get(), exec, this, thisObj, args, _scope.node(), exec->exceptionSlot());186 if (exec->hadException() || !result->isObject())187 return thisObj;188 return static_cast<JSObject*>(result);189 }190 191 // ------------------------------ IndexToNameMap ---------------------------------192 193 // We map indexes in the arguments array to their corresponding argument names.194 // Example: function f(x, y, z): arguments[0] = x, so we map 0 to Identifier("x").195 196 // Once we have an argument name, we can get and set the argument's value in the197 // activation object.198 199 // We use Identifier::null to indicate that a given argument's value200 // isn't stored in the activation object.201 202 IndexToNameMap::IndexToNameMap(JSFunction* func, const ArgList& args)203 {204 _map = new Identifier[args.size()];205 this->size = args.size();206 207 unsigned i = 0;208 ArgList::const_iterator end = args.end();209 for (ArgList::const_iterator it = args.begin(); it != end; ++i, ++it)210 _map[i] = func->getParameterName(i); // null if there is no corresponding parameter211 }212 213 IndexToNameMap::~IndexToNameMap()214 {215 delete [] _map;216 }217 218 bool IndexToNameMap::isMapped(const Identifier& index) const219 {220 bool indexIsNumber;221 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);222 223 if (!indexIsNumber)224 return false;225 226 if (indexAsNumber >= size)227 return false;228 229 if (_map[indexAsNumber].isNull())230 return false;231 232 return true;233 }234 235 void IndexToNameMap::unMap(ExecState* exec, const Identifier& index)236 {237 bool indexIsNumber;238 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);239 240 ASSERT(indexIsNumber && indexAsNumber < size);241 242 _map[indexAsNumber] = exec->propertyNames().nullIdentifier;243 }244 245 Identifier& IndexToNameMap::operator[](const Identifier& index)246 {247 bool indexIsNumber;248 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);249 250 ASSERT(indexIsNumber && indexAsNumber < size);251 252 return _map[indexAsNumber];253 }254 255 // ------------------------------ Arguments ---------------------------------256 33 257 34 const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 }; … … 316 93 } 317 94 318 // ------------------------------ Global Functions -----------------------------------319 320 static JSValue* encode(ExecState* exec, const ArgList& args, const char* do_not_escape)321 {322 UString r = "", s, str = args[0]->toString(exec);323 CString cstr = str.UTF8String(true);324 if (!cstr.c_str())325 return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");326 const char* p = cstr.c_str();327 for (size_t k = 0; k < cstr.size(); k++, p++) {328 char c = *p;329 if (c && strchr(do_not_escape, c)) {330 r.append(c);331 } else {332 char tmp[4];333 sprintf(tmp, "%%%02X", (unsigned char)c);334 r += tmp;335 }336 }337 return jsString(exec, r);338 }339 340 static JSValue* decode(ExecState* exec, const ArgList& args, const char* do_not_unescape, bool strict)341 {342 UString s = "", str = args[0]->toString(exec);343 int k = 0, len = str.size();344 const UChar* d = str.data();345 UChar u = 0;346 while (k < len) {347 const UChar* p = d + k;348 UChar c = *p;349 if (c == '%') {350 int charLen = 0;351 if (k <= len - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {352 const char b0 = Lexer::convertHex(p[1], p[2]);353 const int sequenceLen = UTF8SequenceLength(b0);354 if (sequenceLen != 0 && k <= len - sequenceLen * 3) {355 charLen = sequenceLen * 3;356 char sequence[5];357 sequence[0] = b0;358 for (int i = 1; i < sequenceLen; ++i) {359 const UChar* q = p + i * 3;360 if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))361 sequence[i] = Lexer::convertHex(q[1], q[2]);362 else {363 charLen = 0;364 break;365 }366 }367 if (charLen != 0) {368 sequence[sequenceLen] = 0;369 const int character = decodeUTF8Sequence(sequence);370 if (character < 0 || character >= 0x110000) {371 charLen = 0;372 } else if (character >= 0x10000) {373 // Convert to surrogate pair.374 s.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));375 u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));376 } else {377 u = static_cast<UChar>(character);378 }379 }380 }381 }382 if (charLen == 0) {383 if (strict)384 return throwError(exec, URIError);385 // The only case where we don't use "strict" mode is the "unescape" function.386 // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.387 if (k <= len - 6 && p[1] == 'u'388 && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])389 && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {390 charLen = 6;391 u = Lexer::convertUnicode(p[2], p[3], p[4], p[5]);392 }393 }394 if (charLen && (u == 0 || u >= 128 || !strchr(do_not_unescape, u))) {395 c = u;396 k += charLen - 1;397 }398 }399 k++;400 s.append(c);401 }402 return jsString(exec, s);403 }404 405 static bool isStrWhiteSpace(unsigned short c)406 {407 switch (c) {408 case 0x0009:409 case 0x000A:410 case 0x000B:411 case 0x000C:412 case 0x000D:413 case 0x0020:414 case 0x00A0:415 case 0x2028:416 case 0x2029:417 return true;418 default:419 return c > 0xff && isSeparatorSpace(c);420 }421 }422 423 static int parseDigit(unsigned short c, int radix)424 {425 int digit = -1;426 427 if (c >= '0' && c <= '9') {428 digit = c - '0';429 } else if (c >= 'A' && c <= 'Z') {430 digit = c - 'A' + 10;431 } else if (c >= 'a' && c <= 'z') {432 digit = c - 'a' + 10;433 }434 435 if (digit >= radix)436 return -1;437 return digit;438 }439 440 double parseIntOverflow(const char* s, int length, int radix)441 {442 double number = 0.0;443 double radixMultiplier = 1.0;444 445 for (const char* p = s + length - 1; p >= s; p--) {446 if (radixMultiplier == Inf) {447 if (*p != '0') {448 number = Inf;449 break;450 }451 } else {452 int digit = parseDigit(*p, radix);453 number += digit * radixMultiplier;454 }455 456 radixMultiplier *= radix;457 }458 459 return number;460 }461 462 static double parseInt(const UString& s, int radix)463 {464 int length = s.size();465 int p = 0;466 467 while (p < length && isStrWhiteSpace(s[p])) {468 ++p;469 }470 471 double sign = 1;472 if (p < length) {473 if (s[p] == '+') {474 ++p;475 } else if (s[p] == '-') {476 sign = -1;477 ++p;478 }479 }480 481 if ((radix == 0 || radix == 16) && length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {482 radix = 16;483 p += 2;484 } else if (radix == 0) {485 if (p < length && s[p] == '0')486 radix = 8;487 else488 radix = 10;489 }490 491 if (radix < 2 || radix > 36)492 return NaN;493 494 int firstDigitPosition = p;495 bool sawDigit = false;496 double number = 0;497 while (p < length) {498 int digit = parseDigit(s[p], radix);499 if (digit == -1)500 break;501 sawDigit = true;502 number *= radix;503 number += digit;504 ++p;505 }506 507 if (number >= mantissaOverflowLowerBound) {508 if (radix == 10)509 number = strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0);510 else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)511 number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), p - firstDigitPosition, radix);512 }513 514 if (!sawDigit)515 return NaN;516 517 return sign * number;518 }519 520 static double parseFloat(const UString& s)521 {522 // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0.523 // Need to skip any whitespace and then one + or - sign.524 int length = s.size();525 int p = 0;526 while (p < length && isStrWhiteSpace(s[p])) {527 ++p;528 }529 if (p < length && (s[p] == '+' || s[p] == '-')) {530 ++p;531 }532 if (length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {533 return 0;534 }535 536 return s.toDouble( true /*tolerant*/, false /* NaN for empty string */ );537 }538 539 JSValue* globalFuncEval(ExecState* exec, JSObject* function, JSValue* thisValue, const ArgList& args)540 {541 JSObject* thisObject = thisValue->toThisObject(exec);542 JSGlobalObject* globalObject = thisObject->toGlobalObject(exec);543 if (!globalObject || globalObject->evalFunction() != function)544 return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated");545 546 JSValue* x = args[0];547 if (!x->isString())548 return x;549 550 UString s = x->toString(exec);551 552 int sourceId;553 int errLine;554 UString errMsg;555 556 RefPtr<EvalNode> evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(s), &sourceId, &errLine, &errMsg);557 558 if (!evalNode)559 return throwError(exec, SyntaxError, errMsg, errLine, sourceId, NULL);560 561 return exec->machine()->execute(evalNode.get(), exec, thisObject, globalObject->globalScopeChain().node(), exec->exceptionSlot());562 }563 564 JSValue* globalFuncParseInt(ExecState* exec, JSObject*, JSValue*, const ArgList& args)565 {566 return jsNumber(exec, parseInt(args[0]->toString(exec), args[1]->toInt32(exec)));567 }568 569 JSValue* globalFuncParseFloat(ExecState* exec, JSObject*, JSValue*, const ArgList& args)570 {571 return jsNumber(exec, parseFloat(args[0]->toString(exec)));572 }573 574 JSValue* globalFuncIsNaN(ExecState* exec, JSObject*, JSValue*, const ArgList& args)575 {576 return jsBoolean(isnan(args[0]->toNumber(exec)));577 }578 579 JSValue* globalFuncIsFinite(ExecState* exec, JSObject*, JSValue*, const ArgList& args)580 {581 double n = args[0]->toNumber(exec);582 return jsBoolean(!isnan(n) && !isinf(n));583 }584 585 JSValue* globalFuncDecodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)586 {587 static const char do_not_unescape_when_decoding_URI[] =588 "#$&+,/:;=?@";589 590 return decode(exec, args, do_not_unescape_when_decoding_URI, true);591 }592 593 JSValue* globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)594 {595 return decode(exec, args, "", true);596 }597 598 JSValue* globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)599 {600 static const char do_not_escape_when_encoding_URI[] =601 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"602 "abcdefghijklmnopqrstuvwxyz"603 "0123456789"604 "!#$&'()*+,-./:;=?@_~";605 606 return encode(exec, args, do_not_escape_when_encoding_URI);607 }608 609 JSValue* globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)610 {611 static const char do_not_escape_when_encoding_URI_component[] =612 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"613 "abcdefghijklmnopqrstuvwxyz"614 "0123456789"615 "!'()*-._~";616 617 return encode(exec, args, do_not_escape_when_encoding_URI_component);618 }619 620 JSValue* globalFuncEscape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)621 {622 static const char do_not_escape[] =623 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"624 "abcdefghijklmnopqrstuvwxyz"625 "0123456789"626 "*+-./@_";627 628 UString r = "", s, str = args[0]->toString(exec);629 const UChar* c = str.data();630 for (int k = 0; k < str.size(); k++, c++) {631 int u = c[0];632 if (u > 255) {633 char tmp[7];634 sprintf(tmp, "%%u%04X", u);635 s = UString(tmp);636 } else if (u != 0 && strchr(do_not_escape, (char)u))637 s = UString(c, 1);638 else {639 char tmp[4];640 sprintf(tmp, "%%%02X", u);641 s = UString(tmp);642 }643 r += s;644 }645 646 return jsString(exec, r);647 }648 649 JSValue* globalFuncUnescape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)650 {651 UString s = "", str = args[0]->toString(exec);652 int k = 0, len = str.size();653 while (k < len) {654 const UChar* c = str.data() + k;655 UChar u;656 if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {657 if (Lexer::isHexDigit(c[2]) && Lexer::isHexDigit(c[3]) && Lexer::isHexDigit(c[4]) && Lexer::isHexDigit(c[5])) {658 u = Lexer::convertUnicode(c[2], c[3], c[4], c[5]);659 c = &u;660 k += 5;661 }662 } else if (c[0] == '%' && k <= len - 3 && Lexer::isHexDigit(c[1]) && Lexer::isHexDigit(c[2])) {663 u = UChar(Lexer::convertHex(c[1], c[2]));664 c = &u;665 k += 2;666 }667 k++;668 s.append(*c);669 }670 671 return jsString(exec, s);672 }673 674 #ifndef NDEBUG675 JSValue* globalFuncKJSPrint(ExecState* exec, JSObject*, JSValue*, const ArgList& args)676 {677 CStringBuffer string;678 args[0]->toString(exec).getCString(string);679 puts(string.data());680 return jsUndefined();681 }682 #endif683 684 // ------------------------------ PrototypeFunction -------------------------------685 686 PrototypeFunction::PrototypeFunction(ExecState* exec, int len, const Identifier& name, NativeFunction function)687 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)688 , m_function(function)689 {690 ASSERT_ARG(function, function);691 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);692 }693 694 PrototypeFunction::PrototypeFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function)695 : InternalFunction(functionPrototype, name)696 , m_function(function)697 {698 ASSERT_ARG(function, function);699 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);700 }701 702 CallType PrototypeFunction::getCallData(CallData& callData)703 {704 callData.native.function = m_function;705 return CallTypeNative;706 }707 708 // ------------------------------ PrototypeReflexiveFunction -------------------------------709 710 GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)711 : PrototypeFunction(exec, functionPrototype, len, name, function)712 , m_cachedGlobalObject(cachedGlobalObject)713 {714 ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);715 }716 717 void GlobalEvalFunction::mark()718 {719 PrototypeFunction::mark();720 if (!m_cachedGlobalObject->marked())721 m_cachedGlobalObject->mark();722 }723 724 95 } // namespace KJS -
trunk/JavaScriptCore/kjs/Arguments.h
r35006 r35016 22 22 */ 23 23 24 #ifndef JSFunction_h25 #define JSFunction_h24 #ifndef Arguments_h 25 #define Arguments_h 26 26 27 #include "InternalFunction.h" 28 #include "JSVariableObject.h" 29 #include "SymbolTable.h" 30 #include "nodes.h" 27 #include "IndexToNameMap.h" 31 28 #include "JSObject.h" 32 29 33 30 namespace KJS { 34 31 35 class FunctionBodyNode;36 class FunctionPrototype;37 32 class JSActivation; 38 class JSGlobalObject;39 33 40 class JSFunction : public InternalFunction {41 public:42 JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*);43 44 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);45 virtual void put(ExecState*, const Identifier& propertyName, JSValue*);46 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);47 48 JSObject* construct(ExecState*, const ArgList&);49 JSValue* call(ExecState*, JSValue* thisValue, const ArgList&);50 51 // Note: Returns a null identifier for any parameters that will never get set52 // due to a later parameter with the same name.53 const Identifier& getParameterName(int index);54 55 static const ClassInfo info;56 57 RefPtr<FunctionBodyNode> body;58 59 void setScope(const ScopeChain& s) { _scope = s; }60 ScopeChain& scope() { return _scope; }61 62 virtual void mark();63 64 private:65 virtual const ClassInfo* classInfo() const { return &info; }66 virtual ConstructType getConstructData(ConstructData&);67 virtual CallType getCallData(CallData&);68 69 ScopeChain _scope;70 71 static JSValue* argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);72 static JSValue* callerGetter(ExecState*, const Identifier&, const PropertySlot&);73 static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&);74 };75 76 class IndexToNameMap {77 public:78 IndexToNameMap(JSFunction*, const ArgList&);79 ~IndexToNameMap();80 81 Identifier& operator[](const Identifier& index);82 bool isMapped(const Identifier& index) const;83 void unMap(ExecState* exec, const Identifier& index);84 85 private:86 unsigned size;87 Identifier* _map;88 };89 90 34 class Arguments : public JSObject { 91 35 public: … … 104 48 }; 105 49 106 class PrototypeFunction : public InternalFunction { 107 public: 108 PrototypeFunction(ExecState*, int len, const Identifier&, NativeFunction); 109 PrototypeFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, NativeFunction); 50 } // namespace KJS 110 51 111 private: 112 virtual CallType getCallData(CallData&); 113 114 const NativeFunction m_function; 115 }; 116 117 class GlobalEvalFunction : public PrototypeFunction { 118 public: 119 GlobalEvalFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject); 120 JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; } 121 122 private: 123 virtual void mark(); 124 125 JSGlobalObject* m_cachedGlobalObject; 126 }; 127 128 // Global Functions 129 JSValue* globalFuncEval(ExecState*, JSObject*, JSValue*, const ArgList&); 130 JSValue* globalFuncParseInt(ExecState*, JSObject*, JSValue*, const ArgList&); 131 JSValue* globalFuncParseFloat(ExecState*, JSObject*, JSValue*, const ArgList&); 132 JSValue* globalFuncIsNaN(ExecState*, JSObject*, JSValue*, const ArgList&); 133 JSValue* globalFuncIsFinite(ExecState*, JSObject*, JSValue*, const ArgList&); 134 JSValue* globalFuncDecodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); 135 JSValue* globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); 136 JSValue* globalFuncEncodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); 137 JSValue* globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); 138 JSValue* globalFuncEscape(ExecState*, JSObject*, JSValue*, const ArgList&); 139 JSValue* globalFuncUnescape(ExecState*, JSObject*, JSValue*, const ArgList&); 140 #ifndef NDEBUG 141 JSValue* globalFuncKJSPrint(ExecState*, JSObject*, JSValue*, const ArgList&); 142 #endif 143 144 static const double mantissaOverflowLowerBound = 9007199254740992.0; 145 double parseIntOverflow(const char*, int length, int radix); 146 147 } // namespace 148 149 #endif 52 #endif // Arguments_h -
trunk/JavaScriptCore/kjs/GlobalEvalFunction.cpp
r35006 r35016 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 2 * Copyright (C) 1999-2002 Harri Porten ([email protected]) … … 25 24 26 25 #include "config.h" 27 #include " JSFunction.h"26 #include "GlobalEvalFunction.h" 28 27 29 #include "ExecState.h"30 28 #include "FunctionPrototype.h" 31 #include "JSActivation.h"32 29 #include "JSGlobalObject.h" 33 #include "JSString.h"34 #include "Machine.h"35 #include "ObjectPrototype.h"36 #include "Parser.h"37 #include "PropertyNameArray.h"38 #include "ScopeChainMark.h"39 #include "debugger.h"40 #include "dtoa.h"41 #include "lexer.h"42 #include "nodes.h"43 #include "operations.h"44 #include <errno.h>45 #include <profiler/Profiler.h>46 #include <stdio.h>47 #include <stdlib.h>48 #include <string.h>49 #include <wtf/ASCIICType.h>50 30 #include <wtf/Assertions.h> 51 #include <wtf/MathExtras.h>52 #include <wtf/unicode/UTF8.h>53 54 using namespace WTF;55 using namespace Unicode;56 31 57 32 namespace KJS { 58 59 // ----------------------------- JSFunction ----------------------------------60 61 const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };62 63 JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* b, ScopeChainNode* scopeChain)64 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)65 , body(b)66 , _scope(scopeChain)67 {68 }69 70 void JSFunction::mark()71 {72 InternalFunction::mark();73 body->mark();74 _scope.mark();75 }76 77 CallType JSFunction::getCallData(CallData& callData)78 {79 callData.js.functionBody = body.get();80 callData.js.scopeChain = _scope.node();81 return CallTypeJS;82 }83 84 JSValue* JSFunction::call(ExecState* exec, JSValue* thisValue, const ArgList& args)85 {86 return exec->machine()->execute(body.get(), exec, this, thisValue->toThisObject(exec), args, _scope.node(), exec->exceptionSlot());87 }88 89 JSValue* JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)90 {91 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());92 return exec->machine()->retrieveArguments(exec, thisObj);93 }94 95 JSValue* JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)96 {97 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());98 return exec->machine()->retrieveCaller(exec, thisObj);99 }100 101 JSValue* JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)102 {103 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());104 return jsNumber(exec, thisObj->body->parameters().size());105 }106 107 bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)108 {109 if (propertyName == exec->propertyNames().arguments) {110 slot.setCustom(this, argumentsGetter);111 return true;112 }113 114 if (propertyName == exec->propertyNames().length) {115 slot.setCustom(this, lengthGetter);116 return true;117 }118 119 if (propertyName == exec->propertyNames().caller) {120 slot.setCustom(this, callerGetter);121 return true;122 }123 124 return InternalFunction::getOwnPropertySlot(exec, propertyName, slot);125 }126 127 void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue* value)128 {129 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)130 return;131 InternalFunction::put(exec, propertyName, value);132 }133 134 bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)135 {136 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)137 return false;138 return InternalFunction::deleteProperty(exec, propertyName);139 }140 141 /* Returns the parameter name corresponding to the given index. eg:142 * function f1(x, y, z): getParameterName(0) --> x143 *144 * If a name appears more than once, only the last index at which145 * it appears associates with it. eg:146 * function f2(x, x): getParameterName(0) --> null147 */148 const Identifier& JSFunction::getParameterName(int index)149 {150 Vector<Identifier>& parameters = body->parameters();151 152 if (static_cast<size_t>(index) >= body->parameters().size())153 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;154 155 const Identifier& name = parameters[index];156 157 // Are there any subsequent parameters with the same name?158 size_t size = parameters.size();159 for (size_t i = index + 1; i < size; ++i)160 if (parameters[i] == name)161 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;162 163 return name;164 }165 166 // ECMA 13.2.2 [[Construct]]167 ConstructType JSFunction::getConstructData(ConstructData& constructData)168 {169 constructData.js.functionBody = body.get();170 constructData.js.scopeChain = _scope.node();171 return ConstructTypeJS;172 }173 174 JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)175 {176 JSObject* proto;177 JSValue* p = get(exec, exec->propertyNames().prototype);178 if (p->isObject())179 proto = static_cast<JSObject*>(p);180 else181 proto = exec->lexicalGlobalObject()->objectPrototype();182 183 JSObject* thisObj = new (exec) JSObject(proto);184 185 JSValue* result = exec->machine()->execute(body.get(), exec, this, thisObj, args, _scope.node(), exec->exceptionSlot());186 if (exec->hadException() || !result->isObject())187 return thisObj;188 return static_cast<JSObject*>(result);189 }190 191 // ------------------------------ IndexToNameMap ---------------------------------192 193 // We map indexes in the arguments array to their corresponding argument names.194 // Example: function f(x, y, z): arguments[0] = x, so we map 0 to Identifier("x").195 196 // Once we have an argument name, we can get and set the argument's value in the197 // activation object.198 199 // We use Identifier::null to indicate that a given argument's value200 // isn't stored in the activation object.201 202 IndexToNameMap::IndexToNameMap(JSFunction* func, const ArgList& args)203 {204 _map = new Identifier[args.size()];205 this->size = args.size();206 207 unsigned i = 0;208 ArgList::const_iterator end = args.end();209 for (ArgList::const_iterator it = args.begin(); it != end; ++i, ++it)210 _map[i] = func->getParameterName(i); // null if there is no corresponding parameter211 }212 213 IndexToNameMap::~IndexToNameMap()214 {215 delete [] _map;216 }217 218 bool IndexToNameMap::isMapped(const Identifier& index) const219 {220 bool indexIsNumber;221 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);222 223 if (!indexIsNumber)224 return false;225 226 if (indexAsNumber >= size)227 return false;228 229 if (_map[indexAsNumber].isNull())230 return false;231 232 return true;233 }234 235 void IndexToNameMap::unMap(ExecState* exec, const Identifier& index)236 {237 bool indexIsNumber;238 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);239 240 ASSERT(indexIsNumber && indexAsNumber < size);241 242 _map[indexAsNumber] = exec->propertyNames().nullIdentifier;243 }244 245 Identifier& IndexToNameMap::operator[](const Identifier& index)246 {247 bool indexIsNumber;248 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);249 250 ASSERT(indexIsNumber && indexAsNumber < size);251 252 return _map[indexAsNumber];253 }254 255 // ------------------------------ Arguments ---------------------------------256 257 const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };258 259 // ECMA 10.1.8260 Arguments::Arguments(ExecState* exec, JSFunction* func, const ArgList& args, JSActivation* act)261 : JSObject(exec->lexicalGlobalObject()->objectPrototype())262 , _activationObject(act)263 , indexToNameMap(func, args)264 {265 putDirect(exec->propertyNames().callee, func, DontEnum);266 putDirect(exec, exec->propertyNames().length, args.size(), DontEnum);267 268 int i = 0;269 ArgList::const_iterator end = args.end();270 for (ArgList::const_iterator it = args.begin(); it != end; ++it, ++i) {271 Identifier name = Identifier::from(exec, i);272 if (!indexToNameMap.isMapped(name))273 putDirect(name, *it, DontEnum);274 }275 }276 277 void Arguments::mark()278 {279 JSObject::mark();280 if (_activationObject && !_activationObject->marked())281 _activationObject->mark();282 }283 284 JSValue* Arguments::mappedIndexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)285 {286 Arguments* thisObj = static_cast<Arguments*>(slot.slotBase());287 return thisObj->_activationObject->get(exec, thisObj->indexToNameMap[propertyName]);288 }289 290 bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)291 {292 if (indexToNameMap.isMapped(propertyName)) {293 slot.setCustom(this, mappedIndexGetter);294 return true;295 }296 297 return JSObject::getOwnPropertySlot(exec, propertyName, slot);298 }299 300 void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value)301 {302 if (indexToNameMap.isMapped(propertyName))303 _activationObject->put(exec, indexToNameMap[propertyName], value);304 else305 JSObject::put(exec, propertyName, value);306 }307 308 bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)309 {310 if (indexToNameMap.isMapped(propertyName)) {311 indexToNameMap.unMap(exec, propertyName);312 return true;313 } else {314 return JSObject::deleteProperty(exec, propertyName);315 }316 }317 318 // ------------------------------ Global Functions -----------------------------------319 320 static JSValue* encode(ExecState* exec, const ArgList& args, const char* do_not_escape)321 {322 UString r = "", s, str = args[0]->toString(exec);323 CString cstr = str.UTF8String(true);324 if (!cstr.c_str())325 return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");326 const char* p = cstr.c_str();327 for (size_t k = 0; k < cstr.size(); k++, p++) {328 char c = *p;329 if (c && strchr(do_not_escape, c)) {330 r.append(c);331 } else {332 char tmp[4];333 sprintf(tmp, "%%%02X", (unsigned char)c);334 r += tmp;335 }336 }337 return jsString(exec, r);338 }339 340 static JSValue* decode(ExecState* exec, const ArgList& args, const char* do_not_unescape, bool strict)341 {342 UString s = "", str = args[0]->toString(exec);343 int k = 0, len = str.size();344 const UChar* d = str.data();345 UChar u = 0;346 while (k < len) {347 const UChar* p = d + k;348 UChar c = *p;349 if (c == '%') {350 int charLen = 0;351 if (k <= len - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {352 const char b0 = Lexer::convertHex(p[1], p[2]);353 const int sequenceLen = UTF8SequenceLength(b0);354 if (sequenceLen != 0 && k <= len - sequenceLen * 3) {355 charLen = sequenceLen * 3;356 char sequence[5];357 sequence[0] = b0;358 for (int i = 1; i < sequenceLen; ++i) {359 const UChar* q = p + i * 3;360 if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))361 sequence[i] = Lexer::convertHex(q[1], q[2]);362 else {363 charLen = 0;364 break;365 }366 }367 if (charLen != 0) {368 sequence[sequenceLen] = 0;369 const int character = decodeUTF8Sequence(sequence);370 if (character < 0 || character >= 0x110000) {371 charLen = 0;372 } else if (character >= 0x10000) {373 // Convert to surrogate pair.374 s.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));375 u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));376 } else {377 u = static_cast<UChar>(character);378 }379 }380 }381 }382 if (charLen == 0) {383 if (strict)384 return throwError(exec, URIError);385 // The only case where we don't use "strict" mode is the "unescape" function.386 // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.387 if (k <= len - 6 && p[1] == 'u'388 && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])389 && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {390 charLen = 6;391 u = Lexer::convertUnicode(p[2], p[3], p[4], p[5]);392 }393 }394 if (charLen && (u == 0 || u >= 128 || !strchr(do_not_unescape, u))) {395 c = u;396 k += charLen - 1;397 }398 }399 k++;400 s.append(c);401 }402 return jsString(exec, s);403 }404 405 static bool isStrWhiteSpace(unsigned short c)406 {407 switch (c) {408 case 0x0009:409 case 0x000A:410 case 0x000B:411 case 0x000C:412 case 0x000D:413 case 0x0020:414 case 0x00A0:415 case 0x2028:416 case 0x2029:417 return true;418 default:419 return c > 0xff && isSeparatorSpace(c);420 }421 }422 423 static int parseDigit(unsigned short c, int radix)424 {425 int digit = -1;426 427 if (c >= '0' && c <= '9') {428 digit = c - '0';429 } else if (c >= 'A' && c <= 'Z') {430 digit = c - 'A' + 10;431 } else if (c >= 'a' && c <= 'z') {432 digit = c - 'a' + 10;433 }434 435 if (digit >= radix)436 return -1;437 return digit;438 }439 440 double parseIntOverflow(const char* s, int length, int radix)441 {442 double number = 0.0;443 double radixMultiplier = 1.0;444 445 for (const char* p = s + length - 1; p >= s; p--) {446 if (radixMultiplier == Inf) {447 if (*p != '0') {448 number = Inf;449 break;450 }451 } else {452 int digit = parseDigit(*p, radix);453 number += digit * radixMultiplier;454 }455 456 radixMultiplier *= radix;457 }458 459 return number;460 }461 462 static double parseInt(const UString& s, int radix)463 {464 int length = s.size();465 int p = 0;466 467 while (p < length && isStrWhiteSpace(s[p])) {468 ++p;469 }470 471 double sign = 1;472 if (p < length) {473 if (s[p] == '+') {474 ++p;475 } else if (s[p] == '-') {476 sign = -1;477 ++p;478 }479 }480 481 if ((radix == 0 || radix == 16) && length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {482 radix = 16;483 p += 2;484 } else if (radix == 0) {485 if (p < length && s[p] == '0')486 radix = 8;487 else488 radix = 10;489 }490 491 if (radix < 2 || radix > 36)492 return NaN;493 494 int firstDigitPosition = p;495 bool sawDigit = false;496 double number = 0;497 while (p < length) {498 int digit = parseDigit(s[p], radix);499 if (digit == -1)500 break;501 sawDigit = true;502 number *= radix;503 number += digit;504 ++p;505 }506 507 if (number >= mantissaOverflowLowerBound) {508 if (radix == 10)509 number = strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0);510 else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)511 number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), p - firstDigitPosition, radix);512 }513 514 if (!sawDigit)515 return NaN;516 517 return sign * number;518 }519 520 static double parseFloat(const UString& s)521 {522 // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0.523 // Need to skip any whitespace and then one + or - sign.524 int length = s.size();525 int p = 0;526 while (p < length && isStrWhiteSpace(s[p])) {527 ++p;528 }529 if (p < length && (s[p] == '+' || s[p] == '-')) {530 ++p;531 }532 if (length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {533 return 0;534 }535 536 return s.toDouble( true /*tolerant*/, false /* NaN for empty string */ );537 }538 539 JSValue* globalFuncEval(ExecState* exec, JSObject* function, JSValue* thisValue, const ArgList& args)540 {541 JSObject* thisObject = thisValue->toThisObject(exec);542 JSGlobalObject* globalObject = thisObject->toGlobalObject(exec);543 if (!globalObject || globalObject->evalFunction() != function)544 return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated");545 546 JSValue* x = args[0];547 if (!x->isString())548 return x;549 550 UString s = x->toString(exec);551 552 int sourceId;553 int errLine;554 UString errMsg;555 556 RefPtr<EvalNode> evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(s), &sourceId, &errLine, &errMsg);557 558 if (!evalNode)559 return throwError(exec, SyntaxError, errMsg, errLine, sourceId, NULL);560 561 return exec->machine()->execute(evalNode.get(), exec, thisObject, globalObject->globalScopeChain().node(), exec->exceptionSlot());562 }563 564 JSValue* globalFuncParseInt(ExecState* exec, JSObject*, JSValue*, const ArgList& args)565 {566 return jsNumber(exec, parseInt(args[0]->toString(exec), args[1]->toInt32(exec)));567 }568 569 JSValue* globalFuncParseFloat(ExecState* exec, JSObject*, JSValue*, const ArgList& args)570 {571 return jsNumber(exec, parseFloat(args[0]->toString(exec)));572 }573 574 JSValue* globalFuncIsNaN(ExecState* exec, JSObject*, JSValue*, const ArgList& args)575 {576 return jsBoolean(isnan(args[0]->toNumber(exec)));577 }578 579 JSValue* globalFuncIsFinite(ExecState* exec, JSObject*, JSValue*, const ArgList& args)580 {581 double n = args[0]->toNumber(exec);582 return jsBoolean(!isnan(n) && !isinf(n));583 }584 585 JSValue* globalFuncDecodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)586 {587 static const char do_not_unescape_when_decoding_URI[] =588 "#$&+,/:;=?@";589 590 return decode(exec, args, do_not_unescape_when_decoding_URI, true);591 }592 593 JSValue* globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)594 {595 return decode(exec, args, "", true);596 }597 598 JSValue* globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)599 {600 static const char do_not_escape_when_encoding_URI[] =601 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"602 "abcdefghijklmnopqrstuvwxyz"603 "0123456789"604 "!#$&'()*+,-./:;=?@_~";605 606 return encode(exec, args, do_not_escape_when_encoding_URI);607 }608 609 JSValue* globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)610 {611 static const char do_not_escape_when_encoding_URI_component[] =612 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"613 "abcdefghijklmnopqrstuvwxyz"614 "0123456789"615 "!'()*-._~";616 617 return encode(exec, args, do_not_escape_when_encoding_URI_component);618 }619 620 JSValue* globalFuncEscape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)621 {622 static const char do_not_escape[] =623 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"624 "abcdefghijklmnopqrstuvwxyz"625 "0123456789"626 "*+-./@_";627 628 UString r = "", s, str = args[0]->toString(exec);629 const UChar* c = str.data();630 for (int k = 0; k < str.size(); k++, c++) {631 int u = c[0];632 if (u > 255) {633 char tmp[7];634 sprintf(tmp, "%%u%04X", u);635 s = UString(tmp);636 } else if (u != 0 && strchr(do_not_escape, (char)u))637 s = UString(c, 1);638 else {639 char tmp[4];640 sprintf(tmp, "%%%02X", u);641 s = UString(tmp);642 }643 r += s;644 }645 646 return jsString(exec, r);647 }648 649 JSValue* globalFuncUnescape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)650 {651 UString s = "", str = args[0]->toString(exec);652 int k = 0, len = str.size();653 while (k < len) {654 const UChar* c = str.data() + k;655 UChar u;656 if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {657 if (Lexer::isHexDigit(c[2]) && Lexer::isHexDigit(c[3]) && Lexer::isHexDigit(c[4]) && Lexer::isHexDigit(c[5])) {658 u = Lexer::convertUnicode(c[2], c[3], c[4], c[5]);659 c = &u;660 k += 5;661 }662 } else if (c[0] == '%' && k <= len - 3 && Lexer::isHexDigit(c[1]) && Lexer::isHexDigit(c[2])) {663 u = UChar(Lexer::convertHex(c[1], c[2]));664 c = &u;665 k += 2;666 }667 k++;668 s.append(*c);669 }670 671 return jsString(exec, s);672 }673 674 #ifndef NDEBUG675 JSValue* globalFuncKJSPrint(ExecState* exec, JSObject*, JSValue*, const ArgList& args)676 {677 CStringBuffer string;678 args[0]->toString(exec).getCString(string);679 puts(string.data());680 return jsUndefined();681 }682 #endif683 684 // ------------------------------ PrototypeFunction -------------------------------685 686 PrototypeFunction::PrototypeFunction(ExecState* exec, int len, const Identifier& name, NativeFunction function)687 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)688 , m_function(function)689 {690 ASSERT_ARG(function, function);691 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);692 }693 694 PrototypeFunction::PrototypeFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function)695 : InternalFunction(functionPrototype, name)696 , m_function(function)697 {698 ASSERT_ARG(function, function);699 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);700 }701 702 CallType PrototypeFunction::getCallData(CallData& callData)703 {704 callData.native.function = m_function;705 return CallTypeNative;706 }707 708 // ------------------------------ PrototypeReflexiveFunction -------------------------------709 33 710 34 GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject) -
trunk/JavaScriptCore/kjs/GlobalEvalFunction.h
r35006 r35016 22 22 */ 23 23 24 #ifndef JSFunction_h25 #define JSFunction_h24 #ifndef GlobalEvalFunction_h 25 #define GlobalEvalFunction_h 26 26 27 #include "InternalFunction.h" 28 #include "JSVariableObject.h" 29 #include "SymbolTable.h" 30 #include "nodes.h" 31 #include "JSObject.h" 27 #include "PrototypeFunction.h" 32 28 33 29 namespace KJS { 34 30 35 class FunctionBodyNode;31 class ExecState; 36 32 class FunctionPrototype; 37 class JSActivation;38 33 class JSGlobalObject; 39 40 class JSFunction : public InternalFunction {41 public:42 JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*);43 44 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);45 virtual void put(ExecState*, const Identifier& propertyName, JSValue*);46 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);47 48 JSObject* construct(ExecState*, const ArgList&);49 JSValue* call(ExecState*, JSValue* thisValue, const ArgList&);50 51 // Note: Returns a null identifier for any parameters that will never get set52 // due to a later parameter with the same name.53 const Identifier& getParameterName(int index);54 55 static const ClassInfo info;56 57 RefPtr<FunctionBodyNode> body;58 59 void setScope(const ScopeChain& s) { _scope = s; }60 ScopeChain& scope() { return _scope; }61 62 virtual void mark();63 64 private:65 virtual const ClassInfo* classInfo() const { return &info; }66 virtual ConstructType getConstructData(ConstructData&);67 virtual CallType getCallData(CallData&);68 69 ScopeChain _scope;70 71 static JSValue* argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);72 static JSValue* callerGetter(ExecState*, const Identifier&, const PropertySlot&);73 static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&);74 };75 76 class IndexToNameMap {77 public:78 IndexToNameMap(JSFunction*, const ArgList&);79 ~IndexToNameMap();80 81 Identifier& operator[](const Identifier& index);82 bool isMapped(const Identifier& index) const;83 void unMap(ExecState* exec, const Identifier& index);84 85 private:86 unsigned size;87 Identifier* _map;88 };89 90 class Arguments : public JSObject {91 public:92 Arguments(ExecState*, JSFunction* func, const ArgList& args, JSActivation* act);93 virtual void mark();94 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);95 virtual void put(ExecState*, const Identifier& propertyName, JSValue*);96 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);97 virtual const ClassInfo* classInfo() const { return &info; }98 static const ClassInfo info;99 private:100 static JSValue* mappedIndexGetter(ExecState*, const Identifier&, const PropertySlot& slot);101 102 JSActivation* _activationObject;103 mutable IndexToNameMap indexToNameMap;104 };105 106 class PrototypeFunction : public InternalFunction {107 public:108 PrototypeFunction(ExecState*, int len, const Identifier&, NativeFunction);109 PrototypeFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, NativeFunction);110 111 private:112 virtual CallType getCallData(CallData&);113 114 const NativeFunction m_function;115 };116 34 117 35 class GlobalEvalFunction : public PrototypeFunction { … … 126 44 }; 127 45 128 // Global Functions 129 JSValue* globalFuncEval(ExecState*, JSObject*, JSValue*, const ArgList&); 130 JSValue* globalFuncParseInt(ExecState*, JSObject*, JSValue*, const ArgList&); 131 JSValue* globalFuncParseFloat(ExecState*, JSObject*, JSValue*, const ArgList&); 132 JSValue* globalFuncIsNaN(ExecState*, JSObject*, JSValue*, const ArgList&); 133 JSValue* globalFuncIsFinite(ExecState*, JSObject*, JSValue*, const ArgList&); 134 JSValue* globalFuncDecodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); 135 JSValue* globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); 136 JSValue* globalFuncEncodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); 137 JSValue* globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); 138 JSValue* globalFuncEscape(ExecState*, JSObject*, JSValue*, const ArgList&); 139 JSValue* globalFuncUnescape(ExecState*, JSObject*, JSValue*, const ArgList&); 140 #ifndef NDEBUG 141 JSValue* globalFuncKJSPrint(ExecState*, JSObject*, JSValue*, const ArgList&); 142 #endif 46 } // namespace KJS 143 47 144 static const double mantissaOverflowLowerBound = 9007199254740992.0; 145 double parseIntOverflow(const char*, int length, int radix); 146 147 } // namespace 148 149 #endif 48 #endif // GlobalEvalFunction_h -
trunk/JavaScriptCore/kjs/IndexToNameMap.cpp
r35006 r35016 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 2 * Copyright (C) 1999-2002 Harri Porten ([email protected]) … … 25 24 26 25 #include "config.h" 26 #include "IndexToNameMap.h" 27 28 #include "Identifier.h" 29 #include "list.h" 27 30 #include "JSFunction.h" 28 31 29 #include "ExecState.h"30 #include "FunctionPrototype.h"31 #include "JSActivation.h"32 #include "JSGlobalObject.h"33 #include "JSString.h"34 #include "Machine.h"35 #include "ObjectPrototype.h"36 #include "Parser.h"37 #include "PropertyNameArray.h"38 #include "ScopeChainMark.h"39 #include "debugger.h"40 #include "dtoa.h"41 #include "lexer.h"42 #include "nodes.h"43 #include "operations.h"44 #include <errno.h>45 #include <profiler/Profiler.h>46 #include <stdio.h>47 #include <stdlib.h>48 #include <string.h>49 #include <wtf/ASCIICType.h>50 #include <wtf/Assertions.h>51 #include <wtf/MathExtras.h>52 #include <wtf/unicode/UTF8.h>53 54 using namespace WTF;55 using namespace Unicode;56 57 32 namespace KJS { 58 59 // ----------------------------- JSFunction ----------------------------------60 61 const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };62 63 JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* b, ScopeChainNode* scopeChain)64 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)65 , body(b)66 , _scope(scopeChain)67 {68 }69 70 void JSFunction::mark()71 {72 InternalFunction::mark();73 body->mark();74 _scope.mark();75 }76 77 CallType JSFunction::getCallData(CallData& callData)78 {79 callData.js.functionBody = body.get();80 callData.js.scopeChain = _scope.node();81 return CallTypeJS;82 }83 84 JSValue* JSFunction::call(ExecState* exec, JSValue* thisValue, const ArgList& args)85 {86 return exec->machine()->execute(body.get(), exec, this, thisValue->toThisObject(exec), args, _scope.node(), exec->exceptionSlot());87 }88 89 JSValue* JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)90 {91 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());92 return exec->machine()->retrieveArguments(exec, thisObj);93 }94 95 JSValue* JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)96 {97 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());98 return exec->machine()->retrieveCaller(exec, thisObj);99 }100 101 JSValue* JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)102 {103 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());104 return jsNumber(exec, thisObj->body->parameters().size());105 }106 107 bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)108 {109 if (propertyName == exec->propertyNames().arguments) {110 slot.setCustom(this, argumentsGetter);111 return true;112 }113 114 if (propertyName == exec->propertyNames().length) {115 slot.setCustom(this, lengthGetter);116 return true;117 }118 119 if (propertyName == exec->propertyNames().caller) {120 slot.setCustom(this, callerGetter);121 return true;122 }123 124 return InternalFunction::getOwnPropertySlot(exec, propertyName, slot);125 }126 127 void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue* value)128 {129 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)130 return;131 InternalFunction::put(exec, propertyName, value);132 }133 134 bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)135 {136 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)137 return false;138 return InternalFunction::deleteProperty(exec, propertyName);139 }140 141 /* Returns the parameter name corresponding to the given index. eg:142 * function f1(x, y, z): getParameterName(0) --> x143 *144 * If a name appears more than once, only the last index at which145 * it appears associates with it. eg:146 * function f2(x, x): getParameterName(0) --> null147 */148 const Identifier& JSFunction::getParameterName(int index)149 {150 Vector<Identifier>& parameters = body->parameters();151 152 if (static_cast<size_t>(index) >= body->parameters().size())153 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;154 155 const Identifier& name = parameters[index];156 157 // Are there any subsequent parameters with the same name?158 size_t size = parameters.size();159 for (size_t i = index + 1; i < size; ++i)160 if (parameters[i] == name)161 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;162 163 return name;164 }165 166 // ECMA 13.2.2 [[Construct]]167 ConstructType JSFunction::getConstructData(ConstructData& constructData)168 {169 constructData.js.functionBody = body.get();170 constructData.js.scopeChain = _scope.node();171 return ConstructTypeJS;172 }173 174 JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)175 {176 JSObject* proto;177 JSValue* p = get(exec, exec->propertyNames().prototype);178 if (p->isObject())179 proto = static_cast<JSObject*>(p);180 else181 proto = exec->lexicalGlobalObject()->objectPrototype();182 183 JSObject* thisObj = new (exec) JSObject(proto);184 185 JSValue* result = exec->machine()->execute(body.get(), exec, this, thisObj, args, _scope.node(), exec->exceptionSlot());186 if (exec->hadException() || !result->isObject())187 return thisObj;188 return static_cast<JSObject*>(result);189 }190 191 // ------------------------------ IndexToNameMap ---------------------------------192 33 193 34 // We map indexes in the arguments array to their corresponding argument names. … … 253 94 } 254 95 255 // ------------------------------ Arguments ---------------------------------256 257 const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };258 259 // ECMA 10.1.8260 Arguments::Arguments(ExecState* exec, JSFunction* func, const ArgList& args, JSActivation* act)261 : JSObject(exec->lexicalGlobalObject()->objectPrototype())262 , _activationObject(act)263 , indexToNameMap(func, args)264 {265 putDirect(exec->propertyNames().callee, func, DontEnum);266 putDirect(exec, exec->propertyNames().length, args.size(), DontEnum);267 268 int i = 0;269 ArgList::const_iterator end = args.end();270 for (ArgList::const_iterator it = args.begin(); it != end; ++it, ++i) {271 Identifier name = Identifier::from(exec, i);272 if (!indexToNameMap.isMapped(name))273 putDirect(name, *it, DontEnum);274 }275 }276 277 void Arguments::mark()278 {279 JSObject::mark();280 if (_activationObject && !_activationObject->marked())281 _activationObject->mark();282 }283 284 JSValue* Arguments::mappedIndexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)285 {286 Arguments* thisObj = static_cast<Arguments*>(slot.slotBase());287 return thisObj->_activationObject->get(exec, thisObj->indexToNameMap[propertyName]);288 }289 290 bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)291 {292 if (indexToNameMap.isMapped(propertyName)) {293 slot.setCustom(this, mappedIndexGetter);294 return true;295 }296 297 return JSObject::getOwnPropertySlot(exec, propertyName, slot);298 }299 300 void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value)301 {302 if (indexToNameMap.isMapped(propertyName))303 _activationObject->put(exec, indexToNameMap[propertyName], value);304 else305 JSObject::put(exec, propertyName, value);306 }307 308 bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)309 {310 if (indexToNameMap.isMapped(propertyName)) {311 indexToNameMap.unMap(exec, propertyName);312 return true;313 } else {314 return JSObject::deleteProperty(exec, propertyName);315 }316 }317 318 // ------------------------------ Global Functions -----------------------------------319 320 static JSValue* encode(ExecState* exec, const ArgList& args, const char* do_not_escape)321 {322 UString r = "", s, str = args[0]->toString(exec);323 CString cstr = str.UTF8String(true);324 if (!cstr.c_str())325 return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");326 const char* p = cstr.c_str();327 for (size_t k = 0; k < cstr.size(); k++, p++) {328 char c = *p;329 if (c && strchr(do_not_escape, c)) {330 r.append(c);331 } else {332 char tmp[4];333 sprintf(tmp, "%%%02X", (unsigned char)c);334 r += tmp;335 }336 }337 return jsString(exec, r);338 }339 340 static JSValue* decode(ExecState* exec, const ArgList& args, const char* do_not_unescape, bool strict)341 {342 UString s = "", str = args[0]->toString(exec);343 int k = 0, len = str.size();344 const UChar* d = str.data();345 UChar u = 0;346 while (k < len) {347 const UChar* p = d + k;348 UChar c = *p;349 if (c == '%') {350 int charLen = 0;351 if (k <= len - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {352 const char b0 = Lexer::convertHex(p[1], p[2]);353 const int sequenceLen = UTF8SequenceLength(b0);354 if (sequenceLen != 0 && k <= len - sequenceLen * 3) {355 charLen = sequenceLen * 3;356 char sequence[5];357 sequence[0] = b0;358 for (int i = 1; i < sequenceLen; ++i) {359 const UChar* q = p + i * 3;360 if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))361 sequence[i] = Lexer::convertHex(q[1], q[2]);362 else {363 charLen = 0;364 break;365 }366 }367 if (charLen != 0) {368 sequence[sequenceLen] = 0;369 const int character = decodeUTF8Sequence(sequence);370 if (character < 0 || character >= 0x110000) {371 charLen = 0;372 } else if (character >= 0x10000) {373 // Convert to surrogate pair.374 s.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));375 u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));376 } else {377 u = static_cast<UChar>(character);378 }379 }380 }381 }382 if (charLen == 0) {383 if (strict)384 return throwError(exec, URIError);385 // The only case where we don't use "strict" mode is the "unescape" function.386 // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.387 if (k <= len - 6 && p[1] == 'u'388 && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])389 && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {390 charLen = 6;391 u = Lexer::convertUnicode(p[2], p[3], p[4], p[5]);392 }393 }394 if (charLen && (u == 0 || u >= 128 || !strchr(do_not_unescape, u))) {395 c = u;396 k += charLen - 1;397 }398 }399 k++;400 s.append(c);401 }402 return jsString(exec, s);403 }404 405 static bool isStrWhiteSpace(unsigned short c)406 {407 switch (c) {408 case 0x0009:409 case 0x000A:410 case 0x000B:411 case 0x000C:412 case 0x000D:413 case 0x0020:414 case 0x00A0:415 case 0x2028:416 case 0x2029:417 return true;418 default:419 return c > 0xff && isSeparatorSpace(c);420 }421 }422 423 static int parseDigit(unsigned short c, int radix)424 {425 int digit = -1;426 427 if (c >= '0' && c <= '9') {428 digit = c - '0';429 } else if (c >= 'A' && c <= 'Z') {430 digit = c - 'A' + 10;431 } else if (c >= 'a' && c <= 'z') {432 digit = c - 'a' + 10;433 }434 435 if (digit >= radix)436 return -1;437 return digit;438 }439 440 double parseIntOverflow(const char* s, int length, int radix)441 {442 double number = 0.0;443 double radixMultiplier = 1.0;444 445 for (const char* p = s + length - 1; p >= s; p--) {446 if (radixMultiplier == Inf) {447 if (*p != '0') {448 number = Inf;449 break;450 }451 } else {452 int digit = parseDigit(*p, radix);453 number += digit * radixMultiplier;454 }455 456 radixMultiplier *= radix;457 }458 459 return number;460 }461 462 static double parseInt(const UString& s, int radix)463 {464 int length = s.size();465 int p = 0;466 467 while (p < length && isStrWhiteSpace(s[p])) {468 ++p;469 }470 471 double sign = 1;472 if (p < length) {473 if (s[p] == '+') {474 ++p;475 } else if (s[p] == '-') {476 sign = -1;477 ++p;478 }479 }480 481 if ((radix == 0 || radix == 16) && length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {482 radix = 16;483 p += 2;484 } else if (radix == 0) {485 if (p < length && s[p] == '0')486 radix = 8;487 else488 radix = 10;489 }490 491 if (radix < 2 || radix > 36)492 return NaN;493 494 int firstDigitPosition = p;495 bool sawDigit = false;496 double number = 0;497 while (p < length) {498 int digit = parseDigit(s[p], radix);499 if (digit == -1)500 break;501 sawDigit = true;502 number *= radix;503 number += digit;504 ++p;505 }506 507 if (number >= mantissaOverflowLowerBound) {508 if (radix == 10)509 number = strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0);510 else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)511 number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), p - firstDigitPosition, radix);512 }513 514 if (!sawDigit)515 return NaN;516 517 return sign * number;518 }519 520 static double parseFloat(const UString& s)521 {522 // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0.523 // Need to skip any whitespace and then one + or - sign.524 int length = s.size();525 int p = 0;526 while (p < length && isStrWhiteSpace(s[p])) {527 ++p;528 }529 if (p < length && (s[p] == '+' || s[p] == '-')) {530 ++p;531 }532 if (length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {533 return 0;534 }535 536 return s.toDouble( true /*tolerant*/, false /* NaN for empty string */ );537 }538 539 JSValue* globalFuncEval(ExecState* exec, JSObject* function, JSValue* thisValue, const ArgList& args)540 {541 JSObject* thisObject = thisValue->toThisObject(exec);542 JSGlobalObject* globalObject = thisObject->toGlobalObject(exec);543 if (!globalObject || globalObject->evalFunction() != function)544 return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated");545 546 JSValue* x = args[0];547 if (!x->isString())548 return x;549 550 UString s = x->toString(exec);551 552 int sourceId;553 int errLine;554 UString errMsg;555 556 RefPtr<EvalNode> evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(s), &sourceId, &errLine, &errMsg);557 558 if (!evalNode)559 return throwError(exec, SyntaxError, errMsg, errLine, sourceId, NULL);560 561 return exec->machine()->execute(evalNode.get(), exec, thisObject, globalObject->globalScopeChain().node(), exec->exceptionSlot());562 }563 564 JSValue* globalFuncParseInt(ExecState* exec, JSObject*, JSValue*, const ArgList& args)565 {566 return jsNumber(exec, parseInt(args[0]->toString(exec), args[1]->toInt32(exec)));567 }568 569 JSValue* globalFuncParseFloat(ExecState* exec, JSObject*, JSValue*, const ArgList& args)570 {571 return jsNumber(exec, parseFloat(args[0]->toString(exec)));572 }573 574 JSValue* globalFuncIsNaN(ExecState* exec, JSObject*, JSValue*, const ArgList& args)575 {576 return jsBoolean(isnan(args[0]->toNumber(exec)));577 }578 579 JSValue* globalFuncIsFinite(ExecState* exec, JSObject*, JSValue*, const ArgList& args)580 {581 double n = args[0]->toNumber(exec);582 return jsBoolean(!isnan(n) && !isinf(n));583 }584 585 JSValue* globalFuncDecodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)586 {587 static const char do_not_unescape_when_decoding_URI[] =588 "#$&+,/:;=?@";589 590 return decode(exec, args, do_not_unescape_when_decoding_URI, true);591 }592 593 JSValue* globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)594 {595 return decode(exec, args, "", true);596 }597 598 JSValue* globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)599 {600 static const char do_not_escape_when_encoding_URI[] =601 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"602 "abcdefghijklmnopqrstuvwxyz"603 "0123456789"604 "!#$&'()*+,-./:;=?@_~";605 606 return encode(exec, args, do_not_escape_when_encoding_URI);607 }608 609 JSValue* globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)610 {611 static const char do_not_escape_when_encoding_URI_component[] =612 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"613 "abcdefghijklmnopqrstuvwxyz"614 "0123456789"615 "!'()*-._~";616 617 return encode(exec, args, do_not_escape_when_encoding_URI_component);618 }619 620 JSValue* globalFuncEscape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)621 {622 static const char do_not_escape[] =623 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"624 "abcdefghijklmnopqrstuvwxyz"625 "0123456789"626 "*+-./@_";627 628 UString r = "", s, str = args[0]->toString(exec);629 const UChar* c = str.data();630 for (int k = 0; k < str.size(); k++, c++) {631 int u = c[0];632 if (u > 255) {633 char tmp[7];634 sprintf(tmp, "%%u%04X", u);635 s = UString(tmp);636 } else if (u != 0 && strchr(do_not_escape, (char)u))637 s = UString(c, 1);638 else {639 char tmp[4];640 sprintf(tmp, "%%%02X", u);641 s = UString(tmp);642 }643 r += s;644 }645 646 return jsString(exec, r);647 }648 649 JSValue* globalFuncUnescape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)650 {651 UString s = "", str = args[0]->toString(exec);652 int k = 0, len = str.size();653 while (k < len) {654 const UChar* c = str.data() + k;655 UChar u;656 if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {657 if (Lexer::isHexDigit(c[2]) && Lexer::isHexDigit(c[3]) && Lexer::isHexDigit(c[4]) && Lexer::isHexDigit(c[5])) {658 u = Lexer::convertUnicode(c[2], c[3], c[4], c[5]);659 c = &u;660 k += 5;661 }662 } else if (c[0] == '%' && k <= len - 3 && Lexer::isHexDigit(c[1]) && Lexer::isHexDigit(c[2])) {663 u = UChar(Lexer::convertHex(c[1], c[2]));664 c = &u;665 k += 2;666 }667 k++;668 s.append(*c);669 }670 671 return jsString(exec, s);672 }673 674 #ifndef NDEBUG675 JSValue* globalFuncKJSPrint(ExecState* exec, JSObject*, JSValue*, const ArgList& args)676 {677 CStringBuffer string;678 args[0]->toString(exec).getCString(string);679 puts(string.data());680 return jsUndefined();681 }682 #endif683 684 // ------------------------------ PrototypeFunction -------------------------------685 686 PrototypeFunction::PrototypeFunction(ExecState* exec, int len, const Identifier& name, NativeFunction function)687 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)688 , m_function(function)689 {690 ASSERT_ARG(function, function);691 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);692 }693 694 PrototypeFunction::PrototypeFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function)695 : InternalFunction(functionPrototype, name)696 , m_function(function)697 {698 ASSERT_ARG(function, function);699 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);700 }701 702 CallType PrototypeFunction::getCallData(CallData& callData)703 {704 callData.native.function = m_function;705 return CallTypeNative;706 }707 708 // ------------------------------ PrototypeReflexiveFunction -------------------------------709 710 GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)711 : PrototypeFunction(exec, functionPrototype, len, name, function)712 , m_cachedGlobalObject(cachedGlobalObject)713 {714 ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);715 }716 717 void GlobalEvalFunction::mark()718 {719 PrototypeFunction::mark();720 if (!m_cachedGlobalObject->marked())721 m_cachedGlobalObject->mark();722 }723 724 96 } // namespace KJS -
trunk/JavaScriptCore/kjs/IndexToNameMap.h
r35006 r35016 22 22 */ 23 23 24 #ifndef JSFunction_h 25 #define JSFunction_h 26 27 #include "InternalFunction.h" 28 #include "JSVariableObject.h" 29 #include "SymbolTable.h" 30 #include "nodes.h" 31 #include "JSObject.h" 24 #ifndef IndexToNameMap_h 25 #define IndexToNameMap_h 32 26 33 27 namespace KJS { 34 28 35 class FunctionBodyNode; 36 class FunctionPrototype; 37 class JSActivation; 38 class JSGlobalObject; 39 40 class JSFunction : public InternalFunction { 41 public: 42 JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*); 43 44 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); 45 virtual void put(ExecState*, const Identifier& propertyName, JSValue*); 46 virtual bool deleteProperty(ExecState*, const Identifier& propertyName); 47 48 JSObject* construct(ExecState*, const ArgList&); 49 JSValue* call(ExecState*, JSValue* thisValue, const ArgList&); 50 51 // Note: Returns a null identifier for any parameters that will never get set 52 // due to a later parameter with the same name. 53 const Identifier& getParameterName(int index); 54 55 static const ClassInfo info; 56 57 RefPtr<FunctionBodyNode> body; 58 59 void setScope(const ScopeChain& s) { _scope = s; } 60 ScopeChain& scope() { return _scope; } 61 62 virtual void mark(); 63 64 private: 65 virtual const ClassInfo* classInfo() const { return &info; } 66 virtual ConstructType getConstructData(ConstructData&); 67 virtual CallType getCallData(CallData&); 68 69 ScopeChain _scope; 70 71 static JSValue* argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); 72 static JSValue* callerGetter(ExecState*, const Identifier&, const PropertySlot&); 73 static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&); 74 }; 29 class ArgList; 30 class ExecState; 31 class Identifier; 32 class JSFunction; 75 33 76 34 class IndexToNameMap { … … 87 45 Identifier* _map; 88 46 }; 89 90 class Arguments : public JSObject {91 public:92 Arguments(ExecState*, JSFunction* func, const ArgList& args, JSActivation* act);93 virtual void mark();94 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);95 virtual void put(ExecState*, const Identifier& propertyName, JSValue*);96 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);97 virtual const ClassInfo* classInfo() const { return &info; }98 static const ClassInfo info;99 private:100 static JSValue* mappedIndexGetter(ExecState*, const Identifier&, const PropertySlot& slot);101 47 102 JSActivation* _activationObject; 103 mutable IndexToNameMap indexToNameMap; 104 }; 48 } // namespace KJS 105 49 106 class PrototypeFunction : public InternalFunction { 107 public: 108 PrototypeFunction(ExecState*, int len, const Identifier&, NativeFunction); 109 PrototypeFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, NativeFunction); 110 111 private: 112 virtual CallType getCallData(CallData&); 113 114 const NativeFunction m_function; 115 }; 116 117 class GlobalEvalFunction : public PrototypeFunction { 118 public: 119 GlobalEvalFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject); 120 JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; } 121 122 private: 123 virtual void mark(); 124 125 JSGlobalObject* m_cachedGlobalObject; 126 }; 127 128 // Global Functions 129 JSValue* globalFuncEval(ExecState*, JSObject*, JSValue*, const ArgList&); 130 JSValue* globalFuncParseInt(ExecState*, JSObject*, JSValue*, const ArgList&); 131 JSValue* globalFuncParseFloat(ExecState*, JSObject*, JSValue*, const ArgList&); 132 JSValue* globalFuncIsNaN(ExecState*, JSObject*, JSValue*, const ArgList&); 133 JSValue* globalFuncIsFinite(ExecState*, JSObject*, JSValue*, const ArgList&); 134 JSValue* globalFuncDecodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); 135 JSValue* globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); 136 JSValue* globalFuncEncodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); 137 JSValue* globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); 138 JSValue* globalFuncEscape(ExecState*, JSObject*, JSValue*, const ArgList&); 139 JSValue* globalFuncUnescape(ExecState*, JSObject*, JSValue*, const ArgList&); 140 #ifndef NDEBUG 141 JSValue* globalFuncKJSPrint(ExecState*, JSObject*, JSValue*, const ArgList&); 142 #endif 143 144 static const double mantissaOverflowLowerBound = 9007199254740992.0; 145 double parseIntOverflow(const char*, int length, int radix); 146 147 } // namespace 148 149 #endif 50 #endif // IndexToNameMap_h -
trunk/JavaScriptCore/kjs/JSActivation.cpp
r34906 r35016 30 30 #include "JSActivation.h" 31 31 32 #include "Arguments.h" 32 33 #include "CodeBlock.h" 33 34 #include "Machine.h" -
trunk/JavaScriptCore/kjs/JSFunction.cpp
r34854 r35016 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 2 * Copyright (C) 1999-2002 Harri Porten ([email protected]) … … 29 28 #include "ExecState.h" 30 29 #include "FunctionPrototype.h" 31 #include "JSActivation.h"32 30 #include "JSGlobalObject.h" 33 #include "JSString.h"34 31 #include "Machine.h" 35 32 #include "ObjectPrototype.h" … … 37 34 #include "PropertyNameArray.h" 38 35 #include "ScopeChainMark.h" 39 #include "debugger.h"40 #include "dtoa.h"41 #include "lexer.h"42 #include "nodes.h"43 #include "operations.h"44 #include <errno.h>45 #include <profiler/Profiler.h>46 #include <stdio.h>47 #include <stdlib.h>48 #include <string.h>49 #include <wtf/ASCIICType.h>50 #include <wtf/Assertions.h>51 #include <wtf/MathExtras.h>52 #include <wtf/unicode/UTF8.h>53 36 54 37 using namespace WTF; … … 56 39 57 40 namespace KJS { 58 59 // ----------------------------- JSFunction ----------------------------------60 41 61 42 const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 }; … … 189 170 } 190 171 191 // ------------------------------ IndexToNameMap ---------------------------------192 193 // We map indexes in the arguments array to their corresponding argument names.194 // Example: function f(x, y, z): arguments[0] = x, so we map 0 to Identifier("x").195 196 // Once we have an argument name, we can get and set the argument's value in the197 // activation object.198 199 // We use Identifier::null to indicate that a given argument's value200 // isn't stored in the activation object.201 202 IndexToNameMap::IndexToNameMap(JSFunction* func, const ArgList& args)203 {204 _map = new Identifier[args.size()];205 this->size = args.size();206 207 unsigned i = 0;208 ArgList::const_iterator end = args.end();209 for (ArgList::const_iterator it = args.begin(); it != end; ++i, ++it)210 _map[i] = func->getParameterName(i); // null if there is no corresponding parameter211 }212 213 IndexToNameMap::~IndexToNameMap()214 {215 delete [] _map;216 }217 218 bool IndexToNameMap::isMapped(const Identifier& index) const219 {220 bool indexIsNumber;221 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);222 223 if (!indexIsNumber)224 return false;225 226 if (indexAsNumber >= size)227 return false;228 229 if (_map[indexAsNumber].isNull())230 return false;231 232 return true;233 }234 235 void IndexToNameMap::unMap(ExecState* exec, const Identifier& index)236 {237 bool indexIsNumber;238 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);239 240 ASSERT(indexIsNumber && indexAsNumber < size);241 242 _map[indexAsNumber] = exec->propertyNames().nullIdentifier;243 }244 245 Identifier& IndexToNameMap::operator[](const Identifier& index)246 {247 bool indexIsNumber;248 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);249 250 ASSERT(indexIsNumber && indexAsNumber < size);251 252 return _map[indexAsNumber];253 }254 255 // ------------------------------ Arguments ---------------------------------256 257 const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };258 259 // ECMA 10.1.8260 Arguments::Arguments(ExecState* exec, JSFunction* func, const ArgList& args, JSActivation* act)261 : JSObject(exec->lexicalGlobalObject()->objectPrototype())262 , _activationObject(act)263 , indexToNameMap(func, args)264 {265 putDirect(exec->propertyNames().callee, func, DontEnum);266 putDirect(exec, exec->propertyNames().length, args.size(), DontEnum);267 268 int i = 0;269 ArgList::const_iterator end = args.end();270 for (ArgList::const_iterator it = args.begin(); it != end; ++it, ++i) {271 Identifier name = Identifier::from(exec, i);272 if (!indexToNameMap.isMapped(name))273 putDirect(name, *it, DontEnum);274 }275 }276 277 void Arguments::mark()278 {279 JSObject::mark();280 if (_activationObject && !_activationObject->marked())281 _activationObject->mark();282 }283 284 JSValue* Arguments::mappedIndexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)285 {286 Arguments* thisObj = static_cast<Arguments*>(slot.slotBase());287 return thisObj->_activationObject->get(exec, thisObj->indexToNameMap[propertyName]);288 }289 290 bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)291 {292 if (indexToNameMap.isMapped(propertyName)) {293 slot.setCustom(this, mappedIndexGetter);294 return true;295 }296 297 return JSObject::getOwnPropertySlot(exec, propertyName, slot);298 }299 300 void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value)301 {302 if (indexToNameMap.isMapped(propertyName))303 _activationObject->put(exec, indexToNameMap[propertyName], value);304 else305 JSObject::put(exec, propertyName, value);306 }307 308 bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)309 {310 if (indexToNameMap.isMapped(propertyName)) {311 indexToNameMap.unMap(exec, propertyName);312 return true;313 } else {314 return JSObject::deleteProperty(exec, propertyName);315 }316 }317 318 // ------------------------------ Global Functions -----------------------------------319 320 static JSValue* encode(ExecState* exec, const ArgList& args, const char* do_not_escape)321 {322 UString r = "", s, str = args[0]->toString(exec);323 CString cstr = str.UTF8String(true);324 if (!cstr.c_str())325 return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");326 const char* p = cstr.c_str();327 for (size_t k = 0; k < cstr.size(); k++, p++) {328 char c = *p;329 if (c && strchr(do_not_escape, c)) {330 r.append(c);331 } else {332 char tmp[4];333 sprintf(tmp, "%%%02X", (unsigned char)c);334 r += tmp;335 }336 }337 return jsString(exec, r);338 }339 340 static JSValue* decode(ExecState* exec, const ArgList& args, const char* do_not_unescape, bool strict)341 {342 UString s = "", str = args[0]->toString(exec);343 int k = 0, len = str.size();344 const UChar* d = str.data();345 UChar u = 0;346 while (k < len) {347 const UChar* p = d + k;348 UChar c = *p;349 if (c == '%') {350 int charLen = 0;351 if (k <= len - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {352 const char b0 = Lexer::convertHex(p[1], p[2]);353 const int sequenceLen = UTF8SequenceLength(b0);354 if (sequenceLen != 0 && k <= len - sequenceLen * 3) {355 charLen = sequenceLen * 3;356 char sequence[5];357 sequence[0] = b0;358 for (int i = 1; i < sequenceLen; ++i) {359 const UChar* q = p + i * 3;360 if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))361 sequence[i] = Lexer::convertHex(q[1], q[2]);362 else {363 charLen = 0;364 break;365 }366 }367 if (charLen != 0) {368 sequence[sequenceLen] = 0;369 const int character = decodeUTF8Sequence(sequence);370 if (character < 0 || character >= 0x110000) {371 charLen = 0;372 } else if (character >= 0x10000) {373 // Convert to surrogate pair.374 s.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));375 u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));376 } else {377 u = static_cast<UChar>(character);378 }379 }380 }381 }382 if (charLen == 0) {383 if (strict)384 return throwError(exec, URIError);385 // The only case where we don't use "strict" mode is the "unescape" function.386 // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.387 if (k <= len - 6 && p[1] == 'u'388 && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])389 && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {390 charLen = 6;391 u = Lexer::convertUnicode(p[2], p[3], p[4], p[5]);392 }393 }394 if (charLen && (u == 0 || u >= 128 || !strchr(do_not_unescape, u))) {395 c = u;396 k += charLen - 1;397 }398 }399 k++;400 s.append(c);401 }402 return jsString(exec, s);403 }404 405 static bool isStrWhiteSpace(unsigned short c)406 {407 switch (c) {408 case 0x0009:409 case 0x000A:410 case 0x000B:411 case 0x000C:412 case 0x000D:413 case 0x0020:414 case 0x00A0:415 case 0x2028:416 case 0x2029:417 return true;418 default:419 return c > 0xff && isSeparatorSpace(c);420 }421 }422 423 static int parseDigit(unsigned short c, int radix)424 {425 int digit = -1;426 427 if (c >= '0' && c <= '9') {428 digit = c - '0';429 } else if (c >= 'A' && c <= 'Z') {430 digit = c - 'A' + 10;431 } else if (c >= 'a' && c <= 'z') {432 digit = c - 'a' + 10;433 }434 435 if (digit >= radix)436 return -1;437 return digit;438 }439 440 double parseIntOverflow(const char* s, int length, int radix)441 {442 double number = 0.0;443 double radixMultiplier = 1.0;444 445 for (const char* p = s + length - 1; p >= s; p--) {446 if (radixMultiplier == Inf) {447 if (*p != '0') {448 number = Inf;449 break;450 }451 } else {452 int digit = parseDigit(*p, radix);453 number += digit * radixMultiplier;454 }455 456 radixMultiplier *= radix;457 }458 459 return number;460 }461 462 static double parseInt(const UString& s, int radix)463 {464 int length = s.size();465 int p = 0;466 467 while (p < length && isStrWhiteSpace(s[p])) {468 ++p;469 }470 471 double sign = 1;472 if (p < length) {473 if (s[p] == '+') {474 ++p;475 } else if (s[p] == '-') {476 sign = -1;477 ++p;478 }479 }480 481 if ((radix == 0 || radix == 16) && length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {482 radix = 16;483 p += 2;484 } else if (radix == 0) {485 if (p < length && s[p] == '0')486 radix = 8;487 else488 radix = 10;489 }490 491 if (radix < 2 || radix > 36)492 return NaN;493 494 int firstDigitPosition = p;495 bool sawDigit = false;496 double number = 0;497 while (p < length) {498 int digit = parseDigit(s[p], radix);499 if (digit == -1)500 break;501 sawDigit = true;502 number *= radix;503 number += digit;504 ++p;505 }506 507 if (number >= mantissaOverflowLowerBound) {508 if (radix == 10)509 number = strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0);510 else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)511 number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), p - firstDigitPosition, radix);512 }513 514 if (!sawDigit)515 return NaN;516 517 return sign * number;518 }519 520 static double parseFloat(const UString& s)521 {522 // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0.523 // Need to skip any whitespace and then one + or - sign.524 int length = s.size();525 int p = 0;526 while (p < length && isStrWhiteSpace(s[p])) {527 ++p;528 }529 if (p < length && (s[p] == '+' || s[p] == '-')) {530 ++p;531 }532 if (length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {533 return 0;534 }535 536 return s.toDouble( true /*tolerant*/, false /* NaN for empty string */ );537 }538 539 JSValue* globalFuncEval(ExecState* exec, JSObject* function, JSValue* thisValue, const ArgList& args)540 {541 JSObject* thisObject = thisValue->toThisObject(exec);542 JSGlobalObject* globalObject = thisObject->toGlobalObject(exec);543 if (!globalObject || globalObject->evalFunction() != function)544 return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated");545 546 JSValue* x = args[0];547 if (!x->isString())548 return x;549 550 UString s = x->toString(exec);551 552 int sourceId;553 int errLine;554 UString errMsg;555 556 RefPtr<EvalNode> evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(s), &sourceId, &errLine, &errMsg);557 558 if (!evalNode)559 return throwError(exec, SyntaxError, errMsg, errLine, sourceId, NULL);560 561 return exec->machine()->execute(evalNode.get(), exec, thisObject, globalObject->globalScopeChain().node(), exec->exceptionSlot());562 }563 564 JSValue* globalFuncParseInt(ExecState* exec, JSObject*, JSValue*, const ArgList& args)565 {566 return jsNumber(exec, parseInt(args[0]->toString(exec), args[1]->toInt32(exec)));567 }568 569 JSValue* globalFuncParseFloat(ExecState* exec, JSObject*, JSValue*, const ArgList& args)570 {571 return jsNumber(exec, parseFloat(args[0]->toString(exec)));572 }573 574 JSValue* globalFuncIsNaN(ExecState* exec, JSObject*, JSValue*, const ArgList& args)575 {576 return jsBoolean(isnan(args[0]->toNumber(exec)));577 }578 579 JSValue* globalFuncIsFinite(ExecState* exec, JSObject*, JSValue*, const ArgList& args)580 {581 double n = args[0]->toNumber(exec);582 return jsBoolean(!isnan(n) && !isinf(n));583 }584 585 JSValue* globalFuncDecodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)586 {587 static const char do_not_unescape_when_decoding_URI[] =588 "#$&+,/:;=?@";589 590 return decode(exec, args, do_not_unescape_when_decoding_URI, true);591 }592 593 JSValue* globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)594 {595 return decode(exec, args, "", true);596 }597 598 JSValue* globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)599 {600 static const char do_not_escape_when_encoding_URI[] =601 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"602 "abcdefghijklmnopqrstuvwxyz"603 "0123456789"604 "!#$&'()*+,-./:;=?@_~";605 606 return encode(exec, args, do_not_escape_when_encoding_URI);607 }608 609 JSValue* globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)610 {611 static const char do_not_escape_when_encoding_URI_component[] =612 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"613 "abcdefghijklmnopqrstuvwxyz"614 "0123456789"615 "!'()*-._~";616 617 return encode(exec, args, do_not_escape_when_encoding_URI_component);618 }619 620 JSValue* globalFuncEscape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)621 {622 static const char do_not_escape[] =623 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"624 "abcdefghijklmnopqrstuvwxyz"625 "0123456789"626 "*+-./@_";627 628 UString r = "", s, str = args[0]->toString(exec);629 const UChar* c = str.data();630 for (int k = 0; k < str.size(); k++, c++) {631 int u = c[0];632 if (u > 255) {633 char tmp[7];634 sprintf(tmp, "%%u%04X", u);635 s = UString(tmp);636 } else if (u != 0 && strchr(do_not_escape, (char)u))637 s = UString(c, 1);638 else {639 char tmp[4];640 sprintf(tmp, "%%%02X", u);641 s = UString(tmp);642 }643 r += s;644 }645 646 return jsString(exec, r);647 }648 649 JSValue* globalFuncUnescape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)650 {651 UString s = "", str = args[0]->toString(exec);652 int k = 0, len = str.size();653 while (k < len) {654 const UChar* c = str.data() + k;655 UChar u;656 if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {657 if (Lexer::isHexDigit(c[2]) && Lexer::isHexDigit(c[3]) && Lexer::isHexDigit(c[4]) && Lexer::isHexDigit(c[5])) {658 u = Lexer::convertUnicode(c[2], c[3], c[4], c[5]);659 c = &u;660 k += 5;661 }662 } else if (c[0] == '%' && k <= len - 3 && Lexer::isHexDigit(c[1]) && Lexer::isHexDigit(c[2])) {663 u = UChar(Lexer::convertHex(c[1], c[2]));664 c = &u;665 k += 2;666 }667 k++;668 s.append(*c);669 }670 671 return jsString(exec, s);672 }673 674 #ifndef NDEBUG675 JSValue* globalFuncKJSPrint(ExecState* exec, JSObject*, JSValue*, const ArgList& args)676 {677 CStringBuffer string;678 args[0]->toString(exec).getCString(string);679 puts(string.data());680 return jsUndefined();681 }682 #endif683 684 // ------------------------------ PrototypeFunction -------------------------------685 686 PrototypeFunction::PrototypeFunction(ExecState* exec, int len, const Identifier& name, NativeFunction function)687 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)688 , m_function(function)689 {690 ASSERT_ARG(function, function);691 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);692 }693 694 PrototypeFunction::PrototypeFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function)695 : InternalFunction(functionPrototype, name)696 , m_function(function)697 {698 ASSERT_ARG(function, function);699 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);700 }701 702 CallType PrototypeFunction::getCallData(CallData& callData)703 {704 callData.native.function = m_function;705 return CallTypeNative;706 }707 708 // ------------------------------ PrototypeReflexiveFunction -------------------------------709 710 GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)711 : PrototypeFunction(exec, functionPrototype, len, name, function)712 , m_cachedGlobalObject(cachedGlobalObject)713 {714 ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);715 }716 717 void GlobalEvalFunction::mark()718 {719 PrototypeFunction::mark();720 if (!m_cachedGlobalObject->marked())721 m_cachedGlobalObject->mark();722 }723 724 172 } // namespace KJS -
trunk/JavaScriptCore/kjs/JSFunction.h
r34901 r35016 74 74 }; 75 75 76 class IndexToNameMap { 77 public: 78 IndexToNameMap(JSFunction*, const ArgList&); 79 ~IndexToNameMap(); 80 81 Identifier& operator[](const Identifier& index); 82 bool isMapped(const Identifier& index) const; 83 void unMap(ExecState* exec, const Identifier& index); 84 85 private: 86 unsigned size; 87 Identifier* _map; 88 }; 89 90 class Arguments : public JSObject { 91 public: 92 Arguments(ExecState*, JSFunction* func, const ArgList& args, JSActivation* act); 93 virtual void mark(); 94 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); 95 virtual void put(ExecState*, const Identifier& propertyName, JSValue*); 96 virtual bool deleteProperty(ExecState*, const Identifier& propertyName); 97 virtual const ClassInfo* classInfo() const { return &info; } 98 static const ClassInfo info; 99 private: 100 static JSValue* mappedIndexGetter(ExecState*, const Identifier&, const PropertySlot& slot); 76 } // namespace kJS 101 77 102 JSActivation* _activationObject; 103 mutable IndexToNameMap indexToNameMap; 104 }; 105 106 class PrototypeFunction : public InternalFunction { 107 public: 108 PrototypeFunction(ExecState*, int len, const Identifier&, NativeFunction); 109 PrototypeFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, NativeFunction); 110 111 private: 112 virtual CallType getCallData(CallData&); 113 114 const NativeFunction m_function; 115 }; 116 117 class GlobalEvalFunction : public PrototypeFunction { 118 public: 119 GlobalEvalFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject); 120 JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; } 121 122 private: 123 virtual void mark(); 124 125 JSGlobalObject* m_cachedGlobalObject; 126 }; 127 128 // Global Functions 129 JSValue* globalFuncEval(ExecState*, JSObject*, JSValue*, const ArgList&); 130 JSValue* globalFuncParseInt(ExecState*, JSObject*, JSValue*, const ArgList&); 131 JSValue* globalFuncParseFloat(ExecState*, JSObject*, JSValue*, const ArgList&); 132 JSValue* globalFuncIsNaN(ExecState*, JSObject*, JSValue*, const ArgList&); 133 JSValue* globalFuncIsFinite(ExecState*, JSObject*, JSValue*, const ArgList&); 134 JSValue* globalFuncDecodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); 135 JSValue* globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); 136 JSValue* globalFuncEncodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); 137 JSValue* globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); 138 JSValue* globalFuncEscape(ExecState*, JSObject*, JSValue*, const ArgList&); 139 JSValue* globalFuncUnescape(ExecState*, JSObject*, JSValue*, const ArgList&); 140 #ifndef NDEBUG 141 JSValue* globalFuncKJSPrint(ExecState*, JSObject*, JSValue*, const ArgList&); 142 #endif 143 144 static const double mantissaOverflowLowerBound = 9007199254740992.0; 145 double parseIntOverflow(const char*, int length, int radix); 146 147 } // namespace 148 149 #endif 78 #endif // JSFunction_h -
trunk/JavaScriptCore/kjs/JSGlobalObject.cpp
r34974 r35016 42 42 #include "FunctionConstructor.h" 43 43 #include "FunctionPrototype.h" 44 #include "JSGlobalObjectFunctions.h" 44 45 #include "JSLock.h" 45 46 #include "Machine.h" -
trunk/JavaScriptCore/kjs/JSGlobalObjectFunctions.cpp
r35006 r35016 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 2 * Copyright (C) 1999-2002 Harri Porten ([email protected]) … … 25 24 26 25 #include "config.h" 27 #include "JS Function.h"26 #include "JSGlobalObjectFunctions.h" 28 27 29 28 #include "ExecState.h" 30 #include "FunctionPrototype.h" 31 #include "JSActivation.h" 29 #include "GlobalEvalFunction.h" 32 30 #include "JSGlobalObject.h" 33 31 #include "JSString.h" 34 32 #include "Machine.h" 35 #include "ObjectPrototype.h"36 33 #include "Parser.h" 37 #include "PropertyNameArray.h"38 #include "ScopeChainMark.h"39 #include "debugger.h"40 34 #include "dtoa.h" 41 35 #include "lexer.h" 42 36 #include "nodes.h" 43 #include "operations.h"44 37 #include <errno.h> 45 #include <profiler/Profiler.h>46 38 #include <stdio.h> 47 39 #include <stdlib.h> … … 56 48 57 49 namespace KJS { 58 59 // ----------------------------- JSFunction ----------------------------------60 61 const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };62 63 JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* b, ScopeChainNode* scopeChain)64 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)65 , body(b)66 , _scope(scopeChain)67 {68 }69 70 void JSFunction::mark()71 {72 InternalFunction::mark();73 body->mark();74 _scope.mark();75 }76 77 CallType JSFunction::getCallData(CallData& callData)78 {79 callData.js.functionBody = body.get();80 callData.js.scopeChain = _scope.node();81 return CallTypeJS;82 }83 84 JSValue* JSFunction::call(ExecState* exec, JSValue* thisValue, const ArgList& args)85 {86 return exec->machine()->execute(body.get(), exec, this, thisValue->toThisObject(exec), args, _scope.node(), exec->exceptionSlot());87 }88 89 JSValue* JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)90 {91 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());92 return exec->machine()->retrieveArguments(exec, thisObj);93 }94 95 JSValue* JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)96 {97 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());98 return exec->machine()->retrieveCaller(exec, thisObj);99 }100 101 JSValue* JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)102 {103 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());104 return jsNumber(exec, thisObj->body->parameters().size());105 }106 107 bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)108 {109 if (propertyName == exec->propertyNames().arguments) {110 slot.setCustom(this, argumentsGetter);111 return true;112 }113 114 if (propertyName == exec->propertyNames().length) {115 slot.setCustom(this, lengthGetter);116 return true;117 }118 119 if (propertyName == exec->propertyNames().caller) {120 slot.setCustom(this, callerGetter);121 return true;122 }123 124 return InternalFunction::getOwnPropertySlot(exec, propertyName, slot);125 }126 127 void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue* value)128 {129 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)130 return;131 InternalFunction::put(exec, propertyName, value);132 }133 134 bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)135 {136 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)137 return false;138 return InternalFunction::deleteProperty(exec, propertyName);139 }140 141 /* Returns the parameter name corresponding to the given index. eg:142 * function f1(x, y, z): getParameterName(0) --> x143 *144 * If a name appears more than once, only the last index at which145 * it appears associates with it. eg:146 * function f2(x, x): getParameterName(0) --> null147 */148 const Identifier& JSFunction::getParameterName(int index)149 {150 Vector<Identifier>& parameters = body->parameters();151 152 if (static_cast<size_t>(index) >= body->parameters().size())153 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;154 155 const Identifier& name = parameters[index];156 157 // Are there any subsequent parameters with the same name?158 size_t size = parameters.size();159 for (size_t i = index + 1; i < size; ++i)160 if (parameters[i] == name)161 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;162 163 return name;164 }165 166 // ECMA 13.2.2 [[Construct]]167 ConstructType JSFunction::getConstructData(ConstructData& constructData)168 {169 constructData.js.functionBody = body.get();170 constructData.js.scopeChain = _scope.node();171 return ConstructTypeJS;172 }173 174 JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)175 {176 JSObject* proto;177 JSValue* p = get(exec, exec->propertyNames().prototype);178 if (p->isObject())179 proto = static_cast<JSObject*>(p);180 else181 proto = exec->lexicalGlobalObject()->objectPrototype();182 183 JSObject* thisObj = new (exec) JSObject(proto);184 185 JSValue* result = exec->machine()->execute(body.get(), exec, this, thisObj, args, _scope.node(), exec->exceptionSlot());186 if (exec->hadException() || !result->isObject())187 return thisObj;188 return static_cast<JSObject*>(result);189 }190 191 // ------------------------------ IndexToNameMap ---------------------------------192 193 // We map indexes in the arguments array to their corresponding argument names.194 // Example: function f(x, y, z): arguments[0] = x, so we map 0 to Identifier("x").195 196 // Once we have an argument name, we can get and set the argument's value in the197 // activation object.198 199 // We use Identifier::null to indicate that a given argument's value200 // isn't stored in the activation object.201 202 IndexToNameMap::IndexToNameMap(JSFunction* func, const ArgList& args)203 {204 _map = new Identifier[args.size()];205 this->size = args.size();206 207 unsigned i = 0;208 ArgList::const_iterator end = args.end();209 for (ArgList::const_iterator it = args.begin(); it != end; ++i, ++it)210 _map[i] = func->getParameterName(i); // null if there is no corresponding parameter211 }212 213 IndexToNameMap::~IndexToNameMap()214 {215 delete [] _map;216 }217 218 bool IndexToNameMap::isMapped(const Identifier& index) const219 {220 bool indexIsNumber;221 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);222 223 if (!indexIsNumber)224 return false;225 226 if (indexAsNumber >= size)227 return false;228 229 if (_map[indexAsNumber].isNull())230 return false;231 232 return true;233 }234 235 void IndexToNameMap::unMap(ExecState* exec, const Identifier& index)236 {237 bool indexIsNumber;238 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);239 240 ASSERT(indexIsNumber && indexAsNumber < size);241 242 _map[indexAsNumber] = exec->propertyNames().nullIdentifier;243 }244 245 Identifier& IndexToNameMap::operator[](const Identifier& index)246 {247 bool indexIsNumber;248 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);249 250 ASSERT(indexIsNumber && indexAsNumber < size);251 252 return _map[indexAsNumber];253 }254 255 // ------------------------------ Arguments ---------------------------------256 257 const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };258 259 // ECMA 10.1.8260 Arguments::Arguments(ExecState* exec, JSFunction* func, const ArgList& args, JSActivation* act)261 : JSObject(exec->lexicalGlobalObject()->objectPrototype())262 , _activationObject(act)263 , indexToNameMap(func, args)264 {265 putDirect(exec->propertyNames().callee, func, DontEnum);266 putDirect(exec, exec->propertyNames().length, args.size(), DontEnum);267 268 int i = 0;269 ArgList::const_iterator end = args.end();270 for (ArgList::const_iterator it = args.begin(); it != end; ++it, ++i) {271 Identifier name = Identifier::from(exec, i);272 if (!indexToNameMap.isMapped(name))273 putDirect(name, *it, DontEnum);274 }275 }276 277 void Arguments::mark()278 {279 JSObject::mark();280 if (_activationObject && !_activationObject->marked())281 _activationObject->mark();282 }283 284 JSValue* Arguments::mappedIndexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)285 {286 Arguments* thisObj = static_cast<Arguments*>(slot.slotBase());287 return thisObj->_activationObject->get(exec, thisObj->indexToNameMap[propertyName]);288 }289 290 bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)291 {292 if (indexToNameMap.isMapped(propertyName)) {293 slot.setCustom(this, mappedIndexGetter);294 return true;295 }296 297 return JSObject::getOwnPropertySlot(exec, propertyName, slot);298 }299 300 void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value)301 {302 if (indexToNameMap.isMapped(propertyName))303 _activationObject->put(exec, indexToNameMap[propertyName], value);304 else305 JSObject::put(exec, propertyName, value);306 }307 308 bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)309 {310 if (indexToNameMap.isMapped(propertyName)) {311 indexToNameMap.unMap(exec, propertyName);312 return true;313 } else {314 return JSObject::deleteProperty(exec, propertyName);315 }316 }317 318 // ------------------------------ Global Functions -----------------------------------319 50 320 51 static JSValue* encode(ExecState* exec, const ArgList& args, const char* do_not_escape) … … 682 413 #endif 683 414 684 // ------------------------------ PrototypeFunction -------------------------------685 686 PrototypeFunction::PrototypeFunction(ExecState* exec, int len, const Identifier& name, NativeFunction function)687 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)688 , m_function(function)689 {690 ASSERT_ARG(function, function);691 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);692 }693 694 PrototypeFunction::PrototypeFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function)695 : InternalFunction(functionPrototype, name)696 , m_function(function)697 {698 ASSERT_ARG(function, function);699 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);700 }701 702 CallType PrototypeFunction::getCallData(CallData& callData)703 {704 callData.native.function = m_function;705 return CallTypeNative;706 }707 708 // ------------------------------ PrototypeReflexiveFunction -------------------------------709 710 GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)711 : PrototypeFunction(exec, functionPrototype, len, name, function)712 , m_cachedGlobalObject(cachedGlobalObject)713 {714 ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);715 }716 717 void GlobalEvalFunction::mark()718 {719 PrototypeFunction::mark();720 if (!m_cachedGlobalObject->marked())721 m_cachedGlobalObject->mark();722 }723 724 415 } // namespace KJS -
trunk/JavaScriptCore/kjs/JSGlobalObjectFunctions.h
r35006 r35016 22 22 */ 23 23 24 #ifndef JSFunction_h 25 #define JSFunction_h 26 27 #include "InternalFunction.h" 28 #include "JSVariableObject.h" 29 #include "SymbolTable.h" 30 #include "nodes.h" 31 #include "JSObject.h" 24 #ifndef JSGlobalObjectFunctions_h 25 #define JSGlobalObjectFunctions_h 32 26 33 27 namespace KJS { 34 28 35 class FunctionBodyNode;36 class FunctionPrototype;37 class JSActivation;38 class JSGlobalObject;29 class ArgList; 30 class ExecState; 31 class JSObject; 32 class JSValue; 39 33 40 class JSFunction : public InternalFunction { 41 public: 42 JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*); 34 // FIXME: These functions should really be in JSGlobalObject.cpp, but putting them there 35 // is a 0.5% reduction. 43 36 44 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);45 virtual void put(ExecState*, const Identifier& propertyName, JSValue*);46 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);47 48 JSObject* construct(ExecState*, const ArgList&);49 JSValue* call(ExecState*, JSValue* thisValue, const ArgList&);50 51 // Note: Returns a null identifier for any parameters that will never get set52 // due to a later parameter with the same name.53 const Identifier& getParameterName(int index);54 55 static const ClassInfo info;56 57 RefPtr<FunctionBodyNode> body;58 59 void setScope(const ScopeChain& s) { _scope = s; }60 ScopeChain& scope() { return _scope; }61 62 virtual void mark();63 64 private:65 virtual const ClassInfo* classInfo() const { return &info; }66 virtual ConstructType getConstructData(ConstructData&);67 virtual CallType getCallData(CallData&);68 69 ScopeChain _scope;70 71 static JSValue* argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);72 static JSValue* callerGetter(ExecState*, const Identifier&, const PropertySlot&);73 static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&);74 };75 76 class IndexToNameMap {77 public:78 IndexToNameMap(JSFunction*, const ArgList&);79 ~IndexToNameMap();80 81 Identifier& operator[](const Identifier& index);82 bool isMapped(const Identifier& index) const;83 void unMap(ExecState* exec, const Identifier& index);84 85 private:86 unsigned size;87 Identifier* _map;88 };89 90 class Arguments : public JSObject {91 public:92 Arguments(ExecState*, JSFunction* func, const ArgList& args, JSActivation* act);93 virtual void mark();94 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);95 virtual void put(ExecState*, const Identifier& propertyName, JSValue*);96 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);97 virtual const ClassInfo* classInfo() const { return &info; }98 static const ClassInfo info;99 private:100 static JSValue* mappedIndexGetter(ExecState*, const Identifier&, const PropertySlot& slot);101 102 JSActivation* _activationObject;103 mutable IndexToNameMap indexToNameMap;104 };105 106 class PrototypeFunction : public InternalFunction {107 public:108 PrototypeFunction(ExecState*, int len, const Identifier&, NativeFunction);109 PrototypeFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, NativeFunction);110 111 private:112 virtual CallType getCallData(CallData&);113 114 const NativeFunction m_function;115 };116 117 class GlobalEvalFunction : public PrototypeFunction {118 public:119 GlobalEvalFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject);120 JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; }121 122 private:123 virtual void mark();124 125 JSGlobalObject* m_cachedGlobalObject;126 };127 128 // Global Functions129 37 JSValue* globalFuncEval(ExecState*, JSObject*, JSValue*, const ArgList&); 130 38 JSValue* globalFuncParseInt(ExecState*, JSObject*, JSValue*, const ArgList&); … … 145 53 double parseIntOverflow(const char*, int length, int radix); 146 54 147 } // namespace 55 } // namespace KJS 148 56 149 #endif 57 #endif // JSGlobalObjectFunctions_h -
trunk/JavaScriptCore/kjs/PrototypeFunction.cpp
r35006 r35016 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 2 * Copyright (C) 1999-2002 Harri Porten ([email protected]) … … 25 24 26 25 #include "config.h" 27 #include " JSFunction.h"26 #include "PrototypeFunction.h" 28 27 29 #include "ExecState.h"30 28 #include "FunctionPrototype.h" 31 #include "JSActivation.h"32 29 #include "JSGlobalObject.h" 33 #include "JSString.h"34 #include "Machine.h"35 #include "ObjectPrototype.h"36 #include "Parser.h"37 #include "PropertyNameArray.h"38 #include "ScopeChainMark.h"39 #include "debugger.h"40 #include "dtoa.h"41 #include "lexer.h"42 #include "nodes.h"43 #include "operations.h"44 #include <errno.h>45 #include <profiler/Profiler.h>46 #include <stdio.h>47 #include <stdlib.h>48 #include <string.h>49 #include <wtf/ASCIICType.h>50 30 #include <wtf/Assertions.h> 51 #include <wtf/MathExtras.h>52 #include <wtf/unicode/UTF8.h>53 54 using namespace WTF;55 using namespace Unicode;56 31 57 32 namespace KJS { 58 59 // ----------------------------- JSFunction ----------------------------------60 61 const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };62 63 JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* b, ScopeChainNode* scopeChain)64 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)65 , body(b)66 , _scope(scopeChain)67 {68 }69 70 void JSFunction::mark()71 {72 InternalFunction::mark();73 body->mark();74 _scope.mark();75 }76 77 CallType JSFunction::getCallData(CallData& callData)78 {79 callData.js.functionBody = body.get();80 callData.js.scopeChain = _scope.node();81 return CallTypeJS;82 }83 84 JSValue* JSFunction::call(ExecState* exec, JSValue* thisValue, const ArgList& args)85 {86 return exec->machine()->execute(body.get(), exec, this, thisValue->toThisObject(exec), args, _scope.node(), exec->exceptionSlot());87 }88 89 JSValue* JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)90 {91 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());92 return exec->machine()->retrieveArguments(exec, thisObj);93 }94 95 JSValue* JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)96 {97 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());98 return exec->machine()->retrieveCaller(exec, thisObj);99 }100 101 JSValue* JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)102 {103 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());104 return jsNumber(exec, thisObj->body->parameters().size());105 }106 107 bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)108 {109 if (propertyName == exec->propertyNames().arguments) {110 slot.setCustom(this, argumentsGetter);111 return true;112 }113 114 if (propertyName == exec->propertyNames().length) {115 slot.setCustom(this, lengthGetter);116 return true;117 }118 119 if (propertyName == exec->propertyNames().caller) {120 slot.setCustom(this, callerGetter);121 return true;122 }123 124 return InternalFunction::getOwnPropertySlot(exec, propertyName, slot);125 }126 127 void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue* value)128 {129 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)130 return;131 InternalFunction::put(exec, propertyName, value);132 }133 134 bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)135 {136 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)137 return false;138 return InternalFunction::deleteProperty(exec, propertyName);139 }140 141 /* Returns the parameter name corresponding to the given index. eg:142 * function f1(x, y, z): getParameterName(0) --> x143 *144 * If a name appears more than once, only the last index at which145 * it appears associates with it. eg:146 * function f2(x, x): getParameterName(0) --> null147 */148 const Identifier& JSFunction::getParameterName(int index)149 {150 Vector<Identifier>& parameters = body->parameters();151 152 if (static_cast<size_t>(index) >= body->parameters().size())153 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;154 155 const Identifier& name = parameters[index];156 157 // Are there any subsequent parameters with the same name?158 size_t size = parameters.size();159 for (size_t i = index + 1; i < size; ++i)160 if (parameters[i] == name)161 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;162 163 return name;164 }165 166 // ECMA 13.2.2 [[Construct]]167 ConstructType JSFunction::getConstructData(ConstructData& constructData)168 {169 constructData.js.functionBody = body.get();170 constructData.js.scopeChain = _scope.node();171 return ConstructTypeJS;172 }173 174 JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)175 {176 JSObject* proto;177 JSValue* p = get(exec, exec->propertyNames().prototype);178 if (p->isObject())179 proto = static_cast<JSObject*>(p);180 else181 proto = exec->lexicalGlobalObject()->objectPrototype();182 183 JSObject* thisObj = new (exec) JSObject(proto);184 185 JSValue* result = exec->machine()->execute(body.get(), exec, this, thisObj, args, _scope.node(), exec->exceptionSlot());186 if (exec->hadException() || !result->isObject())187 return thisObj;188 return static_cast<JSObject*>(result);189 }190 191 // ------------------------------ IndexToNameMap ---------------------------------192 193 // We map indexes in the arguments array to their corresponding argument names.194 // Example: function f(x, y, z): arguments[0] = x, so we map 0 to Identifier("x").195 196 // Once we have an argument name, we can get and set the argument's value in the197 // activation object.198 199 // We use Identifier::null to indicate that a given argument's value200 // isn't stored in the activation object.201 202 IndexToNameMap::IndexToNameMap(JSFunction* func, const ArgList& args)203 {204 _map = new Identifier[args.size()];205 this->size = args.size();206 207 unsigned i = 0;208 ArgList::const_iterator end = args.end();209 for (ArgList::const_iterator it = args.begin(); it != end; ++i, ++it)210 _map[i] = func->getParameterName(i); // null if there is no corresponding parameter211 }212 213 IndexToNameMap::~IndexToNameMap()214 {215 delete [] _map;216 }217 218 bool IndexToNameMap::isMapped(const Identifier& index) const219 {220 bool indexIsNumber;221 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);222 223 if (!indexIsNumber)224 return false;225 226 if (indexAsNumber >= size)227 return false;228 229 if (_map[indexAsNumber].isNull())230 return false;231 232 return true;233 }234 235 void IndexToNameMap::unMap(ExecState* exec, const Identifier& index)236 {237 bool indexIsNumber;238 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);239 240 ASSERT(indexIsNumber && indexAsNumber < size);241 242 _map[indexAsNumber] = exec->propertyNames().nullIdentifier;243 }244 245 Identifier& IndexToNameMap::operator[](const Identifier& index)246 {247 bool indexIsNumber;248 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);249 250 ASSERT(indexIsNumber && indexAsNumber < size);251 252 return _map[indexAsNumber];253 }254 255 // ------------------------------ Arguments ---------------------------------256 257 const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };258 259 // ECMA 10.1.8260 Arguments::Arguments(ExecState* exec, JSFunction* func, const ArgList& args, JSActivation* act)261 : JSObject(exec->lexicalGlobalObject()->objectPrototype())262 , _activationObject(act)263 , indexToNameMap(func, args)264 {265 putDirect(exec->propertyNames().callee, func, DontEnum);266 putDirect(exec, exec->propertyNames().length, args.size(), DontEnum);267 268 int i = 0;269 ArgList::const_iterator end = args.end();270 for (ArgList::const_iterator it = args.begin(); it != end; ++it, ++i) {271 Identifier name = Identifier::from(exec, i);272 if (!indexToNameMap.isMapped(name))273 putDirect(name, *it, DontEnum);274 }275 }276 277 void Arguments::mark()278 {279 JSObject::mark();280 if (_activationObject && !_activationObject->marked())281 _activationObject->mark();282 }283 284 JSValue* Arguments::mappedIndexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)285 {286 Arguments* thisObj = static_cast<Arguments*>(slot.slotBase());287 return thisObj->_activationObject->get(exec, thisObj->indexToNameMap[propertyName]);288 }289 290 bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)291 {292 if (indexToNameMap.isMapped(propertyName)) {293 slot.setCustom(this, mappedIndexGetter);294 return true;295 }296 297 return JSObject::getOwnPropertySlot(exec, propertyName, slot);298 }299 300 void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value)301 {302 if (indexToNameMap.isMapped(propertyName))303 _activationObject->put(exec, indexToNameMap[propertyName], value);304 else305 JSObject::put(exec, propertyName, value);306 }307 308 bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)309 {310 if (indexToNameMap.isMapped(propertyName)) {311 indexToNameMap.unMap(exec, propertyName);312 return true;313 } else {314 return JSObject::deleteProperty(exec, propertyName);315 }316 }317 318 // ------------------------------ Global Functions -----------------------------------319 320 static JSValue* encode(ExecState* exec, const ArgList& args, const char* do_not_escape)321 {322 UString r = "", s, str = args[0]->toString(exec);323 CString cstr = str.UTF8String(true);324 if (!cstr.c_str())325 return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");326 const char* p = cstr.c_str();327 for (size_t k = 0; k < cstr.size(); k++, p++) {328 char c = *p;329 if (c && strchr(do_not_escape, c)) {330 r.append(c);331 } else {332 char tmp[4];333 sprintf(tmp, "%%%02X", (unsigned char)c);334 r += tmp;335 }336 }337 return jsString(exec, r);338 }339 340 static JSValue* decode(ExecState* exec, const ArgList& args, const char* do_not_unescape, bool strict)341 {342 UString s = "", str = args[0]->toString(exec);343 int k = 0, len = str.size();344 const UChar* d = str.data();345 UChar u = 0;346 while (k < len) {347 const UChar* p = d + k;348 UChar c = *p;349 if (c == '%') {350 int charLen = 0;351 if (k <= len - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {352 const char b0 = Lexer::convertHex(p[1], p[2]);353 const int sequenceLen = UTF8SequenceLength(b0);354 if (sequenceLen != 0 && k <= len - sequenceLen * 3) {355 charLen = sequenceLen * 3;356 char sequence[5];357 sequence[0] = b0;358 for (int i = 1; i < sequenceLen; ++i) {359 const UChar* q = p + i * 3;360 if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))361 sequence[i] = Lexer::convertHex(q[1], q[2]);362 else {363 charLen = 0;364 break;365 }366 }367 if (charLen != 0) {368 sequence[sequenceLen] = 0;369 const int character = decodeUTF8Sequence(sequence);370 if (character < 0 || character >= 0x110000) {371 charLen = 0;372 } else if (character >= 0x10000) {373 // Convert to surrogate pair.374 s.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));375 u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));376 } else {377 u = static_cast<UChar>(character);378 }379 }380 }381 }382 if (charLen == 0) {383 if (strict)384 return throwError(exec, URIError);385 // The only case where we don't use "strict" mode is the "unescape" function.386 // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.387 if (k <= len - 6 && p[1] == 'u'388 && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])389 && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {390 charLen = 6;391 u = Lexer::convertUnicode(p[2], p[3], p[4], p[5]);392 }393 }394 if (charLen && (u == 0 || u >= 128 || !strchr(do_not_unescape, u))) {395 c = u;396 k += charLen - 1;397 }398 }399 k++;400 s.append(c);401 }402 return jsString(exec, s);403 }404 405 static bool isStrWhiteSpace(unsigned short c)406 {407 switch (c) {408 case 0x0009:409 case 0x000A:410 case 0x000B:411 case 0x000C:412 case 0x000D:413 case 0x0020:414 case 0x00A0:415 case 0x2028:416 case 0x2029:417 return true;418 default:419 return c > 0xff && isSeparatorSpace(c);420 }421 }422 423 static int parseDigit(unsigned short c, int radix)424 {425 int digit = -1;426 427 if (c >= '0' && c <= '9') {428 digit = c - '0';429 } else if (c >= 'A' && c <= 'Z') {430 digit = c - 'A' + 10;431 } else if (c >= 'a' && c <= 'z') {432 digit = c - 'a' + 10;433 }434 435 if (digit >= radix)436 return -1;437 return digit;438 }439 440 double parseIntOverflow(const char* s, int length, int radix)441 {442 double number = 0.0;443 double radixMultiplier = 1.0;444 445 for (const char* p = s + length - 1; p >= s; p--) {446 if (radixMultiplier == Inf) {447 if (*p != '0') {448 number = Inf;449 break;450 }451 } else {452 int digit = parseDigit(*p, radix);453 number += digit * radixMultiplier;454 }455 456 radixMultiplier *= radix;457 }458 459 return number;460 }461 462 static double parseInt(const UString& s, int radix)463 {464 int length = s.size();465 int p = 0;466 467 while (p < length && isStrWhiteSpace(s[p])) {468 ++p;469 }470 471 double sign = 1;472 if (p < length) {473 if (s[p] == '+') {474 ++p;475 } else if (s[p] == '-') {476 sign = -1;477 ++p;478 }479 }480 481 if ((radix == 0 || radix == 16) && length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {482 radix = 16;483 p += 2;484 } else if (radix == 0) {485 if (p < length && s[p] == '0')486 radix = 8;487 else488 radix = 10;489 }490 491 if (radix < 2 || radix > 36)492 return NaN;493 494 int firstDigitPosition = p;495 bool sawDigit = false;496 double number = 0;497 while (p < length) {498 int digit = parseDigit(s[p], radix);499 if (digit == -1)500 break;501 sawDigit = true;502 number *= radix;503 number += digit;504 ++p;505 }506 507 if (number >= mantissaOverflowLowerBound) {508 if (radix == 10)509 number = strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0);510 else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)511 number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), p - firstDigitPosition, radix);512 }513 514 if (!sawDigit)515 return NaN;516 517 return sign * number;518 }519 520 static double parseFloat(const UString& s)521 {522 // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0.523 // Need to skip any whitespace and then one + or - sign.524 int length = s.size();525 int p = 0;526 while (p < length && isStrWhiteSpace(s[p])) {527 ++p;528 }529 if (p < length && (s[p] == '+' || s[p] == '-')) {530 ++p;531 }532 if (length - p >= 2 && s[p] == '0' && (s[p + 1] == 'x' || s[p + 1] == 'X')) {533 return 0;534 }535 536 return s.toDouble( true /*tolerant*/, false /* NaN for empty string */ );537 }538 539 JSValue* globalFuncEval(ExecState* exec, JSObject* function, JSValue* thisValue, const ArgList& args)540 {541 JSObject* thisObject = thisValue->toThisObject(exec);542 JSGlobalObject* globalObject = thisObject->toGlobalObject(exec);543 if (!globalObject || globalObject->evalFunction() != function)544 return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated");545 546 JSValue* x = args[0];547 if (!x->isString())548 return x;549 550 UString s = x->toString(exec);551 552 int sourceId;553 int errLine;554 UString errMsg;555 556 RefPtr<EvalNode> evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(s), &sourceId, &errLine, &errMsg);557 558 if (!evalNode)559 return throwError(exec, SyntaxError, errMsg, errLine, sourceId, NULL);560 561 return exec->machine()->execute(evalNode.get(), exec, thisObject, globalObject->globalScopeChain().node(), exec->exceptionSlot());562 }563 564 JSValue* globalFuncParseInt(ExecState* exec, JSObject*, JSValue*, const ArgList& args)565 {566 return jsNumber(exec, parseInt(args[0]->toString(exec), args[1]->toInt32(exec)));567 }568 569 JSValue* globalFuncParseFloat(ExecState* exec, JSObject*, JSValue*, const ArgList& args)570 {571 return jsNumber(exec, parseFloat(args[0]->toString(exec)));572 }573 574 JSValue* globalFuncIsNaN(ExecState* exec, JSObject*, JSValue*, const ArgList& args)575 {576 return jsBoolean(isnan(args[0]->toNumber(exec)));577 }578 579 JSValue* globalFuncIsFinite(ExecState* exec, JSObject*, JSValue*, const ArgList& args)580 {581 double n = args[0]->toNumber(exec);582 return jsBoolean(!isnan(n) && !isinf(n));583 }584 585 JSValue* globalFuncDecodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)586 {587 static const char do_not_unescape_when_decoding_URI[] =588 "#$&+,/:;=?@";589 590 return decode(exec, args, do_not_unescape_when_decoding_URI, true);591 }592 593 JSValue* globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)594 {595 return decode(exec, args, "", true);596 }597 598 JSValue* globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)599 {600 static const char do_not_escape_when_encoding_URI[] =601 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"602 "abcdefghijklmnopqrstuvwxyz"603 "0123456789"604 "!#$&'()*+,-./:;=?@_~";605 606 return encode(exec, args, do_not_escape_when_encoding_URI);607 }608 609 JSValue* globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)610 {611 static const char do_not_escape_when_encoding_URI_component[] =612 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"613 "abcdefghijklmnopqrstuvwxyz"614 "0123456789"615 "!'()*-._~";616 617 return encode(exec, args, do_not_escape_when_encoding_URI_component);618 }619 620 JSValue* globalFuncEscape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)621 {622 static const char do_not_escape[] =623 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"624 "abcdefghijklmnopqrstuvwxyz"625 "0123456789"626 "*+-./@_";627 628 UString r = "", s, str = args[0]->toString(exec);629 const UChar* c = str.data();630 for (int k = 0; k < str.size(); k++, c++) {631 int u = c[0];632 if (u > 255) {633 char tmp[7];634 sprintf(tmp, "%%u%04X", u);635 s = UString(tmp);636 } else if (u != 0 && strchr(do_not_escape, (char)u))637 s = UString(c, 1);638 else {639 char tmp[4];640 sprintf(tmp, "%%%02X", u);641 s = UString(tmp);642 }643 r += s;644 }645 646 return jsString(exec, r);647 }648 649 JSValue* globalFuncUnescape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)650 {651 UString s = "", str = args[0]->toString(exec);652 int k = 0, len = str.size();653 while (k < len) {654 const UChar* c = str.data() + k;655 UChar u;656 if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {657 if (Lexer::isHexDigit(c[2]) && Lexer::isHexDigit(c[3]) && Lexer::isHexDigit(c[4]) && Lexer::isHexDigit(c[5])) {658 u = Lexer::convertUnicode(c[2], c[3], c[4], c[5]);659 c = &u;660 k += 5;661 }662 } else if (c[0] == '%' && k <= len - 3 && Lexer::isHexDigit(c[1]) && Lexer::isHexDigit(c[2])) {663 u = UChar(Lexer::convertHex(c[1], c[2]));664 c = &u;665 k += 2;666 }667 k++;668 s.append(*c);669 }670 671 return jsString(exec, s);672 }673 674 #ifndef NDEBUG675 JSValue* globalFuncKJSPrint(ExecState* exec, JSObject*, JSValue*, const ArgList& args)676 {677 CStringBuffer string;678 args[0]->toString(exec).getCString(string);679 puts(string.data());680 return jsUndefined();681 }682 #endif683 684 // ------------------------------ PrototypeFunction -------------------------------685 33 686 34 PrototypeFunction::PrototypeFunction(ExecState* exec, int len, const Identifier& name, NativeFunction function) … … 706 54 } 707 55 708 // ------------------------------ PrototypeReflexiveFunction -------------------------------709 710 GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)711 : PrototypeFunction(exec, functionPrototype, len, name, function)712 , m_cachedGlobalObject(cachedGlobalObject)713 {714 ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);715 }716 717 void GlobalEvalFunction::mark()718 {719 PrototypeFunction::mark();720 if (!m_cachedGlobalObject->marked())721 m_cachedGlobalObject->mark();722 }723 724 56 } // namespace KJS -
trunk/JavaScriptCore/kjs/PrototypeFunction.h
r35006 r35016 22 22 */ 23 23 24 #ifndef JSFunction_h25 #define JSFunction_h24 #ifndef PrototypeFunction_h 25 #define PrototypeFunction_h 26 26 27 27 #include "InternalFunction.h" 28 #include "JSVariableObject.h" 29 #include "SymbolTable.h" 30 #include "nodes.h" 31 #include "JSObject.h" 28 #include "CallData.h" 32 29 33 30 namespace KJS { 34 35 class FunctionBodyNode;36 class FunctionPrototype;37 class JSActivation;38 class JSGlobalObject;39 40 class JSFunction : public InternalFunction {41 public:42 JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*);43 44 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);45 virtual void put(ExecState*, const Identifier& propertyName, JSValue*);46 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);47 48 JSObject* construct(ExecState*, const ArgList&);49 JSValue* call(ExecState*, JSValue* thisValue, const ArgList&);50 51 // Note: Returns a null identifier for any parameters that will never get set52 // due to a later parameter with the same name.53 const Identifier& getParameterName(int index);54 55 static const ClassInfo info;56 57 RefPtr<FunctionBodyNode> body;58 59 void setScope(const ScopeChain& s) { _scope = s; }60 ScopeChain& scope() { return _scope; }61 62 virtual void mark();63 64 private:65 virtual const ClassInfo* classInfo() const { return &info; }66 virtual ConstructType getConstructData(ConstructData&);67 virtual CallType getCallData(CallData&);68 69 ScopeChain _scope;70 71 static JSValue* argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);72 static JSValue* callerGetter(ExecState*, const Identifier&, const PropertySlot&);73 static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&);74 };75 76 class IndexToNameMap {77 public:78 IndexToNameMap(JSFunction*, const ArgList&);79 ~IndexToNameMap();80 81 Identifier& operator[](const Identifier& index);82 bool isMapped(const Identifier& index) const;83 void unMap(ExecState* exec, const Identifier& index);84 85 private:86 unsigned size;87 Identifier* _map;88 };89 90 class Arguments : public JSObject {91 public:92 Arguments(ExecState*, JSFunction* func, const ArgList& args, JSActivation* act);93 virtual void mark();94 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);95 virtual void put(ExecState*, const Identifier& propertyName, JSValue*);96 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);97 virtual const ClassInfo* classInfo() const { return &info; }98 static const ClassInfo info;99 private:100 static JSValue* mappedIndexGetter(ExecState*, const Identifier&, const PropertySlot& slot);101 102 JSActivation* _activationObject;103 mutable IndexToNameMap indexToNameMap;104 };105 31 106 32 class PrototypeFunction : public InternalFunction { … … 115 41 }; 116 42 117 class GlobalEvalFunction : public PrototypeFunction { 118 public: 119 GlobalEvalFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject); 120 JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; } 43 } // namespace KJS 121 44 122 private: 123 virtual void mark(); 124 125 JSGlobalObject* m_cachedGlobalObject; 126 }; 127 128 // Global Functions 129 JSValue* globalFuncEval(ExecState*, JSObject*, JSValue*, const ArgList&); 130 JSValue* globalFuncParseInt(ExecState*, JSObject*, JSValue*, const ArgList&); 131 JSValue* globalFuncParseFloat(ExecState*, JSObject*, JSValue*, const ArgList&); 132 JSValue* globalFuncIsNaN(ExecState*, JSObject*, JSValue*, const ArgList&); 133 JSValue* globalFuncIsFinite(ExecState*, JSObject*, JSValue*, const ArgList&); 134 JSValue* globalFuncDecodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); 135 JSValue* globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); 136 JSValue* globalFuncEncodeURI(ExecState*, JSObject*, JSValue*, const ArgList&); 137 JSValue* globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&); 138 JSValue* globalFuncEscape(ExecState*, JSObject*, JSValue*, const ArgList&); 139 JSValue* globalFuncUnescape(ExecState*, JSObject*, JSValue*, const ArgList&); 140 #ifndef NDEBUG 141 JSValue* globalFuncKJSPrint(ExecState*, JSObject*, JSValue*, const ArgList&); 142 #endif 143 144 static const double mantissaOverflowLowerBound = 9007199254740992.0; 145 double parseIntOverflow(const char*, int length, int radix); 146 147 } // namespace 148 149 #endif 45 #endif // PrototypeFunction_h -
trunk/JavaScriptCore/kjs/Shell.cpp
r34947 r35016 34 34 #include "JSObject.h" 35 35 #include "Parser.h" 36 #include "PrototypeFunction.h" 36 37 #include "collector.h" 37 38 #include "completion.h" -
trunk/JavaScriptCore/kjs/lexer.cpp
r34607 r35016 28 28 #include "nodes.h" 29 29 #include "NodeInfo.h" 30 #include "JSGlobalObjectFunctions.h" 30 31 #include <ctype.h> 31 32 #include <limits.h> -
trunk/JavaScriptCore/kjs/ustring.cpp
r34947 r35016 25 25 #include "ustring.h" 26 26 27 #include "JSGlobalObjectFunctions.h" 27 28 #include "collector.h" 28 29 #include "dtoa.h" 29 #include "JSFunction.h"30 30 #include "identifier.h" 31 31 #include "operations.h" … … 36 36 #include <stdio.h> 37 37 #include <stdlib.h> 38 #include <wtf/ASCIICType.h> 38 39 #include <wtf/Assertions.h> 39 #include <wtf/ASCIICType.h>40 40 #include <wtf/MathExtras.h> 41 41 #include <wtf/Vector.h>
Note:
See TracChangeset
for help on using the changeset viewer.