blob: 6051934906fde51bcf5a2af59e97dad0d02cb921 [file] [log] [blame]
/*
* 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;
}
}