Is Dart mirror behavior to not allow invocation of private methods from other libraries guaranteed and part of the spec?

Issue

if I have 2 files:

bin.dart:

import 'lib.dart';
import 'dart:mirrors';

/*
class Foo{
  bool _bar() => true;
}
*/

void main() {
  var foo = new Foo();
  print(reflect(foo).invoke(#_bar, []));
}

lib.dart:

library lib;

class Foo{
  bool _bar() => true;
}

If I run bin.dart I get what I hope to happen, an exception when trying to invoke a private method. but if I comment out the import 'lib.dart' line and uncomment the local Foo definition this timeit runs without exception, which I suppose is ok because now the private mthod is being invoked from the declaring library. So my question is, is the behavior guaranteed? I need to make sure that a point of invocation via mirrors in my library will not allow the invocation of private members from other libraries, presently I explicitly check this by doing a check for a names starting with _:

if(MirrorSystem.getName(inv.method).startsWith('_')){
  throw new RestrictedMethodError(inv.method);
}else{
  _this.invoke(inv.method, inv.posArgs, inv.namArgs);
}

however if the privacy is still respected even by mirrors by default then I can get rid of this check and remove the import for dart:mirrors in my library, thanks.

UPDATE

What if the symbol inv.method was guaranteed to always be derived from:

inv.method = MirrorSystem.getSymbol(stringName);

would this then prevent the private method from being called as in the file dart:mirrors-patch_mirrors_patch.dart line 92:

  static Symbol getSymbol(String name,[LibraryMirror library]) {
    if((library != null && library is !_LocalLibraryMirror) ||
       ((name.length > 0) && (name[0] == "_") && (library == null))) {
      throw new ArgumentError(library);
    }
    if (library != null) name = _mangleName(name, library._reflectee);
    return new _symbol_dev.Symbol.unvalidated(name);
  }

will do the test to check it doesn’t start with underscore, so will prevent any "private symbols" from being generated if you can guarantee that all the symbols are being generated in this fashion?

Solution

Reflection allows you to overcome all privacy mechanisms. So no, you can not rely on it. Think of “_foo” as “foo” prefixed by a library-token that users cannot generate. As such, #_bar in the main-library is different from #_bar in the lib library. However, you could just enumerate all identifiers of the given foo object and find the private function.

If you need real privacy you need to use isolates.

Answered By – Florian Loitsch

Answer Checked By – Clifford M. (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *