| /* |
| * Copyright 2012 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.core.client.impl; |
| |
| import com.google.gwt.core.client.GWT; |
| import com.google.gwt.core.client.GwtScriptOnly; |
| import com.google.gwt.core.client.JavaScriptObject; |
| |
| import java.util.HashMap; |
| import java.util.LinkedHashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * Rebound version switches on unload support. |
| */ |
| @GwtScriptOnly |
| public class UnloadSupportEnabled extends UnloadSupport { |
| |
| static class TimerDisposable implements Disposable { |
| |
| int timerId; |
| private Map<Integer, Disposable> timeoutMap; |
| private boolean timeout; |
| |
| public TimerDisposable(Map<Integer, Disposable> timeoutMap, boolean isTimeout) { |
| this.timeoutMap = timeoutMap; |
| timeout = isTimeout; |
| } |
| |
| @Override |
| public void dispose() { |
| timeoutMap.remove(timerId); |
| if (timeout) { |
| clearTimeout0(timerId); |
| } else { |
| clearInterval0(timerId); |
| } |
| } |
| } |
| |
| private Map<Integer, Disposable> timeouts = new HashMap<Integer, Disposable>(); |
| private Map<Integer, Disposable> intervals = new HashMap<Integer, Disposable>(); |
| private Set<Disposable> disposables = new LinkedHashSet<Disposable>(); |
| |
| public native void exportUnloadModule() /*-{ |
| if (!$wnd.__gwt_activeModules) { |
| $wnd.__gwt_activeModules = {}; |
| } |
| var $moduleName = __gwtModuleFunction.__moduleName; |
| // unfortunately GWT.getModuleName() isn't set up yet when this is called |
| var activeModule = $wnd.__gwt_activeModules[$moduleName]; |
| if (!activeModule) { |
| activeModule = {}; |
| $wnd.__gwt_activeModules[$moduleName] = activeModule; |
| } |
| activeModule.unloadModule = function () { |
| @com.google.gwt.core.client.GWT::unloadModule()(); |
| |
| delete $wnd.__gwt_activeModules[$moduleName]; |
| var modFunc = $moduleName.replace(/\./g, '_'); |
| $wnd[modFunc] = null; |
| setTimeout(function () { |
| // Browsers without Object.keys don't benefit from nulling window |
| var keys = Object.keys ? Object.keys(window) : []; |
| // Browsers without window.frameElement don't benefit from removing the iframe |
| var frame = window.frameElement; |
| var i; |
| // null out seedTable and class entries |
| for (key in @com.google.gwt.lang.SeedUtil::seedTable) { |
| var obj = @com.google.gwt.lang.SeedUtil::seedTable[key]; |
| obj.prototype.@java.lang.Object::___clazz = null; |
| } |
| @com.google.gwt.lang.SeedUtil::seedTable = null; |
| // String is special cased |
| String.prototype.@java.lang.Object::___clazz = null; |
| for (i = 0; i < keys.length; i++) { |
| try { |
| window[keys[i]] = null; |
| } catch (e) { |
| } |
| } |
| if ($wnd != window && frame) { |
| frame.parentNode.removeChild(frame); |
| } |
| }, 1); |
| }; |
| }-*/; |
| |
| public boolean isUnloadSupported() { |
| return true; |
| } |
| |
| public int setInterval(JavaScriptObject func, int time) { |
| if (!Impl.isModuleUnloaded()) { |
| TimerDisposable disposable = new TimerDisposable(intervals, false); |
| final int timerId = setInterval0(func, time); |
| intervals.put(timerId, disposable); |
| disposable.timerId = timerId; |
| scheduleDispose(disposable); |
| return timerId; |
| } |
| return -1; |
| } |
| |
| void clearInterval(int timerId) { |
| if (timerId != -1) { |
| dispose(intervals.get(timerId)); |
| } |
| } |
| |
| void clearTimeout(int timerId) { |
| if (timerId != -1) { |
| dispose(timeouts.get(timerId)); |
| } |
| } |
| |
| void dispose(Disposable d) { |
| if (d != null) { |
| try { |
| d.dispose(); |
| } catch (Throwable e) { |
| GWT.reportUncaughtException(e); |
| } |
| disposables.remove(d); |
| } |
| } |
| |
| void disposeAll() { |
| LinkedHashSet<Disposable> copy = new LinkedHashSet<Disposable>(disposables); |
| for (Disposable d : copy) { |
| dispose(d); |
| } |
| } |
| |
| void scheduleDispose(Disposable d) { |
| disposables.add(d); |
| } |
| |
| int setTimeout(JavaScriptObject func, int time) { |
| if (!Impl.isModuleUnloaded()) { |
| TimerDisposable disposable = new TimerDisposable(timeouts, true); |
| final int timerId = UnloadSupport.setTimeout0(func, time, disposable); |
| timeouts.put(timerId, disposable); |
| disposable.timerId = timerId; |
| scheduleDispose(disposable); |
| return timerId; |
| } |
| return -1; |
| } |
| } |