Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(492)

Side by Side Diff: src/js/regexp.js

Issue 2389233002: [regexp] Port RegExp getters and setters (Closed)
Patch Set: Handle Smi receivers Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 (function(global, utils) { 5 (function(global, utils) {
6 6
7 'use strict'; 7 'use strict';
8 8
9 %CheckIsBootstrapping(); 9 %CheckIsBootstrapping();
10 10
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 if (previousLastIndex != 0) this.lastIndex = 0; 770 if (previousLastIndex != 0) this.lastIndex = 0;
771 var result = RegExpSubclassExec(this, string); 771 var result = RegExpSubclassExec(this, string);
772 var currentLastIndex = this.lastIndex; 772 var currentLastIndex = this.lastIndex;
773 if (currentLastIndex != previousLastIndex) this.lastIndex = previousLastIndex; 773 if (currentLastIndex != previousLastIndex) this.lastIndex = previousLastIndex;
774 if (IS_NULL(result)) return -1; 774 if (IS_NULL(result)) return -1;
775 return result.index; 775 return result.index;
776 } 776 }
777 %FunctionRemovePrototype(RegExpSubclassSearch); 777 %FunctionRemovePrototype(RegExpSubclassSearch);
778 778
779 779
780 // Getters for the static properties lastMatch, lastParen, leftContext, and
781 // rightContext of the RegExp constructor. The properties are computed based
782 // on the captures array of the last successful match and the subject string
783 // of the last successful match.
784 function RegExpGetLastMatch() {
785 var regExpSubject = LAST_SUBJECT(RegExpLastMatchInfo);
786 return %_SubString(regExpSubject,
787 RegExpLastMatchInfo[CAPTURE0],
788 RegExpLastMatchInfo[CAPTURE1]);
789 }
790
791
792 function RegExpGetLastParen() {
793 var length = NUMBER_OF_CAPTURES(RegExpLastMatchInfo);
794 if (length <= 2) return ''; // There were no captures.
795 // We match the SpiderMonkey behavior: return the substring defined by the
796 // last pair (after the first pair) of elements of the capture array even if
797 // it is empty.
798 var regExpSubject = LAST_SUBJECT(RegExpLastMatchInfo);
799 var start = RegExpLastMatchInfo[CAPTURE(length - 2)];
800 var end = RegExpLastMatchInfo[CAPTURE(length - 1)];
801 if (start != -1 && end != -1) {
802 return %_SubString(regExpSubject, start, end);
803 }
804 return "";
805 }
806
807
808 function RegExpGetLeftContext() {
809 var start_index;
810 var subject;
811 start_index = RegExpLastMatchInfo[CAPTURE0];
812 subject = LAST_SUBJECT(RegExpLastMatchInfo);
813 return %_SubString(subject, 0, start_index);
814 }
815
816
817 function RegExpGetRightContext() {
818 var start_index;
819 var subject;
820 start_index = RegExpLastMatchInfo[CAPTURE1];
821 subject = LAST_SUBJECT(RegExpLastMatchInfo);
822 return %_SubString(subject, start_index, subject.length);
823 }
824
825
826 // The properties $1..$9 are the first nine capturing substrings of the last
827 // successful match, or ''. The function RegExpMakeCaptureGetter will be
828 // called with indices from 1 to 9.
829 function RegExpMakeCaptureGetter(n) {
830 return function foo() {
831 var index = n * 2;
832 if (index >= NUMBER_OF_CAPTURES(RegExpLastMatchInfo)) return '';
833 var matchStart = RegExpLastMatchInfo[CAPTURE(index)];
834 var matchEnd = RegExpLastMatchInfo[CAPTURE(index + 1)];
835 if (matchStart == -1 || matchEnd == -1) return '';
836 return %_SubString(LAST_SUBJECT(RegExpLastMatchInfo), matchStart, matchEnd);
837 };
838 }
839
840
841 // ES6 21.2.5.3.
842 function RegExpGetFlags() {
843 if (!IS_RECEIVER(this)) {
844 throw %make_type_error(
845 kRegExpNonObject, "RegExp.prototype.flags", TO_STRING(this));
846 }
847 var result = '';
848 if (this.global) result += 'g';
849 if (this.ignoreCase) result += 'i';
850 if (this.multiline) result += 'm';
851 if (this.unicode) result += 'u';
852 if (this.sticky) result += 'y';
853 return result;
854 }
855
856
857 // ES6 21.2.5.4.
858 function RegExpGetGlobal() {
859 if (!IS_REGEXP(this)) {
860 if (this === GlobalRegExpPrototype) {
861 %IncrementUseCounter(kRegExpPrototypeOldFlagGetter);
862 return UNDEFINED;
863 }
864 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.global");
865 }
866 return TO_BOOLEAN(REGEXP_GLOBAL(this));
867 }
868 %SetForceInlineFlag(RegExpGetGlobal);
869
870
871 // ES6 21.2.5.5.
872 function RegExpGetIgnoreCase() {
873 if (!IS_REGEXP(this)) {
874 if (this === GlobalRegExpPrototype) {
875 %IncrementUseCounter(kRegExpPrototypeOldFlagGetter);
876 return UNDEFINED;
877 }
878 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.ignoreCase");
879 }
880 return TO_BOOLEAN(REGEXP_IGNORE_CASE(this));
881 }
882
883
884 // ES6 21.2.5.7.
885 function RegExpGetMultiline() {
886 if (!IS_REGEXP(this)) {
887 if (this === GlobalRegExpPrototype) {
888 %IncrementUseCounter(kRegExpPrototypeOldFlagGetter);
889 return UNDEFINED;
890 }
891 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.multiline");
892 }
893 return TO_BOOLEAN(REGEXP_MULTILINE(this));
894 }
895
896
897 // ES6 21.2.5.10.
898 function RegExpGetSource() {
899 if (!IS_REGEXP(this)) {
900 if (this === GlobalRegExpPrototype) {
901 %IncrementUseCounter(kRegExpPrototypeSourceGetter);
902 return "(?:)";
903 }
904 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.source");
905 }
906 return REGEXP_SOURCE(this);
907 }
908
909
910 // ES6 21.2.5.12.
911 function RegExpGetSticky() {
912 if (!IS_REGEXP(this)) {
913 if (this === GlobalRegExpPrototype) {
914 %IncrementUseCounter(kRegExpPrototypeStickyGetter);
915 return UNDEFINED;
916 }
917 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.sticky");
918 }
919 return TO_BOOLEAN(REGEXP_STICKY(this));
920 }
921 %SetForceInlineFlag(RegExpGetSticky);
922
923
924 // ES6 21.2.5.15.
925 function RegExpGetUnicode() {
926 if (!IS_REGEXP(this)) {
927 if (this === GlobalRegExpPrototype) {
928 %IncrementUseCounter(kRegExpPrototypeUnicodeGetter);
929 return UNDEFINED;
930 }
931 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.unicode");
932 }
933 return TO_BOOLEAN(REGEXP_UNICODE(this));
934 }
935 %SetForceInlineFlag(RegExpGetUnicode);
936
937
938 function RegExpSpecies() {
939 return this;
940 }
941
942
943 // ------------------------------------------------------------------- 780 // -------------------------------------------------------------------
944 781
945 utils.InstallGetter(GlobalRegExp, speciesSymbol, RegExpSpecies);
946
947 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ 782 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [
948 "test", RegExpSubclassTest, 783 "test", RegExpSubclassTest,
949 "toString", RegExpToString, 784 "toString", RegExpToString,
950 "compile", RegExpCompileJS, 785 "compile", RegExpCompileJS,
951 matchSymbol, RegExpSubclassMatch, 786 matchSymbol, RegExpSubclassMatch,
952 replaceSymbol, RegExpSubclassReplace, 787 replaceSymbol, RegExpSubclassReplace,
953 searchSymbol, RegExpSubclassSearch, 788 searchSymbol, RegExpSubclassSearch,
954 splitSymbol, RegExpSubclassSplit, 789 splitSymbol, RegExpSubclassSplit,
955 ]); 790 ]);
956 791
957 utils.InstallGetter(GlobalRegExp.prototype, 'flags', RegExpGetFlags);
958 utils.InstallGetter(GlobalRegExp.prototype, 'global', RegExpGetGlobal);
959 utils.InstallGetter(GlobalRegExp.prototype, 'ignoreCase', RegExpGetIgnoreCase);
960 utils.InstallGetter(GlobalRegExp.prototype, 'multiline', RegExpGetMultiline);
961 utils.InstallGetter(GlobalRegExp.prototype, 'source', RegExpGetSource);
962 utils.InstallGetter(GlobalRegExp.prototype, 'sticky', RegExpGetSticky);
963 utils.InstallGetter(GlobalRegExp.prototype, 'unicode', RegExpGetUnicode);
964
965 // The properties `input` and `$_` are aliases for each other. When this
966 // value is set the value it is set to is coerced to a string.
967 // Getter and setter for the input.
968 var RegExpGetInput = function() {
969 var regExpInput = LAST_INPUT(RegExpLastMatchInfo);
970 return IS_UNDEFINED(regExpInput) ? "" : regExpInput;
971 };
972 var RegExpSetInput = function(string) {
973 LAST_INPUT(RegExpLastMatchInfo) = TO_STRING(string);
974 };
975
976 // TODO(jgruber): All of these getters and setters were intended to be installed
977 // with various attributes (e.g. DONT_ENUM | DONT_DELETE), but
978 // InstallGetterSetter had a bug which ignored the passed attributes and
979 // simply installed as DONT_ENUM instead. We might want to change back
980 // to the intended attributes at some point.
981 // On the other hand, installing attributes as DONT_ENUM matches the draft
982 // specification at
983 // https://github.com/claudepache/es-regexp-legacy-static-properties
984
985 %OptimizeObjectForAddingMultipleProperties(GlobalRegExp, 22);
986 utils.InstallGetterSetter(GlobalRegExp, 'input', RegExpGetInput, RegExpSetInput,
987 DONT_ENUM);
988 utils.InstallGetterSetter(GlobalRegExp, '$_', RegExpGetInput, RegExpSetInput,
989 DONT_ENUM);
990
991
992 var NoOpSetter = function(ignored) {};
993
994
995 // Static properties set by a successful match.
996 utils.InstallGetterSetter(GlobalRegExp, 'lastMatch', RegExpGetLastMatch,
997 NoOpSetter, DONT_ENUM);
998 utils.InstallGetterSetter(GlobalRegExp, '$&', RegExpGetLastMatch, NoOpSetter,
999 DONT_ENUM);
1000 utils.InstallGetterSetter(GlobalRegExp, 'lastParen', RegExpGetLastParen,
1001 NoOpSetter, DONT_ENUM);
1002 utils.InstallGetterSetter(GlobalRegExp, '$+', RegExpGetLastParen, NoOpSetter,
1003 DONT_ENUM);
1004 utils.InstallGetterSetter(GlobalRegExp, 'leftContext', RegExpGetLeftContext,
1005 NoOpSetter, DONT_ENUM);
1006 utils.InstallGetterSetter(GlobalRegExp, '$`', RegExpGetLeftContext, NoOpSetter,
1007 DONT_ENUM);
1008 utils.InstallGetterSetter(GlobalRegExp, 'rightContext', RegExpGetRightContext,
1009 NoOpSetter, DONT_ENUM);
1010 utils.InstallGetterSetter(GlobalRegExp, "$'", RegExpGetRightContext, NoOpSetter,
1011 DONT_ENUM);
1012
1013 for (var i = 1; i < 10; ++i) {
1014 utils.InstallGetterSetter(GlobalRegExp, '$' + i, RegExpMakeCaptureGetter(i),
1015 NoOpSetter, DONT_ENUM);
1016 }
1017 %ToFastProperties(GlobalRegExp);
1018
1019 %InstallToContext(["regexp_last_match_info", RegExpLastMatchInfo]); 792 %InstallToContext(["regexp_last_match_info", RegExpLastMatchInfo]);
1020 793
1021 // ------------------------------------------------------------------- 794 // -------------------------------------------------------------------
1022 // Internal 795 // Internal
1023 796
1024 var InternalRegExpMatchInfo = { 797 var InternalRegExpMatchInfo = {
1025 REGEXP_NUMBER_OF_CAPTURES: 2, 798 REGEXP_NUMBER_OF_CAPTURES: 2,
1026 REGEXP_LAST_SUBJECT: "", 799 REGEXP_LAST_SUBJECT: "",
1027 REGEXP_LAST_INPUT: UNDEFINED, 800 REGEXP_LAST_INPUT: UNDEFINED,
1028 CAPTURE0: 0, 801 CAPTURE0: 0,
(...skipping 20 matching lines...) Expand all
1049 to.GetSubstitution = GetSubstitution; 822 to.GetSubstitution = GetSubstitution;
1050 to.InternalRegExpMatch = InternalRegExpMatch; 823 to.InternalRegExpMatch = InternalRegExpMatch;
1051 to.InternalRegExpReplace = InternalRegExpReplace; 824 to.InternalRegExpReplace = InternalRegExpReplace;
1052 to.IsRegExp = IsRegExp; 825 to.IsRegExp = IsRegExp;
1053 to.RegExpExec = DoRegExpExec; 826 to.RegExpExec = DoRegExpExec;
1054 to.RegExpInitialize = RegExpInitialize; 827 to.RegExpInitialize = RegExpInitialize;
1055 to.RegExpLastMatchInfo = RegExpLastMatchInfo; 828 to.RegExpLastMatchInfo = RegExpLastMatchInfo;
1056 }); 829 });
1057 830
1058 }) 831 })
OLDNEW
« src/builtins/builtins-regexp.cc ('K') | « src/heap-symbols.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698