Skip to content

Commit 22496e2

Browse files
committed
feat(jsc): Update to newer version of JSC and add support for host objects in JSC
This only supports x86_64 and arm64_v8a abis.
1 parent 3cd93d0 commit 22496e2

76 files changed

Lines changed: 2555 additions & 1335 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright (C) 2013-2020 Apple Inc. All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions
6+
* are met:
7+
* 1. Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21+
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
#ifndef APICallbackFunction_h
27+
#define APICallbackFunction_h
28+
29+
#include "APICast.h"
30+
#include "Error.h"
31+
#include "JSCallbackConstructor.h"
32+
#include "JSLock.h"
33+
#include <wtf/Vector.h>
34+
35+
namespace JSC {
36+
37+
struct APICallbackFunction {
38+
template <typename T> static EncodedJSValue callImpl(JSGlobalObject*, CallFrame*);
39+
template <typename T> static EncodedJSValue constructImpl(JSGlobalObject*, CallFrame*);
40+
};
41+
42+
template <typename T>
43+
EncodedJSValue APICallbackFunction::callImpl(JSGlobalObject* globalObject, CallFrame* callFrame)
44+
{
45+
VM& vm = getVM(globalObject);
46+
auto scope = DECLARE_THROW_SCOPE(vm);
47+
JSContextRef execRef = toRef(globalObject);
48+
JSObjectRef functionRef = toRef(callFrame->jsCallee());
49+
JSObjectRef thisObjRef = toRef(jsCast<JSObject*>(callFrame->thisValue().toThis(globalObject, ECMAMode::sloppy())));
50+
51+
int argumentCount = static_cast<int>(callFrame->argumentCount());
52+
Vector<JSValueRef, 16> arguments(argumentCount, [&](size_t i) {
53+
return toRef(globalObject, callFrame->uncheckedArgument(i));
54+
});
55+
56+
JSValueRef exception = nullptr;
57+
JSValueRef result;
58+
{
59+
JSLock::DropAllLocks dropAllLocks(globalObject);
60+
result = jsCast<T*>(toJS(functionRef))->functionCallback()(execRef, functionRef, thisObjRef, argumentCount, arguments.span().data(), &exception);
61+
}
62+
if (exception) {
63+
throwException(globalObject, scope, toJS(globalObject, exception));
64+
return JSValue::encode(jsUndefined());
65+
}
66+
67+
// result must be a valid JSValue.
68+
if (!result)
69+
return JSValue::encode(jsUndefined());
70+
71+
return JSValue::encode(toJS(globalObject, result));
72+
}
73+
74+
template <typename T>
75+
EncodedJSValue APICallbackFunction::constructImpl(JSGlobalObject* globalObject, CallFrame* callFrame)
76+
{
77+
VM& vm = getVM(globalObject);
78+
auto scope = DECLARE_THROW_SCOPE(vm);
79+
JSValue callee = callFrame->jsCallee();
80+
T* constructor = jsCast<T*>(callFrame->jsCallee());
81+
JSContextRef ctx = toRef(globalObject);
82+
JSObjectRef constructorRef = toRef(constructor);
83+
84+
JSObjectCallAsConstructorCallback callback = constructor->constructCallback();
85+
if (callback) {
86+
JSValue prototype;
87+
JSValue newTarget = callFrame->newTarget();
88+
// If we are doing a derived class construction get the .prototype property off the new target first so we behave closer to normal JS.
89+
if (newTarget != constructor) {
90+
prototype = newTarget.get(globalObject, vm.propertyNames->prototype);
91+
RETURN_IF_EXCEPTION(scope, { });
92+
}
93+
94+
size_t argumentCount = callFrame->argumentCount();
95+
Vector<JSValueRef, 16> arguments(argumentCount, [&](size_t i) {
96+
return toRef(globalObject, callFrame->uncheckedArgument(i));
97+
});
98+
99+
JSValueRef exception = nullptr;
100+
JSObjectRef result;
101+
{
102+
JSLock::DropAllLocks dropAllLocks(globalObject);
103+
result = callback(ctx, constructorRef, argumentCount, arguments.span().data(), &exception);
104+
}
105+
106+
if (exception) {
107+
throwException(globalObject, scope, toJS(globalObject, exception));
108+
return JSValue::encode(jsUndefined());
109+
}
110+
// result must be a valid JSValue.
111+
if (!result)
112+
return throwVMTypeError(globalObject, scope);
113+
114+
JSObject* newObject = toJS(result);
115+
// This won't trigger proxy traps on newObject's prototype handler but that's probably desirable here anyway.
116+
if (newTarget != constructor && newObject->getPrototypeDirect() == constructor->get(globalObject, vm.propertyNames->prototype)) {
117+
RETURN_IF_EXCEPTION(scope, { });
118+
newObject->setPrototype(vm, globalObject, prototype);
119+
RETURN_IF_EXCEPTION(scope, { });
120+
}
121+
122+
return JSValue::encode(newObject);
123+
}
124+
125+
return JSValue::encode(toJS(JSObjectMake(ctx, jsCast<JSCallbackConstructor*>(callee)->classRef(), nullptr)));
126+
}
127+
128+
} // namespace JSC
129+
130+
#endif // APICallbackFunction_h

