Skip to content

Commit 4f850a0

Browse files
Revert "Revert "Allocate function call argument buffer on stack""
This reverts commit d684978.
1 parent 50fd47b commit 4f850a0

File tree

5 files changed

+80
-92
lines changed

5 files changed

+80
-92
lines changed

Diff for: Sources/JavaScriptKit/ConvertibleToJSValue.swift

+18-18
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ extension RawJSValue: ConvertibleToJSValue {
213213
}
214214

215215
extension JSValue {
216-
func withRawJSValue<T>(_ body: (RawJSValue) -> T) -> T {
216+
func toRawJSValue() -> RawJSValue {
217217
let kind: JavaScriptValueKind
218218
let payload1: JavaScriptPayload1
219219
var payload2: JavaScriptPayload2 = 0
@@ -226,7 +226,7 @@ extension JSValue {
226226
payload1 = 0
227227
payload2 = numberValue
228228
case let .string(string):
229-
return string.withRawJSValue(body)
229+
return string.toRawJSValue()
230230
case let .object(ref):
231231
kind = .object
232232
payload1 = JavaScriptPayload1(ref.id)
@@ -246,30 +246,30 @@ extension JSValue {
246246
kind = .bigInt
247247
payload1 = JavaScriptPayload1(bigIntRef.id)
248248
}
249-
let rawValue = RawJSValue(kind: kind, payload1: payload1, payload2: payload2)
250-
return body(rawValue)
249+
return RawJSValue(kind: kind, payload1: payload1, payload2: payload2)
251250
}
252251
}
253252

254-
extension Array where Element == ConvertibleToJSValue {
255-
func withRawJSValues<T>(_ body: ([RawJSValue]) -> T) -> T {
256-
func _withRawJSValues<T>(
257-
_ values: [ConvertibleToJSValue], _ index: Int,
258-
_ results: inout [RawJSValue], _ body: ([RawJSValue]) -> T
259-
) -> T {
260-
if index == values.count { return body(results) }
261-
return values[index].jsValue.withRawJSValue { (rawValue) -> T in
262-
results.append(rawValue)
263-
return _withRawJSValues(values, index + 1, &results, body)
253+
extension Array where Element == JSValue {
254+
func withRawJSValues<T>(_ body: (UnsafeBufferPointer<RawJSValue>) -> T) -> T {
255+
withUnsafeTemporaryAllocation(of: RawJSValue.self, capacity: self.count) { buffer in
256+
for (index, value) in self.enumerated() {
257+
buffer[index] = value.toRawJSValue()
264258
}
259+
return body(UnsafeBufferPointer(buffer))
265260
}
266-
var _results = [RawJSValue]()
267-
return _withRawJSValues(self, 0, &_results, body)
268261
}
269262
}
270263

264+
extension Array where Element == ConvertibleToJSValue {
265+
func withRawJSValues<T>(_ body: (UnsafeBufferPointer<RawJSValue>) -> T) -> T {
266+
map { $0.jsValue }.withRawJSValues(body)
267+
}
268+
}
269+
270+
271271
extension Array where Element: ConvertibleToJSValue {
272-
func withRawJSValues<T>(_ body: ([RawJSValue]) -> T) -> T {
273-
[ConvertibleToJSValue].withRawJSValues(self)(body)
272+
func withRawJSValues<T>(_ body: (UnsafeBufferPointer<RawJSValue>) -> T) -> T {
273+
map { $0.jsValue }.withRawJSValues(body)
274274
}
275275
}

Diff for: Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift

+21-25
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,8 @@ public class JSFunction: JSObject {
3838
/// - Parameter arguments: Arguments to be passed to this constructor function.
3939
/// - Returns: A new instance of this constructor.
4040
public func new(arguments: [ConvertibleToJSValue]) -> JSObject {
41-
arguments.withRawJSValues { rawValues in
42-
rawValues.withUnsafeBufferPointer { bufferPointer in
43-
JSObject(id: _call_new(self.id, bufferPointer.baseAddress!, Int32(bufferPointer.count)))
44-
}
41+
arguments.withRawJSValues { bufferPointer in
42+
JSObject(id: _call_new(self.id, bufferPointer.baseAddress!, Int32(bufferPointer.count)))
4543
}
4644
}
4745

@@ -84,27 +82,25 @@ public class JSFunction: JSObject {
8482
}
8583

8684
func invokeNonThrowingJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJSValue], this: JSObject?) -> RawJSValue {
87-
arguments.withRawJSValues { rawValues in
88-
rawValues.withUnsafeBufferPointer { bufferPointer in
89-
let argv = bufferPointer.baseAddress
90-
let argc = bufferPointer.count
91-
var kindAndFlags = JavaScriptValueKindAndFlags()
92-
var payload1 = JavaScriptPayload1()
93-
var payload2 = JavaScriptPayload2()
94-
if let thisId = this?.id {
95-
_call_function_with_this_no_catch(thisId,
96-
jsFunc.id, argv, Int32(argc),
97-
&kindAndFlags, &payload1, &payload2)
98-
} else {
99-
let result = _call_function_no_catch(
100-
jsFunc.id, argv, Int32(argc),
101-
&payload1, &payload2
102-
)
103-
kindAndFlags = unsafeBitCast(result, to: JavaScriptValueKindAndFlags.self)
104-
}
105-
assert(!kindAndFlags.isException)
106-
let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2)
107-
return result
85+
arguments.withRawJSValues { bufferPointer in
86+
let argv = bufferPointer.baseAddress
87+
let argc = bufferPointer.count
88+
var kindAndFlags = JavaScriptValueKindAndFlags()
89+
var payload1 = JavaScriptPayload1()
90+
var payload2 = JavaScriptPayload2()
91+
if let thisId = this?.id {
92+
_call_function_with_this_no_catch(thisId,
93+
jsFunc.id, argv, Int32(argc),
94+
&kindAndFlags, &payload1, &payload2)
95+
} else {
96+
let result = _call_function_no_catch(
97+
jsFunc.id, argv, Int32(argc),
98+
&payload1, &payload2
99+
)
100+
kindAndFlags = unsafeBitCast(result, to: JavaScriptValueKindAndFlags.self)
108101
}
102+
assert(!kindAndFlags.isException)
103+
let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2)
104+
return result
109105
}
110106
}

Diff for: Sources/JavaScriptKit/FundamentalObjects/JSString.swift

+2-3
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,9 @@ extension JSString {
9595
guts.jsRef
9696
}
9797

98-
func withRawJSValue<T>(_ body: (RawJSValue) -> T) -> T {
99-
let rawValue = RawJSValue(
98+
func toRawJSValue() -> RawJSValue {
99+
return RawJSValue(
100100
kind: .string, payload1: guts.jsRef, payload2: 0
101101
)
102-
return body(rawValue)
103102
}
104103
}

Diff for: Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift

+31-35
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,22 @@ public class JSThrowingFunction {
3636
/// - Parameter arguments: Arguments to be passed to this constructor function.
3737
/// - Returns: A new instance of this constructor.
3838
public func new(arguments: [ConvertibleToJSValue]) throws -> JSObject {
39-
try arguments.withRawJSValues { rawValues -> Result<JSObject, JSValue> in
40-
rawValues.withUnsafeBufferPointer { bufferPointer in
41-
let argv = bufferPointer.baseAddress
42-
let argc = bufferPointer.count
39+
try arguments.withRawJSValues { bufferPointer -> Result<JSObject, JSValue> in
40+
let argv = bufferPointer.baseAddress
41+
let argc = bufferPointer.count
4342

44-
var exceptionKind = JavaScriptValueKindAndFlags()
45-
var exceptionPayload1 = JavaScriptPayload1()
46-
var exceptionPayload2 = JavaScriptPayload2()
47-
let resultObj = _call_throwing_new(
48-
self.base.id, argv, Int32(argc),
49-
&exceptionKind, &exceptionPayload1, &exceptionPayload2
50-
)
51-
if exceptionKind.isException {
52-
let exception = RawJSValue(kind: exceptionKind.kind, payload1: exceptionPayload1, payload2: exceptionPayload2)
53-
return .failure(exception.jsValue)
54-
}
55-
return .success(JSObject(id: resultObj))
43+
var exceptionKind = JavaScriptValueKindAndFlags()
44+
var exceptionPayload1 = JavaScriptPayload1()
45+
var exceptionPayload2 = JavaScriptPayload2()
46+
let resultObj = _call_throwing_new(
47+
self.base.id, argv, Int32(argc),
48+
&exceptionKind, &exceptionPayload1, &exceptionPayload2
49+
)
50+
if exceptionKind.isException {
51+
let exception = RawJSValue(kind: exceptionKind.kind, payload1: exceptionPayload1, payload2: exceptionPayload2)
52+
return .failure(exception.jsValue)
5653
}
54+
return .success(JSObject(id: resultObj))
5755
}.get()
5856
}
5957

@@ -64,26 +62,24 @@ public class JSThrowingFunction {
6462
}
6563

6664
private func invokeJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJSValue], this: JSObject?) throws -> JSValue {
67-
let (result, isException) = arguments.withRawJSValues { rawValues in
68-
rawValues.withUnsafeBufferPointer { bufferPointer -> (JSValue, Bool) in
69-
let argv = bufferPointer.baseAddress
70-
let argc = bufferPointer.count
71-
var kindAndFlags = JavaScriptValueKindAndFlags()
72-
var payload1 = JavaScriptPayload1()
73-
var payload2 = JavaScriptPayload2()
74-
if let thisId = this?.id {
75-
_call_function_with_this(thisId,
76-
jsFunc.id, argv, Int32(argc),
77-
&kindAndFlags, &payload1, &payload2)
78-
} else {
79-
_call_function(
80-
jsFunc.id, argv, Int32(argc),
81-
&kindAndFlags, &payload1, &payload2
82-
)
83-
}
84-
let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2)
85-
return (result.jsValue, kindAndFlags.isException)
65+
let (result, isException): (JSValue, Bool) = arguments.withRawJSValues { bufferPointer in
66+
let argv = bufferPointer.baseAddress
67+
let argc = bufferPointer.count
68+
var kindAndFlags = JavaScriptValueKindAndFlags()
69+
var payload1 = JavaScriptPayload1()
70+
var payload2 = JavaScriptPayload2()
71+
if let thisId = this?.id {
72+
_call_function_with_this(thisId,
73+
jsFunc.id, argv, Int32(argc),
74+
&kindAndFlags, &payload1, &payload2)
75+
} else {
76+
_call_function(
77+
jsFunc.id, argv, Int32(argc),
78+
&kindAndFlags, &payload1, &payload2
79+
)
8680
}
81+
let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2)
82+
return (result.jsValue, kindAndFlags.isException)
8783
}
8884
if isException {
8985
throw result

Diff for: Sources/JavaScriptKit/JSValue.swift

+8-11
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,8 @@ public func getJSValue(this: JSObject, name: JSString) -> JSValue {
203203
}
204204

205205
public func setJSValue(this: JSObject, name: JSString, value: JSValue) {
206-
value.withRawJSValue { rawValue in
207-
_set_prop(this.id, name.asInternalJSRef(), rawValue.kind, rawValue.payload1, rawValue.payload2)
208-
}
206+
let rawValue = value.toRawJSValue()
207+
_set_prop(this.id, name.asInternalJSRef(), rawValue.kind, rawValue.payload1, rawValue.payload2)
209208
}
210209

211210
public func getJSValue(this: JSObject, index: Int32) -> JSValue {
@@ -217,11 +216,10 @@ public func getJSValue(this: JSObject, index: Int32) -> JSValue {
217216
}
218217

219218
public func setJSValue(this: JSObject, index: Int32, value: JSValue) {
220-
value.withRawJSValue { rawValue in
221-
_set_subscript(this.id, index,
222-
rawValue.kind,
223-
rawValue.payload1, rawValue.payload2)
224-
}
219+
let rawValue = value.toRawJSValue()
220+
_set_subscript(this.id, index,
221+
rawValue.kind,
222+
rawValue.payload1, rawValue.payload2)
225223
}
226224

227225
public func getJSValue(this: JSObject, symbol: JSSymbol) -> JSValue {
@@ -233,9 +231,8 @@ public func getJSValue(this: JSObject, symbol: JSSymbol) -> JSValue {
233231
}
234232

235233
public func setJSValue(this: JSObject, symbol: JSSymbol, value: JSValue) {
236-
value.withRawJSValue { rawValue in
237-
_set_prop(this.id, symbol.id, rawValue.kind, rawValue.payload1, rawValue.payload2)
238-
}
234+
let rawValue = value.toRawJSValue()
235+
_set_prop(this.id, symbol.id, rawValue.kind, rawValue.payload1, rawValue.payload2)
239236
}
240237

241238
public extension JSValue {

0 commit comments

Comments
 (0)