/* static */ BOOL
ES_DebugBuiltins::getObjectDemographics(ES_Execution_Context *context, unsigned argc, ES_Value_Internal *argv, ES_Value_Internal *return_value)
{
    return_value->SetNull();

	if (argc == 1)
	{
        if (!argv[0].ToNumber(context) || !argv[0].IsUInt32())
            return FALSE;

		if (ES_Heap *heap = g_ecmaManager->GetHeapById(argv[0].GetNumAsUInt32()))
		{
			TempBuffer *buffer = g_ecmaManager->GetHeapDebuggerBuffer();

			buffer->Clear();
			buffer->Append("{ ");

			unsigned *live_objects = heap->live_objects;

			for (unsigned index = 0; index < GCTAG_UNINITIALIZED; ++index)
			{
				if (index != 0)
					buffer->Append(", ");

				buffer->Append("\"");
				buffer->Append(g_ecmaClassName[index]);
				buffer->Append("\": ");
				buffer->AppendUnsignedLong(live_objects[index]);
			}

			buffer->Append(" }");

            return_value->SetString(JString::Make(context, buffer->GetStorage(), buffer->Length()));
		}
	}

	return TRUE;
}
/* static */ BOOL
ES_DebugBuiltins::getHeapInformation(ES_Execution_Context *context, unsigned argc, ES_Value_Internal *argv, ES_Value_Internal *return_value)
{
	Head *active, *inactive, *destroy;

	g_ecmaManager->GetHeapLists(active, inactive, destroy);

	TempBuffer *buffer = g_ecmaManager->GetHeapDebuggerBuffer();
	buffer->Clear();

	buffer->Append("{ \"heaps\": { ");

	ES_Heap *heads[3] = { static_cast<ES_Heap *>(active->First()), static_cast<ES_Heap *>(inactive->First()), static_cast<ES_Heap *>(destroy->First()) };

	for (unsigned head = 0; head < 3; ++head)
		for (ES_Heap *heap = heads[head]; heap; heap = static_cast<ES_Heap *>(heap->Suc()))
		{
			buffer->AppendFormat(UNI_L("\"%u\": { \"bytesLive\": %u, \"bytesLivePeak\": %u, \"bytesLimit\": %u, \"runtimes\": ["), heap->Id(), heap->GetBytesLive(), heap->GetBytesLivePeak(), heap->GetBytesLimit());

			ES_Runtime *runtime = heap->GetFirstRuntime();

			while (runtime)
			{
#ifndef _STANDALONE
				ES_Object *global_object = runtime->GetGlobalObject();
				if (global_object->IsHostObject() && ES_Runtime::GetHostObject(global_object)->IsA(DOM_TYPE_WINDOW))
				{
					OpString url;

					DOM_Utils::GetOriginURL(DOM_Utils::GetDOM_Runtime(runtime)).GetAttribute(URL::KUniName, url);

					for (unsigned index = 0; index < static_cast<unsigned>(url.Length()); ++index)
						if (url.CStr()[index] == '"')
							url.Insert(index++, "\\");

					buffer->AppendFormat(UNI_L("\"%s\""), url.CStr());
				}
				else
#endif // _STANDALONE
					buffer->Append("\"<unidentified runtime>\"");

				runtime = g_ecmaManager->GetNextRuntimePerHeap(runtime);

				if (runtime)
					buffer->Append(", ");
			}

			buffer->Append("] }, ");
		}

	buffer->AppendFormat(UNI_L("\"count\": %u }, \"allocators\": ["), active->Cardinal() + inactive->Cardinal() + destroy->Cardinal());

	for (ES_PageAllocator *allocator = static_cast<ES_PageAllocator *>(g_ecmaPageAllocatorList->First()); allocator; allocator = static_cast<ES_PageAllocator *>(allocator->Suc()))
	{
		buffer->AppendFormat(UNI_L("{ \"chunks\": %u, \"chunkSize\": %u, \"pages\": %u, \"pageSize\": %u, \"heaps\": ["), allocator->CountChunks(), allocator->ChunkSize(), allocator->CountPages(), allocator->PageSize());

		for (ES_HeapHandle *heaph = allocator->GetFirstHeapHandle(); heaph; heaph = static_cast<ES_HeapHandle *>(heaph->Suc()))
		{
			buffer->AppendUnsignedLong(heaph->heap->Id());

			if (heaph->Suc())
				buffer->Append(", ");
		}

		buffer->Append("] }");

		if (allocator->Suc())
			buffer->Append(", ");
	}

	buffer->Append("], \"cachedPrograms\": [");

	for (Link *link = RT_DATA.program_cache->GetCachedPrograms()->First(); link; link = link->Suc())
	{
		ES_ProgramCodeStatic *program = static_cast<ES_ProgramCodeStatic *>(link);

		buffer->AppendFormat(UNI_L("{ \"url\": \"\", \"length\": %u }"), program->source.GetSource()->length);

		if (link->Suc())
			buffer->Append(", ");
	}

	buffer->Append("] }");

    return_value->SetString(JString::Make(context, buffer->GetStorage(), buffer->Length()));

    return TRUE;
}
Beispiel #3
0
/* virtual */ ES_GetState
JS_Location::GetName(OpAtom property_name, ES_Value* value, ES_Runtime* origining_runtime)
{
	TempBuffer *buffer = GetEmptyTempBuf();
	URL url;

	if (fakewindow)
		url = fakewindow->GetURL();
#ifdef SELFTEST
	else if (!do_navigation)
		url = current_url;
#endif // SELFTEST
	else if (FramesDocument *frames_doc = GetFramesDocument())
	{
		url = frames_doc->GetURL();

		// The anchors (hash) might be better in DocumentManager
		URL doc_man_url = frames_doc->GetDocManager()->GetCurrentURL();
		if (doc_man_url == url) // Doesn't compare anchors
			url = doc_man_url;
	}
#ifdef DOM_WEBWORKERS_SUPPORT
	/* No FramesDocument to query, so consult the origin DocumentManager for the Worker */
	if (!GetFramesDocument())
	{
		DOM_WebWorkerController *web_workers = GetEnvironment()->GetWorkerController();
		if (DOM_WebWorker *ww = web_workers->GetWorkerObject())
			url = ww->GetLocationURL();
		else if (DocumentManager *doc = web_workers->GetWorkerDocManager())
			url = doc->GetCurrentURL();
		OP_ASSERT(!url.IsEmpty());
	}
#endif // DOM_WEBWORKERS_SUPPORT

	switch (property_name)
	{
	case OP_ATOM_href:
		DOMSetString(value, url.GetAttribute(URL::KUniName_With_Fragment_Escaped).CStr());
		return GET_SUCCESS;

	case OP_ATOM_protocol:
		if (value)
		{
			const char *protocol = url.GetAttribute(URL::KProtocolName).CStr();
			if (protocol)
			{
				GET_FAILED_IF_ERROR(buffer->Append(protocol));
				GET_FAILED_IF_ERROR(buffer->Append(":"));
			}

			DOMSetString(value, buffer);
		}
		return GET_SUCCESS;

	case OP_ATOM_host:
	case OP_ATOM_hostname:
		if (value)
		{
			const uni_char *name = url.GetServerName() ? url.GetServerName()->UniName() : NULL;

			if (property_name == OP_ATOM_host)
			{
				unsigned short port = url.GetServerPort();
				if (port)
				{
					GET_FAILED_IF_ERROR(buffer->Append(name));
					GET_FAILED_IF_ERROR(buffer->Append(":"));
					GET_FAILED_IF_ERROR(buffer->AppendUnsignedLong(port));
					name = buffer->GetStorage();
				}
			}

			DOMSetString(value, name);
		}
		return GET_SUCCESS;

	case OP_ATOM_port:
		if (value)
		{
			unsigned short port = url.GetServerPort();
			if (port)
				GET_FAILED_IF_ERROR(buffer->AppendUnsignedLong(port));

			DOMSetString(value, buffer);
		}
		return GET_SUCCESS;

	case OP_ATOM_pathname:
		if (value)
		{
			const uni_char *path = url.GetAttribute(URL::KUniPath).CStr();

			if (path)
			{
				GET_FAILED_IF_ERROR(buffer->Append(path));
				uni_char *path_tmp = buffer->GetStorage();

				/* It isn't obvious from the JS spec and the relevant RFC, but in
				   Javascript the 'pathname' excludes any arguments passed to the page. */
				if (uni_char *query_start = uni_strchr(path_tmp, '?'))
				{
					path = path_tmp;
					*query_start = 0;
				}
			}

			DOMSetString(value, path);
		}
		return GET_SUCCESS;

	case OP_ATOM_search:
		if (value)
		{
			const uni_char *name = url.GetAttribute(URL::KUniName).CStr();

			if (name)
				name = uni_strchr(name, '?');

			DOMSetString(value, name);
		}
		return GET_SUCCESS;

	case OP_ATOM_hash:
		if (value)
		{
			const uni_char *fragment = url.UniRelName();

			// MSIE emits "#" for the empty fragment (as in http://www.opera.com/# ) but no other
			// browser does that and neither will we.
			if (fragment && *fragment)
			{
				GET_FAILED_IF_ERROR(buffer->Append('#'));
				GET_FAILED_IF_ERROR(buffer->Append(fragment));
				fragment = buffer->GetStorage();
			}

			DOMSetString(value, fragment);
		}
		return GET_SUCCESS;
	}

	return GET_FAILED;
}