/* * Returns the identifier for the specified symbol defined in * the specified scope or in any scope above it. Returns null * if this symbol does not have a corresponding identifier. */ private static JavaScriptIdentifier GetIdentifier(string symbol, ScriptOrFunctionScope scope) { while (scope != null) { JavaScriptIdentifier identifier = scope.GetIdentifier(symbol); if (identifier != null) { return identifier; } scope = scope.ParentScope; } return null; }
private void ParseScope(ScriptOrFunctionScope scope) { string symbol; JavaScriptToken token; JavaScriptIdentifier identifier; int length = _tokens.Count; EnterScope(scope); while (_offset < length) { token = ConsumeToken(); switch (token.TokenType) { case Token.VAR: case Token.CONST: if (token.TokenType == Token.VAR) { if (_mode == BUILDING_SYMBOL_TREE && scope.VarCount++ > 1) { Warn("Try to use a single 'var' statement per scope.", true); } } // The var keyword is followed by at least one symbol name. // If several symbols follow, they are comma separated. //for (; ;) while (true) { token = ConsumeToken(); if (token.TokenType != Token.NAME) { throw new InvalidOperationException(); } if (_mode == BUILDING_SYMBOL_TREE) { symbol = token.Value; if (scope.GetIdentifier(symbol) == null) { scope.DeclareIdentifier(symbol); } else { Warn( "The variable " + symbol + " has already been declared in the same scope...", true); } } token = GetToken(0); if (token.TokenType != Token.SEMI && token.TokenType != Token.ASSIGN && token.TokenType != Token.COMMA && token.TokenType != Token.IN) { throw new InvalidOperationException(); } if (token.TokenType == Token.IN) { break; } ParseExpression(); token = GetToken(-1); if (token.TokenType == Token.SEMI) { break; } } break; case Token.FUNCTION: ParseFunctionDeclaration(); break; case Token.LC: _braceNesting++; break; case Token.RC: _braceNesting--; if (_braceNesting < scope.BraceNesting) { throw new InvalidOperationException(); } if (_braceNesting == scope.BraceNesting) { LeaveCurrentScope(); return; } break; case Token.WITH: if (_mode == BUILDING_SYMBOL_TREE) { // Inside a 'with' block, it is impossible to figure out // statically whether a symbol is a local variable or an // object member. As a consequence, the only thing we can // do is turn the obfuscation off for the highest scope // containing the 'with' block. ProtectScopeFromObfuscation(scope); Warn( "Using 'with' is not recommended." + (_munge ? " Moreover, using 'with' reduces the level of compression!" : ""), true); } break; case Token.CATCH: ParseCatch(); break; case Token.CONDCOMMENT: if (_mode == BUILDING_SYMBOL_TREE) { ProtectScopeFromObfuscation(scope); Warn( "Using JScript conditional comments is not recommended." + (_munge ? " Moreover, using JScript conditional comments reduces the level of compression." : ""), true); } break; case Token.NAME: symbol = token.Value; if (_mode == BUILDING_SYMBOL_TREE) { if (!_isEvalIgnored && symbol.Equals("eval", StringComparison.OrdinalIgnoreCase)) { ProtectScopeFromObfuscation(scope); Warn( "Using 'eval' is not recommended." + (_munge ? " Moreover, using 'eval' reduces the level of compression!" : ""), true); } } else if (_mode == CHECKING_SYMBOL_TREE) { if ((_offset < 2 || GetToken(-2).TokenType != Token.DOT) && GetToken(0).TokenType != Token.OBJECTLIT) { identifier = GetIdentifier(symbol, scope); if (identifier == null) { if (symbol.Length <= 3 && !_builtin.Contains(symbol)) { // Here, we found an undeclared and un-namespaced symbol that is // 3 characters or less in length. Declare it in the global scope. // We don't need to declare longer symbols since they won't cause // any conflict with other munged symbols. _globalScope.DeclareIdentifier(symbol); Warn("Found an undeclared symbol: " + symbol, true); } } else { identifier.RefCount++; } } } break; } } }