@@ -105,7 +105,7 @@ class Transaction {
105105 // Whether the function is an `async` function. We can't allow those because
106106 // the isolate could be transferred to another thread during execution.
107107 // Checking the return value seems like the only thing we can in Dart v2.12.
108- if (fn is Future Function ()) {
108+ if (fn is Future Function () && _nullSafetyEnabled ) {
109109 // This is a special case when the given function always throws. Triggered
110110 // in our test code. No need to even start a DB transaction in that case.
111111 if (fn is Never Function ()) {
@@ -124,7 +124,17 @@ class Transaction {
124124 // thus marking before the call allows us to return directly, before an
125125 // intermediary variable.
126126 if (tx._isWrite) tx.markSuccessful ();
127- return fn ();
127+ if (_nullSafetyEnabled) {
128+ return fn ();
129+ } else {
130+ final result = fn ();
131+ if (result is Future ) {
132+ // Let's make sure users change their code not to do use async.
133+ throw UnsupportedError (
134+ 'Executing an "async" function in a transaction is not allowed.' );
135+ }
136+ return result;
137+ }
128138 } catch (ex) {
129139 if (tx._isWrite) tx.markFailed ();
130140 rethrow ;
@@ -133,3 +143,8 @@ class Transaction {
133143 }
134144 }
135145}
146+
147+ /// True if the package enables null-safety (i.e. depends on SDK 2.12+).
148+ /// Otherwise, it's we can distinguish at runtime whether a function is async.
149+ final _nullSafetyEnabled = _nullReturningFn is ! Future Function ();
150+ final _nullReturningFn = () => null ;
0 commit comments