diff --git a/native/v8_extensions/native.js b/native/v8_extensions/native.js index 99ccad613..b19e92a45 100644 --- a/native/v8_extensions/native.js +++ b/native/v8_extensions/native.js @@ -40,9 +40,6 @@ var $native = {}; native function readFromPasteboard(); $native.readFromPasteboard = readFromPasteboard; - native function saveDialog(); - $native.saveDialog = saveDialog; - native function exit(status); $native.exit = exit; diff --git a/native/v8_extensions/native.mm b/native/v8_extensions/native.mm index 649b08ea3..af647f78f 100644 --- a/native/v8_extensions/native.mm +++ b/native/v8_extensions/native.mm @@ -18,15 +18,15 @@ NSString *stringFromCefV8Value(const CefRefPtr& value) { void throwException(const CefRefPtr& global, CefRefPtr exception, NSString *message) { CefV8ValueList arguments; - + message = [message stringByAppendingFormat:@"\n%s", exception->GetMessage().ToString().c_str()]; arguments.push_back(CefV8Value::CreateString(std::string([message UTF8String], [message lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); - + CefRefPtr console = global->GetValue("console"); console->GetValue("error")->ExecuteFunction(console, arguments); } -Native::Native() : CefV8Handler() { +Native::Native() : CefV8Handler() { NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"v8_extensions/native.js"]; NSString *extensionCode = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; CefRegisterExtension("v8/native", [extensionCode UTF8String], this); @@ -49,31 +49,31 @@ bool Native::Execute(const CefString& name, NSError *error = nil; NSString *contents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error]; - + if (error) { exception = [[error localizedDescription] UTF8String]; } - else { + else { retval = CefV8Value::CreateString([contents UTF8String]); } - + return true; } else if (name == "write") { NSString *path = stringFromCefV8Value(arguments[0]); NSString *content = stringFromCefV8Value(arguments[1]); - + NSFileManager *fm = [NSFileManager defaultManager]; - + // Create parent directories if they don't exist BOOL exists = [fm fileExistsAtPath:[path stringByDeletingLastPathComponent] isDirectory:nil]; if (!exists) { [fm createDirectoryAtPath:[path stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil]; } - + NSError *error = nil; BOOL success = [content writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error]; - + if (error) { exception = [[error localizedDescription] UTF8String]; } @@ -82,39 +82,39 @@ bool Native::Execute(const CefString& name, exception += [path UTF8String]; exception += "'"; } - + return true; } else if (name == "absolute") { NSString *path = stringFromCefV8Value(arguments[0]); - + path = [path stringByStandardizingPath]; if ([path characterAtIndex:0] == '/') { retval = CefV8Value::CreateString([path UTF8String]); } - + return true; } else if (name == "list") { NSString *path = stringFromCefV8Value(arguments[0]); bool recursive = arguments[1]->GetBoolValue(); - + if (!path or [path length] == 0) { exception = "$native.list requires a path argument"; return true; } - + NSFileManager *fm = [NSFileManager defaultManager]; NSArray *relativePaths = nil; NSError *error = nil; - + if (recursive) { relativePaths = [fm subpathsOfDirectoryAtPath:path error:&error]; } else { relativePaths = [fm contentsOfDirectoryAtPath:path error:&error]; } - + if (error) { exception = [[error localizedDescription] UTF8String]; } @@ -126,7 +126,7 @@ bool Native::Execute(const CefString& name, retval->SetValue(i, CefV8Value::CreateString([fullPath UTF8String])); } } - + return true; } else if (name == "isDirectory") { @@ -135,40 +135,40 @@ bool Native::Execute(const CefString& name, BOOL isDir = false; BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]; retval = CefV8Value::CreateBool(exists && isDir); - + return true; } else if (name == "isFile") { NSString *path = stringFromCefV8Value(arguments[0]); - + BOOL isDir = false; BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]; retval = CefV8Value::CreateBool(exists && !isDir); - + return true; } else if (name == "remove") { NSString *path = stringFromCefV8Value(arguments[0]); - + NSError *error = nil; [[NSFileManager defaultManager] removeItemAtPath:path error:&error]; - + if (error) { exception = [[error localizedDescription] UTF8String]; } - + return true; } - else if (name == "asyncList") { + else if (name == "asyncList") { return false; } else if (name == "writeToPasteboard") { NSString *text = stringFromCefV8Value(arguments[0]); - + NSPasteboard *pb = [NSPasteboard generalPasteboard]; [pb declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] owner:nil]; [pb setString:text forType:NSStringPboardType]; - + return true; } else if (name == "readFromPasteboard") { @@ -177,19 +177,7 @@ bool Native::Execute(const CefString& name, if (results) { retval = CefV8Value::CreateString([[results objectAtIndex:0] UTF8String]); } - - return true; - } - else if (name == "saveDialog") { - NSSavePanel *panel = [NSSavePanel savePanel]; - if ([panel runModal] == NSFileHandlingPanelOKButton) { - NSURL *url = [panel URL]; - retval = CefV8Value::CreateString([[url path] UTF8String]); - } - else { - return CefV8Value::CreateNull(); - } - + return true; } else if (name == "quit") { @@ -199,7 +187,7 @@ bool Native::Execute(const CefString& name, else if (name == "exit") { int exitStatus = 0; if (arguments.size() > 0) exitStatus = arguments[0]->GetIntValue(); - + exit(exitStatus); return true; } @@ -208,19 +196,19 @@ bool Native::Execute(const CefString& name, CefRefPtr function = arguments[1]; CefRefPtr context = CefV8Context::GetCurrentContext(); - + WatchCallback callback = ^(NSString *eventType, NSString *path) { context->Enter(); - + CefV8ValueList args; - + args.push_back(CefV8Value::CreateString(std::string([eventType UTF8String], [eventType lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); args.push_back(CefV8Value::CreateString(std::string([path UTF8String], [path lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); function->ExecuteFunction(function, args); - + context->Exit(); }; - + PathWatcher *pathWatcher = [PathWatcher pathWatcherForContext:CefV8Context::GetCurrentContext()]; NSString *watchId = [pathWatcher watchPath:path callback:[[callback copy] autorelease]]; if (watchId) { @@ -229,7 +217,7 @@ bool Native::Execute(const CefString& name, else { exception = std::string("Failed to watch path '") + std::string([path UTF8String]) + std::string("' (it may not exist)"); } - + return true; } else if (name == "unwatchPath") { @@ -238,53 +226,53 @@ bool Native::Execute(const CefString& name, NSError *error = nil; PathWatcher *pathWatcher = [PathWatcher pathWatcherForContext:CefV8Context::GetCurrentContext()]; [pathWatcher unwatchPath:path callbackId:callbackId error:&error]; - + if (error) { exception = [[error localizedDescription] UTF8String]; } - - return true; + + return true; } else if (name == "makeDirectory") { NSString *path = stringFromCefV8Value(arguments[0]); NSFileManager *fm = [NSFileManager defaultManager]; NSError *error = nil; [fm createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:&error]; - + if (error) { exception = [[error localizedDescription] UTF8String]; } return true; - } + } else if (name == "move") { NSString *sourcePath = stringFromCefV8Value(arguments[0]); NSString *targetPath = stringFromCefV8Value(arguments[1]); NSFileManager *fm = [NSFileManager defaultManager]; - + NSError *error = nil; [fm moveItemAtPath:sourcePath toPath:targetPath error:&error]; - + if (error) { exception = [[error localizedDescription] UTF8String]; } - - return true; + + return true; } else if (name == "moveToTrash") { NSString *sourcePath = stringFromCefV8Value(arguments[0]); - bool success = [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation + bool success = [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation source:[sourcePath stringByDeletingLastPathComponent] - destination:@"" + destination:@"" files:[NSArray arrayWithObject:[sourcePath lastPathComponent]] tag:nil]; - + if (!success) { std::string exception = "Can not move "; exception += [sourcePath UTF8String]; exception += " to trash."; } - + return true; } else if (name == "reload") { @@ -296,38 +284,38 @@ bool Native::Execute(const CefString& name, NSError *error = nil; NSDictionary *attributes = [fm attributesOfItemAtPath:path error:&error]; - + if (error) { exception = [[error localizedDescription] UTF8String]; } - + NSDate *lastModified = [attributes objectForKey:NSFileModificationDate]; retval = CefV8Value::CreateDate(CefTime([lastModified timeIntervalSince1970])); return true; - } + } else if (name == "md5ForPath") { NSString *path = stringFromCefV8Value(arguments[0]); unsigned char outputData[CC_MD5_DIGEST_LENGTH]; - + NSData *inputData = [[NSData alloc] initWithContentsOfFile:path]; CC_MD5([inputData bytes], [inputData length], outputData); [inputData release]; - + NSMutableString *hash = [[NSMutableString alloc] init]; - + for (NSUInteger i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { [hash appendFormat:@"%02x", outputData[i]]; } - + retval = CefV8Value::CreateString([hash UTF8String]); return true; } else if (name == "exec") { NSString *command = stringFromCefV8Value(arguments[0]); CefRefPtr options = arguments[1]; - CefRefPtr callback = arguments[2]; - - NSTask *task = [[NSTask alloc] init]; + CefRefPtr callback = arguments[2]; + + NSTask *task = [[NSTask alloc] init]; [task setLaunchPath:@"/bin/sh"]; [task setStandardInput:[NSFileHandle fileHandleWithNullDevice]]; [task setArguments:[NSArray arrayWithObjects:@"-l", @"-c", command, nil]]; @@ -336,76 +324,76 @@ bool Native::Execute(const CefString& name, NSPipe *stderr = [NSPipe pipe]; [task setStandardOutput:stdout]; [task setStandardError:stderr]; - + CefRefPtr context = CefV8Context::GetCurrentContext(); void (^outputHandle)(NSFileHandle *fileHandle, CefRefPtr function) = nil; void (^taskTerminatedHandle)() = nil; - + outputHandle = ^(NSFileHandle *fileHandle, CefRefPtr function) { context->Enter(); - + NSData *data = [fileHandle availableData]; NSString *contents = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - - CefV8ValueList args; + + CefV8ValueList args; args.push_back(CefV8Value::CreateString(std::string([contents UTF8String], [contents lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); CefRefPtr retval = function->ExecuteFunction(function, args); - + if (function->HasException()) { throwException(context->GetGlobal(), function->GetException(), @"Error thrown in OutputHandle"); } - + [contents release]; context->Exit(); }; - + taskTerminatedHandle = ^() { context->Enter(); NSString *output = [[NSString alloc] initWithData:[[stdout fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding]; NSString *errorOutput = [[NSString alloc] initWithData:[[task.standardError fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding]; - + CefV8ValueList args; - - args.push_back(CefV8Value::CreateInt([task terminationStatus])); + + args.push_back(CefV8Value::CreateInt([task terminationStatus])); args.push_back(CefV8Value::CreateString([output UTF8String])); args.push_back(CefV8Value::CreateString([errorOutput UTF8String])); - + callback->ExecuteFunction(callback, args); - + if (callback->HasException()) { throwException(context->GetGlobal(), callback->GetException(), @"Error thrown in TaskTerminatedHandle"); } - + context->Exit(); - + stdout.fileHandleForReading.writeabilityHandler = nil; stderr.fileHandleForReading.writeabilityHandler = nil; }; - + task.terminationHandler = ^(NSTask *) { dispatch_sync(dispatch_get_main_queue(), taskTerminatedHandle); }; - + CefRefPtr stdoutFunction = options->GetValue("stdout"); if (stdoutFunction->IsFunction()) { stdout.fileHandleForReading.writeabilityHandler = ^(NSFileHandle *fileHandle) { - dispatch_sync(dispatch_get_main_queue(), ^() { - outputHandle(fileHandle, stdoutFunction); + dispatch_sync(dispatch_get_main_queue(), ^() { + outputHandle(fileHandle, stdoutFunction); }); }; } - + CefRefPtr stderrFunction = options->GetValue("stderr"); if (stderrFunction->IsFunction()) { stderr.fileHandleForReading.writeabilityHandler = ^(NSFileHandle *fileHandle) { - dispatch_sync(dispatch_get_main_queue(), ^() { - outputHandle(fileHandle, stderrFunction); + dispatch_sync(dispatch_get_main_queue(), ^() { + outputHandle(fileHandle, stderrFunction); }); }; } - + [task launch]; - + return true; } else if (name == "getPlatform") { diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 27230ae0c..31866f15c 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -321,11 +321,11 @@ describe "Editor", -> expect(editor.getPath()).toBeUndefined() editor.getBuffer().setText 'Save me to a new path' - spyOn($native, 'saveDialog').andCallFake -> selectedFilePath + spyOn(atom, 'showSaveDialog').andCallFake (callback) -> callback(selectedFilePath) it "presents a 'save as' dialog", -> editor.save() - expect($native.saveDialog).toHaveBeenCalled() + expect(atom.showSaveDialog).toHaveBeenCalled() describe "when a path is chosen", -> it "saves the buffer to the chosen path", -> diff --git a/src/stdlib/native.coffee b/src/stdlib/native.coffee index e35b7b1b3..04c05ae32 100644 --- a/src/stdlib/native.coffee +++ b/src/stdlib/native.coffee @@ -1,7 +1,5 @@ module.exports = class Native - @saveDialog: (args...) -> $native.saveDialog(args...) - @reload: -> $native.reload() @moveToTrash: (args...) -> $native.moveToTrash(args...)