· 7 years ago · Apr 08, 2018, 04:00 PM
1diff --git a/api/binding/global_object.cpp b/api/binding/global_object.cpp
2index 9a27612..6ffc10d 100644
3--- a/api/binding/global_object.cpp
4+++ b/api/binding/global_object.cpp
5@@ -34,14 +34,12 @@ namespace kroll
6
7 void GlobalObject::GetVersion(const ValueList& args, KValueRef result)
8 {
9- static std::string version(PRODUCT_VERSION);
10- result->SetString(version);
11+ result->SetString(PRODUCT_VERSION);
12 }
13
14 void GlobalObject::GetPlatform(const ValueList& args, KValueRef result)
15 {
16- static std::string platform(Host::GetInstance()->GetPlatform());
17- result->SetString(platform);
18+ result->SetString(OS_NAME);
19 }
20
21 /*static*/
22diff --git a/api/host.cpp b/api/host.cpp
23index f958c19..4991dfa 100644
24--- a/api/host.cpp
25+++ b/api/host.cpp
26@@ -38,6 +38,25 @@ using Poco::Environment;
27 #define LOGPATH_ARG "--logpath"
28 #define BOOT_HOME_ARG "--start"
29
30+#ifdef OS_WIN32
31+#define MODULE_SUFFIX "dll"
32+#elif OS_OSX
33+#define MODULE_SUFFIX "dylib"
34+#elif OS_LINUX
35+#define MODULE_SUFFIX "so"
36+#endif
37+
38+#ifndef OS_WIN32
39+extern "C"
40+{
41+ int Execute(int argc, const char **argv)
42+ {
43+ Host host(argc, argv);
44+ return host.Run();
45+ }
46+}
47+#endif
48+
49 namespace kroll
50 {
51 static Host* hostInstance;
52@@ -71,8 +90,11 @@ namespace kroll
53 this->debug = (debug_val == "true" || debug_val == "yes" || debug_val == "1");
54 }
55
56- this->SetupLogging(); // Depends on command-line arguments and this->debug
57- this->SetupProfiling(); // Depends on logging
58+ this->SetupLogging();
59+ this->SetupProfiling();
60+
61+ // Call into the platform-specific initialization.
62+ this->Initialize(argc, argv);
63 }
64
65 Host* Host::GetInstance()
66@@ -80,6 +102,16 @@ namespace kroll
67 return hostInstance;
68 }
69
70+ static void AssertEnvironmentVariable(std::string variable)
71+ {
72+ if (!Environment::has(variable))
73+ {
74+ Logger* logger = Logger::Get("Host");
75+ logger->Fatal("required variable '%s' not defined, aborting.");
76+ exit(__LINE__);
77+ }
78+ }
79+
80 void Host::SetupApplication(int argc, const char* argv[])
81 {
82 AssertEnvironmentVariable(HOME_ENV);
83@@ -138,10 +170,6 @@ namespace kroll
84 this->logger = Logger::Get("Host");
85 }
86
87- Host::~Host()
88- {
89- }
90-
91 void Host::SetupProfiling()
92 {
93 if (this->profile)
94@@ -170,16 +198,6 @@ namespace kroll
95 }
96 }
97
98- void Host::AssertEnvironmentVariable(std::string variable)
99- {
100- if (!Environment::has(variable))
101- {
102- Logger* logger = Logger::Get("Host");
103- logger->Fatal("required variable '%s' not defined, aborting.");
104- exit(-999);
105- }
106- }
107-
108 void Host::ParseCommandLineArguments()
109 {
110 if (this->application->HasArgument(DEBUG_ARG))
111@@ -286,9 +304,9 @@ namespace kroll
112
113 bool Host::IsModule(std::string& filename)
114 {
115- std::string suffix = this->GetModuleSuffix();
116+ static std::string suffix("module."MODULE_SUFFIX);
117 bool isModule = (filename.length() > suffix.length() && filename.substr(
118- filename.length() - suffix.length()) == suffix);
119+ filename.length() - suffix.length()) == suffix);
120
121 return isModule;
122 }
123@@ -414,7 +432,7 @@ namespace kroll
124 Poco::File f = *iter;
125 if (!f.isDirectory() && !f.isHidden())
126 {
127- std::string fpath = iter.path().absolute().toString();
128+ std::string fpath(iter.path().absolute().toString());
129 if (IsModule(fpath))
130 {
131 this->LoadModule(fpath, this);
132@@ -559,26 +577,10 @@ namespace kroll
133 }
134 }
135
136- bool Host::Start()
137- {
138- return true;
139- }
140-
141- void Host::Stop ()
142- {
143- }
144-
145 int Host::Run()
146 {
147 if (this->waitForDebugger)
148- {
149-#ifdef OS_WIN32
150- DebugBreak();
151-#else
152- printf("Waiting for debugger (Press Any Key to Continue pid=%i)...\n", getpid());
153- getchar();
154-#endif
155- }
156+ this->WaitForDebugger();
157
158 try
159 {
160@@ -601,19 +603,9 @@ namespace kroll
161 return this->exitCode;
162 }
163
164- // Depending on the implementation of platform-specific host,
165- // it may block in Start() or implement a UI loop which will
166- // be continually called until it returns false.
167 try
168 {
169- if (this->Start())
170- {
171- // We want the Host implementation to decide
172- // when the best time to break out of the run
173- // loop is. This allows it to handle additional
174- // events if necessary.
175 while (this->RunLoop()) {}
176- }
177 }
178 catch (kroll::ValueException& e)
179 {
180@@ -635,7 +627,6 @@ namespace kroll
181 return;
182
183 ScopedLock lock(&moduleMutex);
184- this->Stop();
185 this->UnloadModuleProviders();
186 this->UnloadModules();
187
188@@ -648,16 +639,16 @@ namespace kroll
189 void Host::Exit(int exitCode)
190 {
191 logger->Notice("Received exit signal (%d)", exitCode);
192- if (GlobalObject::GetInstance()->FireEvent(Event::EXIT) &&
193- GlobalObject::GetInstance()->FireEvent(Event::APP_EXIT))
194- {
195- this->exitCode = exitCode;
196- this->exiting = true;
197- }
198- else
199+ if (!GlobalObject::GetInstance()->FireEvent(Event::EXIT) ||
200+ !GlobalObject::GetInstance()->FireEvent(Event::APP_EXIT))
201 {
202 logger->Notice("Exit signal canceled by event handler");
203+ return;
204 }
205+
206+ this->exitCode = exitCode;
207+ this->exiting = true;
208+ this->ExitImpl(exitCode);
209 }
210
211 KValueRef Host::RunOnMainThread(KMethodRef method, const ValueList& args,
212diff --git a/api/host.h b/api/host.h
213index d761a62..99e39f5 100644
214--- a/api/host.h
215+++ b/api/host.h
216@@ -1,4 +1,4 @@
217-/**
218+/*
219 * Appcelerator Kroll - licensed under the Apache Public License 2
220 * see LICENSE in the root folder for details on the license.
221 * Copyright (c) 2008, 2009 Appcelerator, Inc. All Rights Reserved.
222@@ -22,7 +22,13 @@ namespace kroll
223 {
224 public:
225 Host(int argc, const char** argv);
226+ ~Host();
227
228+ inline SharedApplication GetApplication() { return this->application; }
229+ inline bool DebugModeEnabled() { return this->debug; }
230+ inline bool ProfilingEnabled() { return this->profile; }
231+ inline Poco::Timestamp::TimeDiff GetElapsedTime() { return timeStarted.elapsed(); }
232+ inline KObjectRef GetGlobalObject() { return GlobalObject::GetInstance(); }
233 /**
234 * Get the host singleton.
235 */
236@@ -36,7 +42,7 @@ namespace kroll
237 /**
238 * Called to exit the host and terminate the process
239 */
240- virtual void Exit(int exitcode);
241+ void Exit(int exitcode);
242
243 /*
244 * Call with a method and arguments to invoke the method on the UI thread.
245@@ -55,14 +61,9 @@ namespace kroll
246 * @param waitForCompletion block until method is finished (default: true)
247 * @return the method's return value§
248 */
249- virtual KValueRef RunOnMainThread(KMethodRef method, KObjectRef thisObject,
250+ KValueRef RunOnMainThread(KMethodRef method, KObjectRef thisObject,
251 const ValueList& args, bool waitForCompletion=true);
252
253- /*
254- * Return true if this thread is the main thread.
255- */
256- virtual bool IsMainThread() = 0;
257-
258 /**
259 * Add a module provider to the host
260 */
261@@ -103,28 +104,24 @@ namespace kroll
262 bool HasModule(std::string name);
263
264 /**
265- * @param path The filesystem path of a module
266- * @return true if the file is a native module (.dll / .dylib / .so)
267+ * Execute all jobs waiting to be run on the main thread.
268 */
269- virtual bool IsModule(std::string& path);
270+ void RunMainThreadJobs();
271
272 /**
273- * Execute all jobs waiting to be run on the main thread.
274+ * @param path The filesystem path of a module
275+ * @return true if the file is a native module (.dll / .dylib / .so)
276 */
277- void RunMainThreadJobs();
278+ bool IsModule(std::string& path);
279
280- // TODO: We should eventually move away from sublcassing host.
281- virtual const char* GetDescription() { return "Native module"; }
282- virtual const char* GetPlatform() { return "Base"; }
283- virtual const char* GetModuleSuffix() { return "unimplemented"; }
284+ /*
285+ * Return true if this thread is the main thread.
286+ */
287+ bool IsMainThread();
288
289- inline SharedApplication GetApplication() { return this->application; }
290- inline bool DebugModeEnabled() { return this->debug; }
291- inline bool ProfilingEnabled() { return this->profile; }
292- inline Poco::Timestamp::TimeDiff GetElapsedTime() { return timeStarted.elapsed(); }
293- inline KObjectRef GetGlobalObject() { return GlobalObject::GetInstance(); }
294+ virtual Module* CreateModule(std::string& path);
295
296- protected:
297+ private:
298 ModuleList loadedModules;
299 Mutex moduleMutex;
300 std::vector<ModuleProvider *> moduleProviders;
301@@ -138,13 +135,15 @@ namespace kroll
302 bool profile;
303 std::string profilePath;
304 std::string logFilePath;
305- Poco::FileOutputStream *profileStream;
306+ Poco::FileOutputStream* profileStream;
307 bool consoleLogging;
308 bool fileLogging;
309 Logger* logger;
310 Poco::Timestamp timeStarted;
311+ Poco::Mutex jobQueueMutex;
312+ std::vector<MainThreadJob*> mainThreadJobs;
313+ std::vector<std::string> invalidModuleFiles;
314
315- void AssertEnvironmentVariable(std::string);
316 ModuleProvider* FindModuleProvider(std::string& filename);
317 void ScanInvalidModuleFiles();
318 SharedPtr<Module> LoadModule(std::string& path, ModuleProvider *provider);
319@@ -153,27 +152,28 @@ namespace kroll
320 void UnloadModuleProviders();
321 void FindBasicModules(std::string& dir);
322 void StartModules(std::vector<SharedPtr<Module> > modules);
323-
324- virtual ~Host();
325- virtual bool Start();
326- virtual bool RunLoop() = 0;
327- virtual void Stop();
328- virtual void Shutdown();
329- virtual void SignalNewMainThreadJob() { }
330-
331- private:
332- Poco::Mutex jobQueueMutex;
333- std::vector<MainThreadJob*> mainThreadJobs;
334- std::vector<std::string> invalidModuleFiles;
335-
336 void SetupApplication(int argc, const char* argv[]);
337 void SetupLogging();
338 void SetupProfiling();
339 void StopProfiling();
340 void AddInvalidModuleFile(std::string path);
341 void ParseCommandLineArguments();
342-
343+ void Shutdown();
344 DISALLOW_EVIL_CONSTRUCTORS(Host);
345+
346+ // Platform-specific
347+ void Initialize(int argc, const char* argv[]);
348+ void WaitForDebugger();
349+ bool RunLoop();
350+ void SignalNewMainThreadJob();
351+ void ExitImpl(int exitcode);
352+
353+#ifdef OS_WIN32
354+ EventWindow eventWindow;
355+ HWND AddMessageHandler(MessageHandler handler);
356+ HINSTANCE GetInstanceHandle() { return instanceHandle; }
357+ HWND GetEventWindow() { return eventWindow.GetHandle(); }
358+#endif
359 };
360
361 KROLL_API KValueRef RunOnMainThread(KMethodRef method, const ValueList& args,
362@@ -182,5 +182,15 @@ namespace kroll
363 const ValueList& args, bool waitForCompletion=true);
364 KROLL_API bool IsMainThread();
365 }
366+
367+extern "C"
368+{
369+#ifdef OS_WIN32
370+ KROLL_API int Execute(HINSTANCE hInstance, int argc, const char **argv);
371+#else
372+ KROLL_API int Execute(int argc, const char **argv);
373+#endif
374+}
375+
376 #endif
377
378diff --git a/api/linux/host.cpp b/api/linux/host.cpp
379index b34fb1d..f79dc3b 100644
380--- a/api/linux/host.cpp
381+++ b/api/linux/host.cpp
382@@ -4,20 +4,13 @@
383 * Copyright (c) 2008, 2009 Appcelerator, Inc. All Rights Reserved.
384 */
385
386-#include "host.h"
387+#include "../kroll.h"
388
389-#include <iostream>
390-#include <vector>
391-#include <cstring>
392 #include <dlfcn.h>
393-#include <string>
394-#include <gtk/gtk.h>
395+#include <gcrypt.h>
396 #include <gdk/gdk.h>
397-#include <api/kroll.h>
398-
399 #include <gnutls/gnutls.h>
400-#include <gcrypt.h>
401-#include <errno.h>
402+#include <gtk/gtk.h>
403 #include <pthread.h>
404
405 GCRY_THREAD_OPTION_PTHREAD_IMPL;
406@@ -26,38 +19,54 @@ using Poco::Mutex;
407
408 namespace kroll
409 {
410+ static pthread_t mainThread = 0;
411+
412 static gboolean MainThreadJobCallback(gpointer data)
413 {
414 static_cast<Host*>(data)->RunMainThreadJobs();
415 return TRUE;
416 }
417
418- LinuxHost::LinuxHost(int argc, const char *argv[]) : Host(argc, argv)
419+ void Host::Initialize(int argc, const char *argv[])
420 {
421 gtk_init(&argc, (char***) &argv);
422
423 if (!g_thread_supported())
424 g_thread_init(NULL);
425
426- this->mainThread = pthread_self();
427+ mainThread = pthread_self();
428
429 // Initialize gnutls for multi-threaded usage.
430 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
431 gnutls_global_init();
432 }
433
434- LinuxHost::~LinuxHost()
435+ Host::~Host()
436 {
437 }
438
439- void LinuxHost::Exit(int returnCode)
440+ void Host::WaitForDebugger()
441 {
442- Host::Exit(returnCode);
443+ printf("Waiting for debugger (Press Any Key to Continue pid=%i)...\n", getpid());
444+ getchar();
445+ }
446+
447+ bool Host::RunLoop()
448+ {
449+ string origPath(EnvironmentUtils::Get("KR_ORIG_LD_LIBRARY_PATH"));
450+ EnvironmentUtils::Set("LD_LIBRARY_PATH", origPath);
451+
452+ g_timeout_add(250, &MainThreadJobCallback, this);
453+ gtk_main();
454+ return false;
455+ }
456
457- // Check to see if the event handler cancelled this exit.
458- if (!this->exiting)
459- return;
460+ void Host::SignalNewMainThreadJob()
461+ {
462+ }
463
464+ void Host::ExitImpl(int exitCode)
465+ {
466 // Only call this if gtk_main is running. If called when the gtk_main
467 // is not running, it will cause an assertion failure.
468 static bool mainLoopRunning = true;
469@@ -66,30 +75,10 @@ namespace kroll
470 mainLoopRunning = false;
471 gtk_main_quit();
472 }
473-
474 }
475
476- const char* LinuxHost::GetPlatform()
477- {
478- return "linux";
479- }
480-
481- const char* LinuxHost::GetModuleSuffix()
482- {
483- return "module.so";
484- }
485
486- bool LinuxHost::RunLoop()
487- {
488- string origPath(EnvironmentUtils::Get("KR_ORIG_LD_LIBRARY_PATH"));
489- EnvironmentUtils::Set("LD_LIBRARY_PATH", origPath);
490-
491- g_timeout_add(250, &MainThreadJobCallback, this);
492- gtk_main();
493- return false;
494- }
495-
496- Module* LinuxHost::CreateModule(std::string& path)
497+ Module* Host::CreateModule(std::string& path)
498 {
499 void* handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
500 if (!handle)
501@@ -107,21 +96,11 @@ namespace kroll
502 path.c_str(), dlerror());
503 }
504
505- std::string dir = FileUtils::GetDirectory(path);
506- return create(this, dir.c_str());
507+ return create(this, FileUtils::GetDirectory(path).c_str());
508 }
509
510- bool LinuxHost::IsMainThread()
511- {
512- return pthread_equal(this->mainThread, pthread_self());
513- }
514-}
515-
516-extern "C"
517-{
518- int Execute(int argc,const char **argv)
519+ bool Host::IsMainThread()
520 {
521- Host *host = new LinuxHost(argc,argv);
522- return host->Run();
523+ return pthread_equal(mainThread, pthread_self());
524 }
525 }
526diff --git a/api/linux/host.h b/api/linux/host.h
527deleted file mode 100644
528index 2ee8bb5..0000000
529--- a/api/linux/host.h
530+++ /dev/null
531@@ -1,40 +0,0 @@
532-/**
533- * Appcelerator Kroll - licensed under the Apache Public License 2
534- * see LICENSE in the root folder for details on the license.
535- * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
536- */
537-#ifndef _LINUX_HOST_H
538-#define _LINUX_HOST_H
539-
540-#include <vector>
541-#include <string>
542-#include <kroll/kroll.h>
543-
544-namespace kroll
545-{
546-
547- class KROLL_API LinuxHost : public Host
548- {
549- public:
550- LinuxHost(int argc, const char* argv[]);
551- void Exit(int returnCode);
552- virtual Module* CreateModule(std::string& path);
553- const char* GetPlatform();
554- const char* GetModuleSuffix();
555- bool IsMainThread();
556-
557-
558- protected:
559- pthread_t mainThread;
560- virtual bool RunLoop();
561- virtual ~LinuxHost();
562- };
563-}
564-
565-extern "C"
566-{
567- EXPORT int Execute(int argc,const char** argv);
568-}
569-
570-
571-#endif
572diff --git a/api/module_provider.h b/api/module_provider.h
573index 2c8457c..6bda139 100644
574--- a/api/module_provider.h
575+++ b/api/module_provider.h
576@@ -28,16 +28,10 @@ namespace kroll
577 class EXPORT ModuleProvider
578 {
579 public:
580-
581 ModuleProvider() {}
582 virtual ~ModuleProvider() {};
583
584 /**
585- * @return The description of this module provider
586- */
587- virtual const char * GetDescription() = 0;
588-
589- /**
590 * @param filename an absolute path to a file in the filesystem
591 * @return if the passed-in absolute file path is a supported module or not
592 */
593diff --git a/api/osx/host.h b/api/osx/host.h
594deleted file mode 100644
595index ef454d1..0000000
596--- a/api/osx/host.h
597+++ /dev/null
598@@ -1,38 +0,0 @@
599-/**
600- * Appcelerator Kroll - licensed under the Apache Public License 2
601- * see LICENSE in the root folder for details on the license.
602- * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
603- */
604-#ifndef _OSX_HOST_H
605-#define _OSX_HOST_H
606-
607-#include <api/kroll.h>
608-
609-namespace kroll
610-{
611- class KROLL_API OSXHost : public Host
612- {
613- public:
614- OSXHost(int argc, const char **argv);
615-
616- virtual Module* CreateModule(std::string& path);
617- const char* GetPlatform();
618- const char* GetModuleSuffix();
619- virtual bool IsMainThread();
620- virtual KValueRef RunOnMainThread(KMethodRef method, KObjectRef thisObject,
621- const ValueList& args, bool waitForCompletion=true);
622-
623- protected:
624- virtual ~OSXHost();
625- virtual bool RunLoop();
626- virtual bool Start();
627- virtual void Exit(int exitcode);
628- };
629-}
630-
631-extern "C"
632-{
633- EXPORT int Execute(int argc,const char** argv);
634-}
635-
636-#endif
637diff --git a/api/osx/host.mm b/api/osx/host.mm
638index ed8c974..fe71b4f 100644
639--- a/api/osx/host.mm
640+++ b/api/osx/host.mm
641@@ -3,54 +3,28 @@
642 * see LICENSE in the root folder for details on the license.
643 * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
644 */
645-#include "host.h"
646+#include "../kroll.h"
647
648-#include <iostream>
649-#include <vector>
650-#include <dlfcn.h>
651-#include <string>
652-#include <signal.h>
653+#import <iostream>
654+#import <vector>
655+#import <dlfcn.h>
656+#import <string>
657+#import <signal.h>
658 #import <Cocoa/Cocoa.h>
659-#include <openssl/crypto.h>
660-#include <Poco/Mutex.h>
661+#import <openssl/crypto.h>
662+#import <Poco/Mutex.h>
663+
664+#define MAIN_THREAD_JOB_EVENT_SUBTYPE 6666
665
666 @interface KrollMainThreadCaller : NSObject
667 {
668- MainThreadJob* job;
669 }
670-- (id)initWithJob:(MainThreadJob*)jobIn;
671-- (void)execute;
672+- (void)signalMainThreadJob;
673 @end
674-
675 @implementation KrollMainThreadCaller
676-- (id)initWithJob:(MainThreadJob*)jobIn
677+- (void)signalMainThreadJob
678 {
679- self = [super init];
680- if (self)
681- {
682- job = jobIn;
683- }
684- return self;
685-}
686-- (void)dealloc
687-{
688- delete job;
689- [super dealloc];
690-}
691-- (MainThreadJob*)job
692-{
693- return job;
694-}
695-- (void)execute
696-{
697- job->Execute();
698-
699- // When executing asynchronously, we need to clean ourselves up.
700- if (!job->ShouldWaitForCompletion())
701- {
702- job->PrintException();
703- [self release];
704- }
705+ Host::GetInstance()->RunMainThreadJobs();
706 }
707 @end
708
709@@ -58,6 +32,7 @@ namespace kroll
710 {
711 static NSThread* mainThread;
712 static Poco::Mutex* cryptoMutexes = 0;
713+ static KrollMainThreadCaller* mainThreadCaller = 0;
714
715 static void CryptoLockingCallback(int mode, int n, const char* file, int line)
716 {
717@@ -72,7 +47,7 @@ namespace kroll
718 return ((unsigned long) pthread_self());
719 }
720
721- static void InitializeCryptoMutexes()
722+ void Host::Initialize(int argc, const char **argv)
723 {
724 if (!cryptoMutexes)
725 {
726@@ -80,134 +55,77 @@ namespace kroll
727 CRYPTO_set_id_callback(CryptoThreadIdCallback);
728 CRYPTO_set_locking_callback(CryptoLockingCallback);
729 }
730- }
731
732- static void CleanupCryptoMutexes()
733- {
734- delete [] cryptoMutexes;
735- cryptoMutexes = 0;
736- }
737+ if (!mainThreadCaller)
738+ mainThreadCaller = [[KrollMainThreadCaller alloc] init];
739
740- OSXHost::OSXHost(int _argc, const char **_argv) : Host(_argc,_argv)
741- {
742- InitializeCryptoMutexes();
743 mainThread = [NSThread currentThread];
744 }
745
746- OSXHost::~OSXHost()
747+ Host::~Host()
748 {
749- CleanupCryptoMutexes();
750- }
751+ if (!cryptoMutexes)
752+ return;
753
754- bool OSXHost::IsMainThread()
755- {
756- return [NSThread currentThread] == mainThread;
757+ delete [] cryptoMutexes;
758+ cryptoMutexes = 0;
759 }
760
761- const char* OSXHost::GetPlatform()
762+ void Host::WaitForDebugger()
763 {
764- return "osx";
765+ printf("Waiting for debugger (Press Any Key to Continue pid=%i)...\n", getpid());
766+ getchar();
767 }
768
769- const char* OSXHost::GetModuleSuffix()
770+ bool Host::IsMainThread()
771 {
772- return "module.dylib";
773+ return [NSThread currentThread] == mainThread;
774 }
775
776- void OSXHost::Exit(int exitcode)
777+ bool Host::RunLoop()
778 {
779- Host::Exit(exitCode);
780-
781- // Check to see if the event handler cancelled this event.
782- if (!this->exiting)
783- return;
784+ NSApplication* application = [NSApplication sharedApplication];
785
786- // We're going to post our event to our event queue to cause him
787- // to wake up (since he'll block waiting for pending events)
788- NSEvent *event = [NSEvent
789- otherEventWithType:NSApplicationDefined
790- location:NSZeroPoint modifierFlags:0
791- timestamp:[[NSDate date] timeIntervalSinceNow]
792- windowNumber:0
793- context:nil
794- subtype:1022
795- data1:exitCode
796- data2:0];
797- NSApplication *app = [NSApplication sharedApplication];
798- [app postEvent:event atStart:YES];
799- }
800-
801- bool OSXHost::Start()
802- {
803 string origPath(EnvironmentUtils::Get("KR_ORIG_DYLD_FRAMEWORK_PATH"));
804 EnvironmentUtils::Set("DYLD_FRAMEWORK_PATH", origPath);
805 origPath = EnvironmentUtils::Get("KR_ORIG_DYLD_LIBRARY_PATH");
806 EnvironmentUtils::Set("DYLD_LIBRARY_PATH", origPath);
807+ [application finishLaunching];
808
809- [[NSApplication sharedApplication] finishLaunching];
810- Host::Start();
811- return true;
812+ [application run];
813+ return false;
814 }
815
816- bool OSXHost::RunLoop()
817+ void Host::SignalNewMainThreadJob()
818 {
819- // Number of iterations before we yield back control
820- // to the main loop driver in the superclass
821- static int iterations = 10;
822-
823- // Number of seconds we want to block waiting on a
824- // pending event to be visible in the queue
825- // 0.5 seems to be the most optimal based on testing
826- // on Leopard and using some basic animated JS tests
827- // like John Resig's processing.js demos. 0.5 seems to
828- // keep the CPU at effectively 0.0% when idle and seems
829- // to give us very good frame rate and CPU during animation
830- static double waitTime = 0.5;
831-
832- // Since we call this method a lot, set the app in a static var
833- static NSApplication *app = [NSApplication sharedApplication];
834-
835- // Create a pool to sweep memory throught the loop
836- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
837- for (int c = 0; c < iterations; c++)
838- {
839- // we pull out an event from the queue, blocking a little bit before returning
840- @try
841- {
842- NSEvent *event = [app nextEventMatchingMask:NSAnyEventMask
843- untilDate:[NSDate dateWithTimeIntervalSinceNow:waitTime]
844- inMode:NSDefaultRunLoopMode dequeue:YES];
845-
846- if (event)
847- {
848- NSEventType type = [event type];
849+ [mainThreadCaller
850+ performSelectorOnMainThread:@selector(signalMainThreadJob)
851+ withObject:nil
852+ waitUntilDone:false];
853+ }
854
855- // This is our custom-defined stop event
856- if (type == NSApplicationDefined &&
857- [event subtype] == 1022 && [event data1] == 0)
858- {
859- [pool release];
860- return false;
861- }
862- else
863- {
864- [app sendEvent:event];
865- }
866+ void Host::ExitImpl(int exitcode)
867+ {
868+ // Stop the event loop, but don't terinate the application.
869+ // The host still needs to clean up everything.
870+ [[NSApplication sharedApplication] stop:nil];
871
872- [app updateWindows];
873- } }
874- @catch (NSException *e)
875- {
876- static Logger* logger = Logger::Get("Host");
877- logger->Error("Caught NSException in main loop: %s",[[e reason] UTF8String]);
878- KrollDumpStackTraceFromException(e);
879- }
880- }
881- [pool release];
882- return true;
883+ // NSApplication stop: doesn't stop the main loop until an event
884+ // has been processed, so push an application specific event through.
885+ [[NSApplication sharedApplication] postEvent:[NSEvent
886+ otherEventWithType:NSApplicationDefined
887+ location:NSZeroPoint
888+ modifierFlags:0
889+ timestamp:[[NSDate date] timeIntervalSinceNow]
890+ windowNumber:0
891+ context:nil
892+ subtype:MAIN_THREAD_JOB_EVENT_SUBTYPE
893+ data1:0
894+ data2:0]
895+ atStart:YES];
896 }
897
898- Module* OSXHost::CreateModule(std::string& path)
899+ Module* Host::CreateModule(std::string& path)
900 {
901 void* handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
902 if (!handle)
903@@ -227,44 +145,4 @@ namespace kroll
904 std::string dir(FileUtils::GetDirectory(path));
905 return create(this, dir.c_str());
906 }
907-
908- KValueRef OSXHost::RunOnMainThread(KMethodRef method, KObjectRef thisObject,
909- const ValueList& args, bool waitForCompletion)
910- {
911- if (this->IsMainThread() && waitForCompletion)
912- {
913- return method->Call(args);
914- }
915-
916- MainThreadJob* job = new MainThreadJob(method, thisObject,
917- args, waitForCompletion);
918- KrollMainThreadCaller* caller =
919- [[KrollMainThreadCaller alloc] initWithJob:job];
920- [caller performSelectorOnMainThread:@selector(execute)
921- withObject:nil waitUntilDone:waitForCompletion];
922-
923- if (!waitForCompletion)
924- {
925- // The job will release itself.
926- return Value::Undefined;
927- }
928-
929- KValueRef result(job->GetResult());
930- ValueException exception(job->GetException());
931- [caller release];
932-
933- if (!result.isNull())
934- return result;
935- else
936- throw exception;
937- }
938-}
939-
940-extern "C"
941-{
942- int Execute(int argc,const char **argv)
943- {
944- kroll::Host *host = new kroll::OSXHost(argc,argv);
945- return host->Run();
946- }
947 }
948diff --git a/api/osx/osx.h b/api/osx/osx.h
949index 634d191..deb2132 100644
950--- a/api/osx/osx.h
951+++ b/api/osx/osx.h
952@@ -5,7 +5,6 @@
953 */
954 #include "../base.h"
955 #include "nslog_channel.h"
956-#include "host.h"
957
958 #import <Foundation/Foundation.h>
959
960diff --git a/api/utils/platform_utils.cpp b/api/utils/platform_utils.cpp
961index 8153427..a3b0703 100644
962--- a/api/utils/platform_utils.cpp
963+++ b/api/utils/platform_utils.cpp
964@@ -4,35 +4,11 @@
965 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
966 */
967
968-// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
969-// and Contributors.
970-//
971-// Permission is hereby granted, free of charge, to any person or organization
972-// obtaining a copy of the software and accompanying documentation covered by
973-// this license (the "Software") to use, reproduce, display, distribute,
974-// execute, and transmit the Software, and to prepare derivative works of the
975-// Software, and to permit third-parties to whom the Software is furnished to
976-// do so, all subject to the following:
977-//
978-// The copyright notices in the Software and this entire statement, including
979-// the above license grant, this restriction and the following disclaimer,
980-// must be included in all copies of the Software, in whole or in part, and
981-// all derivative works of the Software, unless such copies or derivative
982-// works are solely in the form of machine-executable object code generated by
983-// a source language processor.
984-//
985-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
986-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
987-// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
988-// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
989-// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
990-// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
991-// DEALINGS IN THE SOFTWARE.
992 #include "utils.h"
993 #include <iostream>
994 #include <fstream>
995-#include <cstring>
996 #include <cstdio>
997+#include <cstring>
998 #define MID_PREFIX "v2:"
999
1000 namespace UTILS_NS
1001diff --git a/api/win32/event_window.cpp b/api/win32/event_window.cpp
1002index c48bf98..fa554de 100644
1003--- a/api/win32/event_window.cpp
1004+++ b/api/win32/event_window.cpp
1005@@ -5,6 +5,8 @@
1006 */
1007
1008 #include "event_window.h"
1009+#include "../kroll.h"
1010+
1011 namespace kroll
1012 {
1013 const wchar_t* EventWindow::windowClassName = L"Kroll Event Window";
1014diff --git a/api/win32/event_window.h b/api/win32/event_window.h
1015index f4c7c4c..921feb3 100644
1016--- a/api/win32/event_window.h
1017+++ b/api/win32/event_window.h
1018@@ -5,10 +5,11 @@
1019 */
1020 #ifndef _HOST_EVENT_WINDOW_H
1021 #define _HOST_EVENT_WINDOW_H
1022-#include <kroll/kroll.h>
1023+
1024 #include <vector>
1025
1026 typedef bool (*MessageHandler)(HWND hwnd, unsigned int message, WPARAM wParam, LPARAM lParam);
1027+
1028 namespace kroll
1029 {
1030 class EventWindow
1031diff --git a/api/win32/host.cpp b/api/win32/host.cpp
1032index 35d1481..7932e27 100644
1033--- a/api/win32/host.cpp
1034+++ b/api/win32/host.cpp
1035@@ -3,75 +3,63 @@
1036 * see LICENSE in the root folder for details on the license.
1037 * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
1038 */
1039-#include "host.h"
1040-#include <iostream>
1041-#include <cstring>
1042+
1043+#include "event_window.h"
1044+#include "../kroll.h"
1045+
1046 #include <windows.h>
1047 #include <commctrl.h>
1048-#include <ole2.h>
1049-#include <stdio.h>
1050 #include <fcntl.h>
1051 #include <io.h>
1052-
1053+#include <ole2.h>
1054 #define MAX_CONSOLE_LINES 500;
1055
1056-using Poco::ScopedLock;
1057-using Poco::Mutex;
1058-
1059 namespace kroll
1060 {
1061+ static void RedirectIOToConsole();
1062 static UINT tickleRequestMessage =
1063 ::RegisterWindowMessageA(PRODUCT_NAME"TickleRequest");
1064+ static HINSTANCE instance = 0;
1065+ static DWORD mainThreadId;
1066+
1067 bool static MainThreadJobsTickleHandler(HWND hWnd, UINT message,
1068 WPARAM wParam, LPARAM lParam)
1069 {
1070 if (message != tickleRequestMessage)
1071 return false;
1072-
1073+
1074 Host::GetInstance()->RunMainThreadJobs();
1075 return true;
1076 }
1077
1078- Win32Host::Win32Host(HINSTANCE hInstance, int argc, const char** argv) :
1079- Host(argc, argv),
1080- instanceHandle(hInstance),
1081- eventWindow(hInstance)
1082+ Host::Initialize(int argc, const char** argv)
1083 {
1084+ this->eventWindow = EventWindow(instance)
1085+ mainThreadId = GetCurrentThreadId();
1086 OleInitialize(0);
1087 this->AddMessageHandler(&MainThreadJobsTickleHandler);
1088- }
1089-
1090- Win32Host::~Win32Host()
1091- {
1092- OleUninitialize();
1093- }
1094
1095- const char* Win32Host::GetPlatform()
1096- {
1097- return "win32";
1098+#ifndef DEBUG
1099+ // only create a debug console when not compiled in debug mode
1100+ // otherwise, it should be autocreated
1101+ if (host->DebugModeEnabled())
1102+ {
1103+ RedirectIOToConsole();
1104+ }
1105+#endif
1106 }
1107
1108- const char* Win32Host::GetModuleSuffix()
1109+ Host::~Host()
1110 {
1111- return "module.dll";
1112+ OleUninitialize();
1113 }
1114
1115- bool Win32Host::Start()
1116+ void Host::WaitForDebugger()
1117 {
1118- // Windows DLLs often load libraries dynamically via LoadLibrary and expect
1119- // dependencies to be on the DLL search path. Thus we really can't restore
1120- // the original path here if we want things to continue working properly.
1121- // This shouldn't be too much of an issue either, as long as programs that
1122- // we launch rely on the safe dll search path.
1123- // string origPath(EnvironmentUtils::Get("KR_ORIG_PATH"));
1124- // EnvironmentUtils::Set("PATH", origPath);
1125-
1126- Host::Start();
1127- mainThreadId = GetCurrentThreadId();
1128- return true;
1129+ DebugBreak();
1130 }
1131
1132- bool Win32Host::RunLoop()
1133+ bool Host::RunLoop()
1134 {
1135 static bool postedQuitMessage = false;
1136
1137@@ -102,7 +90,11 @@ namespace kroll
1138 }
1139 }
1140
1141- Module* Win32Host::CreateModule(std::string& path)
1142+ void Host::ExitImpl(int exitCode)
1143+ {
1144+ }
1145+
1146+ Module* Host::CreateModule(std::string& path)
1147 {
1148 std::wstring widePath(UTF8ToWide(path));
1149 HMODULE module = LoadLibraryExW(widePath.c_str(),
1150@@ -126,25 +118,22 @@ namespace kroll
1151 return create(this, FileUtils::GetDirectory(path).c_str());
1152 }
1153
1154- bool Win32Host::IsMainThread()
1155+ bool Host::IsMainThread()
1156 {
1157 return mainThreadId == GetCurrentThreadId();
1158 }
1159
1160- void Win32Host::SignalNewMainThreadJob()
1161+ void Host::SignalNewMainThreadJob()
1162 {
1163 PostMessage(eventWindow.GetHandle(), tickleRequestMessage, 0, 0);
1164 }
1165
1166- HWND Win32Host::AddMessageHandler(MessageHandler handler)
1167+ HWND Host::AddMessageHandler(MessageHandler handler)
1168 {
1169 return eventWindow.AddMessageHandler(handler);
1170 }
1171-}
1172
1173-extern "C"
1174-{
1175- void RedirectIOToConsole()
1176+ static void RedirectIOToConsole()
1177 {
1178 int hConHandle;
1179 long lStdHandle;
1180@@ -187,18 +176,14 @@ extern "C"
1181 // point to console as well
1182 std::ios::sync_with_stdio();
1183 }
1184+}
1185
1186+extern "C"
1187+{
1188 int Execute(HINSTANCE hInstance, int argc, const char **argv)
1189 {
1190- Host *host = new kroll::Win32Host(hInstance,argc,argv);
1191-#ifndef DEBUG
1192- // only create a debug console when not compiled in debug mode
1193- // otherwise, it should be autocreated
1194- if (host->DebugModeEnabled())
1195- {
1196- RedirectIOToConsole();
1197- }
1198-#endif
1199- return host->Run();
1200+ instance = hInstance;
1201+ Host host(argc, argv);
1202+ return host.Run();
1203 }
1204 }
1205diff --git a/api/win32/host.h b/api/win32/host.h
1206deleted file mode 100644
1207index f8300a8..0000000
1208--- a/api/win32/host.h
1209+++ /dev/null
1210@@ -1,55 +0,0 @@
1211-/**
1212- * Appcelerator Kroll - licensed under the Apache Public License 2
1213- * see LICENSE in the root folder for details on the license.
1214- * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
1215- */
1216-#ifndef _WIN32_HOST_H
1217-#define _WIN32_HOST_H
1218-
1219-#include <api/kroll.h>
1220-#include <string>
1221-#include <vector>
1222-#include <windows.h>
1223-#include <Poco/ScopedLock.h>
1224-#include <Poco/Mutex.h>
1225-#include <Poco/Condition.h>
1226-#include "event_window.h"
1227-
1228-namespace kroll
1229-{
1230- class KROLL_API Win32Host : public Host
1231- {
1232- public:
1233- Win32Host(HINSTANCE hInstance, int argc, const char **argv);
1234- virtual ~Win32Host();
1235- virtual Module* CreateModule(std::string& path);
1236- const char* GetPlatform();
1237- const char* GetModuleSuffix();
1238- virtual bool IsMainThread();
1239-
1240- HWND AddMessageHandler(MessageHandler handler);
1241- HINSTANCE GetInstanceHandle() { return instanceHandle; }
1242- HWND GetEventWindow() { return eventWindow.GetHandle(); }
1243- static inline Win32Host* Win32Instance()
1244- {
1245- return static_cast<Win32Host*>(Host::GetInstance());
1246- }
1247-
1248- protected:
1249- virtual void SignalNewMainThreadJob();
1250- virtual bool RunLoop();
1251- virtual bool Start();
1252-
1253- private:
1254- HINSTANCE instanceHandle;
1255- DWORD mainThreadId;
1256- EventWindow eventWindow;
1257- };
1258-}
1259-
1260-extern "C"
1261-{
1262- KROLL_API int Execute(HINSTANCE hInstance, int argc, const char **argv);
1263-}
1264-
1265-#endif
1266diff --git a/modules/javascript/javascript_module.h b/modules/javascript/javascript_module.h
1267index 2490a87..40cf6f5 100644
1268--- a/modules/javascript/javascript_module.h
1269+++ b/modules/javascript/javascript_module.h
1270@@ -44,7 +44,6 @@ namespace kroll
1271 public:
1272 virtual bool IsModule(std::string& path);
1273 virtual Module* CreateModule(std::string& path);
1274- virtual const char * GetDescription() { return "Javascript Module Loader"; }
1275
1276 Host* GetHost()
1277 {
1278diff --git a/modules/php/php_module.h b/modules/php/php_module.h
1279index b111359..873a15c 100644
1280--- a/modules/php/php_module.h
1281+++ b/modules/php/php_module.h
1282@@ -71,7 +71,6 @@ namespace kroll
1283 virtual Module* CreateModule(std::string& path);
1284 void InitializeBinding();
1285
1286- virtual const char * GetDescription() { return "PHP Module Loader"; }
1287 static PHPModule* Instance() { return instance_; }
1288 static void SetBuffering(bool buffering);
1289 static std::ostringstream& GetBuffer() { return buffer; }
1290diff --git a/modules/python/python_module.h b/modules/python/python_module.h
1291index c832452..fd8bbd3 100644
1292--- a/modules/python/python_module.h
1293+++ b/modules/python/python_module.h
1294@@ -46,14 +46,11 @@ namespace kroll
1295 virtual Module* CreateModule(std::string& path);
1296 void InitializeBinding();
1297
1298- virtual const char * GetDescription()
1299- {
1300- return "Python Module Loader";
1301- }
1302 Host* GetHost()
1303 {
1304 return host;
1305 }
1306+
1307 static PythonModule* Instance()
1308 {
1309 return instance_;
1310diff --git a/modules/ruby/ruby_module.h b/modules/ruby/ruby_module.h
1311index 62014ba..9d18b33 100644
1312--- a/modules/ruby/ruby_module.h
1313+++ b/modules/ruby/ruby_module.h
1314@@ -67,11 +67,6 @@ namespace kroll
1315 {
1316 return instance_;
1317 }
1318- virtual const char * GetDescription()
1319- {
1320- return "Ruby Module Loader";
1321- }
1322-
1323
1324 private:
1325 KObjectRef binding;