All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.dev.js.JsIEBlockSizeVisitor Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
/*
 * Copyright 2008 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.dev.js;

import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.js.ast.JsBlock;
import com.google.gwt.dev.js.ast.JsCase;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsDefault;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsVisitor;

import java.util.List;
import java.util.ListIterator;

/**
 * Some versions of IE7 have a limit on the number of statements that can appear
 * within a JsBlock. This visitor will restructure blocks and other block-like
 * structures with too many statements in order to reduce the total number of
 * statements that appear within any given block to fewer than
 * {@value #MAX_BLOCK_SIZE} statements by creating nested blocks:
 * 
 * 
 * {
 *   { statements }
 *   { statements }
 *   remainder of statements
 * }
 * 
* * This change is purely structural, it will not affect code flow. */ public class JsIEBlockSizeVisitor { /** * Visits every block-like structure. */ private static class BlockVisitor extends JsVisitor { private final JsProgram program; public BlockVisitor(JsProgram program) { this.program = program; } @Override public void endVisit(JsBlock x, JsContext ctx) { // JsFunctionClusterer handles restructuring top-level statement blocks if (!x.isGlobalBlock()) { restructure(x.getStatements()); } } @Override public void endVisit(JsCase x, JsContext ctx) { restructure(x.getStmts()); } @Override public void endVisit(JsDefault x, JsContext ctx) { restructure(x.getStmts()); } /** * Perform the restructuring on a list of statements. Blocks are created as * necessary to prevent any given block from exceeding the maximum size. */ private void restructure(List statements) { SourceInfo sourceInfo = program.createSourceInfoSynthetic(JsIEBlockSizeVisitor.class); // This outer loop will collapse the newly-created block into super-blocks while (statements.size() > MAX_BLOCK_SIZE) { ListIterator i = statements.listIterator(); List statementsInNewBlock = null; // This loop represents a single fold over the list of statements while (statements.size() > MAX_BLOCK_SIZE && i.hasNext()) { JsStatement current = i.next(); if (statementsInNewBlock == null) { // Replace the current statement with a new block JsBlock newBlock = new JsBlock(sourceInfo); statementsInNewBlock = newBlock.getStatements(); i.set(newBlock); } else { /* * There's an open replacement block, remove the statement from its * current block. */ i.remove(); } // Move the statement into the new block statementsInNewBlock.add(current); /* * If we hit the cap on a new block, discard the reference to create a * new block for the next statement that we see. */ if (statementsInNewBlock.size() == MAX_BLOCK_SIZE) { statementsInNewBlock = null; } } } assert statements.size() <= MAX_BLOCK_SIZE; } } // Use this value instead to test the effects of the visitor // private static final int MAX_BLOCK_SIZE = 1 << 5; private static final int MAX_BLOCK_SIZE = 1 << 15 - 1; /** * Entry point. */ public static void exec(JsProgram program) { (new BlockVisitor(program)).accept(program); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy