Remove asserts that do not hold when lazily compiling extension code.

Add checks for the use of eval and with in natives files to the js2c
script.

Review URL: http://codereview.chromium.org/175009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2786 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ager@chromium.org 2009-08-31 15:02:54 +00:00
parent 9230ad29eb
commit 3fe0bc0436
4 changed files with 74 additions and 33 deletions

View File

@ -1143,7 +1143,7 @@ function DebugResponseDetails(response) {
* @constructor
*/
function ProtocolPackage(json) {
this.packet_ = eval('(' + json + ')');
this.packet_ = JSON.parse(json);
this.refs_ = [];
if (this.packet_.refs) {
for (var i = 0; i < this.packet_.refs.length; i++) {

View File

@ -2397,12 +2397,6 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
// WithStatement ::
// 'with' '(' Expression ')' Statement
// We do not allow the use of 'with' statements in the internal JS
// code. If 'with' statements were allowed, the simplified setup of
// the runtime context chain would allow access to properties in the
// global object from within a 'with' statement.
ASSERT(extension_ != NULL || !Bootstrapper::IsActive());
Expect(Token::WITH, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
Expression* expr = ParseExpression(true, CHECK_OK);
@ -3088,9 +3082,6 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
Handle<String> name = callee->name();
Variable* var = top_scope_->Lookup(name);
if (var == NULL) {
// We do not allow direct calls to 'eval' in our internal
// JS files. Use builtin functions instead.
ASSERT(extension_ != NULL || !Bootstrapper::IsActive());
top_scope_->RecordEvalCall();
is_potentially_direct_eval = true;
}

View File

@ -2673,40 +2673,67 @@ THREADED_TEST(SimpleExtensions) {
}
static const char* kEvalExtensionSource =
"function UseEval() {"
static const char* kEvalExtensionSource1 =
"function UseEval1() {"
" var x = 42;"
" return eval('x');"
"}";
static const char* kEvalExtensionSource2 =
"(function() {"
" var x = 42;"
" function e() {"
" return eval('x');"
" }"
" this.UseEval2 = e;"
"})()";
THREADED_TEST(UseEvalFromExtension) {
v8::HandleScope handle_scope;
v8::RegisterExtension(new Extension("evaltest", kEvalExtensionSource));
const char* extension_names[] = { "evaltest" };
v8::ExtensionConfiguration extensions(1, extension_names);
v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
const char* extension_names[] = { "evaltest1", "evaltest2" };
v8::ExtensionConfiguration extensions(2, extension_names);
v8::Handle<Context> context = Context::New(&extensions);
Context::Scope lock(context);
v8::Handle<Value> result = Script::Compile(v8_str("UseEval()"))->Run();
v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
CHECK_EQ(result, v8::Integer::New(42));
result = Script::Compile(v8_str("UseEval2()"))->Run();
CHECK_EQ(result, v8::Integer::New(42));
}
static const char* kWithExtensionSource =
"function UseWith() {"
static const char* kWithExtensionSource1 =
"function UseWith1() {"
" var x = 42;"
" with({x:87}) { return x; }"
"}";
static const char* kWithExtensionSource2 =
"(function() {"
" var x = 42;"
" function e() {"
" with ({x:87}) { return x; }"
" }"
" this.UseWith2 = e;"
"})()";
THREADED_TEST(UseWithFromExtension) {
v8::HandleScope handle_scope;
v8::RegisterExtension(new Extension("withtest", kWithExtensionSource));
const char* extension_names[] = { "withtest" };
v8::ExtensionConfiguration extensions(1, extension_names);
v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
const char* extension_names[] = { "withtest1", "withtest2" };
v8::ExtensionConfiguration extensions(2, extension_names);
v8::Handle<Context> context = Context::New(&extensions);
Context::Scope lock(context);
v8::Handle<Value> result = Script::Compile(v8_str("UseWith()"))->Run();
v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
CHECK_EQ(result, v8::Integer::New(87));
result = Script::Compile(v8_str("UseWith2()"))->Run();
CHECK_EQ(result, v8::Integer::New(87));
}

View File

@ -45,6 +45,13 @@ def ToCArray(lines):
return ", ".join(result)
def RemoveCommentsAndTrailingWhitespace(lines):
lines = re.sub(r'//.*\n', '\n', lines) # end-of-line comments
lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments.
lines = re.sub(r'\s+\n+', '\n', lines) # trailing whitespace
return lines
def CompressScript(lines, do_jsmin):
# If we're not expecting this code to be user visible, we can run it through
# a more aggressive minifier.
@ -55,9 +62,7 @@ def CompressScript(lines, do_jsmin):
# people print the source code using Function.prototype.toString().
# Note that we could easily compress the scripts mode but don't
# since we want it to remain readable.
lines = re.sub('//.*\n', '\n', lines) # end-of-line comments
lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments.
lines = re.sub('\s+\n+', '\n', lines) # trailing whitespace
lines = RemoveCommentsAndTrailingWhitespace(lines)
return lines
@ -96,6 +101,22 @@ def ParseValue(string):
return string
EVAL_PATTERN = re.compile(r'\beval\s*\(');
WITH_PATTERN = re.compile(r'\bwith\s*\(');
def Validate(lines, file):
lines = RemoveCommentsAndTrailingWhitespace(lines)
# Because of simplified context setup, eval and with is not
# allowed in the natives files.
eval_match = EVAL_PATTERN.search(lines)
if eval_match:
raise ("Eval disallowed in natives: %s" % file)
with_match = WITH_PATTERN.search(lines)
if with_match:
raise ("With statements disallowed in natives: %s" % file)
def ExpandConstants(lines, constants):
for key, value in constants.items():
lines = lines.replace(key, str(value))
@ -155,9 +176,9 @@ class PythonMacro:
args.append(mapping[arg])
return str(self.fun(*args))
CONST_PATTERN = re.compile('^const\s+([a-zA-Z0-9_]+)\s*=\s*([^;]*);$')
MACRO_PATTERN = re.compile('^macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
PYTHON_MACRO_PATTERN = re.compile('^python\s+macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
CONST_PATTERN = re.compile(r'^const\s+([a-zA-Z0-9_]+)\s*=\s*([^;]*);$')
MACRO_PATTERN = re.compile(r'^macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
PYTHON_MACRO_PATTERN = re.compile(r'^python\s+macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
def ReadMacros(lines):
constants = { }
@ -275,15 +296,17 @@ def JS2C(source, target, env):
# Build source code lines
source_lines = [ ]
source_lines_empty = []
for s in modules:
delay = str(s).endswith('-delay.js')
lines = ReadFile(str(s))
for module in modules:
filename = str(module)
delay = filename.endswith('-delay.js')
lines = ReadFile(filename)
do_jsmin = lines.find('// jsminify this file, js2c: jsmin') != -1
lines = ExpandConstants(lines, consts)
lines = ExpandMacros(lines, macros)
Validate(lines, filename)
lines = CompressScript(lines, do_jsmin)
data = ToCArray(lines)
id = (os.path.split(str(s))[1])[:-3]
id = (os.path.split(filename)[1])[:-3]
if delay: id = id[:-6]
if delay:
delay_ids.append((id, len(lines)))