Skip to content

MiniJsParser fails to compile []= operator #25053

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
emilniklas opened this issue Nov 27, 2015 · 9 comments
Closed

MiniJsParser fails to compile []= operator #25053

emilniklas opened this issue Nov 27, 2015 · 9 comments
Assignees
Labels
closed-obsolete Closed as the reported issue is no longer relevant web-js-interop Issues that impact all js interop

Comments

@emilniklas
Copy link

I'm on Dart VM version: 1.13.0 on "macos_x64"

Internal Error: The compiler crashed when compiling this element.
  external operator []=(String key, T value);
                    ^^^
The compiler is broken.

When compiling the above element, the compiler crashed. It is not
possible to tell if this is caused by a problem in your program or
not. Regardless, the compiler should not crash.

The Dart team would greatly appreciate if you would take a moment to
report this problem at http://dartbug.com/new.

Please include the following information:

* the name and version of your operating system,

* the Dart SDK build number (1.13.0), and

* the entire message you see here (including the full stack trace
  below as well as the source location above).

The compiler crashed: Error in MiniJsParser:
this.[]=
     ^
     Expected ALPHA

#0      MiniJsParser.error (package:js_ast/src/builder.dart:748)
#1      MiniJsParser.expectCategory (package:js_ast/src/builder.dart:711)
#2      MiniJsParser.getDotRhs (package:js_ast/src/builder.dart:971)
#3      MiniJsParser.parseMember (package:js_ast/src/builder.dart:911)
#4      MiniJsParser.parseCall (package:js_ast/src/builder.dart:925)
#5      MiniJsParser.parsePostfix (package:js_ast/src/builder.dart:977)
#6      MiniJsParser.parseUnaryHigh (package:js_ast/src/builder.dart:999)
#7      MiniJsParser.parseUnaryLow (package:js_ast/src/builder.dart:1010)
#8      MiniJsParser.parseBinary (package:js_ast/src/builder.dart:1014)
#9      MiniJsParser.parseConditional (package:js_ast/src/builder.dart:1041)
#10     MiniJsParser.parseAssignment (package:js_ast/src/builder.dart:1051)
#11     MiniJsParser.parseExpression (package:js_ast/src/builder.dart:1068)
#12     MiniJsParser.parseVarDeclarationOrExpression (package:js_ast/src/builder.dart:1105)
#13     MiniJsParser.expression (package:js_ast/src/builder.dart:1110)
#14     JsBuilder._findExpressionTemplate (package:js_ast/src/builder.dart:243)
#15     JsBuilder.parseForeignJS (package:js_ast/src/builder.dart:235)
#16     SsaBuilder.invokeJsInteropFunction (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/ssa/builder.dart:5895)
#17     SsaBuilder.buildMethod (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/ssa/builder.dart:1655)
#18     SsaBuilder.build (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/ssa/builder.dart:1158)
#19     SsaBuilderTask.build.<anonymous closure>.<anonymous closure> (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/ssa/builder.dart:74)
#20     _CompilerDiagnosticReporter.withCurrentElement (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/compiler.dart:1689)
#21     SsaBuilderTask.build.<anonymous closure> (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/ssa/builder.dart:68)
#22     CompilerTask.measure (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/common/tasks.dart:55)
#23     SsaBuilderTask.build (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/ssa/builder.dart:66)
#24     SsaFunctionCompiler.compile (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/ssa/builder.dart:23)
#25     JavaScriptBackend.codegen (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/js_backend/backend.dart:1594)
#26     Compiler.codegen (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/compiler.dart:1221)
#27     CodegenWorkItem.run (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/common/codegen.dart:197)
#28     Compiler.emptyQueue.<anonymous closure>.<anonymous closure> (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/compiler.dart:1100)
#29     _CompilerDiagnosticReporter.withCurrentElement (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/compiler.dart:1689)
#30     Compiler.emptyQueue.<anonymous closure> (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/compiler.dart:1099)
#31     QueueFilter.processWorkItem (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/enqueue.dart:1072)
#32     Enqueuer.forEach (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/enqueue.dart:769)
#33     Compiler.emptyQueue (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/compiler.dart:1098)
#34     Compiler.processQueue (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/compiler.dart:1126)
#35     Compiler.compileLoadedLibraries (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/compiler.dart:1049)
#36     Compiler.runCompiler.<anonymous closure> (file:///b/build/slave/dart-sdk-mac-stable/build/sdk/pkg/compiler/lib/src/compiler.dart:869)
#37     _RootZone.runUnary (dart:async/zone.dart:1149)
#38     _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:502)
#39     _Future._propagateToListeners (dart:async/future_impl.dart:585)
#40     _Future._completeWithValue (dart:async/future_impl.dart:376)
#41     _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:430)
#42     _microtaskLoop (dart:async/schedule_microtask.dart:43)
#43     _microtaskLoopEntry (dart:async/schedule_microtask.dart:52)
#44     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:96)
#45     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)

