fix randomly crash by stack overflow

This commit is contained in:
ekibun
2020-10-07 00:15:57 +08:00
parent d294dd59bc
commit ee934184ac
8 changed files with 32 additions and 12 deletions

View File

@@ -3,8 +3,12 @@
* @Author: ekibun * @Author: ekibun
* @Date: 2020-08-08 08:16:50 * @Date: 2020-08-08 08:16:50
* @LastEditors: ekibun * @LastEditors: ekibun
* @LastEditTime: 2020-10-03 23:34:30 * @LastEditTime: 2020-10-06 23:18:19
--> -->
## 0.1.3
* fix randomly crash by stack overflow.
## 0.1.2 ## 0.1.2
* fix qjs memory leak. * fix qjs memory leak.

View File

@@ -3,7 +3,7 @@
* @Author: ekibun * @Author: ekibun
* @Date: 2020-09-06 18:32:45 * @Date: 2020-09-06 18:32:45
* @LastEditors: ekibun * @LastEditors: ekibun
* @LastEditTime: 2020-10-03 23:26:14 * @LastEditTime: 2020-10-07 00:03:41
*/ */
#include "ffi.h" #include "ffi.h"
#include <functional> #include <functional>
@@ -100,6 +100,7 @@ extern "C"
DLLEXPORT JSValue *jsEval(JSContext *ctx, const char *input, size_t input_len, const char *filename, int32_t eval_flags) DLLEXPORT JSValue *jsEval(JSContext *ctx, const char *input, size_t input_len, const char *filename, int32_t eval_flags)
{ {
JS_ResetStackTop(JS_GetRuntime(ctx));
return new JSValue(JS_Eval(ctx, input, input_len, filename, eval_flags)); return new JSValue(JS_Eval(ctx, input, input_len, filename, eval_flags));
} }
@@ -196,6 +197,7 @@ extern "C"
DLLEXPORT const char *jsToCString(JSContext *ctx, JSValueConst *val) DLLEXPORT const char *jsToCString(JSContext *ctx, JSValueConst *val)
{ {
JS_ResetStackTop(JS_GetRuntime(ctx));
return JS_ToCString(ctx, *val); return JS_ToCString(ctx, *val);
} }
@@ -270,6 +272,7 @@ extern "C"
DLLEXPORT JSValue *jsCall(JSContext *ctx, JSValueConst *func_obj, JSValueConst *this_obj, DLLEXPORT JSValue *jsCall(JSContext *ctx, JSValueConst *func_obj, JSValueConst *this_obj,
int32_t argc, JSValueConst *argv) int32_t argc, JSValueConst *argv)
{ {
JS_ResetStackTop(JS_GetRuntime(ctx));
return new JSValue(JS_Call(ctx, *func_obj, *this_obj, argc, argv)); return new JSValue(JS_Call(ctx, *func_obj, *this_obj, argc, argv));
} }
@@ -285,6 +288,7 @@ extern "C"
DLLEXPORT int32_t jsExecutePendingJob(JSRuntime *rt) DLLEXPORT int32_t jsExecutePendingJob(JSRuntime *rt)
{ {
JS_ResetStackTop(rt);
JSContext *ctx; JSContext *ctx;
return JS_ExecutePendingJob(rt, &ctx); return JS_ExecutePendingJob(rt, &ctx);
} }

View File

@@ -82,7 +82,7 @@ packages:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "0.1.2" version: "0.1.3"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter

View File

