Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit 384039a

Browse files
committed
fix(introspection): work around http://dartbug.com/17752
1 parent f2d1f2e commit 384039a

File tree

1 file changed

+85
-24
lines changed

1 file changed

+85
-24
lines changed

lib/introspection.dart

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ List<Object> ngDirectives(nodeOrSelector) => ngProbe(nodeOrSelector).directives;
137137

138138

139139
js.JsObject _jsProbe(ElementProbe probe) {
140-
return new js.JsObject.jsify({
140+
return _jsify({
141141
"element": probe.element,
142142
"injector": _jsInjector(probe.injector),
143143
"scope": _jsScopeFromProbe(probe),
@@ -149,15 +149,84 @@ js.JsObject _jsProbe(ElementProbe probe) {
149149

150150

151151
js.JsObject _jsInjector(Injector injector) =>
152-
new js.JsObject.jsify({"get": injector.get})..['_dart_'] = injector;
152+
_jsify({"get": injector.get})..['_dart_'] = injector;
153153

154154

155155
js.JsObject _jsScopeFromProbe(ElementProbe probe) =>
156156
_jsScope(probe.scope, probe.injector.getByKey(SCOPE_STATS_CONFIG_KEY));
157157

158158

159+
160+
// Work around http://dartbug.com/17752
161+
// Proxies a Dart function that accepts up to 10 parameters.
162+
js.JsFunction _jsFunction(Function fn) {
163+
const Object X = __varargSentinel;
164+
Function fnCopy = fn; // workaround a bug.
165+
return new js.JsFunction.withThis(
166+
(thisArg, [o1=X, o2=X, o3=X, o4=X, o5=X, o6=X, o7=X, o8=X, o9=X, o10=X]) {
167+
// Work around a bug in dart 1.4.0 where the closurized variable, fn,
168+
// gets mysteriously replaced with our own closure function leading to a
169+
// stack overflow.
170+
fn = fnCopy;
171+
if (o10 == null && identical(o9, X)) {
172+
// Work around another bug in dart 1.4.0. This bug is not present in
173+
// dart 1.5.0-dev.2.0.
174+
// In dart 1.4.0, when running in Dartium (not dart2js), if you invoke
175+
// a JsFunction from Dart code (either by calling .apply([args]) on it
176+
// or by calling .callMethod(jsFuncName, [args]) on a JsObject
177+
// containing the JsFunction, regardless of whether you specified the
178+
// thisArg keyword parameter, the Dart function is called with the
179+
// first argument in the thisArg param causing all the arguments to be
180+
// shifted by one. We can detect this by the fact that o10 is null
181+
// but o9 is X (should only happen when o9 got a default value) and
182+
// work around it by using thisArg as the first parameter.
183+
return __invokeFn(fn, thisArg, o1, o2, o3, o4, o5, o6, o7, o8, o9);
184+
} else {
185+
return __invokeFn(fn, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10);
186+
}
187+
}
188+
);
189+
}
190+
191+
192+
const Object __varargSentinel = const Object();
193+
194+
195+
__invokeFn(fn, o1, o2, o3, o4, o5, o6, o7, o8, o9, o10) {
196+
var args = [o1, o2, o3, o4, o5, o6, o7, o8, o9, o10];
197+
while (args.length > 0 && identical(args.last, __varargSentinel)) {
198+
args.removeLast();
199+
}
200+
return _jsify(Function.apply(fn, args));
201+
}
202+
203+
204+
// Helper function to JSify a Dart object. While this is *required* to JSify
205+
// the result of a scope.eval(), other uses are not required and are used to
206+
// work around http://dartbug.com/17752 in a convenient way (that bug affects
207+
// dart2js in checked mode.)
208+
_jsify(var obj) {
209+
if (obj == null || obj is js.JsObject) {
210+
return obj;
211+
}
212+
if (obj is Function) {
213+
return _jsFunction(obj);
214+
}
215+
if ((obj is Map) || (obj is Iterable)) {
216+
var mappedObj = (obj is Map) ?
217+
new Map.fromIterables(obj.keys, obj.values.map(_jsify)) : obj.map(_jsify);
218+
if (obj is List) {
219+
return new js.JsArray.from(mappedObj);
220+
} else {
221+
return new js.JsObject.jsify(mappedObj);
222+
}
223+
}
224+
return obj;
225+
}
226+
227+
159228
js.JsObject _jsScope(Scope scope, ScopeStatsConfig config) {
160-
return new js.JsObject.jsify({
229+
return _jsify({
161230
"apply": scope.apply,
162231
"broadcast": scope.broadcast,
163232
"context": scope.context,
@@ -176,18 +245,6 @@ js.JsObject _jsScope(Scope scope, ScopeStatsConfig config) {
176245
}
177246

178247

179-
// Helper function to JSify the result of a scope.eval() for simple cases.
180-
_jsify(var obj) {
181-
if (obj is js.JsObject) {
182-
return obj;
183-
} else if (obj is Iterable) {
184-
return new js.JsObject.jsify(obj)..['_dart_'] = obj;
185-
} else {
186-
return obj;
187-
}
188-
}
189-
190-
191248
_jsDirective(directive) => directive;
192249

193250

@@ -261,7 +318,7 @@ class _Testability implements _JsObjectProxyable {
261318
}
262319

263320
js.JsObject _toJsObject() {
264-
return new js.JsObject.jsify({
321+
return _jsify({
265322
'allowAnimations': allowAnimations,
266323
'findBindings': (bindingString, [exactMatch]) =>
267324
findBindings(bindingString, exactMatch),
@@ -280,14 +337,18 @@ class _Testability implements _JsObjectProxyable {
280337

281338

282339
void publishToJavaScript() {
283-
var C = js.context;
284-
C['ngProbe'] = (nodeOrSelector) => _jsProbe(ngProbe(nodeOrSelector));
285-
C['ngInjector'] = (nodeOrSelector) => _jsInjector(ngInjector(nodeOrSelector));
286-
C['ngScope'] = (nodeOrSelector) => _jsScopeFromProbe(ngProbe(nodeOrSelector));
287-
C['ngQuery'] = (dom.Node node, String selector, [String containsText]) =>
288-
new js.JsArray.from(ngQuery(node, selector, containsText));
289-
C['angular'] = new js.JsObject.jsify({
340+
var D = {};
341+
D['ngProbe'] = (nodeOrSelector) => _jsProbe(ngProbe(nodeOrSelector));
342+
D['ngInjector'] = (nodeOrSelector) => _jsInjector(ngInjector(nodeOrSelector));
343+
D['ngScope'] = (nodeOrSelector) => _jsScopeFromProbe(ngProbe(nodeOrSelector));
344+
D['ngQuery'] = (dom.Node node, String selector, [String containsText]) =>
345+
ngQuery(node, selector, containsText);
346+
D['angular'] = {
290347
'resumeBootstrap': ([arg]) {},
291348
'getTestability': (node) => new _Testability.fromNode(node)._toJsObject(),
292-
});
349+
};
350+
js.JsObject J = _jsify(D);
351+
for (String key in D.keys) {
352+
js.context[key] = J[key];
353+
}
293354
}

0 commit comments

Comments
 (0)