| // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| part of dart2js.js_emitter; |
| |
| class MainCallStubGenerator { |
| final Compiler compiler; |
| final JavaScriptBackend backend; |
| final CodeEmitterTask emitterTask; |
| |
| MainCallStubGenerator(this.compiler, this.backend, this.emitterTask); |
| |
| BackendHelpers get helpers => backend.helpers; |
| |
| /// Returns the code equivalent to: |
| /// `function(args) { $.startRootIsolate(X.main$closure(), args); }` |
| jsAst.Expression _buildIsolateSetupClosure( |
| Element appMain, Element isolateMain) { |
| jsAst.Expression mainAccess = |
| emitterTask.isolateStaticClosureAccess(appMain); |
| // Since we pass the closurized version of the main method to |
| // the isolate method, we must make sure that it exists. |
| return js('function(a){ #(#, a); }', |
| [emitterTask.staticFunctionAccess(isolateMain), mainAccess]); |
| } |
| |
| jsAst.Statement generateInvokeMain() { |
| Element main = compiler.mainFunction; |
| jsAst.Expression mainCallClosure = null; |
| if (compiler.hasIsolateSupport) { |
| Element isolateMain = |
| helpers.isolateHelperLibrary.find(BackendHelpers.START_ROOT_ISOLATE); |
| mainCallClosure = _buildIsolateSetupClosure(main, isolateMain); |
| } else if (compiler.options.hasIncrementalSupport) { |
| mainCallClosure = js( |
| 'function() { return #(); }', emitterTask.staticFunctionAccess(main)); |
| } else { |
| mainCallClosure = emitterTask.staticFunctionAccess(main); |
| } |
| |
| jsAst.Expression currentScriptAccess = |
| emitterTask.generateEmbeddedGlobalAccess(embeddedNames.CURRENT_SCRIPT); |
| |
| // This code finds the currently executing script by listening to the |
| // onload event of all script tags and getting the first script which |
| // finishes. Since onload is called immediately after execution this should |
| // not substantially change execution order. |
| return js.statement( |
| ''' |
| (function (callback) { |
| if (typeof document === "undefined") { |
| callback(null); |
| return; |
| } |
| // When running as a content-script of a chrome-extension the |
| // 'currentScript' is `null` (but not undefined). |
| if (typeof document.currentScript != 'undefined') { |
| callback(document.currentScript); |
| return; |
| } |
| |
| var scripts = document.scripts; |
| function onLoad(event) { |
| for (var i = 0; i < scripts.length; ++i) { |
| scripts[i].removeEventListener("load", onLoad, false); |
| } |
| callback(event.target); |
| } |
| for (var i = 0; i < scripts.length; ++i) { |
| scripts[i].addEventListener("load", onLoad, false); |
| } |
| })(function(currentScript) { |
| #currentScript = currentScript; |
| |
| if (typeof dartMainRunner === "function") { |
| dartMainRunner(#mainCallClosure, []); |
| } else { |
| #mainCallClosure([]); |
| } |
| })''', |
| { |
| 'currentScript': currentScriptAccess, |
| 'mainCallClosure': mainCallClosure |
| }); |
| } |
| } |