Permalink
Browse files

progress on cleaning up the API. Also added C block support to NodeJS…

…Function
  • Loading branch information...
rsms committed Oct 22, 2010
1 parent a964874 commit 38c7ad6150ff5fb907f83b0d0eb555cddd58bada
@@ -10,8 +10,7 @@
3A14685A126DB75B00992F94 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A146859126DB75800992F94 /* libffi.a */; };
3A146879126DBA7A00992F94 /* NodeCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A146872126DB92500992F94 /* NodeCocoa.h */; settings = {ATTRIBUTES = (Public, ); }; };
3A146930126DCFFE00992F94 /* ConsoleTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A14692F126DCFFE00992F94 /* ConsoleTextView.m */; };
- 3A7CA68D126663A0002158A5 /* NSData+node.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3A7CA6881266638F002158A5 /* NSData+node.mm */; };
- 3A7CA68E126663A0002158A5 /* NSObject+v8.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3A7CA68A1266638F002158A5 /* NSObject+v8.mm */; };
+ 3A2947951271F8E500B31B0C /* NodeJSBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A2947931271F8E500B31B0C /* NodeJSBlock.h */; settings = {ATTRIBUTES = (Public, ); }; };
3A7CA6A81266649C002158A5 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3A7CA6A71266649C002158A5 /* MainMenu.xib */; };
3A7CA6AB126664F4002158A5 /* main.js in Resources */ = {isa = PBXBuildFile; fileRef = 3A7CA6AA126664EB002158A5 /* main.js */; };
3A7CA6AE1266F55D002158A5 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3A7CA6AD1266F55D002158A5 /* AppDelegate.mm */; };
@@ -41,10 +40,12 @@
3A835731126A5F040058174F /* v8-debug.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A83572E126A5F040058174F /* v8-debug.h */; settings = {ATTRIBUTES = (Public, ); }; };
3A835732126A5F040058174F /* v8-profiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A83572F126A5F040058174F /* v8-profiler.h */; settings = {ATTRIBUTES = (Public, ); }; };
3A835733126A5F040058174F /* v8.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A835730126A5F040058174F /* v8.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 3A9629E512708EA700C19FB2 /* NodeJSScript.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A9629E312708EA700C19FB2 /* NodeJSScript.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 3A9629E612708EA700C19FB2 /* NodeJSScript.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3A9629E412708EA700C19FB2 /* NodeJSScript.mm */; };
+ 3A962A6912709B0800C19FB2 /* NodeJSFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A962A6712709B0800C19FB2 /* NodeJSFunction.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 3A962A6A12709B0800C19FB2 /* NodeJSFunction.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3A962A6812709B0800C19FB2 /* NodeJSFunction.mm */; };
3ABA18F6126C50F000753966 /* NSObjectProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 3ABA18F4126C50F000753966 /* NSObjectProxy.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 3ABA18F7126C50F000753966 /* NSObjectProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3ABA18F5126C50F000753966 /* NSObjectProxy.mm */; };
3ABA1991126C642200753966 /* NodeJSProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 3ABA198F126C642200753966 /* NodeJSProxy.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 3ABA1992126C642200753966 /* NodeJSProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3ABA1990126C642200753966 /* NodeJSProxy.mm */; };
3AE7CC1F1269C6DC00FEB40E /* NodeJS.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AE7CC1D1269C6DC00FEB40E /* NodeJS.h */; settings = {ATTRIBUTES = (Public, ); }; };
3AE7CC201269C6DC00FEB40E /* NodeJS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3AE7CC1E1269C6DC00FEB40E /* NodeJS.mm */; };
3AE7CC691269CA2A00FEB40E /* NodeCocoa.framework in Copy frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* NodeCocoa.framework */; };
@@ -114,6 +115,8 @@
3A146872126DB92500992F94 /* NodeCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeCocoa.h; sourceTree = "<group>"; };
3A14692E126DCFFE00992F94 /* ConsoleTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConsoleTextView.h; sourceTree = "<group>"; };
3A14692F126DCFFE00992F94 /* ConsoleTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConsoleTextView.m; sourceTree = "<group>"; };
+ 3A2947931271F8E500B31B0C /* NodeJSBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeJSBlock.h; sourceTree = "<group>"; };
+ 3A2947941271F8E500B31B0C /* NodeJSBlock.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NodeJSBlock.mm; sourceTree = "<group>"; };
3A7CA6861266638F002158A5 /* NS+node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NS+node.h"; sourceTree = "<group>"; };
3A7CA6871266638F002158A5 /* NSData+node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+node.h"; sourceTree = "<group>"; };
3A7CA6881266638F002158A5 /* NSData+node.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSData+node.mm"; sourceTree = "<group>"; };
@@ -152,6 +155,10 @@
3A83572E126A5F040058174F /* v8-debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "v8-debug.h"; path = "deps/node/deps/v8/include/v8-debug.h"; sourceTree = "<group>"; };
3A83572F126A5F040058174F /* v8-profiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "v8-profiler.h"; path = "deps/node/deps/v8/include/v8-profiler.h"; sourceTree = "<group>"; };
3A835730126A5F040058174F /* v8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = v8.h; path = deps/node/deps/v8/include/v8.h; sourceTree = "<group>"; };
+ 3A9629E312708EA700C19FB2 /* NodeJSScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeJSScript.h; sourceTree = "<group>"; };
+ 3A9629E412708EA700C19FB2 /* NodeJSScript.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NodeJSScript.mm; sourceTree = "<group>"; };
+ 3A962A6712709B0800C19FB2 /* NodeJSFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeJSFunction.h; sourceTree = "<group>"; };
+ 3A962A6812709B0800C19FB2 /* NodeJSFunction.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NodeJSFunction.mm; sourceTree = "<group>"; };
3ABA18F4126C50F000753966 /* NSObjectProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSObjectProxy.h; sourceTree = "<group>"; };
3ABA18F5126C50F000753966 /* NSObjectProxy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NSObjectProxy.mm; sourceTree = "<group>"; };
3ABA198F126C642200753966 /* NodeJSProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeJSProxy.h; sourceTree = "<group>"; };
@@ -275,6 +282,12 @@
3A146872126DB92500992F94 /* NodeCocoa.h */,
3AE7CC1D1269C6DC00FEB40E /* NodeJS.h */,
3AE7CC1E1269C6DC00FEB40E /* NodeJS.mm */,
+ 3A9629E312708EA700C19FB2 /* NodeJSScript.h */,
+ 3A9629E412708EA700C19FB2 /* NodeJSScript.mm */,
+ 3A962A6712709B0800C19FB2 /* NodeJSFunction.h */,
+ 3A962A6812709B0800C19FB2 /* NodeJSFunction.mm */,
+ 3A2947931271F8E500B31B0C /* NodeJSBlock.h */,
+ 3A2947941271F8E500B31B0C /* NodeJSBlock.mm */,
3ABA198F126C642200753966 /* NodeJSProxy.h */,
3ABA1990126C642200753966 /* NodeJSProxy.mm */,
3ABA18F4126C50F000753966 /* NSObjectProxy.h */,
@@ -361,6 +374,9 @@
files = (
3A146879126DBA7A00992F94 /* NodeCocoa.h in Headers */,
3ABA1991126C642200753966 /* NodeJSProxy.h in Headers */,
+ 3A9629E512708EA700C19FB2 /* NodeJSScript.h in Headers */,
+ 3A962A6912709B0800C19FB2 /* NodeJSFunction.h in Headers */,
+ 3A2947951271F8E500B31B0C /* NodeJSBlock.h in Headers */,
3ABA18F6126C50F000753966 /* NSObjectProxy.h in Headers */,
3AE7CC1F1269C6DC00FEB40E /* NodeJS.h in Headers */,
3A835703126A5E8C0058174F /* node_buffer.h in Headers */,
@@ -539,11 +555,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 3A7CA68D126663A0002158A5 /* NSData+node.mm in Sources */,
- 3A7CA68E126663A0002158A5 /* NSObject+v8.mm in Sources */,
3AE7CC201269C6DC00FEB40E /* NodeJS.mm in Sources */,
- 3ABA18F7126C50F000753966 /* NSObjectProxy.mm in Sources */,
- 3ABA1992126C642200753966 /* NodeJSProxy.mm in Sources */,
+ 3A9629E612708EA700C19FB2 /* NodeJSScript.mm in Sources */,
+ 3A962A6A12709B0800C19FB2 /* NodeJSFunction.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
@@ -1,5 +1,5 @@
#import "AppDelegate.h"
-#import "NodeJS.h"
+#import <NodeCocoa/NodeCocoa.h>
using namespace v8;
@@ -101,7 +101,7 @@ - (void)awakeFromNib {
[textView_ setTextContainerInset:NSMakeSize(2.0, 4.0)];
[textView_ setDelegate:self];
[textView_.textStorage appendAttributedString:[isa linePrefix]];
- [textView_.textStorage setDelegate:self];
+ //[textView_.textStorage setDelegate:self];
// setup output text view
[outputTextView_ setTextColor:kInputLineColor];
@@ -128,6 +128,8 @@ - (void)applicationWillFinishLaunching:(NSNotification *)notification {
object:pipeReadHandle];
[pipeReadHandle readInBackgroundAndNotify];
+ return;
+ // redirect stderr to a pipe
// Alternative 1: Might cause funky crashes if NSLog is invoked at an
// inapropriate time (e.g. during reading of stderr).
nodeStderrPipe_ = [[NSPipe pipe] retain];
@@ -265,7 +267,8 @@ - (void)eval:(NSString*)script {
if (kSysInspectFunction.IsEmpty()) {
HandleScope scope;
Local<Value> result = [NodeJS eval:@"require('sys').inspect"
- name:@"<input>"
+ origin:@"<internal>"
+ context:nil
error:&error];
if (result.IsEmpty() || !result->IsFunction()) {
NSLog(@"failed to look up sys.inspect: %@", error);
@@ -277,7 +280,7 @@ - (void)eval:(NSString*)script {
// Prepare input
script = [script stringByTrimmingCharactersInSet:
- [NSCharacterSet whitespaceCharacterSet]];
+ [NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([script length] == 0) return;
// Save to history & reset history cursor
@@ -286,20 +289,21 @@ - (void)eval:(NSString*)script {
if (uncommitedHistoryEntry_)
self.uncommitedHistoryEntry = nil;
- // If the line starts with a '{' or '[' we need to wrap it in ( and )
- // for eval to function properly
+ // If the line starts with a '{' or '[' (or is a function) we need to wrap it
+ // in ( and ) for eval to function properly
unichar ch0 = [script characterAtIndex:0];
- if (ch0 == '{' || ch0 == '[') {
+ if (ch0 == '{' || ch0 == '[' || [script hasPrefix:@"function"]) {
script = [NSString stringWithFormat:@"(%@)", script];
}
// result = eval(script)
HandleScope scope;
- Local<Value> result = [NodeJS eval:script name:@"<input>" error:&error];
+ Local<Value> result =
+ [NodeJS eval:script origin:@"<input>" context:nil error:&error];
// Handle result
if (result.IsEmpty()) {
- NSLog(@"eval error: %@", error);
+ NSLog(@"eval: %@", error);
[self appendLine:[error localizedDescription]
attributes:kErrorStringAttributes];
} else if (!result->IsUndefined()) {
@@ -310,47 +314,10 @@ - (void)eval:(NSString*)script {
}
}
-
-#pragma mark -
-#pragma mark NSTextStorageDelegate implementation
-
-/*- (void)textStorageDidProcessEditing:(NSNotification *)notification {
- NSLog(@"textStorageDidProcessEditing");
- [scrollView_ scrollToEndOfDocument:self];
- NSTextStorage *textStorage = [notification object];
- NSRange editRange = [textStorage editedRange];
- NSInteger changeInLen = [textStorage changeInLength];
- BOOL wasInUndoRedo = [[textView_ undoManager] isUndoing] ||
- [[textView_ undoManager] isRedoing];
- NSLog(@"textStorageDidProcessEditing:\n"
- @" editRange: %@\n"
- @" changeInLength: %d\n"
- @" wasInUndoRedo: %s",
- NSStringFromRange(editRange), changeInLen, wasInUndoRedo ? "YES":"NO");
- if (changeInLen > 0) {
- // insertion (or additive replacement)
-
- NSString* str = [[textStorage mutableString] substringWithRange:editRange];
- NSLog(@"added: '%@'", str);
- str = [str stringByReplacingOccurrencesOfString:@"\n" withString:@"\n> "];
- [textStorage replaceCharactersInRange:editRange withString:str];
- }
-}*/
-
-
#pragma mark -
#pragma mark NSTextViewDelegate implementation
-/*- (void)textDidChange:(NSNotification *)notification {
- NSTextStorage* textStorage = textView_.textStorage;
- NSInteger changeInLen = [textStorage changeInLength];
- if (changeInLen > 0) {
- // content was added, so make sure we see everything
- [scrollView_ scrollToEndOfDocument:self];
- }
-}*/
-
- (NSRange)rangeOfCurrentInputLinePrefix {
NSMutableString* mstr = [textView_.textStorage mutableString];
NSRange lastNLRange =
@@ -501,6 +468,7 @@ - (NSAttributedString*)replaceInputLineWithAttributedString:
NSRange range;
NSAttributedString* previous = [self currentInputLineSettingRange:&range];
[textView_.textStorage replaceCharactersInRange:range withAttributedString:as];
+ [[outputScrollView_ documentView] scrollToEndOfDocument:self]; // FIXME: buggy
return previous;
}
@@ -521,6 +489,53 @@ - (void)_replaceInputLineFromHistory:(NSArray*)history {
self.uncommitedHistoryEntry = previous;
}
+//-----------------------
+
+- (void)_testReadDirAsync {
+ static NodeJSFunction *readAsyncFunc = nil;
+ if (!readAsyncFunc) {
+ readAsyncFunc = [[NodeJSFunction functionFromString:
+ @"function readAsyncTest(callback){"
+ @"require('fs').readdir('/',"
+ @"callback"
+ //@"function(err, files) {"
+ //@"console.log('fs.readdir called back: '+"
+ // @"inspect(Array.prototype.slice.apply(arguments)) );"
+ //@"}"
+ @")"
+ @"}" error:nil] retain];
+ }
+ HandleScope scope;
+
+ __block NodeJSFunction *callback;
+ callback = [[NodeJSFunction alloc] initWithBlock:^(const Arguments& args){
+ HandleScope scope;
+ Local<Value> result = Local<Value>::New(Undefined());
+ if (callback) {
+ // your code here, which possibly sets |result|
+ [callback release]; callback = nil;
+ }
+ return v8::Handle<v8::Value>(scope.Close(result));
+ }];
+ v8::Local<Value> argv[] = { callback.functionValue };
+ [readAsyncFunc callWithV8Arguments:argv count:1 error:nil];
+ //[callback call];
+
+ /* Convenience: appending a block callback as last argument
+ [fun callWithV8Arguments:argv count:1 error:nil callback:^(const Arguments& args){
+ NSLog(@"fs.readdir called back with %d arguments", args.Length());
+ }];
+ [fun callWithCallback:^(const Arguments& args){
+ NSLog(@"fs.readdir called back with %d arguments", args.Length());
+ }];*/
+
+ // ref test
+ /*Local<Value> data = External::Wrap((void*)self);
+ Local<Function> fun = FunctionTemplate::New(&Handler, data)->GetFunction();
+ Local<Value> argv2[] = { fun };
+ [readAsyncFunc callWithV8Arguments:argv2 count:1 error:nil];*/
+}
+
- (void)consoleTextViewArrowUpKeyEvent:(NSEvent*)event {
// get an older item from history
NSArray* history =
@@ -537,6 +552,19 @@ - (void)consoleTextViewArrowUpKeyEvent:(NSEvent*)event {
historyCursor_ = history.count;
}
}
+
+ // Demonstrates using a NodeJSFunction wrapper, emitting an event on |process|
+ static NodeJSFunction *func = nil;
+ if (!func) {
+ func = [[NodeJSFunction functionFromString:
+ @"function emitKeyCode(keyCode){ process.emit('keyPress', keyCode) }"
+ error:nil] retain];
+ }
+ HandleScope scope;
+ Local<Value> argv[] = { v8::Integer::New([event keyCode]) };
+ [func callWithV8Arguments:argv count:1 error:nil];
+
+ [self _testReadDirAsync];
}
- (void)consoleTextViewArrowDownKeyEvent:(NSEvent*)event {
@@ -551,6 +579,15 @@ - (void)consoleTextViewArrowDownKeyEvent:(NSEvent*)event {
self.uncommitedHistoryEntry = nil;
historyCursor_ = 0;
}
+
+ // Demonstrates compiling and reusing a script in the default (main) context
+ // which emits an event on |process|
+ static NodeJSScript *emitScript = nil;
+ if (!emitScript) {
+ emitScript = [[NodeJSScript compiledScriptFromSource:
+ @"process.emit('keyPress', 125)"] retain];
+ }
+ [emitScript run:nil];
}
- (void)consoleTextViewTabKeyEvent:(NSEvent*)event {
@@ -35,8 +35,8 @@ - (void)interpretKeyEvents:(NSArray *)events {
break;
}
default:
- printf("(ev 1 of %lu) keyCode = %u\n",
- (unsigned long)events.count, keyCode);
+ //printf("(ev 1 of %lu) keyCode = %u\n",
+ // (unsigned long)events.count, keyCode);
[super interpretKeyEvents:events];
}
}
View
@@ -9,6 +9,12 @@ if (typeof process.stdout === 'number') {
console.log('hello from main.js');
+// as our demo app is emitting a "keyPress" event, let's listen for it
+process.on('keyPress', function () {
+ console.log('process.on:keyPress(%s)',
+ inspect(Array.prototype.slice.apply(arguments)))
+})
+
// test timeout (should block graceful program termination)
var t = new Date;
setTimeout(function() {
View
@@ -16,7 +16,7 @@ typedef void (^NSObjectProxyConfigBlock)(v8::Handle<v8::Template>,
*
* Calling from v8-land:
* obj.foo
- * obj.bar_withCode("bararg", "codearg")
+ * obj.bar_withCode_("bararg", "codearg")
*
* Will retrieve @property "foo" and invoke method |bar:withCode:| on the
* NSObject instance.
View
@@ -30,5 +30,7 @@
#endif
#import <NodeCocoa/NodeJS.h>
+#import <NodeCocoa/NodeJSScript.h>
+#import <NodeCocoa/NodeJSFunction.h>
#endif // NODECOCOA_NODECOCOA_H_
View
@@ -2,6 +2,7 @@
#define NODECOCOA_NODEJS_H_
#import <NodeCocoa/node.h>
+#import <NodeCocoa/NodeJSScript.h>
// Program entry point -- replaces use of NSApplicationMain
// You can utilize the NSApplication delegate method
@@ -10,6 +11,13 @@ int NodeJSApplicationMain(int argc, const char** argv);
#ifdef __OBJC__
+// NSError additions
+@interface NSError (v8)
++ (NSError*)errorFromV8TryCatch:(v8::TryCatch &)try_catch;
++ (NSError*)nodeErrorWithLocalizedDescription:(NSString*)description;
+@end
+extern const NSString* NodeJSNSErrorDomain;
+
// Objective-C++ interface to node.js
@interface NodeJS : NSObject {
}
@@ -33,9 +41,26 @@ int NodeJSApplicationMain(int argc, const char** argv);
+ (v8::Local<v8::Object>)hostObject;
+ (void)setHostObject:(NSObject*)hostObject;
-// Compile and run |script| identified by |name| passing |error|.
-+ (v8::Local<v8::Value>)eval:(NSString*)script
- name:(NSString*)name
+/**
+ * Compile |source| in |context| identified by |name| passing |error|.
+ *
+ * @param source JavaScript source.
+ * @param origi Optional identifier (e.g. filename).
+ * @param context An optional custom context in which to compile the script.
+ * @param error Optional output-pointer, providing error information. No
+ * matter if this is |nil| or not, you should always check the
+ * returned handle's |IsEmpty()| method for success.
+ */
++ (v8::Local<v8::Script>)compile:(NSString*)source
+ origin:(NSString*)origin
+ context:(v8::Context*)context
+ error:(NSError**)error;
+
+// Compile and run |source| in |context| identified by |name| passing |error|
+// returning the result.
++ (v8::Local<v8::Value>)eval:(NSString*)source
+ origin:(NSString*)origin
+ context:(v8::Context*)context
error:(NSError**)error;
@end
Oops, something went wrong.

0 comments on commit 38c7ad6

Please sign in to comment.