test-app/runtime/src/main/cpp/napi/jsc/include/JavaScriptCore/APICast.h renamed to test-app/runtime/src/main/cpp/napi/jsc/JavaScriptCore/APICast.h

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2006-2019 Apple Inc. All rights reserved.
2+
* Copyright (C) 2006-2022 Apple Inc. All rights reserved.
33
*
44
* Redistribution and use in source and binary forms, with or without
55
* modification, are permitted provided that the following conditions
@@ -23,17 +23,22 @@
2323
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2424
*/
2525

26-
#ifndef APICast_h
27-
#define APICast_h
26+
#pragma once
2827

28+
#include <wtf/Compiler.h>
29+
30+
WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN
31+
32+
#include "HeapCellInlines.h"
33+
#include "Integrity.h"
2934
#include "JSAPIValueWrapper.h"
3035
#include "JSCJSValue.h"
3136
#include "JSCJSValueInlines.h"
32-
#include "JSGlobalObject.h"
33-
#include "HeapCellInlines.h"
37+
38+
WTF_ALLOW_UNSAFE_BUFFER_USAGE_END
3439

3540
namespace JSC {
36-
class ExecState;
41+
class CallFrame;
3742
class PropertyNameArray;
3843
class VM;
3944
class JSObject;
@@ -49,26 +54,26 @@ typedef struct OpaqueJSValue* JSObjectRef;
4954

5055
/* Opaque typing convenience methods */
5156

52-
inline JSC::ExecState* toJS(JSContextRef c)
57+
inline JSC::JSGlobalObject* toJS(JSContextRef context)
5358
{
54-
ASSERT(c);
55-
return reinterpret_cast<JSC::ExecState*>(const_cast<OpaqueJSContext*>(c));
59+
ASSERT(context);
60+
return JSC::Integrity::audit(reinterpret_cast<JSC::JSGlobalObject*>(const_cast<OpaqueJSContext*>(context)));
5661
}
5762

58-
inline JSC::ExecState* toJS(JSGlobalContextRef c)
63+
inline JSC::JSGlobalObject* toJS(JSGlobalContextRef context)
5964
{
60-
ASSERT(c);
61-
return reinterpret_cast<JSC::ExecState*>(c);
65+
ASSERT(context);
66+
return JSC::Integrity::audit(reinterpret_cast<JSC::JSGlobalObject*>(context));
6267
}
6368

6469
inline JSC::JSGlobalObject* toJSGlobalObject(JSGlobalContextRef context)
6570
{
66-
return toJS(context)->lexicalGlobalObject();
71+
return toJS(context);
6772
}
6873

69-
inline JSC::JSValue toJS(JSC::ExecState* exec, JSValueRef v)
74+
inline JSC::JSValue toJS(JSC::JSGlobalObject* globalObject, JSValueRef v)
7075
{
71-
ASSERT_UNUSED(exec, exec);
76+
ASSERT_UNUSED(globalObject, globalObject);
7277
#if !CPU(ADDRESS64)
7378
JSC::JSCell* jsCell = reinterpret_cast<JSC::JSCell*>(const_cast<OpaqueJSValue*>(v));
7479
if (!jsCell)
@@ -79,42 +84,53 @@ inline JSC::JSValue toJS(JSC::ExecState* exec, JSValueRef v)
7984
else
8085
result = jsCell;
8186
#else
82-
JSC::JSValue result = bitwise_cast<JSC::JSValue>(v);
87+
JSC::JSValue result = std::bit_cast<JSC::JSValue>(v);
8388
#endif
8489
if (!result)
8590
return JSC::jsNull();
86-
if (result.isCell())
87-
RELEASE_ASSERT(result.asCell()->methodTable(exec->vm()));
91+
if (result.isCell()) {
92+
JSC::Integrity::audit(result.asCell());
93+
RELEASE_ASSERT(result.asCell()->methodTable());
94+
}
8895
return result;
8996
}
9097

91-
inline JSC::JSValue toJSForGC(JSC::ExecState* exec, JSValueRef v)
98+
#if CPU(ADDRESS64)
99+
inline JSC::JSValue toJS(JSValueRef value)
100+
{
101+
return JSC::Integrity::audit(std::bit_cast<JSC::JSValue>(value));
102+
}
103+
#endif
104+
105+
inline JSC::JSValue toJSForGC(JSC::JSGlobalObject* globalObject, JSValueRef v)
92106
{
93-
ASSERT_UNUSED(exec, exec);
107+
ASSERT_UNUSED(globalObject, globalObject);
94108
#if !CPU(ADDRESS64)
95109
JSC::JSCell* jsCell = reinterpret_cast<JSC::JSCell*>(const_cast<OpaqueJSValue*>(v));
96110
if (!jsCell)
97111
return JSC::JSValue();
98112
JSC::JSValue result = jsCell;
99113
#else
100-
JSC::JSValue result = bitwise_cast<JSC::JSValue>(v);
114+
JSC::JSValue result = std::bit_cast<JSC::JSValue>(v);
101115
#endif
102-
if (result && result.isCell())
103-
RELEASE_ASSERT(result.asCell()->methodTable(exec->vm()));
116+
if (result && result.isCell()) {
117+
JSC::Integrity::audit(result.asCell());
118+
RELEASE_ASSERT(result.asCell()->methodTable());
119+
}
104120
return result;
105121
}
106122

107123
// Used in JSObjectGetPrivate as that may be called during finalization
108124
inline JSC::JSObject* uncheckedToJS(JSObjectRef o)
109125
{
110-
return reinterpret_cast<JSC::JSObject*>(o);
126+
return JSC::Integrity::audit(reinterpret_cast<JSC::JSObject*>(o));
111127
}
112128

113129
inline JSC::JSObject* toJS(JSObjectRef o)
114130
{
115131
JSC::JSObject* object = uncheckedToJS(o);
116132
if (object)
117-
RELEASE_ASSERT(object->methodTable(object->vm()));
133+
RELEASE_ASSERT(object->methodTable());
118134
return object;
119135
}
120136

@@ -125,7 +141,7 @@ inline JSC::PropertyNameArray* toJS(JSPropertyNameAccumulatorRef a)
125141

126142
inline JSC::VM* toJS(JSContextGroupRef g)
127143
{
128-
return reinterpret_cast<JSC::VM*>(const_cast<OpaqueJSContextGroup*>(g));
144+
return JSC::Integrity::audit(reinterpret_cast<JSC::VM*>(const_cast<OpaqueJSContextGroup*>(g)));
129145
}
130146

131147
inline JSValueRef toRef(JSC::VM& vm, JSC::JSValue v)
@@ -139,34 +155,40 @@ inline JSValueRef toRef(JSC::VM& vm, JSC::JSValue v)
139155
return reinterpret_cast<JSValueRef>(v.asCell());
140156
#else
141157
UNUSED_PARAM(vm);
142-
return bitwise_cast<JSValueRef>(v);
158+
return std::bit_cast<JSValueRef>(JSC::Integrity::audit(v));
143159
#endif
144160
}
145161