@emilniklas
Copy link
Author

I needed to have an anonymous JS class that worked like a map (dynamic keys), and this was my solution:

@JS()
@anonymous
class JsObject<T> {
  external factory JsObject();

  external operator []=(String key, T value);

  external operator [](String key);
}

It works in Dartium, but the above stack trace is thrown when Dart2JS tries to compile the JsObject class.

@sigmundch sigmundch added the web-js-interop Issues that impact all js interop label Nov 30, 2015
@jacob314
Copy link
Member

You are currently not allowed to specify operators for typed JS interop classes. We need to display an error message when this case is detected.
Generally speaking, we could support this case but it would have negative code size and performance implicaitons in dart2js based on an experiment @rakudrama did.

@emilniklas
Copy link
Author

The requirement this was meant to fulfil was that a JS api takes a JS Object with keys that are not fixed. The only other way I found to make it work was to use JsObject from dart:js, but I was under the impression that combining dart:js and package:js was a bad practice.

Is there another way?

@a14n
Copy link
Contributor

a14n commented Dec 11, 2015

You can use Object.defineProperty:

import 'package:js/js.dart';

@JS()
@anonymous
class Description {
  external factory Description({bool configurable, bool enumerable, value});
}

@JS('Object.defineProperty')
external void defineProperty(o, String prop, Description description);

void setValue(o, String key, value) =>
    defineProperty(o, 'key', new Description(value: value));

@JS()
@anonymous
class A {}

void main() {
  final a = new A();
  setValue(a, 'key1', 1);
  setValue(a, 'key2', true);
}

@emilniklas
Copy link
Author

Thanks @a14n!

@kasperpeulen
Copy link

@a14n It doesn't work for me. For example the following code:

import 'dart:html';
import 'package:js/js.dart';

void main() {
  A a = new A();
  setValue(a, 'key1', 1);
  setValue(a, 'key2', true);
  a['key3'] = 1;
  a['key4'] = true;
  print(stringify(a));
}

@JS()
@anonymous
class Description {
  external factory Description({bool configurable, bool enumerable, value});
}

@JS('Object.defineProperty')
external void defineProperty(o, String prop, Description description);

setValue(o, String key, value) =>
    defineProperty(o, key, new Description(value: value));

@JS()
@anonymous
class A {
  external factory A();

  external void operator []=(String key, value);
}

@JS('JSON.stringify')
external String stringify(Object json);

prints:

{"key3":1,"key4":true}

@jacob314 Is there any other way to do something like that, I'm now unable to js interop this case:

MathJax.Hub.Config({
  "HTML-CSS": {
    preferredFont: "TeX",
    availableFonts: ['TeX']
  }
});

@a14n
Copy link
Contributor

a14n commented Dec 22, 2015

Object.defineProperty uses enumerable: false by default. That's why JSON.stringify does not display them.
You can change setValue to make the default to true:

setValue(o, String key, value, {bool enumerable: true}) =>
    defineProperty(o, key, new Description(value: value, enumerable: enumerable));

@kasperpeulen
Copy link

@a14n thanks, this works for me

@PaulAnnekov
Copy link

So instead of something like this, plain and readable (JS example):

L.control.layers({'layer1': L.tileLayer('...'), 'layer2': L.tileLayer('...')})

I need to use some ugly workarounds with defineProperty? Very bad news...

@jacob314 jacob314 mentioned this issue Jul 8, 2016
19 tasks
@matanlurey matanlurey added the closed-obsolete Closed as the reported issue is no longer relevant label Feb 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-obsolete Closed as the reported issue is no longer relevant web-js-interop Issues that impact all js interop
Projects
None yet
Development

No branches or pull requests

7 participants