blob: 0cc2968cb6f932e4d4a76131fa411285ab63dd9a [file] [log] [blame]
/**
* Copyright 2010 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.
*/
// Author: jmaessen@google.com (Jan Maessen)
#include "net/instaweb/rewriter/public/javascript_code_block.h"
#include "net/instaweb/util/public/message_handler.h"
#include "net/instaweb/util/public/statistics.h"
#include "net/instaweb/util/public/string_util.h"
#include "pagespeed/jsminify/js_minify.h"
namespace net_instaweb {
namespace {
// Statistics names
const char kJavascriptBlocksMinified[] = "javascript_blocks_minified";
const char kJavascriptBytesSaved[] = "javascript_bytes_saved";
const char kJavascriptMinificationFailures[] =
"javascript_minification_failures";
const char kJavascriptTotalBlocks[] = "javascript_total_blocks";
} // namespace
JavascriptRewriteConfig::JavascriptRewriteConfig(Statistics* stats)
: minify_(true),
redirect_(true),
blocks_minified_(NULL),
bytes_saved_(NULL),
minification_failures_(NULL),
total_blocks_(NULL) {
if (stats != NULL) {
blocks_minified_ = stats->GetVariable(kJavascriptBlocksMinified);
bytes_saved_ = stats->GetVariable(kJavascriptBytesSaved);
minification_failures_ =
stats->GetVariable(kJavascriptMinificationFailures);
total_blocks_ = stats->GetVariable(kJavascriptTotalBlocks);
}
}
void JavascriptRewriteConfig::Initialize(Statistics* statistics) {
statistics->AddVariable(kJavascriptBlocksMinified);
statistics->AddVariable(kJavascriptBytesSaved);
statistics->AddVariable(kJavascriptMinificationFailures);
statistics->AddVariable(kJavascriptTotalBlocks);
}
JavascriptCodeBlock::JavascriptCodeBlock(
const StringPiece& original_code, JavascriptRewriteConfig* config,
MessageHandler* handler)
: config_(config),
handler_(handler),
original_code_(original_code.data(), original_code.size()),
output_code_(original_code_),
rewritten_(false) { }
JavascriptCodeBlock::~JavascriptCodeBlock() { }
const JavascriptLibraryId JavascriptCodeBlock::ComputeJavascriptLibrary() {
// We always RewriteIfNecessary just to provide a degree of
// predictability to the rewrite flow.
RewriteIfNecessary();
if (!config_->redirect()) {
return JavascriptLibraryId();
}
return JavascriptLibraryId::Find(rewritten_code_);
}
void JavascriptCodeBlock::Rewrite() {
// Before attempting library identification, we minify. However, we only
// point output_code_ at the minified code if we actually want to serve it to
// the rest of the universe.
config_->AddBlock();
if ((config_->minify() || config_->redirect())) {
if (!pagespeed::jsminify::MinifyJs(original_code_, &rewritten_code_)) {
handler_->Message(kError, "Minification failed. Preserving old code.");
config_->AddMinificationFailure();
TrimWhitespace(original_code_, &rewritten_code_);
}
} else {
TrimWhitespace(original_code_, &rewritten_code_);
}
if (config_->minify()) {
output_code_ = rewritten_code_;
if (rewritten_code_.size() < original_code_.size()) {
size_t savings = original_code_.size() - rewritten_code_.size();
config_->AddBytesSaved(savings);
}
}
}
} // namespace net_instaweb