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.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.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : // -----------------------------------------------------------------------------
17 : // ES6 section 21.2 RegExp Objects
18 :
19 13516425 : BUILTIN(RegExpPrototypeToString) {
20 : HandleScope scope(isolate);
21 4506657 : CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.toString");
22 :
23 9010162 : if (*recv == isolate->regexp_function()->prototype()) {
24 49 : isolate->CountUsage(v8::Isolate::kRegExpPrototypeToString);
25 : }
26 :
27 4505081 : IncrementalStringBuilder builder(isolate);
28 :
29 : builder.AppendCharacter('/');
30 : {
31 : Handle<Object> source;
32 9010162 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
33 : isolate, source,
34 : JSReceiver::GetProperty(recv, isolate->factory()->source_string()));
35 : Handle<String> source_str;
36 9010162 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, source_str,
37 : Object::ToString(isolate, source));
38 4505081 : builder.AppendString(source_str);
39 : }
40 :
41 : builder.AppendCharacter('/');
42 : {
43 : Handle<Object> flags;
44 9010162 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
45 : isolate, flags,
46 : JSReceiver::GetProperty(recv, isolate->factory()->flags_string()));
47 : Handle<String> flags_str;
48 9010162 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, flags_str,
49 : Object::ToString(isolate, flags));
50 4505081 : builder.AppendString(flags_str);
51 : }
52 :
53 13515243 : RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
54 : }
55 :
56 : // The properties $1..$9 are the first nine capturing substrings of the last
57 : // successful match, or ''. The function RegExpMakeCaptureGetter will be
58 : // called with indices from 1 to 9.
59 : #define DEFINE_CAPTURE_GETTER(i) \
60 : BUILTIN(RegExpCapture##i##Getter) { \
61 : HandleScope scope(isolate); \
62 : return *RegExpUtils::GenericCaptureGetter( \
63 : isolate, isolate->regexp_last_match_info(), i); \
64 : }
65 1210878 : DEFINE_CAPTURE_GETTER(1)
66 7122 : DEFINE_CAPTURE_GETTER(2)
67 7032 : DEFINE_CAPTURE_GETTER(3)
68 6690 : DEFINE_CAPTURE_GETTER(4)
69 6768 : DEFINE_CAPTURE_GETTER(5)
70 6510 : DEFINE_CAPTURE_GETTER(6)
71 6504 : DEFINE_CAPTURE_GETTER(7)
72 6246 : DEFINE_CAPTURE_GETTER(8)
73 6246 : DEFINE_CAPTURE_GETTER(9)
74 : #undef DEFINE_CAPTURE_GETTER
75 :
76 : // The properties `input` and `$_` are aliases for each other. When this
77 : // value is set, the value it is set to is coerced to a string.
78 : // Getter and setter for the input.
79 :
80 46488 : BUILTIN(RegExpInputGetter) {
81 : HandleScope scope(isolate);
82 30992 : Handle<Object> obj(isolate->regexp_last_match_info()->LastInput(), isolate);
83 14 : return obj->IsUndefined(isolate) ? isolate->heap()->empty_string()
84 30992 : : String::cast(*obj);
85 : }
86 :
87 213 : BUILTIN(RegExpInputSetter) {
88 : HandleScope scope(isolate);
89 71 : Handle<Object> value = args.atOrUndefined(isolate, 1);
90 : Handle<String> str;
91 142 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, str,
92 : Object::ToString(isolate, value));
93 142 : isolate->regexp_last_match_info()->SetLastInput(*str);
94 71 : return isolate->heap()->undefined_value();
95 : }
96 :
97 : // Getters for the static properties lastMatch, lastParen, leftContext, and
98 : // rightContext of the RegExp constructor. The properties are computed based
99 : // on the captures array of the last successful match and the subject string
100 : // of the last successful match.
101 602157 : BUILTIN(RegExpLastMatchGetter) {
102 : HandleScope scope(isolate);
103 : return *RegExpUtils::GenericCaptureGetter(
104 602157 : isolate, isolate->regexp_last_match_info(), 0);
105 : }
106 :
107 3747 : BUILTIN(RegExpLastParenGetter) {
108 : HandleScope scope(isolate);
109 1249 : Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info();
110 : const int length = match_info->NumberOfCaptureRegisters();
111 1249 : if (length <= 2) return isolate->heap()->empty_string(); // No captures.
112 :
113 : DCHECK_EQ(0, length % 2);
114 968 : const int last_capture = (length / 2) - 1;
115 :
116 : // We match the SpiderMonkey behavior: return the substring defined by the
117 : // last pair (after the first pair) of elements of the capture array even if
118 : // it is empty.
119 1936 : return *RegExpUtils::GenericCaptureGetter(isolate, match_info, last_capture);
120 : }
121 :
122 600123 : BUILTIN(RegExpLeftContextGetter) {
123 : HandleScope scope(isolate);
124 200041 : Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info();
125 : const int start_index = match_info->Capture(0);
126 : Handle<String> last_subject(match_info->LastSubject());
127 600123 : return *isolate->factory()->NewSubString(last_subject, 0, start_index);
128 : }
129 :
130 47028 : BUILTIN(RegExpRightContextGetter) {
131 : HandleScope scope(isolate);
132 15676 : Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info();
133 : const int start_index = match_info->Capture(1);
134 : Handle<String> last_subject(match_info->LastSubject());
135 : const int len = last_subject->length();
136 47028 : return *isolate->factory()->NewSubString(last_subject, start_index, len);
137 : }
138 :
139 : } // namespace internal
140 : } // namespace v8
|