@@ -3,7 +3,7 @@
* @Author: ekibun * @Author: ekibun
* @Date: 2020-09-19 10:29:04 * @Date: 2020-09-19 10:29:04
* @LastEditors: ekibun * @LastEditors: ekibun
* @LastEditTime: 2020-10-03 23:27:15 * @LastEditTime: 2020-10-06 23:13:13
*/ */
import 'dart:ffi'; import 'dart:ffi';
import 'dart:io'; import 'dart:io';
@@ -478,6 +478,7 @@ String jsToCString(
Pointer val, Pointer val,
) { ) {
var ptr = _jsToCString(ctx, val); var ptr = _jsToCString(ctx, val);
if (ptr.address == 0) throw Exception("JSValue cannot convert to string");
var str = Utf8.fromUtf8(ptr); var str = Utf8.fromUtf8(ptr);
jsFreeCString(ctx, ptr); jsFreeCString(ctx, ptr);
return str; return str;

View File

@@ -3,7 +3,7 @@
* @Author: ekibun * @Author: ekibun
* @Date: 2020-08-08 08:29:09 * @Date: 2020-08-08 08:29:09
* @LastEditors: ekibun * @LastEditors: ekibun
* @LastEditTime: 2020-10-03 21:55:07 * @LastEditTime: 2020-10-06 23:47:13
*/ */
import 'dart:async'; import 'dart:async';
import 'dart:ffi'; import 'dart:ffi';
@@ -121,6 +121,7 @@ class FlutterQjs {
var jsval = var jsval =
jsEval(_ctx, command, name ?? "<eval>", evalFlags ?? JSEvalType.GLOBAL); jsEval(_ctx, command, name ?? "<eval>", evalFlags ?? JSEvalType.GLOBAL);
if (jsIsException(jsval) != 0) { if (jsIsException(jsval) != 0) {
jsFreeValue(_ctx, jsval);
throw Exception(parseJSException(_ctx)); throw Exception(parseJSException(_ctx));
} }
var ret = runtimeOpaques[_rt]?.promsieToFuture(jsval); var ret = runtimeOpaques[_rt]?.promsieToFuture(jsval);

View File

@@ -1,6 +1,6 @@
name: flutter_qjs name: flutter_qjs
description: This plugin is a simple js engine for flutter using the `quickjs` project. Plugin currently supports all the platforms except web! description: This plugin is a simple js engine for flutter using the `quickjs` project. Plugin currently supports all the platforms except web!
version: 0.1.2 version: 0.1.3
homepage: https://github.com/ekibun/flutter_qjs homepage: https://github.com/ekibun/flutter_qjs
environment: environment:

View File

@@ -3,16 +3,16 @@
* @Author: ekibun * @Author: ekibun
* @Date: 2020-09-06 13:02:46 * @Date: 2020-09-06 13:02:46
* @LastEditors: ekibun * @LastEditors: ekibun
* @LastEditTime: 2020-10-03 21:36:06 * @LastEditTime: 2020-10-07 00:11:27
*/ */
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter_qjs/flutter_qjs.dart';
import 'package:flutter_qjs/isolate.dart'; import 'package:flutter_qjs/isolate.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
dynamic myMethodHandler(method, args) { dynamic myMethodHandler(method, args) {
print([method, args]);
return args; return args;
} }
@@ -57,7 +57,6 @@ void main() async {
test('jsToDart', () async { test('jsToDart', () async {
final qjs = IsolateQjs(myMethodHandler); final qjs = IsolateQjs(myMethodHandler);
qjs.setModuleHandler((name) async { qjs.setModuleHandler((name) async {
print(name);
return "export default '${new DateTime.now()}'"; return "export default '${new DateTime.now()}'";
}); });
var value = await qjs.evaluate(""" var value = await qjs.evaluate("""
@@ -68,8 +67,19 @@ void main() async {
0.1, true, false, 1, "world", module 0.1, true, false, 1, "world", module
])); ]));
""", name: "<eval>"); """, name: "<eval>");
print(value); expect(value[1]['a'], value[1], reason: "recursive object");
print(await value[0]('world')); expect(await value[0]('world'), 'hello world!', reason: "js function call");
qjs.close();
});
test('stack overflow', () async {
final qjs = FlutterQjs();
try {
await qjs.evaluate("a=()=>a();a();", name: "<eval>");
} catch (e) {
expect(
e.toString(), startsWith('Exception: InternalError: stack overflow'),
reason: "throw stack overflow");
}
qjs.close(); qjs.close();
}); });
} }