Skip to content

Commit 47942d4

Browse files
committed
Add JavaScriptCore and test project.
1 parent a5821a2 commit 47942d4

File tree

2,678 files changed

+878958
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2,678 files changed

+878958
-0
lines changed

JSCTest.xcodeproj/project.pbxproj

Lines changed: 467 additions & 0 deletions
Large diffs are not rendered by default.

JSCTest/AppDelegate.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// AppDelegate.h
3+
// JSCTest
4+
//
5+
// Created by Nigel Brooke on 2013-05-13.
6+
// Copyright (c) 2013 Nigel Brooke. All rights reserved.
7+
//
8+
9+
#import <Cocoa/Cocoa.h>
10+
11+
@interface AppDelegate : NSObject <NSApplicationDelegate>
12+
13+
@property (assign) IBOutlet NSWindow *window;
14+
15+
@end

JSCTest/AppDelegate.m

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
//
2+
// AppDelegate.m
3+
// JSCTest
4+
//
5+
// Created by Nigel Brooke on 2013-05-13.
6+
//
7+
8+
#import "AppDelegate.h"
9+
#import "JavaScriptCore/API/JSContext.h"
10+
#import "JavaScriptCore/API/JSExport.h"
11+
#import "objc/runtime.h"
12+
13+
//---------------------------------------------------------------------------
14+
// Protocol to list functions to be exported from a existing class
15+
@protocol NSButtonExport <JSExport>
16+
17+
-(void)setTitle:(NSString*)title;
18+
-(NSString*)title;
19+
20+
@end
21+
22+
//---------------------------------------------------------------------------
23+
// Wrapper class to forward no-arg or one-arg (argument is stripped though)
24+
// selector calls through to a JS object. So that we can call JS directly from
25+
// ObjC rather than going through -[JSValue invokeMethod]
26+
@interface Forwarder : NSObject
27+
@property JSValue* value;
28+
@end
29+
30+
@implementation Forwarder
31+
32+
-(id)initWithValue:(JSValue*)value {
33+
if((self = [super init])) {
34+
self.value = value;
35+
}
36+
37+
return self;
38+
}
39+
40+
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
41+
NSString* functionName = [NSStringFromSelector(aSelector) stringByReplacingOccurrencesOfString:@":" withString:@""];
42+
if ([self.value valueForProperty:functionName] ) {
43+
NSMethodSignature* signature = [NSMethodSignature signatureWithObjCTypes:"@:@"];
44+
return signature;
45+
}
46+
return nil;
47+
}
48+
49+
50+
- (void)forwardInvocation:(NSInvocation *)forwardedInvocation
51+
{
52+
NSString* functionName = [NSStringFromSelector([forwardedInvocation selector]) stringByReplacingOccurrencesOfString:@":" withString:@""];
53+
[self.value invokeMethod:functionName withArguments:@[]];
54+
}
55+
56+
@end
57+
58+
//---------------------------------------------------------------------------
59+
// To call selectors using forwarding, need the selector to be declared somewhere
60+
// This isn't used, just serves to define this selector
61+
@protocol Dummy
62+
-(void)logInfo;
63+
@end
64+
65+
66+
//---------------------------------------------------------------------------
67+
// Our native test object
68+
69+
// Protocol to list bindings
70+
@protocol NativeObjectExport <JSExport>
71+
-(void)test;
72+
-(void)log:(NSString*)string;
73+
@end
74+
75+
// The native test object itself
76+
@interface NativeObject : NSObject <NativeObjectExport>
77+
@end
78+
79+
@implementation NativeObject
80+
81+
-(void)test {
82+
NSLog(@"native: test was called");
83+
}
84+
85+
-(void)log:(NSString*)string {
86+
NSLog(@"js: %@", string);
87+
}
88+
89+
@end
90+
91+
92+
@interface AppDelegate ()
93+
94+
@property JSContext* context; // Our local javascript context
95+
96+
@end
97+
98+
// Need something persistant to store this, since setting it as a target doesn't retain it
99+
id forwarder;
100+
101+
@implementation AppDelegate
102+
103+
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
104+
{
105+
// Could possibly build a protocol dynamically like this, doesn't work for me though, my objc-runtime-fu is not strong enough
106+
/*
107+
Protocol* newProtocol = objc_allocateProtocol("RuntimeProtocol");
108+
Protocol* exportProtocol = objc_getProtocol("JSExport");
109+
protocol_addProtocol(newProtocol, exportProtocol);
110+
protocol_addMethodDescription(newProtocol, @selector(setTitle:), "v@:@", YES, YES);
111+
protocol_addMethodDescription(newProtocol, @selector(title), "@@:", YES, YES);
112+
objc_registerProtocol(newProtocol);
113+
*/
114+
115+
// Attach out export protocol to NSButton
116+
Protocol* newProtocol = @protocol(NSButtonExport);
117+
class_addProtocol([NSButton class], newProtocol);
118+
119+
// Load the script
120+
NSString* script = [[NSString alloc] initWithData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"javascript" ofType:@"js"]] encoding:NSUTF8StringEncoding];
121+
122+
// Create the button
123+
NSButton* button = [[NSButton alloc] initWithFrame:NSRectFromCGRect(CGRectMake(0, 0, 200, 50))];
124+
button.title = @"Hello Objective-C";
125+
[self.window.contentView addSubview:button];
126+
127+
// Create the JS context
128+
self.context = [[JSContext alloc] init];
129+
130+
// Bind out two test objects into global variables in the JS context
131+
self.context[@"nativeObject"] = [[NativeObject alloc] init];
132+
self.context[@"button"] = button;
133+
134+
// Run the script
135+
[self.context evaluateScript:script];
136+
137+
// Now pull out some test values, and run some functions
138+
JSValue* scriptObject = self.context[@"scriptObject"];
139+
140+
// Run a method manually
141+
JSValue* result = [scriptObject invokeMethod:@"logInfo" withArguments:@[]];
142+
NSLog(@"native: logInfo result - \"%@\"", result);
143+
144+
// Peek and poke at some variables
145+
NSLog(@"native: scriptObject data is \"%@\"", [scriptObject valueForProperty:@"data"]);
146+
NSLog(@"native: global variable value is \"%@\"", self.context[@"globalVariable"]);
147+
148+
[scriptObject setValue:@"From Objective-C" forProperty:@"data"];
149+
150+
// create our method forwarder
151+
forwarder = [[Forwarder alloc] initWithValue:scriptObject];
152+
153+
// Call a JS function via forwarding
154+
[forwarder logInfo];
155+
156+
// Set the JS object as the action target for the button
157+
[button setTarget:forwarder];
158+
[button setAction:@selector(buttonPressed:)];
159+
160+
}
161+
162+
@end

