OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
6 | 6 |
7 #include "bin/directory.h" | 7 #include "bin/directory.h" |
8 | 8 |
9 #include "bin/dartutils.h" | 9 #include "bin/dartutils.h" |
| 10 #include "bin/log.h" |
10 #include "include/dart_api.h" | 11 #include "include/dart_api.h" |
11 #include "platform/assert.h" | 12 #include "platform/assert.h" |
12 | 13 |
13 namespace dart { | 14 namespace dart { |
14 namespace bin { | 15 namespace bin { |
15 | 16 |
16 void FUNCTION_NAME(Directory_Current)(Dart_NativeArguments args) { | 17 void FUNCTION_NAME(Directory_Current)(Dart_NativeArguments args) { |
17 const char* current = Directory::Current(); | 18 const char* current = Directory::Current(); |
18 if (current != NULL) { | 19 if (current != NULL) { |
19 Dart_SetReturnValue(args, DartUtils::NewString(current)); | 20 Dart_SetReturnValue(args, DartUtils::NewString(current)); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 } | 133 } |
133 SyncDirectoryListing sync_listing(results, | 134 SyncDirectoryListing sync_listing(results, |
134 DartUtils::GetStringValue(path), | 135 DartUtils::GetStringValue(path), |
135 DartUtils::GetBooleanValue(recursive), | 136 DartUtils::GetBooleanValue(recursive), |
136 DartUtils::GetBooleanValue(follow_links)); | 137 DartUtils::GetBooleanValue(follow_links)); |
137 Directory::List(&sync_listing); | 138 Directory::List(&sync_listing); |
138 Dart_SetReturnValue(args, results); | 139 Dart_SetReturnValue(args, results); |
139 } | 140 } |
140 | 141 |
141 | 142 |
| 143 static const int kAsyncDirectoryListerFieldIndex = 0; |
| 144 |
| 145 |
| 146 void FUNCTION_NAME(Directory_GetAsyncDirectoryListerPointer)( |
| 147 Dart_NativeArguments args) { |
| 148 AsyncDirectoryListing* listing; |
| 149 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); |
| 150 ASSERT(Dart_IsInstance(dart_this)); |
| 151 ThrowIfError(Dart_GetNativeInstanceField( |
| 152 dart_this, |
| 153 kAsyncDirectoryListerFieldIndex, |
| 154 reinterpret_cast<intptr_t*>(&listing))); |
| 155 if (listing != NULL) { |
| 156 intptr_t listing_pointer = reinterpret_cast<intptr_t>(listing); |
| 157 // Increment the listing's reference count. This native should only be |
| 158 // be called when we are about to send the AsyncDirectoryListing* to the |
| 159 // IO service. |
| 160 listing->Retain(); |
| 161 Dart_SetReturnValue(args, Dart_NewInteger(listing_pointer)); |
| 162 } |
| 163 } |
| 164 |
| 165 |
| 166 static void ReleaseListing(void* isolate_callback_data, |
| 167 Dart_WeakPersistentHandle handle, |
| 168 void* peer) { |
| 169 AsyncDirectoryListing* listing = |
| 170 reinterpret_cast<AsyncDirectoryListing*>(peer); |
| 171 listing->Release(); |
| 172 } |
| 173 |
| 174 |
| 175 void FUNCTION_NAME(Directory_SetAsyncDirectoryListerPointer)( |
| 176 Dart_NativeArguments args) { |
| 177 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); |
| 178 intptr_t listing_pointer = |
| 179 DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1)); |
| 180 AsyncDirectoryListing* listing = |
| 181 reinterpret_cast<AsyncDirectoryListing*>(listing_pointer); |
| 182 Dart_NewWeakPersistentHandle( |
| 183 dart_this, |
| 184 reinterpret_cast<void*>(listing), |
| 185 sizeof(*listing), |
| 186 ReleaseListing); |
| 187 Dart_Handle result = Dart_SetNativeInstanceField( |
| 188 dart_this, |
| 189 kAsyncDirectoryListerFieldIndex, |
| 190 listing_pointer); |
| 191 if (Dart_IsError(result)) { |
| 192 Log::PrintErr("SetAsyncDirectoryListerPointer failed\n"); |
| 193 Dart_PropagateError(result); |
| 194 } |
| 195 } |
| 196 |
| 197 |
142 CObject* Directory::CreateRequest(const CObjectArray& request) { | 198 CObject* Directory::CreateRequest(const CObjectArray& request) { |
143 if ((request.Length() == 1) && request[0]->IsString()) { | 199 if ((request.Length() == 1) && request[0]->IsString()) { |
144 CObjectString path(request[0]); | 200 CObjectString path(request[0]); |
145 if (Directory::Create(path.CString())) { | 201 if (Directory::Create(path.CString())) { |
146 return CObject::True(); | 202 return CObject::True(); |
147 } else { | 203 } else { |
148 return CObject::NewOSError(); | 204 return CObject::NewOSError(); |
149 } | 205 } |
150 } | 206 } |
151 return CObject::IllegalArgumentError(); | 207 return CObject::IllegalArgumentError(); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 CObjectString path(request[0]); | 275 CObjectString path(request[0]); |
220 CObjectBool recursive(request[1]); | 276 CObjectBool recursive(request[1]); |
221 CObjectBool follow_links(request[2]); | 277 CObjectBool follow_links(request[2]); |
222 AsyncDirectoryListing* dir_listing = | 278 AsyncDirectoryListing* dir_listing = |
223 new AsyncDirectoryListing(path.CString(), | 279 new AsyncDirectoryListing(path.CString(), |
224 recursive.Value(), | 280 recursive.Value(), |
225 follow_links.Value()); | 281 follow_links.Value()); |
226 if (dir_listing->error()) { | 282 if (dir_listing->error()) { |
227 // Report error now, so we capture the correct OSError. | 283 // Report error now, so we capture the correct OSError. |
228 CObject* err = CObject::NewOSError(); | 284 CObject* err = CObject::NewOSError(); |
229 delete dir_listing; | 285 dir_listing->Release(); |
230 CObjectArray* error = new CObjectArray(CObject::NewArray(3)); | 286 CObjectArray* error = new CObjectArray(CObject::NewArray(3)); |
231 error->SetAt(0, new CObjectInt32( | 287 error->SetAt(0, new CObjectInt32( |
232 CObject::NewInt32(AsyncDirectoryListing::kListError))); | 288 CObject::NewInt32(AsyncDirectoryListing::kListError))); |
233 error->SetAt(1, request[0]); | 289 error->SetAt(1, request[0]); |
234 error->SetAt(2, err); | 290 error->SetAt(2, err); |
235 return error; | 291 return error; |
236 } | 292 } |
237 // TODO(ajohnsen): Consider returning the first few results. | 293 // TODO(ajohnsen): Consider returning the first few results. |
238 return new CObjectIntptr(CObject::NewIntptr( | 294 return new CObjectIntptr(CObject::NewIntptr( |
239 reinterpret_cast<intptr_t>(dir_listing))); | 295 reinterpret_cast<intptr_t>(dir_listing))); |
240 } | 296 } |
241 return CreateIllegalArgumentError(); | 297 return CreateIllegalArgumentError(); |
242 } | 298 } |
243 | 299 |
244 | 300 |
245 CObject* Directory::ListNextRequest(const CObjectArray& request) { | 301 CObject* Directory::ListNextRequest(const CObjectArray& request) { |
246 if ((request.Length() == 1) && request[0]->IsIntptr()) { | 302 if ((request.Length() == 1) && request[0]->IsIntptr()) { |
247 CObjectIntptr ptr(request[0]); | 303 CObjectIntptr ptr(request[0]); |
248 AsyncDirectoryListing* dir_listing = | 304 AsyncDirectoryListing* dir_listing = |
249 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value()); | 305 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value()); |
| 306 RefCntReleaseScope<AsyncDirectoryListing> rs(dir_listing); |
250 if (dir_listing->IsEmpty()) { | 307 if (dir_listing->IsEmpty()) { |
251 return new CObjectArray(CObject::NewArray(0)); | 308 return new CObjectArray(CObject::NewArray(0)); |
252 } | 309 } |
253 const int kArraySize = 128; | 310 const int kArraySize = 128; |
254 CObjectArray* response = new CObjectArray(CObject::NewArray(kArraySize)); | 311 CObjectArray* response = new CObjectArray(CObject::NewArray(kArraySize)); |
255 dir_listing->SetArray(response, kArraySize); | 312 dir_listing->SetArray(response, kArraySize); |
256 Directory::List(dir_listing); | 313 Directory::List(dir_listing); |
257 // In case the listing ended before it hit the buffer length, we need to | 314 // In case the listing ended before it hit the buffer length, we need to |
258 // override the array length. | 315 // override the array length. |
259 response->AsApiCObject()->value.as_array.length = dir_listing->index(); | 316 response->AsApiCObject()->value.as_array.length = dir_listing->index(); |
260 return response; | 317 return response; |
261 } | 318 } |
262 return CreateIllegalArgumentError(); | 319 return CreateIllegalArgumentError(); |
263 } | 320 } |
264 | 321 |
265 | 322 |
266 CObject* Directory::ListStopRequest(const CObjectArray& request) { | 323 CObject* Directory::ListStopRequest(const CObjectArray& request) { |
267 if ((request.Length() == 1) && request[0]->IsIntptr()) { | 324 if ((request.Length() == 1) && request[0]->IsIntptr()) { |
268 CObjectIntptr ptr(request[0]); | 325 CObjectIntptr ptr(request[0]); |
269 AsyncDirectoryListing* dir_listing = | 326 AsyncDirectoryListing* dir_listing = |
270 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value()); | 327 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value()); |
271 delete dir_listing; | 328 RefCntReleaseScope<AsyncDirectoryListing> rs(dir_listing); |
| 329 |
| 330 // We have retained a reference to the listing here. Therefore the listing's |
| 331 // destructor can't be running. Since no further requests are dispatched by |
| 332 // the Dart code after an async stop call, this PopAll() can't be racing |
| 333 // with any other call on the listing. We don't do an extra Release(), and |
| 334 // we don't delete the weak persistent handle. The file is closed here, but |
| 335 // the memory for the listing will be cleaned up when the finalizer runs. |
| 336 dir_listing->PopAll(); |
272 return new CObjectBool(CObject::Bool(true)); | 337 return new CObjectBool(CObject::Bool(true)); |
273 } | 338 } |
274 return CreateIllegalArgumentError(); | 339 return CreateIllegalArgumentError(); |
275 } | 340 } |
276 | 341 |
277 | 342 |
278 CObject* Directory::RenameRequest(const CObjectArray& request) { | 343 CObject* Directory::RenameRequest(const CObjectArray& request) { |
279 if ((request.Length() == 2) && | 344 if ((request.Length() == 2) && |
280 request[0]->IsString() && | 345 request[0]->IsString() && |
281 request[1]->IsString()) { | 346 request[1]->IsString()) { |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 listing->HandleDone(); | 484 listing->HandleDone(); |
420 } else { | 485 } else { |
421 while (ListNext(listing)) {} | 486 while (ListNext(listing)) {} |
422 } | 487 } |
423 } | 488 } |
424 | 489 |
425 } // namespace bin | 490 } // namespace bin |
426 } // namespace dart | 491 } // namespace dart |
427 | 492 |
428 #endif // !defined(DART_IO_DISABLED) | 493 #endif // !defined(DART_IO_DISABLED) |
OLD | NEW |