Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/javascript_darwin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Unreleased

- Remove per-runtime callback registrations and cancel timers on disposal.
- Guard asynchronous replies and Promise polling after context disposal.
- Release temporary JavaScriptCore strings and pointer slots in runtime paths.
- Handle null JSON string references without calling JSStringRelease on null.

# 2.0.0

- Update dependency of `javascript_platform_interface` to version `2.0.0`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extension HandlePromises on JavascriptRuntime {
function FLUTTER_NATIVEJS_IS_REJECTED_PROMISE(idx) {
return FLUTTER_NATIVEJS_PENDING_PROMISES[idx].isRejected();
}

/**
* This function allow you to modify a JS Promise by adding some status properties.
* Based on: http://stackoverflow.com/questions/21485545/is-there-a-way-to-tell-if-an-es6-promise-is-fulfilled-rejected-resolved
Expand All @@ -56,12 +56,12 @@ extension HandlePromises on JavascriptRuntime {
isFulfilled = true;
isPending = false;
value = v;
return v;
},
return v;
},
function(e) {
isRejected = true;
isPending = false;
value = e;
value = e;
}
);

Expand Down Expand Up @@ -107,6 +107,7 @@ extension HandlePromises on JavascriptRuntime {
var completed = false;
Function? fnEvaluatePromise;
fnEvaluatePromise = () async {
if (isDisposed || completed) return;
this.executePendingJob();
if (!completed) {
await Future.delayed(
Expand Down Expand Up @@ -140,6 +141,13 @@ extension HandlePromises on JavascriptRuntime {
callFunction(evalRegisterPromise, value.rawResult).stringResult;
int idxPromise = int.parse(promiseQuerableIdx);
Timer.periodic(Duration(milliseconds: 20), (timer) {
if (isDisposed) {
timer.cancel();
if (!completer.isCompleted) {
completer.completeError(StateError('JavaScript runtime is disposed'));
}
return;
}
// call to _JS_ExecutePendingJob
this.executePendingJob();
//eval(REGISTER_PROMISE_FUNCTION);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,19 @@ abstract class JavascriptRuntime {

Map<String, dynamic> dartContext = {};

final Set<Timer> _timers = {};

@protected
void releaseDartResources() {
channelFunctionsRegistered.remove(getEngineInstanceId());
for (final timer in _timers) {
timer.cancel();
}
_timers.clear();
localContext.clear();
dartContext.clear();
}

void dispose();

static final Map<String, Map<String, Function(dynamic arg)>>
Expand Down Expand Up @@ -133,7 +146,7 @@ abstract class JavascriptRuntime {
// console.log(typeof(sendMessage));
// console.log('BLA');
sendMessage('SetTimeout', JSON.stringify({ timeoutIndex, timeout}));

} catch (e) {
console.error('ERROR HERE',e.message);
}
Expand All @@ -146,13 +159,16 @@ abstract class JavascriptRuntime {
int duration = args['timeout'] ?? 0;
String idx = args['timeoutIndex'];

Timer(Duration(milliseconds: duration), () {
late final Timer timer;
timer = Timer(Duration(milliseconds: duration), () {
_timers.remove(timer);
if (isDisposed) return;
evaluate("""
__NATIVE_FLUTTER_JS__setTimeoutCallbacks[$idx].call();
delete __NATIVE_FLUTTER_JS__setTimeoutCallbacks[$idx];
""");
});
_timers.add(timer);
} on Exception catch (e) {
print('Exception no setTimeout: $e');
} on Error catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ class JSObject {
context.pointer,
arguments.count,
arguments.pointer,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);

/// Creates a JavaScript Date object, as if by invoking the built-in Date constructor.
/// [arguments] A JSValue array of arguments to pass to the Date Constructor. Pass NULL if argumentCount is 0.
Expand All @@ -561,7 +561,7 @@ class JSObject {
context.pointer,
arguments.count,
arguments.pointer,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);

/// Creates a JavaScript Error object, as if by invoking the built-in Error constructor.
/// [arguments] (JSValueRef[]) A JSValue array of arguments to pass to the Error Constructor. Pass NULL if argumentCount is 0.
Expand All @@ -574,7 +574,7 @@ class JSObject {
context.pointer,
arguments.count,
arguments.pointer,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);

/// Creates a JavaScript RegExp object, as if by invoking the built-in RegExp constructor.
/// [arguments] (JSValueRef[]) A JSValue array of arguments to pass to the RegExp Constructor. Pass NULL if argumentCount is 0.
Expand All @@ -587,7 +587,7 @@ class JSObject {
context.pointer,
arguments.count,
arguments.pointer,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);

/// Creates a JavaScript promise object by invoking the provided executor.
/// [resolve] (JSObjectRef*) A pointer to a JSObjectRef in which to store the resolve function for the new promise. Pass NULL if you do not care to store the resolve callback.
Expand All @@ -602,7 +602,7 @@ class JSObject {
context.pointer,
resolve.pointer,
reject.pointer,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);

/// Creates a function with a given script as its body.
/// Use this method when you want to execute a script repeatedly, to avoid the cost of re-parsing the script before each execution.
Expand All @@ -628,7 +628,7 @@ class JSObject {
JSString.fromString(body).pointer,
JSString.fromString(sourceURL).pointer,
startingLineNumber,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);

/// Creates a JavaScript Typed Array object with the given number of elements.
/// [arrayType] A value [JSTypedArrayType] identifying the type of array to create. If arrayType is kJSTypedArrayTypeNone or kJSTypedArrayTypeArrayBuffer then NULL will be returned.
Expand All @@ -643,7 +643,7 @@ class JSObject {
context.pointer,
JSValue.jSTypedArrayTypeToCEnum(arrayType),
length,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);

/// Creates a JavaScript Typed Array object from an existing pointer.
/// If an exception is thrown during this function the bytesDeallocator will always be called.
Expand All @@ -668,7 +668,7 @@ class JSObject {
bytes.length,
bytesDeallocator ?? nullptr,
deallocatorContext,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);

/// Creates a JavaScript Typed Array object from an existing JavaScript Array Buffer object.
/// [arrayType] A value [JSTypedArrayType] identifying the type of array to create. If arrayType is kJSTypedArrayTypeNone or kJSTypedArrayTypeArrayBuffer then NULL will be returned.
Expand All @@ -683,7 +683,7 @@ class JSObject {
context.pointer,
JSValue.jSTypedArrayTypeToCEnum(arrayType),
buffer.pointer,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);

/// Creates a JavaScript Typed Array object from an existing JavaScript Array Buffer object with the given offset and length.
/// [arrayType] A value [JSTypedArrayType] identifying the type of array to create. If arrayType is kJSTypedArrayTypeNone or kJSTypedArrayTypeArrayBuffer then NULL will be returned.
Expand All @@ -705,7 +705,7 @@ class JSObject {
buffer.pointer,
byteOffset,
length,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);

/// Creates a JavaScript Array Buffer object from an existing pointer.
/// If an exception is thrown during this function the bytesDeallocator will always be called.
Expand All @@ -726,7 +726,7 @@ class JSObject {
bytes.length,
bytesDeallocator ?? nullptr,
deallocatorContext,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);

/// Gets an object's prototype.
JSValue get prototype {
Expand Down Expand Up @@ -755,13 +755,13 @@ class JSObject {
String propertyName, {
JSValuePointer? exception,
}) {
return JSValue(
context,
JSObjectRef.jSObjectGetProperty(
context.pointer,
pointer,
JSString.fromString(propertyName).pointer,
(exception ?? JSValuePointer(nullptr)).pointer));
final name = JSString.fromString(propertyName);
try {
return JSValue(context, JSObjectRef.jSObjectGetProperty(
context.pointer, pointer, name.pointer, exception?.pointer ?? nullptr));
} finally {
name.release();
}
}

/// Sets a property on an object.
Expand All @@ -781,7 +781,7 @@ class JSObject {
JSString.fromString(propertyName).pointer,
value.pointer,
jSPropertyAttributesToCEnum(attributes),
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);
}

/// Deletes a property from an object.
Expand All @@ -796,7 +796,7 @@ class JSObject {
context.pointer,
pointer,
JSString.fromString(propertyName).pointer,
(exception ?? JSValuePointer(nullptr)).pointer) ==
exception?.pointer ?? nullptr) ==
1;
}

Expand All @@ -812,7 +812,7 @@ class JSObject {
context.pointer,
pointer,
JSString.fromString(propertyKey).pointer,
(exception ?? JSValuePointer(nullptr)).pointer) ==
exception?.pointer ?? nullptr) ==
1;
}

Expand All @@ -830,7 +830,7 @@ class JSObject {
context.pointer,
pointer,
JSString.fromString(propertyKey).pointer,
(exception ?? JSValuePointer(nullptr)).pointer));
exception?.pointer ?? nullptr));
}

/// Sets a property on an object using a JSValueRef as the property key.
Expand All @@ -851,7 +851,7 @@ class JSObject {
JSString.fromString(propertyKey).pointer,
value.pointer,
jSPropertyAttributesToCEnum(attributes),
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);
}

/// Gets a property from an object by numeric index.
Expand All @@ -865,7 +865,7 @@ class JSObject {
return JSValue(
context,
JSObjectRef.jSObjectGetPropertyAtIndex(context.pointer, pointer,
propertyIndex, (exception ?? JSValuePointer(nullptr)).pointer));
propertyIndex, exception?.pointer ?? nullptr));
}

/// Sets a property on an object by numeric index.
Expand All @@ -883,7 +883,7 @@ class JSObject {
pointer,
propertyIndex,
value.pointer,
(exception ?? JSValuePointer(nullptr)).pointer);
exception?.pointer ?? nullptr);
}

/// Gets an object's private data.
Expand Down Expand Up @@ -921,7 +921,7 @@ class JSObject {
thisObject.pointer,
arguments.count,
arguments.pointer,
(exception ?? JSValuePointer(nullptr)).pointer));
exception?.pointer ?? nullptr));
}

/// Tests whether an object can be called as a constructor.
Expand All @@ -944,7 +944,7 @@ class JSObject {
pointer,
arguments.count,
arguments.pointer,
(exception ?? JSValuePointer(nullptr)).pointer));
exception?.pointer ?? nullptr));
}

/// Gets the names of an object's enumerable properties.
Expand All @@ -970,9 +970,9 @@ class JSObject {
}) {
return Bytes(
JSTypedArray.jSObjectGetTypedArrayBytesPtr(context.pointer, pointer,
(exception ?? JSValuePointer(nullptr)).pointer),
exception?.pointer ?? nullptr),
JSTypedArray.jSObjectGetTypedArrayLength(context.pointer, pointer,
(exception ?? JSValuePointer(nullptr)).pointer));
exception?.pointer ?? nullptr));
}

/// Returns the byte length of a JavaScript Typed Array object.
Expand All @@ -981,7 +981,7 @@ class JSObject {
JSValuePointer? exception,
}) {
return JSTypedArray.jSObjectGetTypedArrayByteLength(context.pointer,
pointer, (exception ?? JSValuePointer(nullptr)).pointer);
pointer, exception?.pointer ?? nullptr);
}

/// Returns the byte offset of a JavaScript Typed Array object.
Expand All @@ -990,7 +990,7 @@ class JSObject {
JSValuePointer? exception,
}) {
return JSTypedArray.jSObjectGetTypedArrayByteOffset(context.pointer,
pointer, (exception ?? JSValuePointer(nullptr)).pointer);
pointer, exception?.pointer ?? nullptr);
}

/// Returns the JavaScript Array Buffer object that is used as the backing of a JavaScript Typed Array object.
Expand All @@ -1001,7 +1001,7 @@ class JSObject {
return JSObject(
context,
JSTypedArray.jSObjectGetTypedArrayBuffer(context.pointer, pointer,
(exception ?? JSValuePointer(nullptr)).pointer));
exception?.pointer ?? nullptr));
}

/// Returns a pointer to the data buffer that serves as the backing store for a JavaScript Typed Array object.
Expand All @@ -1012,9 +1012,9 @@ class JSObject {
}) {
return Bytes(
JSTypedArray.jSObjectGetArrayBufferBytesPtr(context.pointer, pointer,
(exception ?? JSValuePointer(nullptr)).pointer),
exception?.pointer ?? nullptr),
JSTypedArray.jSObjectGetArrayBufferByteLength(context.pointer, pointer,
(exception ?? JSValuePointer(nullptr)).pointer));
exception?.pointer ?? nullptr));
}

/// JSObject to JSValue
Expand Down
Loading