Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/builtins/builtins-utils-inl.h"
6 : #include "src/builtins/builtins.h"
7 : #include "src/counters.h"
8 : #include "src/objects-inl.h"
9 : #include "src/regexp/jsregexp.h"
10 : #include "src/regexp/regexp-utils.h"
11 : #include "src/string-builder-inl.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : // -----------------------------------------------------------------------------
17 : // ES6 section 21.2 RegExp Objects
18 :
19 30745 : BUILTIN(RegExpPrototypeToString) {
20 : HandleScope scope(isolate);
21 6866 : CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.toString");
22 :
23 17730 : if (*recv == isolate->regexp_function()->prototype()) {
24 32 : isolate->CountUsage(v8::Isolate::kRegExpPrototypeToString);
25 : }
26 :
27 5910 : IncrementalStringBuilder builder(isolate);
28 :
29 : builder.AppendCharacter('/');
30 : {
31 : Handle<Object> source;
32 11820 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
33 : isolate, source,
34 : JSReceiver::GetProperty(isolate, recv,
35 : isolate->factory()->source_string()));
36 : Handle<String> source_str;
37 11820 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, source_str,
38 : Object::ToString(isolate, source));
39 5910 : builder.AppendString(source_str);
40 : }
41 :
42 : builder.AppendCharacter('/');
43 : {
44 : Handle<Object> flags;
45 11820 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
46 : isolate, flags,
47 : JSReceiver::GetProperty(isolate, recv,
48 : isolate->factory()->flags_string()));
49 : Handle<String> flags_str;
50 11820 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, flags_str,
51 : Object::ToString(isolate, flags));
52 5910 : builder.AppendString(flags_str);
53 : }
54 :
55 11820 : RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
56 : }
57 :
58 : // The properties $1..$9 are the first nine capturing substrings of the last
59 : // successful match, or ''. The function RegExpMakeCaptureGetter will be
60 : // called with indices from 1 to 9.
61 : #define DEFINE_CAPTURE_GETTER(i) \
62 : BUILTIN(RegExpCapture##i##Getter) { \
63 : HandleScope scope(isolate); \
64 : return *RegExpUtils::GenericCaptureGetter( \
65 : isolate, isolate->regexp_last_match_info(), i); \
66 : }
67 967080 : DEFINE_CAPTURE_GETTER(1)
68 2376 : DEFINE_CAPTURE_GETTER(2)
69 2304 : DEFINE_CAPTURE_GETTER(3)
70 2016 : DEFINE_CAPTURE_GETTER(4)
71 2088 : DEFINE_CAPTURE_GETTER(5)
72 1872 : DEFINE_CAPTURE_GETTER(6)
73 1872 : DEFINE_CAPTURE_GETTER(7)
74 1656 : DEFINE_CAPTURE_GETTER(8)
75 1656 : DEFINE_CAPTURE_GETTER(9)
76 : #undef DEFINE_CAPTURE_GETTER
77 :
78 : // The properties `input` and `$_` are aliases for each other. When this
79 : // value is set, the value it is set to is coerced to a string.
80 : // Getter and setter for the input.
81 :
82 47660 : BUILTIN(RegExpInputGetter) {
83 : HandleScope scope(isolate);
84 19064 : Handle<Object> obj(isolate->regexp_last_match_info()->LastInput(), isolate);
85 : return obj->IsUndefined(isolate) ? ReadOnlyRoots(isolate).empty_string()
86 28596 : : String::cast(*obj);
87 : }
88 :
89 225 : BUILTIN(RegExpInputSetter) {
90 : HandleScope scope(isolate);
91 45 : Handle<Object> value = args.atOrUndefined(isolate, 1);
92 : Handle<String> str;
93 90 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, str,
94 : Object::ToString(isolate, value));
95 135 : isolate->regexp_last_match_info()->SetLastInput(*str);
96 45 : return ReadOnlyRoots(isolate).undefined_value();
97 : }
98 :
99 : // Getters for the static properties lastMatch, lastParen, leftContext, and
100 : // rightContext of the RegExp constructor. The properties are computed based
101 : // on the captures array of the last successful match and the subject string
102 : // of the last successful match.
103 604385 : BUILTIN(RegExpLastMatchGetter) {
104 : HandleScope scope(isolate);
105 241754 : return *RegExpUtils::GenericCaptureGetter(
106 362631 : isolate, isolate->regexp_last_match_info(), 0);
107 : }
108 :
109 1665 : BUILTIN(RegExpLastParenGetter) {
110 : HandleScope scope(isolate);
111 333 : Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info();
112 : const int length = match_info->NumberOfCaptureRegisters();
113 333 : if (length <= 2) {
114 171 : return ReadOnlyRoots(isolate).empty_string(); // No captures.
115 : }
116 :
117 : DCHECK_EQ(0, length % 2);
118 162 : const int last_capture = (length / 2) - 1;
119 :
120 : // We match the SpiderMonkey behavior: return the substring defined by the
121 : // last pair (after the first pair) of elements of the capture array even if
122 : // it is empty.
123 324 : return *RegExpUtils::GenericCaptureGetter(isolate, match_info, last_capture);
124 : }
125 :
126 601295 : BUILTIN(RegExpLeftContextGetter) {
127 : HandleScope scope(isolate);
128 120259 : Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info();
129 : const int start_index = match_info->Capture(0);
130 : Handle<String> last_subject(match_info->LastSubject(), isolate);
131 360777 : return *isolate->factory()->NewSubString(last_subject, 0, start_index);
132 : }
133 :
134 48200 : BUILTIN(RegExpRightContextGetter) {
135 : HandleScope scope(isolate);
136 9640 : Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info();
137 : const int start_index = match_info->Capture(1);
138 : Handle<String> last_subject(match_info->LastSubject(), isolate);
139 : const int len = last_subject->length();
140 28920 : return *isolate->factory()->NewSubString(last_subject, start_index, len);
141 : }
142 :
143 : } // namespace internal
144 121996 : } // namespace v8
|