OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 28 matching lines...) Expand all Loading... |
39 icu::BreakIterator* BreakIterator::UnpackBreakIterator( | 39 icu::BreakIterator* BreakIterator::UnpackBreakIterator( |
40 v8::Handle<v8::Object> obj) { | 40 v8::Handle<v8::Object> obj) { |
41 if (break_iterator_template_->HasInstance(obj)) { | 41 if (break_iterator_template_->HasInstance(obj)) { |
42 return static_cast<icu::BreakIterator*>( | 42 return static_cast<icu::BreakIterator*>( |
43 obj->GetPointerFromInternalField(0)); | 43 obj->GetPointerFromInternalField(0)); |
44 } | 44 } |
45 | 45 |
46 return NULL; | 46 return NULL; |
47 } | 47 } |
48 | 48 |
| 49 UnicodeString* BreakIterator::ResetAdoptedText( |
| 50 v8::Handle<v8::Object> obj, v8::Handle<v8::Value> value) { |
| 51 // Get the previous value from the internal field. |
| 52 UnicodeString* text = static_cast<UnicodeString*>( |
| 53 obj->GetPointerFromInternalField(1)); |
| 54 delete text; |
| 55 |
| 56 // Assign new value to the internal pointer. |
| 57 v8::String::Value text_value(value); |
| 58 text = new UnicodeString( |
| 59 reinterpret_cast<const UChar*>(*text_value), text_value.length()); |
| 60 obj->SetPointerInInternalField(1, text); |
| 61 |
| 62 // Return new unicode string pointer. |
| 63 return text; |
| 64 } |
| 65 |
49 void BreakIterator::DeleteBreakIterator(v8::Persistent<v8::Value> object, | 66 void BreakIterator::DeleteBreakIterator(v8::Persistent<v8::Value> object, |
50 void* param) { | 67 void* param) { |
51 v8::Persistent<v8::Object> persistent_object = | 68 v8::Persistent<v8::Object> persistent_object = |
52 v8::Persistent<v8::Object>::Cast(object); | 69 v8::Persistent<v8::Object>::Cast(object); |
53 | 70 |
54 // First delete the hidden C++ object. | 71 // First delete the hidden C++ object. |
55 // Unpacking should never return NULL here. That would only happen if | 72 // Unpacking should never return NULL here. That would only happen if |
56 // this method is used as the weak callback for persistent handles not | 73 // this method is used as the weak callback for persistent handles not |
57 // pointing to a break iterator. | 74 // pointing to a break iterator. |
58 delete UnpackBreakIterator(persistent_object); | 75 delete UnpackBreakIterator(persistent_object); |
59 | 76 |
| 77 delete static_cast<UnicodeString*>( |
| 78 persistent_object->GetPointerFromInternalField(1)); |
| 79 |
60 // Then dispose of the persistent handle to JS object. | 80 // Then dispose of the persistent handle to JS object. |
61 persistent_object.Dispose(); | 81 persistent_object.Dispose(); |
62 } | 82 } |
63 | 83 |
64 // Throws a JavaScript exception. | 84 // Throws a JavaScript exception. |
65 static v8::Handle<v8::Value> ThrowUnexpectedObjectError() { | 85 static v8::Handle<v8::Value> ThrowUnexpectedObjectError() { |
66 // Returns undefined, and schedules an exception to be thrown. | 86 // Returns undefined, and schedules an exception to be thrown. |
67 return v8::ThrowException(v8::Exception::Error( | 87 return v8::ThrowException(v8::Exception::Error( |
68 v8::String::New("BreakIterator method called on an object " | 88 v8::String::New("BreakIterator method called on an object " |
69 "that is not a BreakIterator."))); | 89 "that is not a BreakIterator."))); |
70 } | 90 } |
71 | 91 |
72 v8::Handle<v8::Value> BreakIterator::BreakIteratorAdoptText( | 92 v8::Handle<v8::Value> BreakIterator::BreakIteratorAdoptText( |
73 const v8::Arguments& args) { | 93 const v8::Arguments& args) { |
74 if (args.Length() != 1 || !args[0]->IsString()) { | 94 if (args.Length() != 1 || !args[0]->IsString()) { |
75 return v8::ThrowException(v8::Exception::SyntaxError( | 95 return v8::ThrowException(v8::Exception::SyntaxError( |
76 v8::String::New("Text input is required."))); | 96 v8::String::New("Text input is required."))); |
77 } | 97 } |
78 | 98 |
79 icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder()); | 99 icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder()); |
80 if (!break_iterator) { | 100 if (!break_iterator) { |
81 return ThrowUnexpectedObjectError(); | 101 return ThrowUnexpectedObjectError(); |
82 } | 102 } |
83 | 103 |
84 v8::String::Value text_value(args[0]); | 104 break_iterator->setText(*ResetAdoptedText(args.Holder(), args[0])); |
85 UnicodeString text( | |
86 reinterpret_cast<const UChar*>(*text_value), text_value.length()); | |
87 | |
88 break_iterator->setText(text); | |
89 | 105 |
90 return v8::Undefined(); | 106 return v8::Undefined(); |
91 } | 107 } |
92 | 108 |
93 v8::Handle<v8::Value> BreakIterator::BreakIteratorFirst( | 109 v8::Handle<v8::Value> BreakIterator::BreakIteratorFirst( |
94 const v8::Arguments& args) { | 110 const v8::Arguments& args) { |
95 icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder()); | 111 icu::BreakIterator* break_iterator = UnpackBreakIterator(args.Holder()); |
96 if (!break_iterator) { | 112 if (!break_iterator) { |
97 return ThrowUnexpectedObjectError(); | 113 return ThrowUnexpectedObjectError(); |
98 } | 114 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 } | 201 } |
186 | 202 |
187 if (break_iterator_template_.IsEmpty()) { | 203 if (break_iterator_template_.IsEmpty()) { |
188 v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New()); | 204 v8::Local<v8::FunctionTemplate> raw_template(v8::FunctionTemplate::New()); |
189 | 205 |
190 raw_template->SetClassName(v8::String::New("v8Locale.v8BreakIterator")); | 206 raw_template->SetClassName(v8::String::New("v8Locale.v8BreakIterator")); |
191 | 207 |
192 // Define internal field count on instance template. | 208 // Define internal field count on instance template. |
193 v8::Local<v8::ObjectTemplate> object_template = | 209 v8::Local<v8::ObjectTemplate> object_template = |
194 raw_template->InstanceTemplate(); | 210 raw_template->InstanceTemplate(); |
195 object_template->SetInternalFieldCount(1); | 211 |
| 212 // Set aside internal fields for icu break iterator and adopted text. |
| 213 object_template->SetInternalFieldCount(2); |
196 | 214 |
197 // Define all of the prototype methods on prototype template. | 215 // Define all of the prototype methods on prototype template. |
198 v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate(); | 216 v8::Local<v8::ObjectTemplate> proto = raw_template->PrototypeTemplate(); |
199 proto->Set(v8::String::New("adoptText"), | 217 proto->Set(v8::String::New("adoptText"), |
200 v8::FunctionTemplate::New(BreakIteratorAdoptText)); | 218 v8::FunctionTemplate::New(BreakIteratorAdoptText)); |
201 proto->Set(v8::String::New("first"), | 219 proto->Set(v8::String::New("first"), |
202 v8::FunctionTemplate::New(BreakIteratorFirst)); | 220 v8::FunctionTemplate::New(BreakIteratorFirst)); |
203 proto->Set(v8::String::New("next"), | 221 proto->Set(v8::String::New("next"), |
204 v8::FunctionTemplate::New(BreakIteratorNext)); | 222 v8::FunctionTemplate::New(BreakIteratorNext)); |
205 proto->Set(v8::String::New("current"), | 223 proto->Set(v8::String::New("current"), |
206 v8::FunctionTemplate::New(BreakIteratorCurrent)); | 224 v8::FunctionTemplate::New(BreakIteratorCurrent)); |
207 proto->Set(v8::String::New("breakType"), | 225 proto->Set(v8::String::New("breakType"), |
208 v8::FunctionTemplate::New(BreakIteratorBreakType)); | 226 v8::FunctionTemplate::New(BreakIteratorBreakType)); |
209 | 227 |
210 break_iterator_template_ = | 228 break_iterator_template_ = |
211 v8::Persistent<v8::FunctionTemplate>::New(raw_template); | 229 v8::Persistent<v8::FunctionTemplate>::New(raw_template); |
212 } | 230 } |
213 | 231 |
214 // Create an empty object wrapper. | 232 // Create an empty object wrapper. |
215 v8::Local<v8::Object> local_object = | 233 v8::Local<v8::Object> local_object = |
216 break_iterator_template_->GetFunction()->NewInstance(); | 234 break_iterator_template_->GetFunction()->NewInstance(); |
217 v8::Persistent<v8::Object> wrapper = | 235 v8::Persistent<v8::Object> wrapper = |
218 v8::Persistent<v8::Object>::New(local_object); | 236 v8::Persistent<v8::Object>::New(local_object); |
219 | 237 |
220 // Set break iterator as internal field of the resulting JS object. | 238 // Set break iterator as internal field of the resulting JS object. |
221 wrapper->SetPointerInInternalField(0, break_iterator); | 239 wrapper->SetPointerInInternalField(0, break_iterator); |
| 240 // Make sure that the pointer to adopted text is NULL. |
| 241 wrapper->SetPointerInInternalField(1, NULL); |
222 | 242 |
223 // Make object handle weak so we can delete iterator once GC kicks in. | 243 // Make object handle weak so we can delete iterator once GC kicks in. |
224 wrapper.MakeWeak(NULL, DeleteBreakIterator); | 244 wrapper.MakeWeak(NULL, DeleteBreakIterator); |
225 | 245 |
226 return wrapper; | 246 return wrapper; |
227 } | 247 } |
228 | 248 |
229 } } // namespace v8::internal | 249 } } // namespace v8::internal |
OLD | NEW |