146-
inline JSValueRef toRef(JSC::ExecState* exec, JSC::JSValue v)
162+
inline JSValueRef toRef(JSC::JSGlobalObject* globalObject, JSC::JSValue v)
147163
{
148-
return toRef(exec->vm(), v);
164+
return toRef(getVM(globalObject), v);
149165
}
150166

167+
#if CPU(ADDRESS64)
168+
inline JSValueRef toRefWithoutGlobalObject(JSC::JSValue v)
169+
{
170+
return std::bit_cast<JSValueRef>(JSC::Integrity::audit(v));
171+
}
172+
#endif
173+
151174
inline JSObjectRef toRef(JSC::JSObject* o)
152175
{
153-
return reinterpret_cast<JSObjectRef>(o);
176+
return reinterpret_cast<JSObjectRef>(JSC::Integrity::audit(o));
154177
}
155178

156179
inline JSObjectRef toRef(const JSC::JSObject* o)
157180
{
158-
return reinterpret_cast<JSObjectRef>(const_cast<JSC::JSObject*>(o));
181+
return reinterpret_cast<JSObjectRef>(JSC::Integrity::audit(const_cast<JSC::JSObject*>(o)));
159182
}
160183

161-
inline JSContextRef toRef(JSC::ExecState* e)
184+
inline JSContextRef toRef(JSC::JSGlobalObject* globalObject)
162185
{
163-
return reinterpret_cast<JSContextRef>(e);
186+
return reinterpret_cast<JSContextRef>(JSC::Integrity::audit(globalObject));
164187
}
165188

166-
inline JSGlobalContextRef toGlobalRef(JSC::ExecState* e)
189+
inline JSGlobalContextRef toGlobalRef(JSC::JSGlobalObject* globalObject)
167190
{
168-
ASSERT(e == e->lexicalGlobalObject()->globalExec());
169-
return reinterpret_cast<JSGlobalContextRef>(e);
191+
return reinterpret_cast<JSGlobalContextRef>(JSC::Integrity::audit(globalObject));
170192
}
171193

172194
inline JSPropertyNameAccumulatorRef toRef(JSC::PropertyNameArray* l)
@@ -176,7 +198,5 @@ inline JSPropertyNameAccumulatorRef toRef(JSC::PropertyNameArray* l)
176198

177199
inline JSContextGroupRef toRef(JSC::VM* g)
178200
{
179-
return reinterpret_cast<JSContextGroupRef>(g);
201+
return reinterpret_cast<JSContextGroupRef>(JSC::Integrity::audit(g));
180202
}
181-
182-
#endif // APICast_h

0 commit comments

Comments
 (0)