JSCTest/JSCTest-Info.plist

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>en</string>
7+
<key>CFBundleExecutable</key>
8+
<string>${EXECUTABLE_NAME}</string>
9+
<key>CFBundleIconFile</key>
10+
<string></string>
11+
<key>CFBundleIdentifier</key>
12+
<string>com.steamclock.${PRODUCT_NAME:rfc1034identifier}</string>
13+
<key>CFBundleInfoDictionaryVersion</key>
14+
<string>6.0</string>
15+
<key>CFBundleName</key>
16+
<string>${PRODUCT_NAME}</string>
17+
<key>CFBundlePackageType</key>
18+
<string>APPL</string>
19+
<key>CFBundleShortVersionString</key>
20+
<string>1.0</string>
21+
<key>CFBundleSignature</key>
22+
<string>????</string>
23+
<key>CFBundleVersion</key>
24+
<string>1</string>
25+
<key>LSMinimumSystemVersion</key>
26+
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
27+
<key>NSHumanReadableCopyright</key>
28+
<string>Copyright © 2013 Nigel Brooke. All rights reserved.</string>
29+
<key>NSMainNibFile</key>
30+
<string>MainMenu</string>
31+
<key>NSPrincipalClass</key>
32+
<string>NSApplication</string>
33+
</dict>
34+
</plist>

JSCTest/JSCTest-Prefix.pch

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//
2+
// Prefix header for all source files of the 'JSCTest' target in the 'JSCTest' project
3+
//
4+
5+
#ifdef __OBJC__
6+
#import <Cocoa/Cocoa.h>
7+
#endif

JSCTest/en.lproj/Credits.rtf

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
2+
{\colortbl;\red255\green255\blue255;}
3+
\paperw9840\paperh8400
4+
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
5+
6+
\f0\b\fs24 \cf0 Engineering:
7+
\b0 \
8+
Some people\
9+
\
10+
11+
\b Human Interface Design:
12+
\b0 \
13+
Some other people\
14+
\
15+
16+
\b Testing:
17+
\b0 \
18+
Hopefully not nobody\
19+
\
20+
21+
\b Documentation:
22+
\b0 \
23+
Whoever\
24+
\
25+
26+
\b With special thanks to:
27+
\b0 \
28+
Mom\
29+
}

JSCTest/en.lproj/InfoPlist.strings

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/* Localized versions of Info.plist keys */
2+

0 commit comments

Comments
 (0)