Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: test/cctest/test-api.cc

Issue 566553002: Add script streaming API. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebased Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/scanner-character-streams.cc ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 23035 matching lines...) Expand 10 before | Expand all | Expand 10 after
23046 IndexedAccessCounter); 23046 IndexedAccessCounter);
23047 23047
23048 v8::Handle<Context> context = Context::New(isolate); 23048 v8::Handle<Context> context = Context::New(isolate);
23049 v8::Context::Scope context_scope(context); 23049 v8::Context::Scope context_scope(context);
23050 23050
23051 context->Global()->Set(v8_str("o"), object_template->NewInstance()); 23051 context->Global()->Set(v8_str("o"), object_template->NewInstance());
23052 CompileRun( 23052 CompileRun(
23053 "Object.defineProperty(o, 'key', " 23053 "Object.defineProperty(o, 'key', "
23054 " { get: function() {}, set: function() {} });"); 23054 " { get: function() {}, set: function() {} });");
23055 } 23055 }
23056
23057 class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
23058 public:
23059 explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
23060
23061 virtual size_t GetMoreData(const uint8_t** src) {
23062 // Unlike in real use cases, this function will never block.
23063 if (chunks_[index_] == NULL) {
23064 return 0;
23065 }
23066 // Copy the data, since the caller takes ownership of it.
23067 size_t len = strlen(chunks_[index_]);
23068 // We don't need to zero-terminate since we return the length.
23069 uint8_t* copy = new uint8_t[len];
23070 memcpy(copy, chunks_[index_], len);
23071 *src = copy;
23072 ++index_;
23073 return len;
23074 }
23075
23076 // Helper for constructing a string from chunks (the compilation needs it
23077 // too).
23078 static char* FullSourceString(const char** chunks) {
23079 size_t total_len = 0;
23080 for (size_t i = 0; chunks[i] != NULL; ++i) {
23081 total_len += strlen(chunks[i]);
23082 }
23083 char* full_string = new char[total_len + 1];
23084 size_t offset = 0;
23085 for (size_t i = 0; chunks[i] != NULL; ++i) {
23086 size_t len = strlen(chunks[i]);
23087 memcpy(full_string + offset, chunks[i], len);
23088 offset += len;
23089 }
23090 full_string[total_len] = 0;
23091 return full_string;
23092 }
23093
23094 private:
23095 const char** chunks_;
23096 unsigned index_;
23097 };
23098
23099
23100 // Helper function for running streaming tests.
23101 void RunStreamingTest(const char** chunks,
23102 v8::ScriptCompiler::StreamedSource::Encoding encoding =
23103 v8::ScriptCompiler::StreamedSource::ONE_BYTE,
23104 bool expected_success = true) {
23105 LocalContext env;
23106 v8::Isolate* isolate = env->GetIsolate();
23107 v8::HandleScope scope(isolate);
23108 v8::TryCatch try_catch;
23109
23110 v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
23111 encoding);
23112 v8::ScriptCompiler::ScriptStreamingTask* task =
23113 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23114
23115 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23116 // task here in the main thread.
23117 task->Run();
23118 delete task;
23119
23120 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23121 char* full_source = TestSourceStream::FullSourceString(chunks);
23122
23123 // The possible errors are only produced while compiling.
23124 CHECK_EQ(false, try_catch.HasCaught());
23125
23126 v8::Handle<Script> script = v8::ScriptCompiler::Compile(
23127 isolate, &source, v8_str(full_source), origin);
23128 if (expected_success) {
23129 CHECK(!script.IsEmpty());
23130 v8::Handle<Value> result(script->Run());
23131 // All scripts are supposed to return the fixed value 13 when ran.
23132 CHECK_EQ(13, result->Int32Value());
23133 } else {
23134 CHECK(script.IsEmpty());
23135 CHECK(try_catch.HasCaught());
23136 }
23137 delete[] full_source;
23138 }
23139
23140
23141 TEST(StreamingSimpleScript) {
23142 // This script is unrealistically small, since no one chunk is enough to fill
23143 // the backing buffer of Scanner, let alone overflow it.
23144 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23145 NULL};
23146 RunStreamingTest(chunks);
23147 }
23148
23149
23150 TEST(StreamingBiggerScript) {
23151 const char* chunk1 =
23152 "function foo() {\n"
23153 " // Make this chunk sufficiently long so that it will overflow the\n"
23154 " // backing buffer of the Scanner.\n"
23155 " var i = 0;\n"
23156 " var result = 0;\n"
23157 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23158 " result = 0;\n"
23159 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23160 " result = 0;\n"
23161 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23162 " result = 0;\n"
23163 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23164 " return result;\n"
23165 "}\n";
23166 const char* chunks[] = {chunk1, "foo(); ", NULL};
23167 RunStreamingTest(chunks);
23168 }
23169
23170
23171 TEST(StreamingScriptWithParseError) {
23172 // Test that parse errors from streamed scripts are propagated correctly.
23173 {
23174 char chunk1[] =
23175 " // This will result in a parse error.\n"
23176 " var if else then foo";
23177 char chunk2[] = " 13\n";
23178 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23179
23180 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
23181 false);
23182 }
23183 // Test that the next script succeeds normally.
23184 {
23185 char chunk1[] =
23186 " // This will be parsed successfully.\n"
23187 " function foo() { return ";
23188 char chunk2[] = " 13; }\n";
23189 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23190
23191 RunStreamingTest(chunks);
23192 }
23193 }
23194
23195
23196 TEST(StreamingUtf8Script) {
23197 // We'd want to write \uc481 instead of \xeb\x91\x80, but Windows compilers
23198 // don't like it.
23199 const char* chunk1 =
23200 "function foo() {\n"
23201 " // This function will contain an UTF-8 character which is not in\n"
23202 " // ASCII.\n"
23203 " var foob\xeb\x91\x80r = 13;\n"
23204 " return foob\xeb\x91\x80r;\n"
23205 "}\n";
23206 const char* chunks[] = {chunk1, "foo(); ", NULL};
23207 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23208 }
23209
23210
23211 TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
23212 // A sanity check to prove that the approach of splitting UTF-8
23213 // characters is correct. Here is an UTF-8 character which will take three
23214 // bytes.
23215 const char* reference = "\xeb\x91\x80";
23216 CHECK(3u == strlen(reference)); // NOLINT - no CHECK_EQ for unsigned.
23217
23218 char chunk1[] =
23219 "function foo() {\n"
23220 " // This function will contain an UTF-8 character which is not in\n"
23221 " // ASCII.\n"
23222 " var foob";
23223 char chunk2[] =
23224 "XXXr = 13;\n"
23225 " return foob\xeb\x91\x80r;\n"
23226 "}\n";
23227 for (int i = 0; i < 3; ++i) {
23228 chunk2[i] = reference[i];
23229 }
23230 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23231 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23232 }
23233
23234
23235 TEST(StreamingUtf8ScriptWithSplitCharacters) {
23236 // Stream data where a multi-byte UTF-8 character is split between two data
23237 // chunks.
23238 const char* reference = "\xeb\x91\x80";
23239 char chunk1[] =
23240 "function foo() {\n"
23241 " // This function will contain an UTF-8 character which is not in\n"
23242 " // ASCII.\n"
23243 " var foobX";
23244 char chunk2[] =
23245 "XXr = 13;\n"
23246 " return foob\xeb\x91\x80r;\n"
23247 "}\n";
23248 chunk1[strlen(chunk1) - 1] = reference[0];
23249 chunk2[0] = reference[1];
23250 chunk2[1] = reference[2];
23251 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23252 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23253 }
23254
23255
23256 TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
23257 // Tests edge cases which should still be decoded correctly.
23258
23259 // Case 1: a chunk contains only bytes for a split character (and no other
23260 // data). This kind of a chunk would be exceptionally small, but we should
23261 // still decode it correctly.
23262 const char* reference = "\xeb\x91\x80";
23263 // The small chunk is at the beginning of the split character
23264 {
23265 char chunk1[] =
23266 "function foo() {\n"
23267 " // This function will contain an UTF-8 character which is not in\n"
23268 " // ASCII.\n"
23269 " var foob";
23270 char chunk2[] = "XX";
23271 char chunk3[] =
23272 "Xr = 13;\n"
23273 " return foob\xeb\x91\x80r;\n"
23274 "}\n";
23275 chunk2[0] = reference[0];
23276 chunk2[1] = reference[1];
23277 chunk3[0] = reference[2];
23278 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23279 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23280 }
23281 // The small chunk is at the end of a character
23282 {
23283 char chunk1[] =
23284 "function foo() {\n"
23285 " // This function will contain an UTF-8 character which is not in\n"
23286 " // ASCII.\n"
23287 " var foobX";
23288 char chunk2[] = "XX";
23289 char chunk3[] =
23290 "r = 13;\n"
23291 " return foob\xeb\x91\x80r;\n"
23292 "}\n";
23293 chunk1[strlen(chunk1) - 1] = reference[0];
23294 chunk2[0] = reference[1];
23295 chunk2[1] = reference[2];
23296 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23297 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23298 }
23299 // Case 2: the script ends with a multi-byte character. Make sure that it's
23300 // decoded correctly and not just ignored.
23301 {
23302 char chunk1[] =
23303 "var foob\xeb\x91\x80 = 13;\n"
23304 "foob\xeb\x91\x80";
23305 const char* chunks[] = {chunk1, NULL};
23306 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23307 }
23308 }
23309
23310
23311 TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
23312 // Test cases where a UTF-8 character is split over several chunks. Those
23313 // cases are not supported (the embedder should give the data in big enough
23314 // chunks), but we shouldn't crash, just produce a parse error.
23315 const char* reference = "\xeb\x91\x80";
23316 char chunk1[] =
23317 "function foo() {\n"
23318 " // This function will contain an UTF-8 character which is not in\n"
23319 " // ASCII.\n"
23320 " var foobX";
23321 char chunk2[] = "X";
23322 char chunk3[] =
23323 "Xr = 13;\n"
23324 " return foob\xeb\x91\x80r;\n"
23325 "}\n";
23326 chunk1[strlen(chunk1) - 1] = reference[0];
23327 chunk2[0] = reference[1];
23328 chunk3[0] = reference[2];
23329 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23330
23331 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23332 }
23333
23334
23335 TEST(StreamingProducesParserCache) {
23336 i::FLAG_min_preparse_length = 0;
23337 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23338 NULL};
23339
23340 LocalContext env;
23341 v8::Isolate* isolate = env->GetIsolate();
23342 v8::HandleScope scope(isolate);
23343
23344 v8::ScriptCompiler::StreamedSource source(
23345 new TestSourceStream(chunks),
23346 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23347 v8::ScriptCompiler::ScriptStreamingTask* task =
23348 v8::ScriptCompiler::StartStreamingScript(
23349 isolate, &source, v8::ScriptCompiler::kProduceParserCache);
23350
23351 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23352 // task here in the main thread.
23353 task->Run();
23354 delete task;
23355
23356 const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
23357 CHECK(cached_data != NULL);
23358 CHECK(cached_data->data != NULL);
23359 CHECK_GT(cached_data->length, 0);
23360 }
OLDNEW
« no previous file with comments | « src/scanner-character-streams.cc ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698