]> git.saurik.com Git - cycript.git/blame - Java/Execute.cpp
Unify the build environment for Android and Apple.
[cycript.git] / Java / Execute.cpp
CommitLineData
7341eedb
JF
1/* Cycript - The Truly Universal Scripting Language
2 * Copyright (C) 2009-2016 Jay Freeman (saurik)
e17ad658
JF
3*/
4
f95d2598 5/* GNU Affero General Public License, Version 3 {{{ */
e17ad658 6/*
f95d2598
JF
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
e17ad658 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f95d2598
JF
15 * GNU Affero General Public License for more details.
16
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
e17ad658
JF
19**/
20/* }}} */
21
dbf05bfd
JF
22#include <map>
23#include <sstream>
24#include <vector>
25
def90846
JF
26#ifdef __APPLE__
27#include <JavaVM/jni.h>
28#else
e17ad658 29#include <jni.h>
def90846 30#endif
dbf05bfd
JF
31
32#include "cycript.hpp"
c9c16dde 33#include "Error.hpp"
dbf05bfd
JF
34#include "Execute.hpp"
35#include "Internal.hpp"
36#include "JavaScript.hpp"
37#include "Pooling.hpp"
38
39#define _jnicall(expr) ({ \
40 jint _value(expr); \
41 if (_value != JNI_OK) \
42 CYThrow("_jnicall(%s) == %d", #expr, _value); \
43})
44
45#define _envcall(jni, expr) ({ \
46 __typeof__(jni->expr) _value(jni->expr); \
47 if (jthrowable _error = jni->ExceptionOccurred()) { \
48 jni->ExceptionClear(); \
fc664744 49 throw CYJavaError(CYJavaLocal<jthrowable>(jni, _error)); \
dbf05bfd
JF
50 } \
51_value; })
52
53#define _envcallv(jni, expr) do { \
54 jni->expr; \
55 if (jthrowable _error = jni->ExceptionOccurred()) { \
56 jni->ExceptionClear(); \
fc664744 57 throw CYJavaError(CYJavaLocal<jthrowable>(jni, _error)); \
dbf05bfd
JF
58 } \
59} while (false)
60
c9c16dde 61#define CYJavaTry \
fc664744 62 CYJavaEnv jni(env); \
824bc1ec
JF
63 auto &protect(*reinterpret_cast<CYProtect *>(jprotect)); \
64 _disused JSContextRef context(protect); \
65 _disused JSObjectRef object(protect); \
c9c16dde
JF
66 try
67#define CYJavaCatch(value) \
68 catch (const CYException &error) { \
fc664744 69 jni->Throw(CYCastJavaObject(jni, context, error.CastJSValue(context, "Error")).cast<jthrowable>()); \
c9c16dde
JF
70 return value; \
71 }
72
dbf05bfd
JF
73extern "C" {
74 // Android's jni.h seriously doesn't declare these :/
75 jint JNI_CreateJavaVM(JavaVM **, void **, void *);
76 jint JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
77}
78
fc664744 79JNIEnv *GetJNI(JSContextRef context);
c9c16dde 80
fc664744
JF
81#define CYJavaForEachPrimitive \
82 CYJavaForEachPrimitive_(Z, z, Boolean, Boolean, boolean) \
83 CYJavaForEachPrimitive_(B, b, Byte, Byte, byte) \
84 CYJavaForEachPrimitive_(C, c, Char, Character, char) \
85 CYJavaForEachPrimitive_(S, s, Short, Short, short) \
86 CYJavaForEachPrimitive_(I, i, Int, Integer, int) \
87 CYJavaForEachPrimitive_(J, j, Long, Long, long) \
88 CYJavaForEachPrimitive_(F, f, Float, Float, float) \
89 CYJavaForEachPrimitive_(D, d, Double, Double, double)
c9c16dde 90
fc664744
JF
91enum CYJavaPrimitive : char {
92 CYJavaPrimitiveObject,
93 CYJavaPrimitiveVoid,
94#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
95 CYJavaPrimitive ## Type,
96CYJavaForEachPrimitive
97#undef CYJavaForEachPrimitive_
98};
dbf05bfd 99
0e832de4
JF
100template <typename Type_>
101struct IsJavaPrimitive { static const bool value = false; };
102
103#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
104 template <> \
105 struct IsJavaPrimitive<j ## type> { static const bool value = true; };
106CYJavaForEachPrimitive
107#undef CYJavaForEachPrimitive_
108
fc664744
JF
109// Java References {{{
110template <typename Value_>
111struct CYJavaRef {
112 JNIEnv *jni_;
113 Value_ value_;
dbf05bfd 114
fc664744
JF
115 _finline CYJavaRef(JNIEnv *jni, Value_ value) :
116 jni_(jni),
117 value_(value)
118 {
119 }
dbf05bfd 120
477549f5
JF
121 _finline operator Value_() const {
122 return value_;
fc664744 123 }
c9c16dde 124
477549f5 125 _finline JNIEnv *jni() const {
fc664744
JF
126 return jni_;
127 }
c9c16dde 128
0e832de4 129 // XXX: this is only needed to support CYJavaEnv relying on C variadics
fc664744
JF
130 _finline Value_ get() const {
131 return value_;
132 }
c9c16dde 133
fc664744
JF
134 template <typename Other_>
135 _finline CYJavaRef<Other_> cast() const {
136 return {jni_, static_cast<Other_>(value_)};
137 }
138
4e2cc9d3 139 // XXX: this should be tied into CYJavaFrame
fc664744
JF
140 Value_ leak() {
141 Value_ value(value_);
142 value_ = NULL;
143 return value;
144 }
145};
146
147template <typename Value_, void (JNIEnv::*Delete_)(jobject)>
148struct CYJavaDelete :
149 CYJavaRef<Value_>
150{
151 _finline CYJavaDelete(JNIEnv *jni, Value_ value) :
152 CYJavaRef<Value_>(jni, value)
153 {
154 }
155
4e2cc9d3 156 void clear() {
fc664744
JF
157 if (this->value_ != NULL)
158 (this->jni_->*Delete_)(this->value_);
4e2cc9d3
JF
159 this->value_ = NULL;
160 }
161
162 ~CYJavaDelete() {
163 clear();
fc664744
JF
164 }
165};
166
167template <typename Value_>
168struct CYJavaGlobal :
169 CYJavaDelete<Value_, &JNIEnv::DeleteGlobalRef>
170{
171 typedef CYJavaDelete<Value_, &JNIEnv::DeleteGlobalRef> CYJavaBase;
172
173 CYJavaGlobal() :
174 CYJavaBase(NULL, NULL)
175 {
176 }
177
178 template <typename Other_>
179 CYJavaGlobal(const CYJavaRef<Other_> &other) :
180 CYJavaBase(other.jni_, static_cast<Other_>(other.jni_->NewGlobalRef(other.value_)))
181 {
182 }
183
184 CYJavaGlobal(const CYJavaGlobal<Value_> &other) :
185 CYJavaGlobal(static_cast<const CYJavaRef<Value_> &>(other))
186 {
187 }
188
189 CYJavaGlobal(CYJavaGlobal &&value) :
190 CYJavaBase(value.jni_, value.value_)
191 {
192 value.value_ = NULL;
193 }
194};
195
196template <typename Value_>
197struct CYJavaLocal :
198 CYJavaDelete<Value_, &JNIEnv::DeleteLocalRef>
199{
200 typedef CYJavaDelete<Value_, &JNIEnv::DeleteLocalRef> CYJavaBase;
201
202 CYJavaLocal() :
203 CYJavaBase(NULL, NULL)
204 {
205 }
206
207 CYJavaLocal(JNIEnv *jni, Value_ value) :
208 CYJavaBase(jni, value)
209 {
210 }
211
212 template <typename Other_>
213 CYJavaLocal(const CYJavaRef<Other_> &other) :
214 CYJavaLocal(other.jni_, static_cast<Other_>(other.jni_->NewLocalRef(other.value_)))
215 {
216 }
217
4e2cc9d3
JF
218 template <typename Other_>
219 CYJavaLocal(CYJavaRef<Other_> &&other) :
220 CYJavaLocal(other.jni_, other.value_)
221 {
222 other.value_ = NULL;
223 }
224
225 CYJavaLocal(CYJavaLocal &&other) :
226 CYJavaLocal(static_cast<CYJavaRef<Value_> &&>(other))
fc664744 227 {
fc664744
JF
228 }
229
4e2cc9d3
JF
230 template <typename Other_>
231 CYJavaLocal &operator =(CYJavaLocal<Other_> &&other) {
232 this->clear();
233 this->jni_ = other.jni_;
234 this->value_ = other.value_;
235 other.value_ = NULL;
fc664744
JF
236 return *this;
237 }
238};
239// }}}
240// Java Strings {{{
241static CYJavaLocal<jstring> CYCastJavaString(const CYJavaRef<jobject> &value);
dbf05bfd
JF
242
243class CYJavaUTF8String :
244 public CYUTF8String
245{
246 private:
fc664744 247 const CYJavaRef<jstring> *value_;
dbf05bfd
JF
248
249 public:
fc664744
JF
250 CYJavaUTF8String(const CYJavaRef<jstring> &value) :
251 value_(&value)
252 {
253 _assert(value);
477549f5 254 JNIEnv *jni(value.jni());
fc664744
JF
255 size = jni->GetStringUTFLength(value);
256 data = jni->GetStringUTFChars(value, NULL);
257 }
258
259 CYJavaUTF8String(const CYJavaRef<jobject> &value) :
260 CYJavaUTF8String(CYCastJavaString(value))
dbf05bfd 261 {
dbf05bfd
JF
262 }
263
264 ~CYJavaUTF8String() {
fc664744 265 if (value_ != NULL) {
477549f5 266 JNIEnv *jni(value_->jni());
fc664744
JF
267 jni->ReleaseStringUTFChars(*value_, data);
268 }
dbf05bfd
JF
269 }
270
271 CYJavaUTF8String(const CYJavaUTF8String &) = delete;
272
273 CYJavaUTF8String(CYJavaUTF8String &&rhs) :
dbf05bfd
JF
274 value_(rhs.value_)
275 {
276 rhs.value_ = NULL;
277 }
278};
279
fc664744
JF
280CYJavaUTF8String CYCastUTF8String(const CYJavaRef<jstring> &value) {
281 return CYJavaUTF8String(value);
dbf05bfd
JF
282}
283
fc664744
JF
284JSStringRef CYCopyJSString(const CYJavaRef<jstring> &value) {
285 return CYCopyJSString(CYCastUTF8String(value));
dbf05bfd 286}
fc664744
JF
287// }}}
288// Java Error {{{
289struct CYJavaError :
290 CYException
291{
292 CYJavaGlobal<jthrowable> value_;
dbf05bfd 293
fc664744
JF
294 CYJavaError(const CYJavaRef<jthrowable> &value) :
295 value_(value)
296 {
297 }
298
299 virtual const char *PoolCString(CYPool &pool) const {
300 return CYPoolCString(pool, CYJavaUTF8String(value_.cast<jobject>()));
301 }
302
477549f5 303 virtual JSValueRef CastJSValue(JSContextRef context, const char *name) const;
fc664744
JF
304};
305// }}}
306
307struct CYJavaFrame {
dbf05bfd 308 JNIEnv *jni_;
dbf05bfd 309
fc664744
JF
310 CYJavaFrame(JNIEnv *jni, jint capacity) :
311 jni_(jni)
dbf05bfd 312 {
fc664744 313 _assert(jni->PushLocalFrame(capacity) == 0);
dbf05bfd
JF
314 }
315
fc664744
JF
316 ~CYJavaFrame() {
317 operator ()(NULL);
dbf05bfd
JF
318 }
319
4e2cc9d3
JF
320 operator JNIEnv *() const {
321 return jni_;
322 }
323
fc664744
JF
324 jobject operator ()(jobject object) {
325 JNIEnv *jni(jni_);
326 jni_ = NULL;
327 return jni->PopLocalFrame(object);
dbf05bfd 328 }
fc664744 329};
dbf05bfd 330
fc664744
JF
331struct CYJavaEnv {
332 private:
333 JNIEnv *jni;
334
335 public:
336 CYJavaEnv(JNIEnv *jni) :
337 jni(jni)
dbf05bfd 338 {
dbf05bfd
JF
339 }
340
477549f5
JF
341 template <typename Other_>
342 CYJavaEnv(const CYJavaRef<Other_> &value) :
343 jni(value.jni())
344 {
345 }
346
fc664744
JF
347 operator JNIEnv *() const {
348 return jni;
dbf05bfd
JF
349 }
350
fc664744
JF
351 JNIEnv *operator ->() const {
352 return jni;
dbf05bfd
JF
353 }
354
fc664744
JF
355 CYJavaLocal<jclass> FindClass(const char *name) const {
356 return {jni, _envcall(jni, FindClass(name))};
dbf05bfd
JF
357 }
358
fc664744
JF
359 CYJavaLocal<jclass> GetObjectClass(jobject object) const {
360 return {jni, _envcall(jni, GetObjectClass(object))};
361 }
362
363 CYJavaLocal<jclass> GetSuperclass(jclass _class) const {
364 return {jni, _envcall(jni, GetSuperclass(_class))};
365 }
366
367 CYJavaLocal<jobject> NewObject(jclass _class, jmethodID method, ...) const {
368 va_list args;
369 va_start(args, method);
370 jobject object(_envcall(jni, NewObjectV(_class, method, args)));
371 va_end(args);
372 return {jni, object};
373 }
374
375 CYJavaLocal<jobject> NewObjectA(jclass _class, jmethodID method, jvalue *args) const {
376 return {jni, _envcall(jni, NewObjectA(_class, method, args))};
dbf05bfd 377 }
fc664744
JF
378
379 CYJavaLocal<jstring> NewString(const jchar *data, jsize size) const {
380 return {jni, _envcall(jni, NewString(data, size))};
381 }
382
383#define CYJavaEnv_(Code) \
384 template <typename... Args_> \
385 void Code(Args_ &&... args) const { \
386 _envcallv(jni, Code(cy::Forward<Args_>(args)...)); \
387 }
388
389#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
390 CYJavaEnv_(Get ## Typ ## ArrayRegion) \
391 CYJavaEnv_(Set ## Typ ## Field) \
392 CYJavaEnv_(SetStatic ## Typ ## Field)
393CYJavaForEachPrimitive
394#undef CYJavaForEachPrimitive_
395
396 CYJavaEnv_(CallVoidMethod)
397 CYJavaEnv_(CallStaticVoidMethod)
398 CYJavaEnv_(CallVoidMethodA)
399 CYJavaEnv_(CallStaticVoidMethodA)
400 CYJavaEnv_(SetObjectArrayElement)
401 CYJavaEnv_(SetObjectField)
402 CYJavaEnv_(SetStaticObjectField)
403#undef CYJavaEnv_
404
405#define CYJavaEnv_(Code) \
406 template <typename... Args_> \
0e832de4 407 auto Code(Args_ &&... args) const -> decltype(jni->Code(cy::Forward<Args_>(args)...)) { \
fc664744
JF
408 return _envcall(jni, Code(cy::Forward<Args_>(args)...)); \
409 }
410
411#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
412 CYJavaEnv_(Call ## Typ ## Method) \
413 CYJavaEnv_(CallStatic ## Typ ## Method) \
414 CYJavaEnv_(Call ## Typ ## MethodA) \
415 CYJavaEnv_(CallStatic ## Typ ## MethodA) \
416 CYJavaEnv_(Get ## Typ ## Field) \
417 CYJavaEnv_(GetStatic ## Typ ## Field)
418CYJavaForEachPrimitive
419#undef CYJavaForEachPrimitive_
420
421 CYJavaEnv_(FromReflectedField)
422 CYJavaEnv_(FromReflectedMethod)
423 CYJavaEnv_(GetArrayLength)
424 CYJavaEnv_(GetMethodID)
425 CYJavaEnv_(GetStaticMethodID)
426 CYJavaEnv_(IsSameObject)
427#undef CYJavaEnv_
428
429#define CYJavaEnv_(Code) \
430 template <typename Other_, typename... Args_> \
431 auto Code(Args_ &&... args) const -> CYJavaLocal<Other_> { \
432 return {jni, static_cast<Other_>(_envcall(jni, Code(cy::Forward<Args_>(args)...)))}; \
433 }
434
435 CYJavaEnv_(CallObjectMethod)
436 CYJavaEnv_(CallStaticObjectMethod)
437 CYJavaEnv_(CallObjectMethodA)
438 CYJavaEnv_(CallStaticObjectMethodA)
439 CYJavaEnv_(GetObjectArrayElement)
440 CYJavaEnv_(GetObjectField)
441 CYJavaEnv_(GetStaticObjectField)
442#undef CYJavaEnv_
dbf05bfd
JF
443};
444
fc664744
JF
445static CYJavaLocal<jstring> CYCastJavaString(const CYJavaRef<jobject> &value) {
446 CYJavaEnv jni(value);
447 auto Object$(jni.FindClass("java/lang/Object"));
448 auto Object$toString(jni.GetMethodID(Object$, "toString", "()Ljava/lang/String;"));
449 return jni.CallObjectMethod<jstring>(value, Object$toString);
450}
451
dbf05bfd
JF
452template <typename Internal_, typename Value_>
453struct CYJavaValue :
454 CYPrivate<Internal_>
455{
456 CYJavaGlobal<Value_> value_;
457
fc664744
JF
458 CYJavaValue(const CYJavaRef<Value_> &value) :
459 value_(value)
dbf05bfd
JF
460 {
461 }
462
463 CYJavaValue(const CYJavaValue &) = delete;
464};
465
477549f5
JF
466static JSValueRef CYCastJSValue(JSContextRef context, const CYJavaRef<jobject> &value);
467
468template <typename Other_>
469static _finline JSValueRef CYCastJSValue(JSContextRef context, const CYJavaRef<Other_> &value) {
470 return CYCastJSValue(context, value.template cast<jobject>());
471}
472
dbf05bfd
JF
473template <typename Type_>
474static _finline JSValueRef CYJavaCastJSValue(JSContextRef context, Type_ value) {
475 return CYCastJSValue(context, value);
476}
477
478static _finline JSValueRef CYJavaCastJSValue(JSContextRef context, jboolean value) {
479 return CYCastJSValue(context, static_cast<bool>(value));
480}
481
477549f5
JF
482JSValueRef CYJavaError::CastJSValue(JSContextRef context, const char *name) const {
483 return CYCastJSValue(context, value_);
484}
485
dbf05bfd
JF
486static std::map<std::string, CYJavaPrimitive> Primitives_;
487
fc664744
JF
488static CYJavaPrimitive CYJavaGetPrimitive(JSContextRef context, const CYJavaRef<jclass> &type, jmethodID Class$get$$Name) {
489 CYJavaEnv jni(type);
490 auto string(jni.CallObjectMethod<jstring>(type, Class$get$$Name));
491 _assert(string);
492
493 CYJavaUTF8String name(string);
dbf05bfd
JF
494 auto primitive(Primitives_.find(name));
495 return primitive != Primitives_.end() ? primitive->second : CYJavaPrimitiveObject;
496}
497
498typedef std::vector<CYJavaPrimitive> CYJavaShorty;
499
fc664744
JF
500static CYJavaShorty CYJavaGetShorty(JSContextRef context, const CYJavaRef<jobjectArray> &types, jmethodID Class$get$$Name) {
501 CYJavaEnv jni(types);
502 size_t count(jni.GetArrayLength(types));
dbf05bfd
JF
503 CYJavaShorty shorty(count);
504 for (size_t index(0); index != count; ++index)
fc664744 505 shorty[index] = CYJavaGetPrimitive(context, jni.GetObjectArrayElement<jclass>(types, index), Class$get$$Name);
dbf05bfd
JF
506 return shorty;
507}
508
509struct CYJavaField {
510 jfieldID field_;
511 CYJavaPrimitive primitive_;
512};
513
514typedef std::map<std::string, CYJavaField> CYJavaFieldMap;
515
516struct CYJavaSignature {
4b645e23 517 CYJavaGlobal<jobject> reflected_;
fc664744 518 jmethodID method_;
4b645e23
JF
519 CYJavaPrimitive primitive_;
520 CYJavaShorty shorty_;
521
fc664744
JF
522 CYJavaSignature(const CYJavaRef<jobject> &reflected, jmethodID method, CYJavaPrimitive primitive, const CYJavaShorty &shorty) :
523 reflected_(reflected),
4b645e23 524 method_(method),
4b645e23
JF
525 primitive_(primitive),
526 shorty_(shorty)
dbf05bfd
JF
527 {
528 }
529
530 CYJavaSignature(unsigned count) :
4b645e23 531 shorty_(count)
dbf05bfd
JF
532 {
533 }
534
535 bool operator <(const CYJavaSignature &rhs) const {
4b645e23 536 return shorty_.size() < rhs.shorty_.size();
dbf05bfd
JF
537 }
538};
539
540typedef std::multiset<CYJavaSignature> CYJavaOverload;
541
542struct CYJavaMethod :
543 CYPrivate<CYJavaMethod>
544{
dbf05bfd
JF
545 CYJavaOverload overload_;
546
c9c16dde
JF
547 CYJavaMethod(const CYJavaOverload &overload) :
548 overload_(overload)
549 {
550 }
551};
552
553struct CYJavaStaticMethod :
554 CYPrivate<CYJavaStaticMethod>
555{
556 CYJavaOverload overload_;
557
558 CYJavaStaticMethod(const CYJavaOverload &overload) :
dbf05bfd
JF
559 overload_(overload)
560 {
561 }
562};
563
564struct CYJavaClass :
565 CYJavaValue<CYJavaClass, jclass>
566{
c9c16dde
JF
567 bool interface_;
568
dbf05bfd
JF
569 CYJavaFieldMap static_;
570 CYJavaFieldMap instance_;
571 CYJavaOverload overload_;
572
fc664744
JF
573 CYJavaClass(const CYJavaRef<jclass> &value, bool interface) :
574 CYJavaValue(value),
c9c16dde 575 interface_(interface)
dbf05bfd
JF
576 {
577 }
578};
579
fc664744 580static JSObjectRef CYGetJavaClass(JSContextRef context, const CYJavaRef<jclass> &_class);
8effd381 581
dbf05bfd
JF
582struct CYJavaObject :
583 CYJavaValue<CYJavaObject, jobject>
584{
8effd381
JF
585 CYJavaClass *table_;
586
fc664744
JF
587 CYJavaObject(const CYJavaRef<jobject> &value, CYJavaClass *table) :
588 CYJavaValue(value),
4b645e23 589 table_(table)
dbf05bfd
JF
590 {
591 }
592
593 JSValueRef GetPrototype(JSContextRef context) const;
594};
595
8effd381
JF
596struct CYJavaInterior :
597 CYJavaValue<CYJavaInterior, jobject>
598{
599 CYJavaClass *table_;
600
fc664744
JF
601 CYJavaInterior(const CYJavaRef<jobject> &value, CYJavaClass *table) :
602 CYJavaValue(value),
8effd381
JF
603 table_(table)
604 {
605 }
606};
607
c9c16dde 608struct CYJavaStaticInterior :
fc664744 609 CYJavaValue<CYJavaStaticInterior, jclass>
4b645e23
JF
610{
611 CYJavaClass *table_;
612
fc664744
JF
613 CYJavaStaticInterior(const CYJavaRef<jclass> &value, CYJavaClass *table) :
614 CYJavaValue(value),
4b645e23
JF
615 table_(table)
616 {
617 }
618};
619
620struct CYJavaArray :
621 CYJavaValue<CYJavaArray, jarray>
622{
623 CYJavaPrimitive primitive_;
624
fc664744
JF
625 CYJavaArray(const CYJavaRef<jarray> &value, CYJavaPrimitive primitive) :
626 CYJavaValue(value),
4b645e23
JF
627 primitive_(primitive)
628 {
629 }
630
631 JSValueRef GetPrototype(JSContextRef context) const;
632};
633
dbf05bfd
JF
634struct CYJavaPackage :
635 CYPrivate<CYJavaPackage>
636{
637 typedef std::vector<std::string> Path;
638 Path package_;
639
640 _finline CYJavaPackage(const Path &package) :
641 package_(package)
642 {
643 }
644};
645
dbf05bfd 646JSValueRef CYJavaObject::GetPrototype(JSContextRef context) const {
fc664744
JF
647 CYJavaEnv jni(value_);
648 return CYGetProperty(context, CYGetJavaClass(context, jni.GetObjectClass(value_)), prototype_s);
dbf05bfd
JF
649}
650
4b645e23
JF
651JSValueRef CYJavaArray::GetPrototype(JSContextRef context) const {
652 return CYGetCachedObject(context, CYJSString("Array_prototype"));
653}
654
fc664744
JF
655static JSValueRef CYCastJSValue(JSContextRef context, const CYJavaRef<jobject> &value) {
656 if (!value)
dbf05bfd 657 return CYJSNull(context);
fc664744
JF
658 CYJavaEnv jni(value);
659
660 auto _class(jni.GetObjectClass(value));
661 if (jni.IsSameObject(_class, jni.FindClass("java/lang/String")))
662 return CYCastJSValue(context, CYJSString(value.cast<jstring>()));
663
664 auto Class$(jni.FindClass("java/lang/Class"));
665 auto Class$isArray(jni.GetMethodID(Class$, "isArray", "()Z"));
666 if (jni.CallBooleanMethod(_class, Class$isArray)) {
667 auto Class$getComponentType(jni.GetMethodID(Class$, "getComponentType", "()Ljava/lang/Class;"));
668 auto component(jni.CallObjectMethod<jclass>(_class, Class$getComponentType));
669 auto Class$getName(jni.GetMethodID(Class$, "getName", "()Ljava/lang/String;"));
670 return CYJavaArray::Make(context, value.cast<jarray>(), CYJavaGetPrimitive(context, component, Class$getName));
c9c16dde
JF
671 }
672
fc664744
JF
673 auto Wrapper$(jni.FindClass("Cycript$Wrapper"));
674 if (jni.IsSameObject(_class, Wrapper$)) {
675 auto Wrapper$getProtect(jni.GetMethodID(Wrapper$, "getProtect", "()J"));
676 auto &protect(*reinterpret_cast<CYProtect *>(jni.CallLongMethod(value, Wrapper$getProtect)));
c9c16dde 677 return protect;
4b645e23
JF
678 }
679
fc664744
JF
680 CYJavaClass *table(reinterpret_cast<CYJavaClass *>(JSObjectGetPrivate(CYGetJavaClass(context, _class))));
681 return CYJavaObject::Make(context, value, table);
dbf05bfd
JF
682}
683
fc664744
JF
684static _finline JSObjectRef CYCastJSObject(JSContextRef context, const CYJavaRef<jobject> &value) {
685 return CYCastJSObject(context, CYCastJSValue(context, value));
c9c16dde
JF
686}
687
fc664744
JF
688static CYJavaLocal<jstring> CYCastJavaString(const CYJavaEnv &jni, JSContextRef context, CYUTF16String value) {
689 return jni.NewString(value.data, value.size);
dbf05bfd
JF
690}
691
fc664744 692static CYJavaLocal<jstring> CYCastJavaString(const CYJavaEnv &jni, JSContextRef context, JSStringRef value) {
c9c16dde 693 return CYCastJavaString(jni, context, CYCastUTF16String(value));
dbf05bfd
JF
694}
695
696#define CYCastJava$(T, Type, jtype, Cast) \
fc664744
JF
697_disused static CYJavaLocal<jobject> CYCastJava ## Type(const CYJavaEnv &jni, JSContextRef context, JSValueRef value) { \
698 auto Type$(jni.FindClass("java/lang/" #Type)); \
699 auto Type$init$(jni.GetMethodID(Type$, "<init>", "(" #T ")V")); \
700 return jni.NewObject(Type$, Type$init$, static_cast<jtype>(Cast(context, value))); \
dbf05bfd
JF
701}
702
703CYCastJava$(Z, Boolean, jboolean, CYCastBool)
704CYCastJava$(B, Byte, jbyte, CYCastDouble)
705CYCastJava$(C, Character, jchar, CYCastDouble)
706CYCastJava$(S, Short, jshort, CYCastDouble)
707CYCastJava$(I, Integer, jint, CYCastDouble)
708CYCastJava$(J, Long, jlong, CYCastDouble)
709CYCastJava$(F, Float, jfloat, CYCastDouble)
710CYCastJava$(D, Double, jdouble, CYCastDouble)
711
c9c16dde
JF
712static CYJavaClass *CYGetJavaTable(JSContextRef context, JSObjectRef object) {
713 if (!JSValueIsObjectOfClass(context, object, CYJavaClass::Class_))
714 return NULL;
715 return reinterpret_cast<CYJavaClass *>(JSObjectGetPrivate(object));
716}
717
718static CYJavaObject *CYGetJavaObject(JSContextRef context, JSObjectRef object) {
719 if (!JSValueIsObjectOfClass(context, object, CYJavaObject::Class_))
720 return NULL;
721 return reinterpret_cast<CYJavaObject *>(JSObjectGetPrivate(object));
722}
723
fc664744 724static CYJavaLocal<jobject> CYCastJavaObject(const CYJavaEnv &jni, JSContextRef context, JSObjectRef value) {
c9c16dde 725 if (CYJavaObject *internal = CYGetJavaObject(context, value))
dbf05bfd 726 return internal->value_;
dbf05bfd 727
fc664744
JF
728 auto Wrapper$(jni.FindClass("Cycript$Wrapper"));
729 auto Wrapper$$init$(jni.GetMethodID(Wrapper$, "<init>", "(J)V"));
c9c16dde 730 CYProtect *protect(new CYProtect(context, value));
fc664744 731 return jni.NewObject(Wrapper$, Wrapper$$init$, reinterpret_cast<jlong>(protect));
dbf05bfd
JF
732}
733
fc664744 734static CYJavaLocal<jobject> CYCastJavaObject(const CYJavaEnv &jni, JSContextRef context, JSValueRef value) {
dbf05bfd
JF
735 switch (JSValueGetType(context, value)) {
736 case kJSTypeNull:
fc664744 737 return {jni, NULL};
dbf05bfd
JF
738 case kJSTypeBoolean:
739 return CYCastJavaBoolean(jni, context, value);
740 case kJSTypeNumber:
741 return CYCastJavaDouble(jni, context, value);
742 case kJSTypeString:
c9c16dde 743 return CYCastJavaString(jni, context, CYJSString(context, value));
dbf05bfd
JF
744 case kJSTypeObject:
745 return CYCastJavaObject(jni, context, CYCastJSObject(context, value));
746
747 case kJSTypeUndefined:
c9c16dde 748 // XXX: I am currently relying on this for dynamic proxy of void method
fc664744 749 return {jni, NULL};
dbf05bfd
JF
750 default:
751 _assert(false);
752 }
753}
754
fc664744
JF
755static JSObjectRef CYGetJavaClass(JSContextRef context, const CYJavaRef<jclass> &value) {
756 CYJavaEnv jni(value);
757 CYJavaFrame frame(jni, 64);
758
dbf05bfd
JF
759 JSObjectRef global(CYGetGlobalObject(context));
760 JSObjectRef cy(CYCastJSObject(context, CYGetProperty(context, global, cy_s)));
761
fc664744
JF
762 auto Class$(jni.FindClass("java/lang/Class"));
763 auto Class$getName(jni.GetMethodID(Class$, "getName", "()Ljava/lang/String;"));
dbf05bfd 764
fc664744 765 CYJSString name(jni.CallObjectMethod<jstring>(value, Class$getName));
dbf05bfd
JF
766 JSValueRef cached(CYGetProperty(context, cy, name));
767 if (!JSValueIsUndefined(context, cached))
768 return CYCastJSObject(context, cached);
769
fc664744
JF
770 JSObjectRef constructor;
771 JSObjectRef prototype;
c9c16dde 772
fc664744 773 {
dbf05bfd 774
fc664744 775 auto Class$isInterface(jni.GetMethodID(Class$, "isInterface", "()Z"));
dbf05bfd 776
fc664744
JF
777 auto Class$getDeclaredConstructors(jni.GetMethodID(Class$, "getDeclaredConstructors", "()[Ljava/lang/reflect/Constructor;"));
778 auto Class$getDeclaredFields(jni.GetMethodID(Class$, "getDeclaredFields", "()[Ljava/lang/reflect/Field;"));
779 auto Class$getDeclaredMethods(jni.GetMethodID(Class$, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;"));
dbf05bfd 780
fc664744
JF
781 auto Constructor$(jni.FindClass("java/lang/reflect/Constructor"));
782 //auto Constructor$getModifiers(jni.GetMethodID(Constructor$, "getModifiers", "()I"));
783 auto Constructor$getParameterTypes(jni.GetMethodID(Constructor$, "getParameterTypes", "()[Ljava/lang/Class;"));
dbf05bfd 784
fc664744
JF
785 auto Field$(jni.FindClass("java/lang/reflect/Field"));
786 auto Field$getModifiers(jni.GetMethodID(Field$, "getModifiers", "()I"));
787 auto Field$getName(jni.GetMethodID(Field$, "getName", "()Ljava/lang/String;"));
788 auto Field$getType(jni.GetMethodID(Field$, "getType", "()Ljava/lang/Class;"));
dbf05bfd 789
fc664744
JF
790 auto Method$(jni.FindClass("java/lang/reflect/Method"));
791 auto Method$getModifiers(jni.GetMethodID(Method$, "getModifiers", "()I"));
792 auto Method$getName(jni.GetMethodID(Method$, "getName", "()Ljava/lang/String;"));
793 auto Method$getParameterTypes(jni.GetMethodID(Method$, "getParameterTypes", "()[Ljava/lang/Class;"));
794 auto Method$getReturnType(jni.GetMethodID(Method$, "getReturnType", "()Ljava/lang/Class;"));
dbf05bfd 795
fc664744
JF
796 auto Modifier$(jni.FindClass("java/lang/reflect/Modifier"));
797 auto Modifier$isStatic(jni.GetStaticMethodID(Modifier$, "isStatic", "(I)Z"));
dbf05bfd 798
fc664744
JF
799 auto interface(jni.CallBooleanMethod(value, Class$isInterface));
800 auto table(new CYJavaClass(value, interface));
801
802 for (CYJavaLocal<jclass> prototype(value); prototype; prototype = jni.GetSuperclass(prototype)) {
803 auto fields(jni.CallObjectMethod<jobjectArray>(prototype, Class$getDeclaredFields));
804
805 for (jsize i(0), e(jni.GetArrayLength(fields)); i != e; ++i) {
806 auto field(jni.GetObjectArrayElement<jobject>(fields, e - i - 1));
807 auto modifiers(jni.CallIntMethod(field, Field$getModifiers));
808 auto instance(!jni.CallStaticBooleanMethod(Modifier$, Modifier$isStatic, modifiers));
dbf05bfd 809 auto &map(instance ? table->instance_ : table->static_);
fc664744
JF
810 CYJavaUTF8String name(jni.CallObjectMethod<jstring>(field, Field$getName));
811 auto id(jni.FromReflectedField(field));
812 auto type(jni.CallObjectMethod<jclass>(field, Field$getType));
813 map.insert(std::make_pair(std::string(name), CYJavaField{id, CYJavaGetPrimitive(context, type, Class$getName)}));
dbf05bfd
JF
814 }
815 }
816
fc664744 817 constructor = JSObjectMake(context, CYJavaClass::Class_, table);
dbf05bfd 818
fc664744 819 prototype = JSObjectMake(context, NULL, NULL);
dbf05bfd
JF
820 CYSetProperty(context, constructor, prototype_s, prototype, kJSPropertyAttributeDontEnum);
821
fc664744 822 auto constructors(jni.CallObjectMethod<jobjectArray>(value, Class$getDeclaredConstructors));
dbf05bfd 823
fc664744
JF
824 for (jsize i(0), e(jni.GetArrayLength(constructors)); i != e; ++i) {
825 auto constructor(jni.GetObjectArrayElement<jobject>(constructors, i));
826 auto parameters(jni.CallObjectMethod<jobjectArray>(constructor, Constructor$getParameterTypes));
827 CYJavaShorty shorty(CYJavaGetShorty(context, parameters, Class$getName));
828 auto id(jni.FromReflectedMethod(constructor));
829 table->overload_.insert(CYJavaSignature(constructor, id, CYJavaPrimitiveObject, shorty));
dbf05bfd
JF
830 }
831
fc664744 832 auto methods(jni.CallObjectMethod<jobjectArray>(value, Class$getDeclaredMethods));
dbf05bfd
JF
833
834 std::map<std::pair<bool, std::string>, CYJavaOverload> entries;
835
fc664744
JF
836 for (jsize i(0), e(jni.GetArrayLength(methods)); i != e; ++i) {
837 auto method(jni.GetObjectArrayElement<jobject>(methods, i));
838 auto modifiers(jni.CallIntMethod(method, Method$getModifiers));
839 auto instance(!jni.CallStaticBooleanMethod(Modifier$, Modifier$isStatic, modifiers));
840 CYJavaUTF8String name(jni.CallObjectMethod<jstring>(method, Method$getName));
841 auto parameters(jni.CallObjectMethod<jobjectArray>(method, Method$getParameterTypes));
842 CYJavaShorty shorty(CYJavaGetShorty(context, parameters, Class$getName));
843 auto type(jni.CallObjectMethod<jclass>(method, Method$getReturnType));
844 auto primitive(CYJavaGetPrimitive(context, type, Class$getName));
845 auto id(jni.FromReflectedMethod(method));
846 entries[std::make_pair(instance, std::string(name))].insert(CYJavaSignature(method, id, primitive, shorty));
dbf05bfd
JF
847 }
848
849 for (const auto &entry : entries) {
850 bool instance(entry.first.first);
851 CYJSString name(entry.first.second);
852 auto &overload(entry.second);
c9c16dde
JF
853 if (instance)
854 CYSetProperty(context, prototype, name, CYJavaMethod::Make(context, overload), kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete);
855 else
856 CYSetProperty(context, constructor, name, CYJavaStaticMethod::Make(context, overload), kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete);
dbf05bfd
JF
857 }
858
fc664744
JF
859 }
860
dbf05bfd
JF
861 // XXX: for some reason kJSPropertyAttributeDontEnum doesn't work if there's already a property with the same name
862 // by not linking the prototypes until after we set the properties, we hide the parent property from this issue :(
863
fc664744
JF
864 if (auto super = jni.GetSuperclass(value)) {
865 JSObjectRef parent(CYGetJavaClass(context, super));
4b645e23 866 CYSetPrototype(context, constructor, parent);
dbf05bfd
JF
867 CYSetPrototype(context, prototype, CYGetProperty(context, parent, prototype_s));
868 }
869
870 CYSetProperty(context, cy, name, constructor);
871 return constructor;
872}
873
4b645e23
JF
874static void CYCastJavaNumeric(jvalue &value, CYJavaPrimitive primitive, JSContextRef context, JSValueRef argument) {
875 switch (primitive) {
876#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
877 case CYJavaPrimitive ## Type: \
878 value.t = static_cast<j ## type>(CYCastDouble(context, argument)); \
879 break;
dbf05bfd
JF
880CYJavaForEachPrimitive
881#undef CYJavaForEachPrimitive_
4b645e23
JF
882 default:
883 _assert(false);
884 }
885}
886
4e2cc9d3
JF
887static bool CYCastJavaArguments(const CYJavaFrame &frame, const CYJavaShorty &shorty, JSContextRef context, const JSValueRef arguments[], jvalue *array) {
888 CYJavaEnv jni(frame);
889
4b645e23
JF
890 for (size_t index(0); index != shorty.size(); ++index) {
891 JSValueRef argument(arguments[index]);
892 JSType type(JSValueGetType(context, argument));
893 jvalue &value(array[index]);
894
895 switch (CYJavaPrimitive primitive = shorty[index]) {
896 case CYJavaPrimitiveObject:
4e2cc9d3 897 // XXX: figure out a way to tie this in to the CYJavaFrame
fc664744 898 value.l = CYCastJavaObject(jni, context, argument).leak();
4b645e23
JF
899 break;
900
901 case CYJavaPrimitiveBoolean:
902 if (type != kJSTypeBoolean)
903 return false;
904 value.z = CYCastBool(context, argument);
905 break;
906
907 case CYJavaPrimitiveCharacter:
908 if (type == kJSTypeNumber)
909 CYCastJavaNumeric(value, primitive, context, argument);
910 else if (type != kJSTypeString)
911 return false;
912 else {
913 CYJSString string(context, argument);
914 if (JSStringGetLength(string) != 1)
915 return false;
916 else
917 value.c = JSStringGetCharactersPtr(string)[0];
918 }
919 break;
920
921 case CYJavaPrimitiveByte:
922 case CYJavaPrimitiveShort:
923 case CYJavaPrimitiveInteger:
924 case CYJavaPrimitiveLong:
925 case CYJavaPrimitiveFloat:
926 case CYJavaPrimitiveDouble:
927 if (type != kJSTypeNumber)
928 return false;
929 CYCastJavaNumeric(value, primitive, context, argument);
930 break;
931
dbf05bfd
JF
932 default:
933 _assert(false);
934 }
dbf05bfd
JF
935 }
936
4b645e23 937 return true;
dbf05bfd
JF
938}
939
940static JSValueRef JavaMethod_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
941 CYJavaMethod *internal(reinterpret_cast<CYJavaMethod *>(JSObjectGetPrivate(object)));
c9c16dde 942 CYJavaObject *self(CYGetJavaObject(context, _this));
fc664744 943 CYJavaEnv jni(self->value_);
c9c16dde
JF
944
945 CYJavaSignature bound(count);
946 for (auto overload(internal->overload_.lower_bound(bound)), e(internal->overload_.upper_bound(bound)); overload != e; ++overload) {
4e2cc9d3 947 CYJavaFrame frame(jni, count + 16);
c9c16dde 948 jvalue array[count];
4e2cc9d3 949 if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array))
c9c16dde 950 continue;
fc664744 951 jvalue *values(array);
c9c16dde
JF
952 switch (overload->primitive_) {
953 case CYJavaPrimitiveObject:
fc664744 954 return CYCastJSValue(context, jni.CallObjectMethodA<jobject>(self->value_, overload->method_, values));
c9c16dde 955 case CYJavaPrimitiveVoid:
fc664744 956 jni.CallVoidMethodA(self->value_, overload->method_, values);
c9c16dde
JF
957 return CYJSUndefined(context);
958#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
959 case CYJavaPrimitive ## Type: \
fc664744 960 return CYJavaCastJSValue(context, jni.Call ## Typ ## MethodA(self->value_, overload->method_, values));
c9c16dde
JF
961CYJavaForEachPrimitive
962#undef CYJavaForEachPrimitive_
963 default: _assert(false);
964 }
965 }
966
967 CYThrow("invalid method call");
968} CYCatch(NULL) }
969
970static JSValueRef JavaStaticMethod_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
971 CYJavaMethod *internal(reinterpret_cast<CYJavaMethod *>(JSObjectGetPrivate(object)));
972 CYJavaClass *table(CYGetJavaTable(context, _this));
fc664744 973 CYJavaEnv jni(table->value_);
dbf05bfd
JF
974
975 CYJavaSignature bound(count);
976 for (auto overload(internal->overload_.lower_bound(bound)), e(internal->overload_.upper_bound(bound)); overload != e; ++overload) {
4e2cc9d3 977 CYJavaFrame frame(jni, count + 16);
4b645e23 978 jvalue array[count];
4e2cc9d3 979 if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array))
4b645e23 980 continue;
fc664744 981 jvalue *values(array);
4b645e23
JF
982 switch (overload->primitive_) {
983 case CYJavaPrimitiveObject:
fc664744 984 return CYCastJSValue(context, jni.CallStaticObjectMethodA<jobject>(table->value_, overload->method_, values));
c9c16dde 985 case CYJavaPrimitiveVoid:
fc664744 986 jni.CallStaticVoidMethodA(table->value_, overload->method_, values);
c9c16dde 987 return CYJSUndefined(context);
4b645e23
JF
988#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
989 case CYJavaPrimitive ## Type: \
fc664744 990 return CYJavaCastJSValue(context, jni.CallStatic ## Typ ## MethodA(table->value_, overload->method_, values));
4b645e23
JF
991CYJavaForEachPrimitive
992#undef CYJavaForEachPrimitive_
993 default: _assert(false);
994 }
dbf05bfd
JF
995 }
996
997 CYThrow("invalid method call");
998} CYCatch(NULL) }
999
1000static JSObjectRef JavaClass_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
1001 CYJavaClass *table(reinterpret_cast<CYJavaClass *>(JSObjectGetPrivate(object)));
fc664744 1002 CYJavaEnv jni(table->value_);
c9c16dde
JF
1003 jclass _class(table->value_);
1004
1005 if (table->interface_ && count == 1) {
fc664744 1006 auto Cycript$(jni.FindClass("Cycript"));
0e832de4
JF
1007 auto Cycript$Make(jni.GetStaticMethodID(Cycript$, "proxy", "(Ljava/lang/Class;LCycript$Wrapper;)Ljava/lang/Object;"));
1008 return CYCastJSObject(context, jni.CallObjectMethod<jobject>(Cycript$, Cycript$Make, _class, CYCastJavaObject(jni, context, CYCastJSObject(context, arguments[0])).get()));
c9c16dde 1009 }
dbf05bfd 1010
dbf05bfd
JF
1011 CYJavaSignature bound(count);
1012 for (auto overload(table->overload_.lower_bound(bound)), e(table->overload_.upper_bound(bound)); overload != e; ++overload) {
4e2cc9d3 1013 CYJavaFrame frame(jni, count + 16);
4b645e23 1014 jvalue array[count];
4e2cc9d3 1015 if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array))
4b645e23 1016 continue;
fc664744
JF
1017 jvalue *values(array);
1018 auto object(jni.NewObjectA(_class, overload->method_, values));
1019 return CYCastJSObject(context, object);
dbf05bfd
JF
1020 }
1021
1022 CYThrow("invalid constructor call");
1023} CYCatch(NULL) }
1024
c9c16dde
JF
1025static bool JavaStaticInterior_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) {
1026 CYJavaStaticInterior *internal(reinterpret_cast<CYJavaStaticInterior *>(JSObjectGetPrivate(object)));
4b645e23 1027 CYJavaClass *table(internal->table_);
dbf05bfd
JF
1028 CYPool pool;
1029 auto name(CYPoolUTF8String(pool, context, property));
1030 auto field(table->static_.find(name));
1031 if (field == table->static_.end())
1032 return false;
1033 return true;
1034}
1035
c9c16dde
JF
1036static JSValueRef JavaStaticInterior_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
1037 CYJavaStaticInterior *internal(reinterpret_cast<CYJavaStaticInterior *>(JSObjectGetPrivate(object)));
4b645e23 1038 CYJavaClass *table(internal->table_);
fc664744 1039 CYJavaEnv jni(table->value_);
dbf05bfd
JF
1040 CYPool pool;
1041 auto name(CYPoolUTF8String(pool, context, property));
1042 auto field(table->static_.find(name));
1043 if (field == table->static_.end())
1044 return NULL;
1045
1046 switch (field->second.primitive_) {
1047 case CYJavaPrimitiveObject:
fc664744 1048 return CYCastJSValue(context, jni.GetStaticObjectField<jobject>(table->value_, field->second.field_));
4b645e23 1049#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
dbf05bfd 1050 case CYJavaPrimitive ## Type: \
fc664744 1051 return CYJavaCastJSValue(context, jni.GetStatic ## Typ ## Field(table->value_, field->second.field_));
dbf05bfd
JF
1052CYJavaForEachPrimitive
1053#undef CYJavaForEachPrimitive_
1054 default: _assert(false);
1055 }
1056} CYCatch(NULL) }
1057
c9c16dde
JF
1058static bool JavaStaticInterior_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry {
1059 CYJavaStaticInterior *internal(reinterpret_cast<CYJavaStaticInterior *>(JSObjectGetPrivate(object)));
4b645e23 1060 CYJavaClass *table(internal->table_);
fc664744 1061 CYJavaEnv jni(table->value_);
dbf05bfd
JF
1062 CYPool pool;
1063 auto name(CYPoolUTF8String(pool, context, property));
1064 auto field(table->static_.find(name));
1065 if (field == table->static_.end())
1066 return false;
1067
1068 switch (field->second.primitive_) {
1069 case CYJavaPrimitiveObject:
fc664744 1070 jni.SetStaticObjectField(table->value_, field->second.field_, CYCastJavaObject(jni, context, value));
4b645e23 1071#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
dbf05bfd 1072 case CYJavaPrimitive ## Type: \
fc664744 1073 jni.SetStatic ## Typ ## Field(table->value_, field->second.field_, CYCastDouble(context, value)); \
dbf05bfd
JF
1074 break;
1075CYJavaForEachPrimitive
1076#undef CYJavaForEachPrimitive_
1077 default: _assert(false);
1078 }
1079
1080 return true;
1081} CYCatch(false) }
1082
c9c16dde
JF
1083static void JavaStaticInterior_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) {
1084 CYJavaStaticInterior *internal(reinterpret_cast<CYJavaStaticInterior *>(JSObjectGetPrivate(object)));
4b645e23 1085 CYJavaClass *table(internal->table_);
dbf05bfd
JF
1086 for (const auto &field : table->static_)
1087 JSPropertyNameAccumulatorAddName(names, CYJSString(field.first));
1088}
1089
1090static JSValueRef JavaClass_getProperty_class(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
1091 CYJavaClass *table(reinterpret_cast<CYJavaClass *>(JSObjectGetPrivate(object)));
fc664744 1092 return CYCastJSValue(context, table->value_);
dbf05bfd
JF
1093} CYCatch(NULL) }
1094
8effd381
JF
1095static bool JavaInterior_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) {
1096 CYJavaInterior *internal(reinterpret_cast<CYJavaInterior *>(JSObjectGetPrivate(object)));
1097 CYJavaClass *table(internal->table_);
dbf05bfd
JF
1098 CYPool pool;
1099 auto name(CYPoolUTF8String(pool, context, property));
1100 auto field(table->instance_.find(name));
1101 if (field == table->instance_.end())
1102 return false;
1103 return true;
1104}
1105
8effd381
JF
1106static JSValueRef JavaInterior_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
1107 CYJavaInterior *internal(reinterpret_cast<CYJavaInterior *>(JSObjectGetPrivate(object)));
fc664744 1108 CYJavaEnv jni(internal->value_);
8effd381 1109 CYJavaClass *table(internal->table_);
dbf05bfd
JF
1110 CYPool pool;
1111 auto name(CYPoolUTF8String(pool, context, property));
1112 auto field(table->instance_.find(name));
1113 if (field == table->instance_.end())
1114 return NULL;
1115
1116 switch (field->second.primitive_) {
1117 case CYJavaPrimitiveObject:
fc664744 1118 return CYCastJSValue(context, jni.GetObjectField<jobject>(internal->value_, field->second.field_));
4b645e23 1119#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
dbf05bfd 1120 case CYJavaPrimitive ## Type: \
fc664744 1121 return CYJavaCastJSValue(context, jni.Get ## Typ ## Field(internal->value_, field->second.field_));
dbf05bfd
JF
1122CYJavaForEachPrimitive
1123#undef CYJavaForEachPrimitive_
1124 default: _assert(false);
1125 }
1126} CYCatch(NULL) }
1127
8effd381
JF
1128static bool JavaInterior_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry {
1129 CYJavaInterior *internal(reinterpret_cast<CYJavaInterior *>(JSObjectGetPrivate(object)));
fc664744 1130 CYJavaEnv jni(internal->value_);
8effd381 1131 CYJavaClass *table(internal->table_);
dbf05bfd
JF
1132 CYPool pool;
1133 auto name(CYPoolUTF8String(pool, context, property));
1134 auto field(table->instance_.find(name));
1135 if (field == table->instance_.end())
1136 return false;
1137
1138 switch (field->second.primitive_) {
1139 case CYJavaPrimitiveObject:
fc664744 1140 jni.SetObjectField(table->value_, field->second.field_, CYCastJavaObject(jni, context, value));
4b645e23 1141#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
dbf05bfd 1142 case CYJavaPrimitive ## Type: \
fc664744 1143 jni.Set ## Typ ## Field(table->value_, field->second.field_, CYCastDouble(context, value)); \
dbf05bfd
JF
1144 break;
1145CYJavaForEachPrimitive
1146#undef CYJavaForEachPrimitive_
1147 default: _assert(false);
1148 }
1149
1150 return true;
1151} CYCatch(false) }
1152
8effd381
JF
1153static void JavaInterior_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) {
1154 CYJavaInterior *internal(reinterpret_cast<CYJavaInterior *>(JSObjectGetPrivate(object)));
1155 CYJavaClass *table(internal->table_);
dbf05bfd
JF
1156 for (const auto &field : table->instance_)
1157 JSPropertyNameAccumulatorAddName(names, CYJSString(field.first));
1158}
1159
1160static JSValueRef JavaObject_getProperty_constructor(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
1161 CYJavaObject *internal(reinterpret_cast<CYJavaObject *>(JSObjectGetPrivate(object)));
fc664744
JF
1162 CYJavaEnv jni(internal->value_);
1163 return CYGetJavaClass(context, jni.GetObjectClass(internal->value_));
dbf05bfd
JF
1164} CYCatch(NULL) }
1165
4b645e23
JF
1166static JSValueRef JavaClass_getProperty_$cyi(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
1167 CYJavaClass *internal(reinterpret_cast<CYJavaClass *>(JSObjectGetPrivate(object)));
fc664744 1168 return CYJavaStaticInterior::Make(context, internal->value_, internal);
4b645e23
JF
1169} CYCatch(NULL) }
1170
8effd381
JF
1171static JSValueRef JavaObject_getProperty_$cyi(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
1172 CYJavaObject *internal(reinterpret_cast<CYJavaObject *>(JSObjectGetPrivate(object)));
fc664744 1173 return CYJavaInterior::Make(context, internal->value_, internal->table_);
8effd381
JF
1174} CYCatch(NULL) }
1175
4b645e23
JF
1176static JSValueRef JavaClass_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
1177 CYJavaClass *internal(reinterpret_cast<CYJavaClass *>(JSObjectGetPrivate(_this)));
fc664744
JF
1178 CYJavaEnv jni(internal->value_);
1179 auto Class$(jni.FindClass("java/lang/Class"));
1180 auto Class$getCanonicalName(jni.GetMethodID(Class$, "getCanonicalName", "()Ljava/lang/String;"));
1181 return CYCastJSValue(context, CYJSString(jni.CallObjectMethod<jstring>(internal->value_, Class$getCanonicalName)));
4b645e23
JF
1182} CYCatch(NULL) }
1183
1184static JSValueRef JavaMethod_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
1185 std::ostringstream cyon;
1186 return CYCastJSValue(context, CYJSString(cyon.str()));
1187} CYCatch(NULL) }
1188
c9c16dde
JF
1189static JSValueRef JavaStaticMethod_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
1190 std::ostringstream cyon;
1191 return CYCastJSValue(context, CYJSString(cyon.str()));
1192} CYCatch(NULL) }
1193
4b645e23
JF
1194static JSValueRef JavaArray_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
1195 CYJavaArray *internal(reinterpret_cast<CYJavaArray *>(JSObjectGetPrivate(object)));
fc664744 1196 CYJavaEnv jni(internal->value_);
4b645e23 1197 if (JSStringIsEqual(property, length_s))
fc664744 1198 return CYCastJSValue(context, jni.GetArrayLength(internal->value_));
4b645e23
JF
1199
1200 CYPool pool;
1201 ssize_t offset;
1202 if (!CYGetOffset(pool, context, property, offset))
1203 return NULL;
1204
1205 if (internal->primitive_ == CYJavaPrimitiveObject)
fc664744 1206 return CYCastJSValue(context, jni.GetObjectArrayElement<jobject>(static_cast<jobjectArray>(internal->value_.value_), offset));
4b645e23
JF
1207 else switch (internal->primitive_) {
1208#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
1209 case CYJavaPrimitive ## Type: { \
1210 j ## type element; \
fc664744 1211 jni.Get ## Typ ## ArrayRegion(static_cast<j ## type ## Array>(internal->value_.value_), offset, 1, &element); \
4b645e23
JF
1212 return CYJavaCastJSValue(context, element); \
1213 } break;
1214CYJavaForEachPrimitive
1215#undef CYJavaForEachPrimitive_
1216 default: _assert(false);
1217 }
1218} CYCatch(NULL) }
1219
1220static bool JavaArray_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry {
1221 CYJavaArray *internal(reinterpret_cast<CYJavaArray *>(JSObjectGetPrivate(object)));
fc664744 1222 CYJavaEnv jni(internal->value_);
4b645e23
JF
1223
1224 CYPool pool;
1225 ssize_t offset;
1226 if (!CYGetOffset(pool, context, property, offset))
1227 return false;
1228
1229 if (internal->primitive_ == CYJavaPrimitiveObject)
fc664744 1230 jni.SetObjectArrayElement(static_cast<jobjectArray>(internal->value_.value_), offset, CYCastJavaObject(jni, context, value));
4b645e23
JF
1231 else switch (internal->primitive_) {
1232#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
1233 case CYJavaPrimitive ## Type: { \
1234 j ## type element; \
fc664744 1235 jni.Get ## Typ ## ArrayRegion(static_cast<j ## type ## Array>(internal->value_.value_), offset, 1, &element); \
4b645e23
JF
1236 return CYJavaCastJSValue(context, element); \
1237 } break;
1238CYJavaForEachPrimitive
1239#undef CYJavaForEachPrimitive_
1240 default: _assert(false);
1241 }
1242
1243 return true;
1244} CYCatch(false) }
1245
1246static JSValueRef JavaPackage_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
1247 CYJavaPackage *internal(reinterpret_cast<CYJavaPackage *>(JSObjectGetPrivate(_this)));
1248 std::ostringstream name;
1249 for (auto &package : internal->package_)
1250 name << package << '.';
1251 name << '*';
1252 return CYCastJSValue(context, CYJSString(name.str()));
1253} CYCatch(NULL) }
1254
dbf05bfd
JF
1255static bool CYJavaPackage_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) {
1256 return true;
1257}
1258
1259static JSValueRef CYJavaPackage_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
1260 CYJavaPackage *internal(reinterpret_cast<CYJavaPackage *>(JSObjectGetPrivate(object)));
1261 CYJavaPackage::Path package(internal->package_);
1262
1263 CYPool pool;
1264 const char *next(CYPoolCString(pool, context, property));
1265
1266 std::ostringstream name;
1267 for (auto &package : internal->package_)
1268 name << package << '/';
1269 name << next;
1270
c9c16dde 1271 JNIEnv *jni(GetJNI(context));
fc664744
JF
1272 if (auto _class = jni->FindClass(name.str().c_str()))
1273 return CYGetJavaClass(context, CYJavaLocal<jclass>(jni, _class));
dbf05bfd
JF
1274 jni->ExceptionClear();
1275
1276 package.push_back(next);
1277 return CYJavaPackage::Make(context, package);
1278} CYCatch(NULL) }
1279
fc664744 1280static void Cycript_delete(JNIEnv *env, jclass api, jlong jprotect) { CYJavaTry {
824bc1ec 1281 delete &protect;
c9c16dde
JF
1282} CYJavaCatch() }
1283
fc664744
JF
1284static jobject Cycript_handle(JNIEnv *env, jclass api, jlong jprotect, jstring property, jobjectArray jarguments) { CYJavaTry {
1285 JSValueRef function(CYGetProperty(context, object, CYJSString(CYJavaRef<jstring>(jni, property))));
c9c16dde
JF
1286 if (JSValueIsUndefined(context, function))
1287 return NULL;
1288
fc664744 1289 size_t count(jarguments == NULL ? 0 : jni.GetArrayLength(jarguments));
c9c16dde 1290 JSValueRef arguments[count];
4e2cc9d3 1291 for (size_t index(0); index != count; ++index)
fc664744 1292 arguments[index] = CYCastJSValue(context, jni.GetObjectArrayElement<jobject>(jarguments, index));
c9c16dde 1293
4e2cc9d3 1294 return CYCastJavaObject(jni, context, CYCallAsFunction(context, CYCastJSObject(context, function), object, count, arguments)).leak();
c9c16dde
JF
1295} CYJavaCatch(NULL) }
1296
1297static JNINativeMethod Cycript_[] = {
1298 {(char *) "delete", (char *) "(J)V", (void *) &Cycript_delete},
1299 {(char *) "handle", (char *) "(JLjava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;", (void *) &Cycript_handle},
1300};
1301
fc664744
JF
1302JNIEnv *GetJNI(JSContextRef context) {
1303 static JavaVM *jvm(NULL);
1304 static JNIEnv *jni(NULL);
1305
1306 if (jni != NULL)
1307 return jni;
1308 jint version(JNI_VERSION_1_4);
1309
1310 jsize capacity(16);
1311 JavaVM *jvms[capacity];
1312 jsize size;
1313 _jnicall(JNI_GetCreatedJavaVMs(jvms, capacity, &size));
1314
1315 if (size != 0) {
1316 jvm = jvms[0];
1317 _jnicall(jvm->GetEnv(reinterpret_cast<void **>(&jni), version));
1318 } else {
1319 CYPool pool;
1320 std::vector<JavaVMOption> options;
1321
1322 {
1323 std::ostringstream option;
1324 option << "-Djava.class.path=";
1325 option << CYPoolLibraryPath(pool) << "/libcycript.jar";
1326 if (const char *classpath = getenv("CLASSPATH"))
1327 option << ':' << classpath;
1328 options.push_back(JavaVMOption{pool.strdup(option.str().c_str()), NULL});
1329 }
1330
1331 JavaVMInitArgs args;
1332 memset(&args, 0, sizeof(args));
1333 args.version = version;
1334 args.nOptions = options.size();
1335 args.options = options.data();
1336 _jnicall(JNI_CreateJavaVM(&jvm, reinterpret_cast<void **>(&jni), &args));
1337 }
1338
1339 auto Cycript$(CYJavaEnv(jni).FindClass("Cycript"));
c9c16dde 1340 _envcall(jni, RegisterNatives(Cycript$, Cycript_, sizeof(Cycript_) / sizeof(Cycript_[0])));
fc664744
JF
1341
1342 return jni;
c9c16dde
JF
1343}
1344
4b645e23 1345static JSStaticValue JavaClass_staticValues[3] = {
dbf05bfd 1346 {"class", &JavaClass_getProperty_class, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
4b645e23 1347 {"$cyi", &JavaClass_getProperty_$cyi, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
dbf05bfd
JF
1348 {NULL, NULL, NULL, 0}
1349};
1350
4b645e23
JF
1351static JSStaticFunction JavaClass_staticFunctions[2] = {
1352 {"toCYON", &JavaClass_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
1353 {NULL, NULL, 0}
1354};
1355
8effd381 1356static JSStaticValue JavaObject_staticValues[3] = {
dbf05bfd 1357 {"constructor", &JavaObject_getProperty_constructor, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
8effd381 1358 {"$cyi", &JavaObject_getProperty_$cyi, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
dbf05bfd
JF
1359 {NULL, NULL, NULL, 0}
1360};
1361
4b645e23
JF
1362static JSStaticFunction JavaMethod_staticFunctions[2] = {
1363 {"toCYON", &JavaMethod_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
1364 {NULL, NULL, 0}
1365};
1366
c9c16dde
JF
1367static JSStaticFunction JavaStaticMethod_staticFunctions[2] = {
1368 {"toCYON", &JavaStaticMethod_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
1369 {NULL, NULL, 0}
1370};
1371
4b645e23
JF
1372static JSStaticFunction JavaPackage_staticFunctions[2] = {
1373 {"toCYON", &JavaPackage_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
dbf05bfd
JF
1374 {NULL, NULL, 0}
1375};
1376
1377void CYJava_Initialize() {
1378 Primitives_.insert(std::make_pair("void", CYJavaPrimitiveVoid));
4b645e23 1379#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
42619b59
JF
1380 Primitives_.insert(std::make_pair(#type, CYJavaPrimitive ## Type));
1381CYJavaForEachPrimitive
1382#undef CYJavaForEachPrimitive_
dbf05bfd
JF
1383
1384 JSClassDefinition definition;
1385
1386 definition = kJSClassDefinitionEmpty;
1387 definition.className = "JavaClass";
1388 definition.staticValues = JavaClass_staticValues;
4b645e23 1389 definition.staticFunctions = JavaClass_staticFunctions;
dbf05bfd
JF
1390 definition.callAsConstructor = &JavaClass_callAsConstructor;
1391 definition.finalize = &CYFinalize;
1392 CYJavaClass::Class_ = JSClassCreate(&definition);
1393
8effd381
JF
1394 definition = kJSClassDefinitionEmpty;
1395 definition.attributes = kJSClassAttributeNoAutomaticPrototype;
1396 definition.className = "JavaInterior";
1397 definition.hasProperty = &JavaInterior_hasProperty;
1398 definition.getProperty = &JavaInterior_getProperty;
1399 definition.setProperty = &JavaInterior_setProperty;
1400 definition.getPropertyNames = &JavaInterior_getPropertyNames;
1401 definition.finalize = &CYFinalize;
1402 CYJavaInterior::Class_ = JSClassCreate(&definition);
1403
dbf05bfd
JF
1404 definition = kJSClassDefinitionEmpty;
1405 definition.className = "JavaMethod";
4b645e23 1406 definition.staticFunctions = JavaMethod_staticFunctions;
dbf05bfd
JF
1407 definition.callAsFunction = &JavaMethod_callAsFunction;
1408 definition.finalize = &CYFinalize;
1409 CYJavaMethod::Class_ = JSClassCreate(&definition);
1410
c9c16dde
JF
1411 definition = kJSClassDefinitionEmpty;
1412 definition.className = "JavaStaticMethod";
1413 definition.staticFunctions = JavaStaticMethod_staticFunctions;
1414 definition.callAsFunction = &JavaStaticMethod_callAsFunction;
1415 definition.finalize = &CYFinalize;
1416 CYJavaStaticMethod::Class_ = JSClassCreate(&definition);
1417
dbf05bfd
JF
1418 definition = kJSClassDefinitionEmpty;
1419 definition.attributes = kJSClassAttributeNoAutomaticPrototype;
1420 definition.className = "JavaObject";
1421 definition.staticValues = JavaObject_staticValues;
dbf05bfd
JF
1422 definition.finalize = &CYFinalize;
1423 CYJavaObject::Class_ = JSClassCreate(&definition);
1424
4b645e23
JF
1425 definition = kJSClassDefinitionEmpty;
1426 definition.className = "JavaArray";
1427 definition.getProperty = &JavaArray_getProperty;
1428 definition.setProperty = &JavaArray_setProperty;
1429 definition.finalize = &CYFinalize;
1430 CYJavaArray::Class_ = JSClassCreate(&definition);
1431
dbf05bfd
JF
1432 definition = kJSClassDefinitionEmpty;
1433 definition.className = "JavaPackage";
1434 definition.staticFunctions = JavaPackage_staticFunctions;
1435 definition.hasProperty = &CYJavaPackage_hasProperty;
1436 definition.getProperty = &CYJavaPackage_getProperty;
1437 definition.finalize = &CYFinalize;
1438 CYJavaPackage::Class_ = JSClassCreate(&definition);
4b645e23
JF
1439
1440 definition = kJSClassDefinitionEmpty;
1441 definition.attributes = kJSClassAttributeNoAutomaticPrototype;
c9c16dde
JF
1442 definition.className = "JavaStaticInterior";
1443 definition.hasProperty = &JavaStaticInterior_hasProperty;
1444 definition.getProperty = &JavaStaticInterior_getProperty;
1445 definition.setProperty = &JavaStaticInterior_setProperty;
1446 definition.getPropertyNames = &JavaStaticInterior_getPropertyNames;
4b645e23 1447 definition.finalize = &CYFinalize;
c9c16dde 1448 CYJavaStaticInterior::Class_ = JSClassCreate(&definition);
dbf05bfd
JF
1449}
1450
1451void CYJava_SetupContext(JSContextRef context) {
1452 JSObjectRef global(CYGetGlobalObject(context));
1453 //JSObjectRef cy(CYCastJSObject(context, CYGetProperty(context, global, cy_s)));
1454 JSObjectRef cycript(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Cycript"))));
1455 JSObjectRef all(CYCastJSObject(context, CYGetProperty(context, cycript, CYJSString("all"))));
1456 //JSObjectRef alls(CYCastJSObject(context, CYGetProperty(context, cycript, CYJSString("alls"))));
1457
1458 JSObjectRef Java(JSObjectMake(context, NULL, NULL));
1459 CYSetProperty(context, cycript, CYJSString("Java"), Java);
1460
1461 JSObjectRef Packages(CYJavaPackage::Make(context, CYJavaPackage::Path()));
1462 CYSetProperty(context, all, CYJSString("Packages"), Packages);
1463
1464 for (auto name : (const char *[]) {"java", "javax", "android", "com", "net", "org"}) {
1465 CYJSString js(name);
1466 CYSetProperty(context, all, js, CYGetProperty(context, Packages, js));
1467 }
1468}
1469
1470static CYHook CYJavaHook = {
1471 NULL,
1472 NULL,
1473 NULL,
1474 &CYJava_Initialize,
1475 &CYJava_SetupContext,
1476 NULL,
1477};
1478
1479CYRegisterHook CYJava(&CYJavaHook);