]> git.saurik.com Git - cycript.git/blame - Internal.hpp
new operator must return JSObject even for errors.
[cycript.git] / Internal.hpp
CommitLineData
7341eedb
JF
1/* Cycript - The Truly Universal Scripting Language
2 * Copyright (C) 2009-2016 Jay Freeman (saurik)
d15b59f5
JF
3*/
4
f95d2598 5/* GNU Affero General Public License, Version 3 {{{ */
d15b59f5 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
c15969fd 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/>.
b3378a02 19**/
d15b59f5
JF
20/* }}} */
21
3c1c3635
JF
22#ifndef CYCRIPT_INTERNAL_HPP
23#define CYCRIPT_INTERNAL_HPP
24
b799113b
JF
25#include <sig/parse.hpp>
26#include <sig/ffi_type.hpp>
3c1c3635
JF
27
28#include <JavaScriptCore/JSBase.h>
bc60fb46 29#include <JavaScriptCore/JSContextRef.h>
37954781 30#include <JavaScriptCore/JSObjectRef.h>
3c1c3635
JF
31#include <JavaScriptCore/JSValueRef.h>
32
d6848e73 33#include "JavaScript.hpp"
b799113b 34#include "Pooling.hpp"
d6848e73 35#include "Utility.hpp"
3c1c3635 36
bc60fb46 37JSGlobalContextRef CYGetJSContext(JSContextRef context);
0559abf8 38sig::Type *Structor_(CYPool &pool, sig::Aggregate *aggregate);
8a23fb2e 39
3f9ae37c
JF
40extern JSClassRef Functor_;
41
d4222ffb 42struct CYRoot :
3c1c3635
JF
43 CYData
44{
dbf05bfd
JF
45 _finline JSValueRef GetPrototype(JSContextRef context) const {
46 return NULL;
47 }
d4222ffb
JF
48};
49
50template <typename Internal_, typename Base_ = CYRoot>
51struct CYPrivateOld :
52 Base_
53{
54 static JSClassRef Class_;
dbf05bfd
JF
55
56 template <typename... Args_>
57 _finline static JSClassRef GetClass(Args_ &&... args) {
58 return Class_;
59 }
60
61 template <typename... Args_>
62 static JSObjectRef Make(JSContextRef context, Args_ &&... args) {
63 Internal_ *internal(new Internal_(cy::Forward<Args_>(args)...));
64 JSObjectRef object(JSObjectMake(context, Internal_::GetClass(cy::Forward<Args_>(args)...), internal));
65 if (JSValueRef prototype = internal->GetPrototype(context))
66 CYSetPrototype(context, object, prototype);
67 return object;
68 }
0b5f88f6
JF
69
70 static Internal_ *Get(JSContextRef context, JSObjectRef object) {
71 _assert(JSValueIsObjectOfClass(context, object, Class_));
72 return static_cast<Internal_ *>(JSObjectGetPrivate(object));
73 }
dbf05bfd
JF
74};
75
d4222ffb
JF
76template <typename Internal_, typename Base_>
77JSClassRef CYPrivateOld<Internal_, Base_>::Class_;
78
79template <typename Internal_>
80struct CYPrivate {
81 static JSClassRef Class_;
82
83 template <typename... Args_>
84 static JSObjectRef Make(JSContextRef context, Args_ &&... args) {
85 Internal_ *internal(new Internal_(cy::Forward<Args_>(args)...));
86 JSObjectRef object(JSObjectMake(context, Class_, internal));
87 if (JSValueRef prototype = internal->GetPrototype(context))
88 CYSetPrototype(context, object, prototype);
89 return object;
90 }
91
3d2d95a0
JF
92 template <typename Arg_>
93 static JSObjectRef Cache(JSContextRef context, Arg_ *arg) {
94 JSObjectRef global(CYGetGlobalObject(context));
95 JSObjectRef cy(CYCastJSObject(context, CYGetProperty(context, global, cy_s)));
96
97 char label[32];
98 sprintf(label, "%s%p", Internal_::Cache_, arg);
99 CYJSString name(label);
100
101 JSValueRef value(CYGetProperty(context, cy, name));
102 if (!JSValueIsUndefined(context, value))
103 return CYCastJSObject(context, value);
104
105 JSObjectRef object(Make(context, arg));
106 CYSetProperty(context, cy, name, object);
107 return object;
108 }
109
d4222ffb
JF
110 static Internal_ *Get(JSContextRef context, JSObjectRef object) {
111 _assert(JSValueIsObjectOfClass(context, object, Class_));
112 return static_cast<Internal_ *>(JSObjectGetPrivate(object));
113 }
114};
115
116template <typename Internal_>
117JSClassRef CYPrivate<Internal_>::Class_;
118
dbf05bfd 119struct Type_privateData :
d4222ffb 120 CYRoot
dbf05bfd 121{
3c1c3635
JF
122 ffi_type *ffi_;
123 sig::Type *type_;
124
807a88be
JF
125 Type_privateData(const char *type) :
126 ffi_(NULL)
127 {
3c1c3635 128 sig::Signature signature;
b799113b 129 sig::Parse(*pool_, &signature, type, &Structor_);
3c1c3635
JF
130 type_ = signature.elements[0].type;
131 }
132
0559abf8
JF
133 Type_privateData(const sig::Type &type, ffi_type *ffi = NULL) :
134 type_(type.Copy(*pool_))
baea6375 135 {
baea6375 136
0559abf8
JF
137 if (ffi == NULL)
138 ffi_ = NULL;
139 else {
140 ffi_ = new(*pool_) ffi_type;
141 sig::Copy(*pool_, *ffi_, *ffi);
142 }
3c1c3635
JF
143 }
144
145 ffi_type *GetFFI() {
146 if (ffi_ == NULL) {
3c1c3635
JF
147 sig::Element element;
148 element.name = NULL;
149 element.type = type_;
150 element.offset = 0;
151
152 sig::Signature signature;
153 signature.elements = &element;
154 signature.count = 1;
155
156 ffi_cif cif;
574d4720 157 sig::sig_ffi_cif(*pool_, false, signature, &cif);
446d46d2
JF
158
159 ffi_ = new(*pool_) ffi_type;
3c1c3635
JF
160 *ffi_ = *cif.rtype;
161 }
162
163 return ffi_;
164 }
165};
166
d6848e73 167struct CYProtect {
3c1c3635 168 private:
bc60fb46 169 JSGlobalContextRef context_;
d6848e73 170 JSObjectRef object_;
3c1c3635
JF
171
172 public:
d6848e73 173 CYProtect(JSContextRef context, JSObjectRef object) :
bc60fb46 174 context_(CYGetJSContext(context)),
d6848e73 175 object_(object)
3c1c3635 176 {
bc60fb46 177 //XXX:JSGlobalContextRetain(context_);
d6848e73
JF
178 if (object_ != NULL)
179 JSValueProtect(context_, object_);
3c1c3635
JF
180 }
181
d6848e73
JF
182 ~CYProtect() {
183 if (object_ != NULL)
184 JSValueUnprotect(context_, object_);
bc60fb46 185 //XXX:JSGlobalContextRelease(context_);
3c1c3635
JF
186 }
187
5f7a1d38
JF
188 operator bool() const {
189 return object_ != NULL;
190 }
191
192 operator JSContextRef() const {
193 return context_;
194 }
195
d6848e73
JF
196 operator JSObjectRef() const {
197 return object_;
3c1c3635
JF
198 }
199};
200
37954781
JF
201namespace cy {
202struct Functor :
d4222ffb 203 CYRoot
37954781 204{
077756a4
JF
205 private:
206 void set() {
574d4720 207 sig::sig_ffi_cif(*pool_, variadic_ ? signature_.count : 0, signature_, &cif_);
077756a4
JF
208 }
209
210 public:
88c31c1e 211 void (*value_)();
574d4720 212 bool variadic_;
37954781
JF
213 sig::Signature signature_;
214 ffi_cif cif_;
215
574d4720 216 Functor(void (*value)(), bool variadic, const sig::Signature &signature) :
88c31c1e 217 value_(value),
574d4720 218 variadic_(variadic)
37954781 219 {
077756a4
JF
220 sig::Copy(*pool_, signature_, signature);
221 set();
222 }
223
574d4720 224 Functor(void (*value)(), const char *encoding) :
88c31c1e 225 value_(value),
574d4720 226 variadic_(false)
077756a4
JF
227 {
228 sig::Parse(*pool_, &signature_, encoding, &Structor_);
229 set();
37954781
JF
230 }
231
37954781 232 static JSStaticFunction const * const StaticFunctions;
8493347d 233 static JSStaticValue const * const StaticValues;
37954781
JF
234}; }
235
236struct Closure_privateData :
237 cy::Functor
238{
5f7a1d38 239 CYProtect function_;
24e7b1a6 240 JSValueRef (*adapter_)(JSContextRef, size_t, JSValueRef[], JSObjectRef);
37954781 241
24e7b1a6 242 Closure_privateData(JSContextRef context, JSObjectRef function, JSValueRef (*adapter)(JSContextRef, size_t, JSValueRef[], JSObjectRef), const sig::Signature &signature) :
574d4720 243 cy::Functor(NULL, false, signature),
5f7a1d38 244 function_(context, function),
24e7b1a6 245 adapter_(adapter)
37954781 246 {
37954781
JF
247 }
248};
249
24e7b1a6 250Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, const sig::Signature &signature, JSValueRef (*adapter)(JSContextRef, size_t, JSValueRef[], JSObjectRef));
9ec7dd18 251void CYExecuteClosure(ffi_cif *cif, void *result, void **arguments, void *arg, JSValueRef (*adapter)(JSContextRef, size_t, JSValueRef[], JSObjectRef));
37954781 252
3c1c3635 253#endif/*CYCRIPT_INTERNAL_HPP*/