mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central and mozilla-inbound
This commit is contained in:
commit
7531e87587
@ -665,7 +665,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA(Navigator, nsNavigatorSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS |
|
||||
nsIXPCScriptable::WANT_PRECREATE)
|
||||
nsIXPCScriptable::WANT_PRECREATE |
|
||||
nsIXPCScriptable::WANT_NEWRESOLVE)
|
||||
NS_DEFINE_CLASSINFO_DATA(Plugin, nsPluginSH,
|
||||
ARRAY_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(PluginArray, nsPluginArraySH,
|
||||
@ -2014,7 +2015,8 @@ CutPrefix(const char *aName) {
|
||||
nsresult
|
||||
nsDOMClassInfo::RegisterClassName(PRInt32 aClassInfoID)
|
||||
{
|
||||
nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
|
||||
nsScriptNameSpaceManager *nameSpaceManager =
|
||||
nsJSRuntime::GetNameSpaceManager();
|
||||
NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nameSpaceManager->RegisterClassName(sClassInfoData[aClassInfoID].mName,
|
||||
@ -2030,7 +2032,8 @@ nsDOMClassInfo::RegisterClassName(PRInt32 aClassInfoID)
|
||||
nsresult
|
||||
nsDOMClassInfo::RegisterClassProtos(PRInt32 aClassInfoID)
|
||||
{
|
||||
nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
|
||||
nsScriptNameSpaceManager *nameSpaceManager =
|
||||
nsJSRuntime::GetNameSpaceManager();
|
||||
NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
|
||||
PRBool found_old;
|
||||
|
||||
@ -2082,7 +2085,8 @@ nsDOMClassInfo::RegisterClassProtos(PRInt32 aClassInfoID)
|
||||
nsresult
|
||||
nsDOMClassInfo::RegisterExternalClasses()
|
||||
{
|
||||
nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
|
||||
nsScriptNameSpaceManager *nameSpaceManager =
|
||||
nsJSRuntime::GetNameSpaceManager();
|
||||
NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsCOMPtr<nsIComponentRegistrar> registrar;
|
||||
@ -5531,7 +5535,8 @@ private:
|
||||
{
|
||||
*aNameStruct = nsnull;
|
||||
|
||||
nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
|
||||
nsScriptNameSpaceManager *nameSpaceManager =
|
||||
nsJSRuntime::GetNameSpaceManager();
|
||||
if (!nameSpaceManager) {
|
||||
NS_ERROR("Can't get namespace manager.");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
@ -5739,7 +5744,8 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
|
||||
nsScriptNameSpaceManager *nameSpaceManager =
|
||||
nsJSRuntime::GetNameSpaceManager();
|
||||
NS_ASSERTION(nameSpaceManager, "Can't get namespace manager?");
|
||||
|
||||
const nsIID *class_iid;
|
||||
@ -6092,7 +6098,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
{
|
||||
*did_resolve = PR_FALSE;
|
||||
|
||||
nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
|
||||
nsScriptNameSpaceManager *nameSpaceManager =
|
||||
nsJSRuntime::GetNameSpaceManager();
|
||||
NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsDependentJSString name(id);
|
||||
@ -7031,6 +7038,77 @@ nsLocationSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
}
|
||||
|
||||
// DOM Navigator helper
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavigatorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval)
|
||||
{
|
||||
if (!JSID_IS_STRING(id) || (flags & JSRESOLVE_ASSIGNING)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsScriptNameSpaceManager *nameSpaceManager =
|
||||
nsJSRuntime::GetNameSpaceManager();
|
||||
NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsDependentJSString name(id);
|
||||
|
||||
const nsGlobalNameStruct *name_struct = nsnull;
|
||||
|
||||
nameSpaceManager->LookupNavigatorName(name, &name_struct);
|
||||
|
||||
if (!name_struct) {
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeNavigatorProperty,
|
||||
"unexpected type");
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsISupports> native(do_CreateInstance(name_struct->mCID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
jsval prop_val = JSVAL_VOID; // Property value.
|
||||
|
||||
nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native));
|
||||
|
||||
if (gpi) {
|
||||
JSObject *global = JS_GetGlobalForObject(cx, obj);
|
||||
|
||||
nsISupports *globalNative = XPConnect()->GetNativeOfWrapper(cx, global);
|
||||
nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(globalNative);
|
||||
|
||||
if (!window) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
rv = gpi->Init(window, &prop_val);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(prop_val)) {
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = WrapNative(cx, obj, native, PR_TRUE, &prop_val,
|
||||
getter_AddRefs(holder));
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (!JS_WrapValue(cx, &prop_val)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
JSBool ok = ::JS_DefinePropertyById(cx, obj, id, prop_val, nsnull, nsnull,
|
||||
JSPROP_ENUMERATE);
|
||||
|
||||
*_retval = PR_TRUE;
|
||||
*objp = obj;
|
||||
|
||||
return ok ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsNavigatorSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
JSObject *globalObj, JSObject **parentObj)
|
||||
|
@ -481,6 +481,9 @@ protected:
|
||||
public:
|
||||
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
|
||||
JSObject *globalObj, JSObject **parentObj);
|
||||
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, PRUint32 flags,
|
||||
JSObject **objp, PRBool *_retval);
|
||||
|
||||
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
|
||||
{
|
||||
|
@ -51,6 +51,9 @@
|
||||
#define JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY \
|
||||
"JavaScript-global-privileged-property"
|
||||
|
||||
#define JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY \
|
||||
"JavaScript-navigator-property"
|
||||
|
||||
#define JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY \
|
||||
"JavaScript-global-static-nameset"
|
||||
|
||||
|
@ -148,18 +148,19 @@ nsScriptNameSpaceManager::~nsScriptNameSpaceManager()
|
||||
if (mIsInitialized) {
|
||||
// Destroy the hash
|
||||
PL_DHashTableFinish(&mGlobalNames);
|
||||
PL_DHashTableFinish(&mNavigatorNames);
|
||||
}
|
||||
MOZ_COUNT_DTOR(nsScriptNameSpaceManager);
|
||||
}
|
||||
|
||||
nsGlobalNameStruct *
|
||||
nsScriptNameSpaceManager::AddToHash(const char *aKey,
|
||||
nsScriptNameSpaceManager::AddToHash(PLDHashTable *aTable, const char *aKey,
|
||||
const PRUnichar **aClassName)
|
||||
{
|
||||
NS_ConvertASCIItoUTF16 key(aKey);
|
||||
GlobalNameMapEntry *entry =
|
||||
static_cast<GlobalNameMapEntry *>
|
||||
(PL_DHashTableOperate(&mGlobalNames, &key, PL_DHASH_ADD));
|
||||
(PL_DHashTableOperate(aTable, &key, PL_DHASH_ADD));
|
||||
|
||||
if (!entry) {
|
||||
return nsnull;
|
||||
@ -371,7 +372,7 @@ nsScriptNameSpaceManager::RegisterInterface(const char* aIfName,
|
||||
{
|
||||
*aFoundOld = PR_FALSE;
|
||||
|
||||
nsGlobalNameStruct *s = AddToHash(aIfName);
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aIfName);
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (s->mType != nsGlobalNameStruct::eTypeNotInitialized) {
|
||||
@ -408,6 +409,15 @@ nsScriptNameSpaceManager::Init()
|
||||
GLOBALNAME_HASHTABLE_INITIAL_SIZE);
|
||||
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
mIsInitialized = PL_DHashTableInit(&mNavigatorNames, &hash_table_ops, nsnull,
|
||||
sizeof(GlobalNameMapEntry),
|
||||
GLOBALNAME_HASHTABLE_INITIAL_SIZE);
|
||||
if (!mIsInitialized) {
|
||||
PL_DHashTableFinish(&mGlobalNames);
|
||||
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
rv = FillHashWithDOMInterfaces();
|
||||
@ -432,6 +442,9 @@ nsScriptNameSpaceManager::Init()
|
||||
rv = FillHash(cm, JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = FillHash(cm, JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Initial filling of the has table has been done.
|
||||
// Now, listen for changes.
|
||||
nsCOMPtr<nsIObserverService> serv =
|
||||
@ -509,6 +522,25 @@ nsScriptNameSpaceManager::LookupName(const nsAString& aName,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptNameSpaceManager::LookupNavigatorName(const nsAString& aName,
|
||||
const nsGlobalNameStruct **aNameStruct)
|
||||
{
|
||||
GlobalNameMapEntry *entry =
|
||||
static_cast<GlobalNameMapEntry *>
|
||||
(PL_DHashTableOperate(&mNavigatorNames, &aName,
|
||||
PL_DHASH_LOOKUP));
|
||||
|
||||
if (PL_DHASH_ENTRY_IS_BUSY(entry) &&
|
||||
!((&entry->mGlobalName)->mDisabled)) {
|
||||
*aNameStruct = &entry->mGlobalName;
|
||||
} else {
|
||||
*aNameStruct = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptNameSpaceManager::RegisterClassName(const char *aClassName,
|
||||
PRInt32 aDOMClassInfoID,
|
||||
@ -520,7 +552,7 @@ nsScriptNameSpaceManager::RegisterClassName(const char *aClassName,
|
||||
NS_ERROR("Trying to register a non-ASCII class name");
|
||||
return NS_OK;
|
||||
}
|
||||
nsGlobalNameStruct *s = AddToHash(aClassName, aResult);
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName, aResult);
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (s->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
@ -555,7 +587,7 @@ nsScriptNameSpaceManager::RegisterClassProto(const char *aClassName,
|
||||
|
||||
*aFoundOld = PR_FALSE;
|
||||
|
||||
nsGlobalNameStruct *s = AddToHash(aClassName);
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName);
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (s->mType != nsGlobalNameStruct::eTypeNotInitialized &&
|
||||
@ -575,7 +607,7 @@ nsresult
|
||||
nsScriptNameSpaceManager::RegisterExternalClassName(const char *aClassName,
|
||||
nsCID& aCID)
|
||||
{
|
||||
nsGlobalNameStruct *s = AddToHash(aClassName);
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName);
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// If an external constructor is already defined with aClassName we
|
||||
@ -605,7 +637,7 @@ nsScriptNameSpaceManager::RegisterDOMCIData(const char *aName,
|
||||
const nsCID *aConstructorCID)
|
||||
{
|
||||
const PRUnichar* className;
|
||||
nsGlobalNameStruct *s = AddToHash(aName, &className);
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aName, &className);
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// If an external constructor is already defined with aClassName we
|
||||
@ -657,6 +689,8 @@ nsScriptNameSpaceManager::AddCategoryEntryToHash(nsICategoryManager* aCategoryMa
|
||||
} else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY) == 0 ||
|
||||
strcmp(aCategory, JAVASCRIPT_GLOBAL_PRIVILEGED_PROPERTY_CATEGORY) == 0) {
|
||||
type = nsGlobalNameStruct::eTypeProperty;
|
||||
} else if (strcmp(aCategory, JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY) == 0) {
|
||||
type = nsGlobalNameStruct::eTypeNavigatorProperty;
|
||||
} else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY) == 0) {
|
||||
type = nsGlobalNameStruct::eTypeStaticNameSet;
|
||||
} else if (strcmp(aCategory, JAVASCRIPT_GLOBAL_DYNAMIC_NAMESET_CATEGORY) == 0) {
|
||||
@ -704,7 +738,7 @@ nsScriptNameSpaceManager::AddCategoryEntryToHash(nsICategoryManager* aCategoryMa
|
||||
categoryEntry.get(),
|
||||
getter_Copies(constructorProto));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsGlobalNameStruct *s = AddToHash(categoryEntry.get());
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, categoryEntry.get());
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
|
||||
@ -722,7 +756,14 @@ nsScriptNameSpaceManager::AddCategoryEntryToHash(nsICategoryManager* aCategoryMa
|
||||
}
|
||||
}
|
||||
|
||||
nsGlobalNameStruct *s = AddToHash(categoryEntry.get());
|
||||
PLDHashTable *table;
|
||||
if (type == nsGlobalNameStruct::eTypeNavigatorProperty) {
|
||||
table = &mNavigatorNames;
|
||||
} else {
|
||||
table = &mGlobalNames;
|
||||
}
|
||||
|
||||
nsGlobalNameStruct *s = AddToHash(table, categoryEntry.get());
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
|
||||
|
@ -75,6 +75,7 @@ struct nsGlobalNameStruct
|
||||
eTypeNotInitialized,
|
||||
eTypeInterface,
|
||||
eTypeProperty,
|
||||
eTypeNavigatorProperty,
|
||||
eTypeExternalConstructor,
|
||||
eTypeStaticNameSet,
|
||||
eTypeDynamicNameSet,
|
||||
@ -128,6 +129,12 @@ public:
|
||||
nsresult LookupName(const nsAString& aName,
|
||||
const nsGlobalNameStruct **aNameStruct,
|
||||
const PRUnichar **aClassName = nsnull);
|
||||
// Returns a nsGlobalNameStruct for the navigator property aName, or
|
||||
// null if one is not found. The returned nsGlobalNameStruct is only
|
||||
// guaranteed to be valid until the next call to any of the methods
|
||||
// in this class.
|
||||
nsresult LookupNavigatorName(const nsAString& aName,
|
||||
const nsGlobalNameStruct **aNameStruct);
|
||||
|
||||
nsresult RegisterClassName(const char *aClassName,
|
||||
PRInt32 aDOMClassInfoID,
|
||||
@ -161,7 +168,7 @@ protected:
|
||||
// that aKey will be mapped to. If mType in the returned
|
||||
// nsGlobalNameStruct is != eTypeNotInitialized, an entry for aKey
|
||||
// already existed.
|
||||
nsGlobalNameStruct *AddToHash(const char *aKey,
|
||||
nsGlobalNameStruct *AddToHash(PLDHashTable *aTable, const char *aKey,
|
||||
const PRUnichar **aClassName = nsnull);
|
||||
|
||||
nsresult FillHash(nsICategoryManager *aCategoryManager,
|
||||
@ -184,9 +191,8 @@ protected:
|
||||
const char* aCategory,
|
||||
nsISupports* aEntry);
|
||||
|
||||
// Inline PLDHashTable, init with PL_DHashTableInit() and delete
|
||||
// with PL_DHashTableFinish().
|
||||
PLDHashTable mGlobalNames;
|
||||
PLDHashTable mNavigatorNames;
|
||||
|
||||
PRPackedBool mIsInitialized;
|
||||
};
|
||||
|
@ -985,7 +985,7 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
||||
#ifdef MOZ_WIDGET_GTK2
|
||||
if (gtk_check_version(2,18,7) != NULL) { // older
|
||||
if (aWindow.type == NPWindowTypeWindow) {
|
||||
GdkWindow* socket_window = gdk_window_lookup(aWindow.window);
|
||||
GdkWindow* socket_window = gdk_window_lookup(static_cast<GdkNativeWindow>(aWindow.window));
|
||||
if (socket_window) {
|
||||
// A GdkWindow for the socket already exists. Need to
|
||||
// workaround https://bugzilla.gnome.org/show_bug.cgi?id=607061
|
||||
@ -1039,7 +1039,7 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
||||
if (!CreatePluginWindow())
|
||||
return false;
|
||||
|
||||
ReparentPluginWindow((HWND)aWindow.window);
|
||||
ReparentPluginWindow(reinterpret_cast<HWND>(aWindow.window));
|
||||
SizePluginWindow(aWindow.width, aWindow.height);
|
||||
|
||||
mWindow.window = (void*)mPluginWindowHWND;
|
||||
|
@ -604,7 +604,7 @@ PluginInstanceParent::AsyncSetWindow(NPWindow* aWindow)
|
||||
{
|
||||
NPRemoteWindow window;
|
||||
mWindowType = aWindow->type;
|
||||
window.window = reinterpret_cast<uintptr_t>(aWindow->window);
|
||||
window.window = reinterpret_cast<uint64_t>(aWindow->window);
|
||||
window.x = aWindow->x;
|
||||
window.y = aWindow->y;
|
||||
window.width = aWindow->width;
|
||||
@ -911,7 +911,7 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
|
||||
else {
|
||||
SubclassPluginWindow(reinterpret_cast<HWND>(aWindow->window));
|
||||
|
||||
window.window = reinterpret_cast<uintptr_t>(aWindow->window);
|
||||
window.window = reinterpret_cast<uint64_t>(aWindow->window);
|
||||
window.x = aWindow->x;
|
||||
window.y = aWindow->y;
|
||||
window.width = aWindow->width;
|
||||
@ -919,7 +919,7 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
|
||||
window.type = aWindow->type;
|
||||
}
|
||||
#else
|
||||
window.window = reinterpret_cast<unsigned long>(aWindow->window);
|
||||
window.window = reinterpret_cast<uint64_t>(aWindow->window);
|
||||
window.x = aWindow->x;
|
||||
window.y = aWindow->y;
|
||||
window.width = aWindow->width;
|
||||
|
@ -110,7 +110,7 @@ typedef nsCString Buffer;
|
||||
|
||||
struct NPRemoteWindow
|
||||
{
|
||||
unsigned long window;
|
||||
uint64_t window;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
uint32_t width;
|
||||
@ -363,7 +363,7 @@ struct ParamTraits<mozilla::plugins::NPRemoteWindow>
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
aMsg->WriteULong(aParam.window);
|
||||
aMsg->WriteUInt64(aParam.window);
|
||||
WriteParam(aMsg, aParam.x);
|
||||
WriteParam(aMsg, aParam.y);
|
||||
WriteParam(aMsg, aParam.width);
|
||||
@ -381,12 +381,12 @@ struct ParamTraits<mozilla::plugins::NPRemoteWindow>
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
unsigned long window;
|
||||
uint64_t window;
|
||||
int32_t x, y;
|
||||
uint32_t width, height;
|
||||
NPRect clipRect;
|
||||
NPWindowType type;
|
||||
if (!(aMsg->ReadULong(aIter, &window) &&
|
||||
if (!(aMsg->ReadUInt64(aIter, &window) &&
|
||||
ReadParam(aMsg, aIter, &x) &&
|
||||
ReadParam(aMsg, aIter, &y) &&
|
||||
ReadParam(aMsg, aIter, &width) &&
|
||||
|
@ -137,6 +137,7 @@ _TEST_FILES = \
|
||||
test_bug620947.html \
|
||||
test_bug622361.html \
|
||||
test_bug633133.html \
|
||||
test_bug641552.html \
|
||||
test_bug642026.html \
|
||||
test_bug648465.html \
|
||||
test_bug654137.html \
|
||||
|
@ -18,14 +18,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=597809
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var cm = Components.classes["@mozilla.org/categorymanager;1"]
|
||||
.getService(Components.interfaces.nsICategoryManager);
|
||||
cm.addCategoryEntry("JavaScript-global-property", "testSNSM", "@mozilla.org/embedcomp/prompt-service;1",
|
||||
SpecialPowers.addCategoryEntry("JavaScript-global-property", "testSNSM", "@mozilla.org/embedcomp/prompt-service;1",
|
||||
false, true);
|
||||
|
||||
SimpleTest.executeSoon(function () {
|
||||
ok(window.testSNSM, "testSNSM should returns an object");
|
||||
ok(window.testSNSM, "testSNSM should return an object");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
|
42
dom/tests/mochitest/bugs/test_bug641552.html
Normal file
42
dom/tests/mochitest/bugs/test_bug641552.html
Normal file
@ -0,0 +1,42 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=641552
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 641552</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=641552">Mozilla Bug 641552</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 641552 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SpecialPowers.addCategoryEntry("JavaScript-global-property", "randomname", "@mozilla.org/embedcomp/prompt-service;1",
|
||||
false, true);
|
||||
|
||||
SpecialPowers.addCategoryEntry("JavaScript-navigator-property", "randomname1", "@mozilla.org/embedcomp/prompt-service;1",
|
||||
false, true);
|
||||
|
||||
SpecialPowers.addCategoryEntry("JavaScript-navigator-property", "randomname2", "@mozilla.org/embedcomp/prompt-service;1",
|
||||
false, true);
|
||||
|
||||
SimpleTest.executeSoon(function () {
|
||||
ok(window.randomname, "window.randomname should return an object");
|
||||
is(typeof(window.navigator.randomname1), 'object', "navigator.randomname1 should return an object");
|
||||
is(typeof(window.navigator.randomname2), 'object', "navigator.randomname1 should return an object");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -10,7 +10,7 @@
|
||||
#endif
|
||||
>
|
||||
<uses-sdk android:minSdkVersion="5"
|
||||
android:targetSdkVersion="11"/>
|
||||
android:targetSdkVersion="5"/>
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
|
@ -155,20 +155,20 @@ void GetPathToBinary(FilePath& exePath)
|
||||
nsCString path;
|
||||
greDir->GetNativePath(path);
|
||||
exePath = FilePath(path.get());
|
||||
#ifdef OS_MACOSX
|
||||
// We need to use an App Bundle on OS X so that we can hide
|
||||
// the dock icon. See Bug 557225.
|
||||
exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_BUNDLE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exePath.empty()) {
|
||||
exePath = FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
|
||||
exePath = exePath.DirName();
|
||||
}
|
||||
|
||||
#ifdef OS_MACOSX
|
||||
// We need to use an App Bundle on OS X so that we can hide
|
||||
// the dock icon. See Bug 557225
|
||||
exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_BUNDLE);
|
||||
#endif
|
||||
|
||||
exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_NAME);
|
||||
#endif
|
||||
}
|
||||
|
@ -1116,19 +1116,24 @@ namespace JSC {
|
||||
static void relinkCall(void* from, void* to)
|
||||
{
|
||||
js::JaegerSpew(js::JSpew_Insns,
|
||||
ISPFX "##linkCall ((from=%p)) ((to=%p))\n",
|
||||
ISPFX "##relinkCall ((from=%p)) ((to=%p))\n",
|
||||
from, to);
|
||||
|
||||
int disp = ((int)to - (int)from)/4;
|
||||
*(uint32_t *)((int)from) &= 0x40000000;
|
||||
*(uint32_t *)((int)from) |= disp & 0x3fffffff;
|
||||
ExecutableAllocator::cacheFlush(from, 4);
|
||||
void * where= (void *)((intptr_t)from - 20);
|
||||
patchPointerInternal(where, (int)to);
|
||||
ExecutableAllocator::cacheFlush(where, 8);
|
||||
}
|
||||
|
||||
static void linkCall(void* code, JmpSrc where, void* to)
|
||||
{
|
||||
void *from = (void *)((intptr_t)code + where.m_offset);
|
||||
relinkCall(from, to);
|
||||
js::JaegerSpew(js::JSpew_Insns,
|
||||
ISPFX "##linkCall ((from=%p)) ((to=%p))\n",
|
||||
from, to);
|
||||
int disp = ((int)to - (int)from)/4;
|
||||
*(uint32_t *)((int)from) &= 0x40000000;
|
||||
*(uint32_t *)((int)from) |= disp & 0x3fffffff;
|
||||
ExecutableAllocator::cacheFlush(from, 4);
|
||||
}
|
||||
|
||||
static void linkPointer(void* code, JmpDst where, void* value)
|
||||
|
4
js/src/jit-test/tests/basic/bug684348.js
Normal file
4
js/src/jit-test/tests/basic/bug684348.js
Normal file
@ -0,0 +1,4 @@
|
||||
var x = Proxy.create({ fix: function() { return []; } });
|
||||
Object.__proto__ = x;
|
||||
Object.freeze(x);
|
||||
quit();
|
7
js/src/jit-test/tests/jaeger/bug684084.js
Normal file
7
js/src/jit-test/tests/jaeger/bug684084.js
Normal file
@ -0,0 +1,7 @@
|
||||
// |jit-test| error: TypeError
|
||||
function Integer( value, exception ) {
|
||||
try { } catch ( e ) { }
|
||||
new (value = this)( this.value );
|
||||
if ( Math.floor(value) != value || isNaN(value) ) { }
|
||||
}
|
||||
new Integer( 3, false );
|
10
js/src/jit-test/tests/jaeger/bug684576.js
Normal file
10
js/src/jit-test/tests/jaeger/bug684576.js
Normal file
@ -0,0 +1,10 @@
|
||||
// |jit-test| error: TypeError
|
||||
function f0(p0,p1) {
|
||||
var v3;
|
||||
do {
|
||||
p1 > v3
|
||||
v3=1.7
|
||||
} while (((p0[p1][5]==1)||(p0[p1][5]==2)||(p0[p1][5] == 3)) + 0 > p0);
|
||||
+ (v3(f0));
|
||||
}
|
||||
f0(4105,8307);
|
18
js/src/jit-test/tests/jaeger/closure-01.js
Normal file
18
js/src/jit-test/tests/jaeger/closure-01.js
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
/* Non-reentrant call on an inner and outer closure. */
|
||||
|
||||
function foo() {
|
||||
var x = 0;
|
||||
function bar() {
|
||||
var y = 0;
|
||||
function baz() {
|
||||
return ++x + ++y;
|
||||
}
|
||||
return baz;
|
||||
}
|
||||
return bar();
|
||||
}
|
||||
|
||||
var a = foo();
|
||||
var b = foo();
|
||||
assertEq(a() + a() + b() + b(), 12);
|
14
js/src/jit-test/tests/jaeger/closure-02.js
Normal file
14
js/src/jit-test/tests/jaeger/closure-02.js
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
/* Non-reentrant closure used in an invoke session. */
|
||||
|
||||
var last = null;
|
||||
|
||||
var a = [1,2,3,4,5,6,7,8];
|
||||
var b = a.map(function(x) {
|
||||
x++;
|
||||
var res = last ? last() : 0;
|
||||
last = function() { return x; };
|
||||
return res;
|
||||
});
|
||||
|
||||
assertEq("" + b, "0,2,3,4,5,6,7,8");
|
15
js/src/jit-test/tests/jaeger/closure-03.js
Normal file
15
js/src/jit-test/tests/jaeger/closure-03.js
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
/* Recovering non-reentrant information on singletons after a GC. */
|
||||
|
||||
function foo(a) {
|
||||
return function() {
|
||||
gc();
|
||||
var n = 0;
|
||||
for (var i = 0; i < 20; i++)
|
||||
n = a++;
|
||||
assertEq(n, 29);
|
||||
};
|
||||
}
|
||||
var a = foo(10);
|
||||
var b = foo(20);
|
||||
a();
|
23
js/src/jit-test/tests/jaeger/closure-04.js
Normal file
23
js/src/jit-test/tests/jaeger/closure-04.js
Normal file
@ -0,0 +1,23 @@
|
||||
test();
|
||||
function test() {
|
||||
var catch1, catch2, catch3, finally1, finally2, finally3;
|
||||
function gen() {
|
||||
yield 1;
|
||||
try {
|
||||
try {
|
||||
try {
|
||||
yield 1;
|
||||
} finally {
|
||||
test();
|
||||
}
|
||||
} catch (e) {
|
||||
finally2 = true;
|
||||
}
|
||||
} catch (e) { }
|
||||
}
|
||||
iter = gen();
|
||||
iter.next();
|
||||
iter.next();
|
||||
iter.close();
|
||||
gc();
|
||||
}
|
17
js/src/jit-test/tests/jaeger/closure-05.js
Normal file
17
js/src/jit-test/tests/jaeger/closure-05.js
Normal file
@ -0,0 +1,17 @@
|
||||
var gTestcases = new Array();
|
||||
var gTc = gTestcases.length;
|
||||
function TestCase(n, d, e, a) {
|
||||
gTestcases[gTc++] = this;
|
||||
}
|
||||
new TestCase("SECTION", "with MyObject, eval should return square of ");
|
||||
test();
|
||||
function test() {
|
||||
for (gTc = 0; gTc < gTestcases.length; gTc++) {
|
||||
var MYOBJECT = (function isPrototypeOf(message) {
|
||||
delete input;
|
||||
})();
|
||||
with({}) {
|
||||
gTestcases[gTc].actual = eval("");
|
||||
}
|
||||
}
|
||||
}
|
15
js/src/jit-test/tests/jaeger/loops/bug684621.js
Normal file
15
js/src/jit-test/tests/jaeger/loops/bug684621.js
Normal file
@ -0,0 +1,15 @@
|
||||
function runRichards() {
|
||||
queue = new Packet;
|
||||
Packet(queue, ID_DEVICE_A, KIND_DEVICE);
|
||||
new Packet;
|
||||
}
|
||||
var ID_DEVICE_A = 4;
|
||||
var KIND_DEVICE = 0;
|
||||
Packet = function (queue) {
|
||||
this.link = null
|
||||
if (queue == null) return;
|
||||
var peek, next = queue;
|
||||
while ((peek = next.link) != null)
|
||||
ID_HANDLER_B
|
||||
};
|
||||
runRichards()
|
@ -342,7 +342,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
* any safe point.
|
||||
*/
|
||||
if (cx->compartment->debugMode())
|
||||
usesRval = true;
|
||||
usesReturnValue_ = true;
|
||||
|
||||
isInlineable = true;
|
||||
if (script->nClosedArgs || script->nClosedVars || script->nfixed >= LOCAL_LIMIT ||
|
||||
@ -498,7 +498,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
|
||||
case JSOP_SETRVAL:
|
||||
case JSOP_POPV:
|
||||
usesRval = true;
|
||||
usesReturnValue_ = true;
|
||||
isInlineable = false;
|
||||
break;
|
||||
|
||||
@ -510,7 +510,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
case JSOP_QNAMEPART:
|
||||
case JSOP_QNAMECONST:
|
||||
checkAliasedName(cx, pc);
|
||||
usesScope = true;
|
||||
usesScopeChain_ = true;
|
||||
isInlineable = false;
|
||||
break;
|
||||
|
||||
@ -519,20 +519,34 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
case JSOP_DEFCONST:
|
||||
case JSOP_SETCONST:
|
||||
checkAliasedName(cx, pc);
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case JSOP_ENTERWITH:
|
||||
extendsScope_ = true;
|
||||
isInlineable = canTrackVars = false;
|
||||
break;
|
||||
|
||||
case JSOP_EVAL:
|
||||
extendsScope_ = true;
|
||||
isInlineable = canTrackVars = false;
|
||||
break;
|
||||
|
||||
case JSOP_ENTERWITH:
|
||||
addsScopeObjects_ = true;
|
||||
isInlineable = canTrackVars = false;
|
||||
break;
|
||||
|
||||
case JSOP_ENTERBLOCK:
|
||||
case JSOP_LEAVEBLOCK:
|
||||
addsScopeObjects_ = true;
|
||||
isInlineable = false;
|
||||
break;
|
||||
|
||||
case JSOP_THIS:
|
||||
usesThis = true;
|
||||
usesThisValue_ = true;
|
||||
break;
|
||||
|
||||
case JSOP_CALL:
|
||||
case JSOP_NEW:
|
||||
/* Only consider potentially inlineable calls here. */
|
||||
hasCalls = true;
|
||||
hasFunctionCalls_ = true;
|
||||
break;
|
||||
|
||||
case JSOP_TABLESWITCH:
|
||||
@ -717,7 +731,6 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
|
||||
/* Additional opcodes which can be compiled but which can't be inlined. */
|
||||
case JSOP_ARGUMENTS:
|
||||
case JSOP_EVAL:
|
||||
case JSOP_THROW:
|
||||
case JSOP_EXCEPTION:
|
||||
case JSOP_DEFLOCALFUN:
|
||||
@ -729,8 +742,6 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
case JSOP_ARGSUB:
|
||||
case JSOP_ARGCNT:
|
||||
case JSOP_DEBUGGER:
|
||||
case JSOP_ENTERBLOCK:
|
||||
case JSOP_LEAVEBLOCK:
|
||||
case JSOP_FUNCALL:
|
||||
case JSOP_FUNAPPLY:
|
||||
isInlineable = false;
|
||||
|
@ -886,15 +886,18 @@ class ScriptAnalysis
|
||||
|
||||
/* --------- Bytecode analysis --------- */
|
||||
|
||||
bool usesRval;
|
||||
bool usesScope;
|
||||
bool usesThis;
|
||||
bool hasCalls;
|
||||
bool canTrackVars;
|
||||
bool isInlineable;
|
||||
bool usesReturnValue_:1;
|
||||
bool usesScopeChain_:1;
|
||||
bool usesThisValue_:1;
|
||||
bool hasFunctionCalls_:1;
|
||||
bool modifiesArguments_:1;
|
||||
bool extendsScope_:1;
|
||||
bool addsScopeObjects_:1;
|
||||
bool localsAliasStack_:1;
|
||||
bool isInlineable:1;
|
||||
bool canTrackVars:1;
|
||||
|
||||
uint32 numReturnSites_;
|
||||
bool modifiesArguments_;
|
||||
bool localsAliasStack_;
|
||||
|
||||
/* Offsets at which each local becomes unconditionally defined, or a value below. */
|
||||
uint32 *definedLocals;
|
||||
@ -928,13 +931,13 @@ class ScriptAnalysis
|
||||
bool inlineable(uint32 argc) { return isInlineable && argc == script->function()->nargs; }
|
||||
|
||||
/* Whether there are POPV/SETRVAL bytecodes which can write to the frame's rval. */
|
||||
bool usesReturnValue() const { return usesRval; }
|
||||
bool usesReturnValue() const { return usesReturnValue_; }
|
||||
|
||||
/* Whether there are NAME bytecodes which can access the frame's scope chain. */
|
||||
bool usesScopeChain() const { return usesScope; }
|
||||
bool usesScopeChain() const { return usesScopeChain_; }
|
||||
|
||||
bool usesThisValue() const { return usesThis; }
|
||||
bool hasFunctionCalls() const { return hasCalls; }
|
||||
bool usesThisValue() const { return usesThisValue_; }
|
||||
bool hasFunctionCalls() const { return hasFunctionCalls_; }
|
||||
uint32 numReturnSites() const { return numReturnSites_; }
|
||||
|
||||
/*
|
||||
@ -943,6 +946,15 @@ class ScriptAnalysis
|
||||
*/
|
||||
bool modifiesArguments() { return modifiesArguments_; }
|
||||
|
||||
/*
|
||||
* True if the script may extend declarations in its top level scope with
|
||||
* dynamic fun/var declarations or through eval.
|
||||
*/
|
||||
bool extendsScope() { return extendsScope_; }
|
||||
|
||||
/* True if the script may add block or with objects to its scope chain. */
|
||||
bool addsScopeObjects() { return addsScopeObjects_; }
|
||||
|
||||
/*
|
||||
* True if there are any LOCAL opcodes aliasing values on the stack (above
|
||||
* script->nfixed).
|
||||
@ -1168,6 +1180,21 @@ class ScriptAnalysis
|
||||
return lifetimes[slot];
|
||||
}
|
||||
|
||||
/*
|
||||
* If a NAME or similar opcode is definitely accessing a particular slot
|
||||
* of a script this one is nested in, get that script/slot.
|
||||
*/
|
||||
struct NameAccess {
|
||||
JSScript *script;
|
||||
types::TypeScriptNesting *nesting;
|
||||
uint32 slot;
|
||||
|
||||
/* Decompose the slot above. */
|
||||
bool arg;
|
||||
uint32 index;
|
||||
};
|
||||
NameAccess resolveNameAccess(JSContext *cx, jsid id, bool addDependency = false);
|
||||
|
||||
void printSSA(JSContext *cx);
|
||||
void printTypes(JSContext *cx);
|
||||
|
||||
|
@ -1488,8 +1488,7 @@ class AutoGCRooter {
|
||||
DESCRIPTOR = -13, /* js::AutoPropertyDescriptorRooter */
|
||||
STRING = -14, /* js::AutoStringRooter */
|
||||
IDVECTOR = -15, /* js::AutoIdVector */
|
||||
OBJVECTOR = -16, /* js::AutoObjectVector */
|
||||
TYPE = -17 /* js::types::AutoTypeRooter */
|
||||
OBJVECTOR = -16 /* js::AutoObjectVector */
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -585,9 +585,26 @@ JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
||||
|
||||
#endif
|
||||
|
||||
if (!activeAnalysis) {
|
||||
#ifdef JS_METHODJIT
|
||||
if (types.inferenceEnabled)
|
||||
mjit::ClearAllFrames(this);
|
||||
#endif
|
||||
|
||||
if (activeAnalysis) {
|
||||
/*
|
||||
* Clear the analysis pool, but don't releas its data yet. While
|
||||
* Analysis information is in use, so don't clear the analysis pool.
|
||||
* jitcode still needs to be released, if this is a shape-regenerating
|
||||
* GC then shape numbers baked into the code may change.
|
||||
*/
|
||||
if (types.inferenceEnabled) {
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
mjit::ReleaseScriptCode(cx, script);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Clear the analysis pool, but don't release its data yet. While
|
||||
* sweeping types any live data will be allocated into the pool.
|
||||
*/
|
||||
JSArenaPool oldPool;
|
||||
@ -599,9 +616,6 @@ JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
||||
* enabled in the compartment.
|
||||
*/
|
||||
if (types.inferenceEnabled) {
|
||||
#ifdef JS_METHODJIT
|
||||
mjit::ClearAllFrames(this);
|
||||
#endif
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->types) {
|
||||
@ -615,6 +629,7 @@ JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
||||
if (discardScripts) {
|
||||
script->types->destroy();
|
||||
script->types = NULL;
|
||||
script->typesPurged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -624,8 +639,7 @@ JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
||||
|
||||
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if (script->types)
|
||||
script->types->analysis = NULL;
|
||||
script->clearAnalysis();
|
||||
}
|
||||
|
||||
/* Reset the analysis pool, releasing all analysis and intermediate type data. */
|
||||
|
@ -771,6 +771,17 @@ NewCallObject(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObject *c
|
||||
size_t slots = JSObject::CALL_RESERVED_SLOTS + argsVars;
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(slots);
|
||||
|
||||
/*
|
||||
* Make sure that the arguments and variables in the call object all end up
|
||||
* in a contiguous range of slots. We need this to be able to embed the
|
||||
* args/vars arrays in the TypeScriptNesting for the function, after the
|
||||
* call object's frame has finished.
|
||||
*/
|
||||
if (cx->typeInferenceEnabled() && gc::GetGCKindSlots(kind) < slots) {
|
||||
kind = gc::GetGCObjectKind(JSObject::CALL_RESERVED_SLOTS);
|
||||
JS_ASSERT(gc::GetGCKindSlots(kind) == JSObject::CALL_RESERVED_SLOTS);
|
||||
}
|
||||
|
||||
JSObject *callobj = js_NewGCObject(cx, kind);
|
||||
if (!callobj)
|
||||
return NULL;
|
||||
@ -829,7 +840,7 @@ CreateFunCallObject(JSContext *cx, StackFrame *fp)
|
||||
* For a named function expression Call's parent points to an environment
|
||||
* object holding function's name.
|
||||
*/
|
||||
if (JSAtom *lambdaName = (fp->fun()->flags & JSFUN_LAMBDA) ? fp->fun()->atom : NULL) {
|
||||
if (JSAtom *lambdaName = CallObjectLambdaName(fp->fun())) {
|
||||
scopeChain = NewDeclEnvObject(cx, fp);
|
||||
if (!scopeChain)
|
||||
return NULL;
|
||||
@ -946,6 +957,16 @@ js_PutCallObject(StackFrame *fp)
|
||||
callobj.setSlot(JSObject::CALL_RESERVED_SLOTS + nargs + e, fp->slots()[e]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the args and vars for the active call if this is an outer
|
||||
* function in a script nesting.
|
||||
*/
|
||||
types::TypeScriptNesting *nesting = script->nesting();
|
||||
if (nesting && script->isOuterFunction) {
|
||||
nesting->argArray = callobj.callObjArgArray();
|
||||
nesting->varArray = callobj.callObjVarArray();
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear private pointers to fp, which is about to go away. */
|
||||
@ -1028,7 +1049,11 @@ SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
else
|
||||
obj->setCallObjArg(i, *vp);
|
||||
|
||||
JSScript *script = obj->getCallObjCalleeFunction()->script();
|
||||
JSFunction *fun = obj->getCallObjCalleeFunction();
|
||||
JSScript *script = fun->script();
|
||||
if (!script->ensureHasTypes(cx, fun))
|
||||
return false;
|
||||
|
||||
TypeScript::SetArgument(cx, script, i, *vp);
|
||||
|
||||
return true;
|
||||
@ -1095,7 +1120,11 @@ SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
else
|
||||
obj->setCallObjVar(i, *vp);
|
||||
|
||||
JSScript *script = obj->getCallObjCalleeFunction()->script();
|
||||
JSFunction *fun = obj->getCallObjCalleeFunction();
|
||||
JSScript *script = fun->script();
|
||||
if (!script->ensureHasTypes(cx, fun))
|
||||
return false;
|
||||
|
||||
TypeScript::SetLocal(cx, script, i, *vp);
|
||||
|
||||
return true;
|
||||
@ -2384,9 +2413,8 @@ js_InitFunctionClass(JSContext *cx, JSObject *obj)
|
||||
script->code[0] = JSOP_STOP;
|
||||
script->code[1] = SRC_NULL;
|
||||
fun->u.i.script = script;
|
||||
fun->getType(cx)->functionScript = script;
|
||||
fun->getType(cx)->interpretedFunction = fun;
|
||||
script->hasFunction = true;
|
||||
script->where.fun = fun;
|
||||
script->setOwnerObject(fun);
|
||||
js_CallNewScriptHook(cx, script, fun);
|
||||
|
||||
|
@ -234,8 +234,8 @@ MarkTypeObject(JSTracer *trc, types::TypeObject *type, const char *name)
|
||||
if (IS_GC_MARKING_TRACER(trc)) {
|
||||
if (type->singleton)
|
||||
MarkObject(trc, *type->singleton, "type_singleton");
|
||||
if (type->functionScript)
|
||||
MarkScript(trc, type->functionScript, "functionScript");
|
||||
if (type->interpretedFunction)
|
||||
MarkObject(trc, *type->interpretedFunction, "type_function");
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,7 +415,7 @@ MarkKind(JSTracer *trc, void *thing, JSGCTraceKind kind)
|
||||
Mark(trc, reinterpret_cast<Shape *>(thing));
|
||||
break;
|
||||
case JSTRACE_TYPE_OBJECT:
|
||||
Mark(trc, reinterpret_cast<types::TypeObject *>(thing));
|
||||
MarkTypeObject(trc, reinterpret_cast<types::TypeObject *>(thing), "type_stack");
|
||||
break;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
case JSTRACE_XML:
|
||||
@ -851,14 +851,15 @@ MarkChildren(JSTracer *trc, JSScript *script)
|
||||
|
||||
if (!script->isCachedEval && script->u.object)
|
||||
MarkObject(trc, *script->u.object, "object");
|
||||
if (script->hasFunction)
|
||||
MarkObject(trc, *script->function(), "script_fun");
|
||||
|
||||
if (IS_GC_MARKING_TRACER(trc) && script->filename)
|
||||
js_MarkScriptFilename(script->filename);
|
||||
|
||||
script->bindings.trace(trc);
|
||||
|
||||
if (script->types)
|
||||
script->types->trace(trc);
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
if (script->jitNormal)
|
||||
script->jitNormal->trace(trc);
|
||||
@ -913,7 +914,7 @@ ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type)
|
||||
PushMarkStack(gcmarker, type->proto);
|
||||
|
||||
if (type->newScript) {
|
||||
PushMarkStack(gcmarker, type->newScript->script);
|
||||
PushMarkStack(gcmarker, type->newScript->fun);
|
||||
PushMarkStack(gcmarker, type->newScript->shape);
|
||||
}
|
||||
|
||||
@ -953,12 +954,12 @@ MarkChildren(JSTracer *trc, types::TypeObject *type)
|
||||
MarkObject(trc, *type->singleton, "type_singleton");
|
||||
|
||||
if (type->newScript) {
|
||||
MarkScript(trc, type->newScript->script, "type_new_script");
|
||||
MarkObject(trc, *type->newScript->fun, "type_new_function");
|
||||
MarkShape(trc, type->newScript->shape, "type_new_shape");
|
||||
}
|
||||
|
||||
if (type->functionScript)
|
||||
MarkScript(trc, type->functionScript, "functionScript");
|
||||
if (type->interpretedFunction)
|
||||
MarkObject(trc, *type->interpretedFunction, "type_function");
|
||||
}
|
||||
|
||||
#ifdef JS_HAS_XML_SUPPORT
|
||||
|
@ -50,9 +50,6 @@
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
template<typename T>
|
||||
void Mark(JSTracer *trc, T *thing);
|
||||
|
||||
void
|
||||
MarkString(JSTracer *trc, JSString *str);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
170
js/src/jsinfer.h
170
js/src/jsinfer.h
@ -55,6 +55,7 @@ namespace js {
|
||||
namespace analyze {
|
||||
class ScriptAnalysis;
|
||||
}
|
||||
struct GlobalObject;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
@ -311,37 +312,40 @@ enum {
|
||||
OBJECT_FLAG_PROPERTY_COUNT_MASK >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT,
|
||||
|
||||
/*
|
||||
* Whether any objects this represents are not dense arrays. This also
|
||||
* includes dense arrays whose length property does not fit in an int32.
|
||||
* Some objects are not dense arrays, or are dense arrays whose length
|
||||
* property does not fit in an int32.
|
||||
*/
|
||||
OBJECT_FLAG_NON_DENSE_ARRAY = 0x010000,
|
||||
OBJECT_FLAG_NON_DENSE_ARRAY = 0x0010000,
|
||||
|
||||
/* Whether any objects this represents are not packed arrays. */
|
||||
OBJECT_FLAG_NON_PACKED_ARRAY = 0x020000,
|
||||
OBJECT_FLAG_NON_PACKED_ARRAY = 0x0020000,
|
||||
|
||||
/* Whether any objects this represents are not typed arrays. */
|
||||
OBJECT_FLAG_NON_TYPED_ARRAY = 0x040000,
|
||||
OBJECT_FLAG_NON_TYPED_ARRAY = 0x0040000,
|
||||
|
||||
/* Whether any represented script has had arguments objects created. */
|
||||
OBJECT_FLAG_CREATED_ARGUMENTS = 0x080000,
|
||||
OBJECT_FLAG_CREATED_ARGUMENTS = 0x0080000,
|
||||
|
||||
/* Whether any represented script is considered uninlineable. */
|
||||
OBJECT_FLAG_UNINLINEABLE = 0x100000,
|
||||
OBJECT_FLAG_UNINLINEABLE = 0x0100000,
|
||||
|
||||
/* Whether any objects have an equality hook. */
|
||||
OBJECT_FLAG_SPECIAL_EQUALITY = 0x200000,
|
||||
OBJECT_FLAG_SPECIAL_EQUALITY = 0x0200000,
|
||||
|
||||
/* Whether any objects have been iterated over. */
|
||||
OBJECT_FLAG_ITERATED = 0x400000,
|
||||
OBJECT_FLAG_ITERATED = 0x0400000,
|
||||
|
||||
/* Outer function which has been marked reentrant. */
|
||||
OBJECT_FLAG_REENTRANT_FUNCTION = 0x0800000,
|
||||
|
||||
/* Flags which indicate dynamic properties of represented objects. */
|
||||
OBJECT_FLAG_DYNAMIC_MASK = 0x7f0000,
|
||||
OBJECT_FLAG_DYNAMIC_MASK = 0x0ff0000,
|
||||
|
||||
/*
|
||||
* Whether all properties of this object are considered unknown.
|
||||
* If set, all flags in DYNAMIC_MASK will also be set.
|
||||
*/
|
||||
OBJECT_FLAG_UNKNOWN_PROPERTIES = 0x800000,
|
||||
OBJECT_FLAG_UNKNOWN_PROPERTIES = 0x1000000,
|
||||
|
||||
/* Mask for objects created with unknown properties. */
|
||||
OBJECT_FLAG_UNKNOWN_MASK =
|
||||
@ -429,6 +433,12 @@ class TypeSet
|
||||
bool hasPropagatedProperty() { return !!(flags & TYPE_FLAG_PROPAGATED_PROPERTY); }
|
||||
void setPropagatedProperty() { flags |= TYPE_FLAG_PROPAGATED_PROPERTY; }
|
||||
|
||||
enum FilterKind {
|
||||
FILTER_ALL_PRIMITIVES,
|
||||
FILTER_NULL_VOID,
|
||||
FILTER_VOID
|
||||
};
|
||||
|
||||
/* Add specific kinds of constraints to this set. */
|
||||
inline void add(JSContext *cx, TypeConstraint *constraint, bool callExisting = true);
|
||||
void addSubset(JSContext *cx, TypeSet *target);
|
||||
@ -443,7 +453,7 @@ class TypeSet
|
||||
void addArith(JSContext *cx, TypeSet *target, TypeSet *other = NULL);
|
||||
void addTransformThis(JSContext *cx, JSScript *script, TypeSet *target);
|
||||
void addPropagateThis(JSContext *cx, JSScript *script, jsbytecode *pc, Type type);
|
||||
void addFilterPrimitives(JSContext *cx, TypeSet *target, bool onlyNullVoid);
|
||||
void addFilterPrimitives(JSContext *cx, TypeSet *target, FilterKind filter);
|
||||
void addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target);
|
||||
void addLazyArguments(JSContext *cx, TypeSet *target);
|
||||
|
||||
@ -500,6 +510,9 @@ class TypeSet
|
||||
/* Get the single value which can appear in this type set, otherwise NULL. */
|
||||
JSObject *getSingleton(JSContext *cx, bool freeze = true);
|
||||
|
||||
/* Whether all objects in this set are parented to a particular global. */
|
||||
bool hasGlobalObject(JSContext *cx, JSObject *global);
|
||||
|
||||
inline void clearObjects();
|
||||
|
||||
private:
|
||||
@ -644,7 +657,7 @@ struct Property
|
||||
*/
|
||||
struct TypeNewScript
|
||||
{
|
||||
JSScript *script;
|
||||
JSFunction *fun;
|
||||
|
||||
/* Allocation kind to use for newly constructed objects. */
|
||||
gc::AllocKind allocKind;
|
||||
@ -776,8 +789,8 @@ struct TypeObject : gc::Cell
|
||||
*/
|
||||
Property **propertySet;
|
||||
|
||||
/* If this is an interpreted function, the corresponding script. */
|
||||
JSScript *functionScript;
|
||||
/* If this is an interpreted function, the function object. */
|
||||
JSFunction *interpretedFunction;
|
||||
|
||||
inline TypeObject(JSObject *proto, bool isFunction, bool unknown);
|
||||
|
||||
@ -825,6 +838,12 @@ struct TypeObject : gc::Cell
|
||||
/* Set flags on this object which are implied by the specified key. */
|
||||
inline void setFlagsFromKey(JSContext *cx, JSProtoKey kind);
|
||||
|
||||
/*
|
||||
* Get the global object which all objects of this type are parented to,
|
||||
* or NULL if there is none known.
|
||||
*/
|
||||
inline JSObject *getGlobal();
|
||||
|
||||
/* Helpers */
|
||||
|
||||
bool addProperty(JSContext *cx, jsid id, Property **pprop);
|
||||
@ -902,19 +921,131 @@ struct TypeCallsite
|
||||
bool isNew, unsigned argumentCount);
|
||||
};
|
||||
|
||||
/* Persistent type information for a script, retained across GCs. */
|
||||
struct TypeScript
|
||||
/*
|
||||
* Information attached to outer and inner function scripts nested in one
|
||||
* another for tracking the reentrance state for outer functions. This state is
|
||||
* used to generate fast accesses to the args and vars of the outer function.
|
||||
*
|
||||
* A function is non-reentrant if, at any point in time, only the most recent
|
||||
* activation (i.e. call object) is live. An activation is live if either the
|
||||
* activation is on the stack, or a transitive inner function parented to the
|
||||
* activation is on the stack.
|
||||
*
|
||||
* Because inner functions can be (and, quite often, are) stored in object
|
||||
* properties and it is difficult to build a fast and robust escape analysis
|
||||
* to cope with such flow, we detect reentrance dynamically. For the outer
|
||||
* function, we keep track of the call object for the most recent activation,
|
||||
* and the number of frames for the function and its inner functions which are
|
||||
* on the stack.
|
||||
*
|
||||
* If the outer function is called while frames associated with a previous
|
||||
* activation are on the stack, the outer function is reentrant. If an inner
|
||||
* function is called whose scope does not match the most recent activation,
|
||||
* the outer function is reentrant.
|
||||
*
|
||||
* The situation gets trickier when there are several levels of nesting.
|
||||
*
|
||||
* function foo() {
|
||||
* var a;
|
||||
* function bar() {
|
||||
* var b;
|
||||
* function baz() { return a + b; }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* At calls to 'baz', we don't want to do the scope check for the activations
|
||||
* of both 'foo' and 'bar', but rather 'bar' only. For this to work, a call to
|
||||
* 'baz' which is a reentrant call on 'foo' must also be a reentrant call on
|
||||
* 'bar'. When 'foo' is called, we clear the most recent call object for 'bar'.
|
||||
*/
|
||||
struct TypeScriptNesting
|
||||
{
|
||||
/*
|
||||
* If this is an inner function, the outer function. If non-NULL, this will
|
||||
* be the immediate nested parent of the script (even if that parent has
|
||||
* been marked reentrant). May be NULL even if the script has a nested
|
||||
* parent, if NAME accesses cannot be tracked into the parent (either the
|
||||
* script extends its scope with eval() etc., or the parent can make new
|
||||
* scope chain objects with 'let' or 'with').
|
||||
*/
|
||||
JSScript *parent;
|
||||
|
||||
/* If this is an outer function, list of inner functions. */
|
||||
JSScript *children;
|
||||
|
||||
/* Link for children list of parent. */
|
||||
JSScript *next;
|
||||
|
||||
/* If this is an outer function, the most recent activation. */
|
||||
JSObject *activeCall;
|
||||
|
||||
/*
|
||||
* If this is an outer function, pointers to the most recent activation's
|
||||
* arguments and variables arrays. These could be referring either to stack
|
||||
* values in activeCall's frame (if it has not finished yet) or to the
|
||||
* internal slots of activeCall (if the frame has finished). Pointers to
|
||||
* these fields can be embedded directly in JIT code (though remember to
|
||||
* use 'addDependency == true' when calling resolveNameAccess).
|
||||
*/
|
||||
Value *argArray;
|
||||
Value *varArray;
|
||||
|
||||
/* Number of frames for this function on the stack. */
|
||||
uint32 activeFrames;
|
||||
|
||||
TypeScriptNesting() { PodZero(this); }
|
||||
~TypeScriptNesting();
|
||||
};
|
||||
|
||||
/* Construct nesting information for script wrt its parent. */
|
||||
bool CheckScriptNesting(JSContext *cx, JSScript *script);
|
||||
|
||||
/* Track nesting state when calling or finishing an outer/inner function. */
|
||||
void NestingPrologue(JSContext *cx, StackFrame *fp);
|
||||
void NestingEpilogue(StackFrame *fp);
|
||||
|
||||
/* Persistent type information for a script, retained across GCs. */
|
||||
class TypeScript
|
||||
{
|
||||
friend struct ::JSScript;
|
||||
|
||||
/* Analysis information for the script, cleared on each GC. */
|
||||
analyze::ScriptAnalysis *analysis;
|
||||
|
||||
/* Function for the script, if it has one. */
|
||||
JSFunction *function;
|
||||
|
||||
/*
|
||||
* Information about the scope in which a script executes. This information
|
||||
* is not set until the script has executed at least once and SetScope
|
||||
* called, before that 'global' will be poisoned per GLOBAL_MISSING_SCOPE.
|
||||
*/
|
||||
static const size_t GLOBAL_MISSING_SCOPE = 0x1;
|
||||
|
||||
/* Global object for the script, if compileAndGo. */
|
||||
js::GlobalObject *global;
|
||||
|
||||
/* Nesting state for outer or inner function scripts. */
|
||||
TypeScriptNesting *nesting;
|
||||
|
||||
public:
|
||||
|
||||
/* Dynamic types generated at points within this script. */
|
||||
TypeResult *dynamicList;
|
||||
|
||||
TypeScript(JSFunction *fun) {
|
||||
this->function = fun;
|
||||
this->global = (js::GlobalObject *) GLOBAL_MISSING_SCOPE;
|
||||
}
|
||||
|
||||
bool hasScope() { return size_t(global) != GLOBAL_MISSING_SCOPE; }
|
||||
|
||||
/* Array of type type sets for variables and JOF_TYPESET ops. */
|
||||
TypeSet *typeArray() { return (TypeSet *) (jsuword(this) + sizeof(TypeScript)); }
|
||||
|
||||
static inline unsigned NumTypeSets(JSScript *script);
|
||||
|
||||
/* Dynamic types generated at points within this script. */
|
||||
TypeResult *dynamicList;
|
||||
static bool SetScope(JSContext *cx, JSScript *script, JSObject *scope);
|
||||
|
||||
static inline TypeSet *ReturnTypes(JSScript *script);
|
||||
static inline TypeSet *ThisTypes(JSScript *script);
|
||||
@ -966,6 +1097,7 @@ struct TypeScript
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value);
|
||||
|
||||
static void Sweep(JSContext *cx, JSScript *script);
|
||||
inline void trace(JSTracer *trc);
|
||||
void destroy();
|
||||
};
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "jsarray.h"
|
||||
#include "jsanalyze.h"
|
||||
#include "jscompartment.h"
|
||||
#include "jsgcmark.h"
|
||||
#include "jsinfer.h"
|
||||
#include "jsprf.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
@ -318,10 +319,16 @@ TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
|
||||
extern void TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
|
||||
const CallArgs &args, bool constructing);
|
||||
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
JSObject *callee = &args.callee();
|
||||
if (callee->isFunction() && callee->getFunctionPrivate()->isInterpreted())
|
||||
TypeMonitorCallSlow(cx, callee, args, constructing);
|
||||
JSObject *callee = &args.callee();
|
||||
if (callee->isFunction()) {
|
||||
JSFunction *fun = callee->getFunctionPrivate();
|
||||
if (fun->isInterpreted()) {
|
||||
JSScript *script = fun->script();
|
||||
if (!script->ensureRanAnalysis(cx, fun, callee->getParent()))
|
||||
return;
|
||||
if (cx->typeInferenceEnabled())
|
||||
TypeMonitorCallSlow(cx, callee, args, constructing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,6 +515,7 @@ TypeScript::StandardType(JSContext *cx, JSScript *script, JSProtoKey key)
|
||||
|
||||
struct AllocationSiteKey {
|
||||
JSScript *script;
|
||||
|
||||
uint32 offset : 24;
|
||||
JSProtoKey kind : 8;
|
||||
|
||||
@ -601,8 +609,9 @@ TypeScript::MonitorAssign(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
/* static */ inline void
|
||||
TypeScript::SetThis(JSContext *cx, JSScript *script, Type type)
|
||||
{
|
||||
if (!cx->typeInferenceEnabled() || !script->ensureHasTypes(cx))
|
||||
if (!cx->typeInferenceEnabled())
|
||||
return;
|
||||
JS_ASSERT(script->types);
|
||||
|
||||
/* Analyze the script regardless if -a was used. */
|
||||
bool analyze = cx->hasRunOption(JSOPTION_METHODJIT_ALWAYS);
|
||||
@ -614,7 +623,7 @@ TypeScript::SetThis(JSContext *cx, JSScript *script, Type type)
|
||||
script->id(), TypeString(type));
|
||||
ThisTypes(script)->addType(cx, type);
|
||||
|
||||
if (analyze)
|
||||
if (analyze && script->types->hasScope())
|
||||
script->ensureRanInference(cx);
|
||||
}
|
||||
}
|
||||
@ -629,8 +638,10 @@ TypeScript::SetThis(JSContext *cx, JSScript *script, const js::Value &value)
|
||||
/* static */ inline void
|
||||
TypeScript::SetLocal(JSContext *cx, JSScript *script, unsigned local, Type type)
|
||||
{
|
||||
if (!cx->typeInferenceEnabled() || !script->ensureHasTypes(cx))
|
||||
if (!cx->typeInferenceEnabled())
|
||||
return;
|
||||
JS_ASSERT(script->types);
|
||||
|
||||
if (!LocalTypes(script, local)->hasType(type)) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
@ -652,8 +663,10 @@ TypeScript::SetLocal(JSContext *cx, JSScript *script, unsigned local, const js::
|
||||
/* static */ inline void
|
||||
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type)
|
||||
{
|
||||
if (!cx->typeInferenceEnabled() || !script->ensureHasTypes(cx))
|
||||
if (!cx->typeInferenceEnabled())
|
||||
return;
|
||||
JS_ASSERT(script->types);
|
||||
|
||||
if (!ArgTypes(script, arg)->hasType(type)) {
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
@ -672,6 +685,17 @@ TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TypeScript::trace(JSTracer *trc)
|
||||
{
|
||||
if (function)
|
||||
gc::MarkObject(trc, *function, "script_fun");
|
||||
if (hasScope() && global)
|
||||
gc::MarkObject(trc, *global, "script_global");
|
||||
|
||||
/* Note: nesting does not keep anything alive. */
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// TypeCompartment
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
@ -1085,6 +1109,7 @@ inline TypeObject::TypeObject(JSObject *proto, bool function, bool unknown)
|
||||
PodZero(this);
|
||||
|
||||
this->proto = proto;
|
||||
|
||||
if (function)
|
||||
flags |= OBJECT_FLAG_FUNCTION;
|
||||
if (unknown)
|
||||
@ -1216,23 +1241,33 @@ TypeObject::setFlagsFromKey(JSContext *cx, JSProtoKey key)
|
||||
setFlags(cx, flags);
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
TypeObject::getGlobal()
|
||||
{
|
||||
if (singleton)
|
||||
return singleton->getGlobal();
|
||||
if (interpretedFunction && interpretedFunction->script()->compileAndGo)
|
||||
return interpretedFunction->getGlobal();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} } /* namespace js::types */
|
||||
|
||||
inline bool
|
||||
JSScript::ensureHasTypes(JSContext *cx)
|
||||
JSScript::ensureHasTypes(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
return types || makeTypes(cx);
|
||||
return types || makeTypes(cx, fun);
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScript::ensureRanBytecode(JSContext *cx)
|
||||
JSScript::ensureRanAnalysis(JSContext *cx, JSFunction *fun, JSObject *scope)
|
||||
{
|
||||
if (!ensureHasTypes(cx))
|
||||
if (!ensureHasTypes(cx, fun))
|
||||
return false;
|
||||
if (!types->hasScope() && !js::types::TypeScript::SetScope(cx, this, scope))
|
||||
return false;
|
||||
if (!hasAnalysis() && !makeAnalysis(cx))
|
||||
return false;
|
||||
if (!hasAnalysis()) {
|
||||
if (!makeAnalysis(cx))
|
||||
return false;
|
||||
}
|
||||
JS_ASSERT(analysis()->ranBytecode());
|
||||
return true;
|
||||
}
|
||||
@ -1240,7 +1275,7 @@ JSScript::ensureRanBytecode(JSContext *cx)
|
||||
inline bool
|
||||
JSScript::ensureRanInference(JSContext *cx)
|
||||
{
|
||||
if (!ensureRanBytecode(cx))
|
||||
if (!ensureRanAnalysis(cx))
|
||||
return false;
|
||||
if (!analysis()->ranInference()) {
|
||||
js::types::AutoEnterTypeInference enter(cx);
|
||||
@ -1262,6 +1297,13 @@ JSScript::analysis()
|
||||
return types->analysis;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::clearAnalysis()
|
||||
{
|
||||
if (types)
|
||||
types->analysis = NULL;
|
||||
}
|
||||
|
||||
inline void
|
||||
js::analyze::ScriptAnalysis::addPushedType(JSContext *cx, uint32 offset, uint32 which,
|
||||
js::types::Type type)
|
||||
|
@ -668,7 +668,7 @@ js::InvokeKernel(JSContext *cx, const CallArgs &argsRef, MaybeConstruct construc
|
||||
|
||||
/* Now that the new frame is rooted, maybe create a call object. */
|
||||
StackFrame *fp = ifg.fp();
|
||||
if (fun->isHeavyweight() && !CreateFunCallObject(cx, fp))
|
||||
if (!fp->functionPrologue(cx))
|
||||
return false;
|
||||
|
||||
/* Run function until JSOP_STOP, JSOP_RETURN or error. */
|
||||
@ -683,6 +683,106 @@ js::InvokeKernel(JSContext *cx, const CallArgs &argsRef, MaybeConstruct construc
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool
|
||||
InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &thisv, uintN argc)
|
||||
{
|
||||
#ifdef JS_TRACER
|
||||
if (TRACE_RECORDER(cx))
|
||||
AbortRecording(cx, "attempt to reenter VM while recording");
|
||||
LeaveTrace(cx);
|
||||
#endif
|
||||
|
||||
/* Always push arguments, regardless of optimized/normal invoke. */
|
||||
ContextStack &stack = cx->stack;
|
||||
if (!stack.pushInvokeArgs(cx, argc, &args_))
|
||||
return false;
|
||||
|
||||
/* Callees may clobber 'this' or 'callee'. */
|
||||
savedCallee_ = args_.calleev() = calleev;
|
||||
savedThis_ = args_.thisv() = thisv;
|
||||
|
||||
/* If anyone (through jsdbgapi) finds this frame, make it safe. */
|
||||
MakeRangeGCSafe(args_.argv(), args_.argc());
|
||||
|
||||
do {
|
||||
/* Hoist dynamic checks from scripted Invoke. */
|
||||
if (!calleev.isObject())
|
||||
break;
|
||||
JSObject &callee = calleev.toObject();
|
||||
if (callee.getClass() != &FunctionClass)
|
||||
break;
|
||||
JSFunction *fun = callee.getFunctionPrivate();
|
||||
if (fun->isNative())
|
||||
break;
|
||||
script_ = fun->script();
|
||||
if (!script_->ensureRanAnalysis(cx, fun, callee.getParent()))
|
||||
return false;
|
||||
if (FunctionNeedsPrologue(cx, fun) || script_->isEmpty())
|
||||
break;
|
||||
|
||||
/*
|
||||
* The frame will remain pushed even when the callee isn't active which
|
||||
* will affect the observable current global, so avoid any change.
|
||||
*/
|
||||
if (callee.getGlobal() != GetGlobalForScopeChain(cx))
|
||||
break;
|
||||
|
||||
/* Push the stack frame once for the session. */
|
||||
if (!stack.pushInvokeFrame(cx, args_, INITIAL_NONE, &ifg_))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Update the 'this' type of the callee according to the value given,
|
||||
* along with the types of any missing arguments. These will be the
|
||||
* same across all calls.
|
||||
*/
|
||||
TypeScript::SetThis(cx, script_, thisv);
|
||||
for (unsigned i = argc; i < fun->nargs; i++)
|
||||
TypeScript::SetArgument(cx, script_, i, types::Type::UndefinedType());
|
||||
|
||||
StackFrame *fp = ifg_.fp();
|
||||
#ifdef JS_METHODJIT
|
||||
/* Hoist dynamic checks from RunScript. */
|
||||
mjit::CompileStatus status = mjit::CanMethodJIT(cx, script_, false,
|
||||
mjit::CompileRequest_JIT);
|
||||
if (status == mjit::Compile_Error)
|
||||
return false;
|
||||
if (status != mjit::Compile_Okay)
|
||||
break;
|
||||
/* Cannot also cache the raw code pointer; it can change. */
|
||||
|
||||
/* Hoist dynamic checks from CheckStackAndEnterMethodJIT. */
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
stackLimit_ = stack.space().getStackLimit(cx, REPORT_ERROR);
|
||||
if (!stackLimit_)
|
||||
return false;
|
||||
|
||||
stop_ = script_->code + script_->length - 1;
|
||||
JS_ASSERT(*stop_ == JSOP_STOP);
|
||||
#endif
|
||||
|
||||
/* Cached to avoid canonicalActualArg in InvokeSessionGuard::operator[]. */
|
||||
nformals_ = fp->numFormalArgs();
|
||||
formals_ = fp->formalArgs();
|
||||
actuals_ = args_.argv();
|
||||
JS_ASSERT(actuals_ == fp->actualArgs());
|
||||
return true;
|
||||
} while (0);
|
||||
|
||||
/*
|
||||
* Use the normal invoke path.
|
||||
*
|
||||
* The callee slot gets overwritten during an unoptimized Invoke, so we
|
||||
* cache it here and restore it before every Invoke call. The 'this' value
|
||||
* does not get overwritten, so we can fill it here once.
|
||||
*/
|
||||
if (ifg_.pushed())
|
||||
ifg_.pop();
|
||||
formals_ = actuals_ = args_.argv();
|
||||
nformals_ = (unsigned)-1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, uintN argc, Value *argv,
|
||||
Value *rval)
|
||||
@ -805,6 +905,9 @@ js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const V
|
||||
|
||||
Probes::startExecution(cx, script);
|
||||
|
||||
if (!script->ensureRanAnalysis(cx, NULL, &scopeChain))
|
||||
return false;
|
||||
|
||||
TypeScript::SetThis(cx, script, fp->thisValue());
|
||||
|
||||
AutoPreserveEnumerators preserve(cx);
|
||||
@ -812,6 +915,9 @@ js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const V
|
||||
if (result && ok)
|
||||
*result = fp->returnValue();
|
||||
|
||||
if (fp->isStrictEvalFrame())
|
||||
js_PutCallObject(fp);
|
||||
|
||||
Probes::stopExecution(cx, script);
|
||||
|
||||
return !!ok;
|
||||
@ -4070,15 +4176,16 @@ BEGIN_CASE(JSOP_FUNAPPLY)
|
||||
|
||||
RESTORE_INTERP_VARS();
|
||||
|
||||
/* Only create call object after frame is rooted. */
|
||||
if (fun->isHeavyweight() && !CreateFunCallObject(cx, regs.fp()))
|
||||
if (!regs.fp()->functionPrologue(cx))
|
||||
goto error;
|
||||
|
||||
RESET_USE_METHODJIT();
|
||||
TRACE_0(EnterFrame);
|
||||
|
||||
bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
{
|
||||
if (!newType) {
|
||||
/* Try to ensure methods are method JIT'd. */
|
||||
mjit::CompileRequest request = (interpMode == JSINTERP_NORMAL)
|
||||
? mjit::CompileRequest_Interpreter
|
||||
@ -4096,7 +4203,6 @@ BEGIN_CASE(JSOP_FUNAPPLY)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
|
||||
if (!ScriptPrologue(cx, regs.fp(), newType))
|
||||
goto error;
|
||||
|
||||
|
@ -71,6 +71,127 @@ class AutoPreserveEnumerators {
|
||||
}
|
||||
};
|
||||
|
||||
class InvokeSessionGuard
|
||||
{
|
||||
InvokeArgsGuard args_;
|
||||
InvokeFrameGuard ifg_;
|
||||
Value savedCallee_, savedThis_;
|
||||
Value *formals_, *actuals_;
|
||||
unsigned nformals_;
|
||||
JSScript *script_;
|
||||
Value *stackLimit_;
|
||||
jsbytecode *stop_;
|
||||
|
||||
bool optimized() const { return ifg_.pushed(); }
|
||||
|
||||
public:
|
||||
InvokeSessionGuard() : args_(), ifg_() {}
|
||||
~InvokeSessionGuard() {}
|
||||
|
||||
bool start(JSContext *cx, const Value &callee, const Value &thisv, uintN argc);
|
||||
bool invoke(JSContext *cx);
|
||||
|
||||
bool started() const {
|
||||
return args_.pushed();
|
||||
}
|
||||
|
||||
Value &operator[](unsigned i) const {
|
||||
JS_ASSERT(i < argc());
|
||||
Value &arg = i < nformals_ ? formals_[i] : actuals_[i];
|
||||
JS_ASSERT_IF(optimized(), &arg == &ifg_.fp()->canonicalActualArg(i));
|
||||
JS_ASSERT_IF(!optimized(), &arg == &args_[i]);
|
||||
return arg;
|
||||
}
|
||||
|
||||
uintN argc() const {
|
||||
return args_.argc();
|
||||
}
|
||||
|
||||
const Value &rval() const {
|
||||
return optimized() ? ifg_.fp()->returnValue() : args_.rval();
|
||||
}
|
||||
};
|
||||
|
||||
inline bool
|
||||
InvokeSessionGuard::invoke(JSContext *cx)
|
||||
{
|
||||
/* N.B. Must be kept in sync with Invoke */
|
||||
|
||||
/* Refer to canonical (callee, this) for optimized() sessions. */
|
||||
formals_[-2] = savedCallee_;
|
||||
formals_[-1] = savedThis_;
|
||||
|
||||
/* Prevent spurious accessing-callee-after-rval assert. */
|
||||
args_.calleeHasBeenReset();
|
||||
|
||||
if (!optimized())
|
||||
return Invoke(cx, args_);
|
||||
|
||||
/*
|
||||
* Update the types of each argument. The 'this' type and missing argument
|
||||
* types were handled when the invoke session was created.
|
||||
*/
|
||||
for (unsigned i = 0; i < Min(argc(), nformals_); i++)
|
||||
types::TypeScript::SetArgument(cx, script_, i, (*this)[i]);
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
mjit::JITScript *jit = script_->getJIT(false /* !constructing */);
|
||||
if (!jit) {
|
||||
/* Watch in case the code was thrown away due a recompile. */
|
||||
mjit::CompileStatus status = mjit::TryCompile(cx, script_, false);
|
||||
if (status == mjit::Compile_Error)
|
||||
return false;
|
||||
JS_ASSERT(status == mjit::Compile_Okay);
|
||||
jit = script_->getJIT(false);
|
||||
}
|
||||
void *code;
|
||||
if (!(code = jit->invokeEntry))
|
||||
return Invoke(cx, args_);
|
||||
#endif
|
||||
|
||||
StackFrame *fp = ifg_.fp();
|
||||
|
||||
/*
|
||||
* Clear any activation objects on the frame. Normally the frame should not
|
||||
* have any, but since we leave it on the stack between calls to invoke()
|
||||
* the debugger can start operating on it. See markFunctionEpilogueDone()
|
||||
* calls below. :XXX: this is pretty gross, and slows us down. Can the
|
||||
* debugger be prevented from observing this frame?
|
||||
*/
|
||||
fp->functionEpilogue(/* activationOnly = */ true);
|
||||
fp->markFunctionEpilogueDone(/* activationOnly = */ true);
|
||||
|
||||
fp->resetCallFrame(script_);
|
||||
|
||||
JSBool ok;
|
||||
{
|
||||
AutoPreserveEnumerators preserve(cx);
|
||||
args_.setActive(); /* From js::Invoke(InvokeArgsGuard) overload. */
|
||||
Probes::enterJSFun(cx, fp->fun(), script_);
|
||||
#ifdef JS_METHODJIT
|
||||
ok = mjit::EnterMethodJIT(cx, fp, code, stackLimit_, /* partial = */ false);
|
||||
cx->regs().pc = stop_;
|
||||
#else
|
||||
cx->regs().pc = script_->code;
|
||||
ok = Interpret(cx, cx->fp());
|
||||
|
||||
/* Interpret does not perform the entry frame's epilogue, unlike EnterMethodJIT. */
|
||||
cx->fp()->functionEpilogue();
|
||||
#endif
|
||||
Probes::exitJSFun(cx, fp->fun(), script_);
|
||||
args_.setInactive();
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear activation object flags, for the functionEpilogue() call in the
|
||||
* next invoke().
|
||||
*/
|
||||
fp->markFunctionEpilogueDone(/* activationOnly = */ true);
|
||||
|
||||
/* Don't clobber callee with rval; rval gets read from fp->rval. */
|
||||
return ok;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T> class PrimitiveBehavior { };
|
||||
@ -229,6 +350,20 @@ ValuePropertyBearer(JSContext *cx, const Value &v, int spindex)
|
||||
return pobj;
|
||||
}
|
||||
|
||||
inline bool
|
||||
FunctionNeedsPrologue(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
/* Heavyweight functions need call objects created. */
|
||||
if (fun->isHeavyweight())
|
||||
return true;
|
||||
|
||||
/* Outer and inner functions need to preserve nesting invariants. */
|
||||
if (cx->typeInferenceEnabled() && fun->script()->nesting())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ScriptPrologue(JSContext *cx, StackFrame *fp, bool newType)
|
||||
{
|
||||
|
@ -3018,11 +3018,10 @@ CreateThisForFunctionWithType(JSContext *cx, types::TypeObject *type, JSObject *
|
||||
JSObject *
|
||||
js_CreateThisForFunctionWithProto(JSContext *cx, JSObject *callee, JSObject *proto)
|
||||
{
|
||||
JSScript *calleeScript = callee->getFunctionPrivate()->script();
|
||||
JSObject *res;
|
||||
|
||||
if (proto) {
|
||||
types::TypeObject *type = proto->getNewType(cx, calleeScript);
|
||||
types::TypeObject *type = proto->getNewType(cx, callee->getFunctionPrivate());
|
||||
if (!type)
|
||||
return NULL;
|
||||
res = CreateThisForFunctionWithType(cx, type, callee->getParent());
|
||||
@ -3032,7 +3031,7 @@ js_CreateThisForFunctionWithProto(JSContext *cx, JSObject *callee, JSObject *pro
|
||||
}
|
||||
|
||||
if (res && cx->typeInferenceEnabled())
|
||||
TypeScript::SetThis(cx, calleeScript, types::Type::ObjectType(res));
|
||||
TypeScript::SetThis(cx, callee->getFunctionPrivate()->script(), types::Type::ObjectType(res));
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -3802,6 +3801,10 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
|
||||
JS_ASSERT(!a->isDenseArray() && !b->isDenseArray());
|
||||
JS_ASSERT(!a->isArrayBuffer() && !b->isArrayBuffer());
|
||||
|
||||
/* New types for a JSObject need to be stable when trading guts. */
|
||||
TypeObject *newTypeA = a->newType;
|
||||
TypeObject *newTypeB = b->newType;
|
||||
|
||||
/* Trade the guts of the objects. */
|
||||
const size_t size = a->structSize();
|
||||
if (size == b->structSize()) {
|
||||
@ -3872,6 +3875,9 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
|
||||
reserved.newaslots = NULL;
|
||||
reserved.newbslots = NULL;
|
||||
}
|
||||
|
||||
a->newType = newTypeA;
|
||||
b->newType = newTypeB;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4479,6 +4485,14 @@ JSObject::allocSlots(JSContext *cx, size_t newcap)
|
||||
bool
|
||||
JSObject::growSlots(JSContext *cx, size_t newcap)
|
||||
{
|
||||
/*
|
||||
* Slots are only allocated for call objects when new properties are
|
||||
* added to them, which can only happen while the call is still on the
|
||||
* stack (and an eval, DEFFUN, etc. happens). We thus do not need to
|
||||
* worry about updating any active outer function args/vars.
|
||||
*/
|
||||
JS_ASSERT_IF(isCall(), maybeCallObjStackFrame() != NULL);
|
||||
|
||||
/*
|
||||
* When an object with CAPACITY_DOUBLING_MAX or fewer slots needs to
|
||||
* grow, double its capacity, to add N elements in amortized O(N) time.
|
||||
@ -4545,6 +4559,15 @@ JSObject::growSlots(JSContext *cx, size_t newcap)
|
||||
void
|
||||
JSObject::shrinkSlots(JSContext *cx, size_t newcap)
|
||||
{
|
||||
/*
|
||||
* Refuse to shrink slots for call objects. This only happens in a very
|
||||
* obscure situation (deleting names introduced by a direct 'eval') and
|
||||
* allowing the slots pointer to change may require updating pointers in
|
||||
* the function's active args/vars information.
|
||||
*/
|
||||
if (isCall())
|
||||
return;
|
||||
|
||||
uint32 oldcap = numSlots();
|
||||
JS_ASSERT(newcap <= oldcap);
|
||||
JS_ASSERT(newcap >= slotSpan());
|
||||
|
@ -733,6 +733,7 @@ struct JSObject : js::gc::Cell {
|
||||
|
||||
private:
|
||||
inline js::Value* fixedSlots() const;
|
||||
inline bool hasContiguousSlots(size_t start, size_t count) const;
|
||||
|
||||
public:
|
||||
/* Minimum size for dynamically allocated slots. */
|
||||
@ -793,12 +794,22 @@ struct JSObject : js::gc::Cell {
|
||||
|
||||
void rollbackProperties(JSContext *cx, uint32 slotSpan);
|
||||
|
||||
js::Value& getSlotRef(uintN slot) {
|
||||
JS_ASSERT(slot < capacity);
|
||||
js::Value *getSlotAddress(uintN slot) {
|
||||
/*
|
||||
* This can be used to get the address of the end of the slots for the
|
||||
* object, which may be necessary when fetching zero-length arrays of
|
||||
* slots (e.g. for callObjVarArray).
|
||||
*/
|
||||
JS_ASSERT(slot <= capacity);
|
||||
size_t fixed = numFixedSlots();
|
||||
if (slot < fixed)
|
||||
return fixedSlots()[slot];
|
||||
return slots[slot - fixed];
|
||||
return fixedSlots() + slot;
|
||||
return slots + (slot - fixed);
|
||||
}
|
||||
|
||||
js::Value &getSlotRef(uintN slot) {
|
||||
JS_ASSERT(slot < capacity);
|
||||
return *getSlotAddress(slot);
|
||||
}
|
||||
|
||||
inline js::Value &nativeGetSlotRef(uintN slot);
|
||||
@ -888,10 +899,10 @@ struct JSObject : js::gc::Cell {
|
||||
inline void clearType();
|
||||
inline void setType(js::types::TypeObject *newType);
|
||||
|
||||
inline js::types::TypeObject *getNewType(JSContext *cx, JSScript *script = NULL,
|
||||
inline js::types::TypeObject *getNewType(JSContext *cx, JSFunction *fun = NULL,
|
||||
bool markUnknown = false);
|
||||
private:
|
||||
void makeNewType(JSContext *cx, JSScript *script, bool markUnknown);
|
||||
void makeNewType(JSContext *cx, JSFunction *fun, bool markUnknown);
|
||||
public:
|
||||
|
||||
/* Set a new prototype for an object with a singleton type. */
|
||||
@ -1098,6 +1109,14 @@ struct JSObject : js::gc::Cell {
|
||||
inline const js::Value &callObjVar(uintN i) const;
|
||||
inline void setCallObjVar(uintN i, const js::Value &v);
|
||||
|
||||
/*
|
||||
* Get the actual arrays of arguments and variables. Only call if type
|
||||
* inference is enabled, where we ensure that call object variables are in
|
||||
* contiguous slots (see NewCallObject).
|
||||
*/
|
||||
inline js::Value *callObjArgArray();
|
||||
inline js::Value *callObjVarArray();
|
||||
|
||||
/*
|
||||
* Date-specific getters and setters.
|
||||
*/
|
||||
|
@ -143,7 +143,7 @@ JSObject::getProperty(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp)
|
||||
} else {
|
||||
if (!js_GetProperty(cx, this, receiver, id, vp))
|
||||
return false;
|
||||
JS_ASSERT_IF(!hasSingletonType(),
|
||||
JS_ASSERT_IF(!hasSingletonType() && nativeContains(js_CheckForStringIndex(id)),
|
||||
js::types::TypeHasProperty(cx, type(), id, *vp));
|
||||
}
|
||||
return true;
|
||||
@ -404,6 +404,17 @@ JSObject::hasSlotsArray() const
|
||||
return slots && slots != fixedSlots();
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::hasContiguousSlots(size_t start, size_t count) const
|
||||
{
|
||||
/*
|
||||
* Check that the range [start, start+count) is either all inline or all
|
||||
* out of line.
|
||||
*/
|
||||
JS_ASSERT(start + count <= numSlots());
|
||||
return (start + count <= numFixedSlots()) || (start >= numFixedSlots());
|
||||
}
|
||||
|
||||
inline size_t
|
||||
JSObject::structSize() const
|
||||
{
|
||||
@ -600,6 +611,14 @@ JSObject::setCallObjArg(uintN i, const js::Value &v)
|
||||
setSlot(JSObject::CALL_RESERVED_SLOTS + i, v);
|
||||
}
|
||||
|
||||
inline js::Value *
|
||||
JSObject::callObjArgArray()
|
||||
{
|
||||
js::DebugOnly<JSFunction*> fun = getCallObjCalleeFunction();
|
||||
JS_ASSERT(hasContiguousSlots(JSObject::CALL_RESERVED_SLOTS, fun->nargs));
|
||||
return getSlotAddress(JSObject::CALL_RESERVED_SLOTS);
|
||||
}
|
||||
|
||||
inline const js::Value &
|
||||
JSObject::callObjVar(uintN i) const
|
||||
{
|
||||
@ -618,6 +637,29 @@ JSObject::setCallObjVar(uintN i, const js::Value &v)
|
||||
setSlot(JSObject::CALL_RESERVED_SLOTS + fun->nargs + i, v);
|
||||
}
|
||||
|
||||
inline js::Value *
|
||||
JSObject::callObjVarArray()
|
||||
{
|
||||
JSFunction *fun = getCallObjCalleeFunction();
|
||||
JS_ASSERT(hasContiguousSlots(JSObject::CALL_RESERVED_SLOTS + fun->nargs,
|
||||
fun->script()->bindings.countVars()));
|
||||
return getSlotAddress(JSObject::CALL_RESERVED_SLOTS + fun->nargs);
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* Any name atom for a function which will be added as a DeclEnv object to the
|
||||
* scope chain above call objects for fun.
|
||||
*/
|
||||
static inline JSAtom *
|
||||
CallObjectLambdaName(JSFunction *fun)
|
||||
{
|
||||
return (fun->flags & JSFUN_LAMBDA) ? fun->atom : NULL;
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
inline const js::Value &
|
||||
JSObject::getDateUTCTime() const
|
||||
{
|
||||
@ -852,7 +894,7 @@ JSObject::getType(JSContext *cx)
|
||||
}
|
||||
|
||||
inline js::types::TypeObject *
|
||||
JSObject::getNewType(JSContext *cx, JSScript *script, bool markUnknown)
|
||||
JSObject::getNewType(JSContext *cx, JSFunction *fun, bool markUnknown)
|
||||
{
|
||||
if (isDenseArray() && !makeDenseArraySlow(cx))
|
||||
return NULL;
|
||||
@ -868,12 +910,12 @@ JSObject::getNewType(JSContext *cx, JSScript *script, bool markUnknown)
|
||||
* Object.create is called with a prototype object that is also the
|
||||
* 'prototype' property of some scripted function.
|
||||
*/
|
||||
if (newType->newScript && newType->newScript->script != script)
|
||||
if (newType->newScript && newType->newScript->fun != fun)
|
||||
newType->clearNewScript(cx);
|
||||
if (markUnknown && cx->typeInferenceEnabled() && !newType->unknownProperties())
|
||||
newType->markUnknown(cx);
|
||||
} else {
|
||||
makeNewType(cx, script, markUnknown);
|
||||
makeNewType(cx, fun, markUnknown);
|
||||
}
|
||||
return newType;
|
||||
}
|
||||
|
@ -359,9 +359,35 @@ js_DumpScript(JSContext *cx, JSScript *script)
|
||||
return ok;
|
||||
}
|
||||
|
||||
static char *
|
||||
QuoteString(Sprinter *sp, JSString *str, uint32 quote);
|
||||
|
||||
static bool
|
||||
ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
|
||||
{
|
||||
if (JSVAL_IS_STRING(v)) {
|
||||
Sprinter sprinter;
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
char *nbytes = QuoteString(&sprinter, JSVAL_TO_STRING(v), '"');
|
||||
if (!nbytes)
|
||||
return false;
|
||||
nbytes = JS_sprintf_append(NULL, "%s", nbytes);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
if (!nbytes)
|
||||
return false;
|
||||
bytes->initBytes(nbytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cx->runtime->gcRunning || JS_THREAD_DATA(cx)->noGCOrAllocationCheck) {
|
||||
char *source = JS_sprintf_append(NULL, "<value>");
|
||||
if (!source)
|
||||
return false;
|
||||
bytes->initBytes(source);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
JSObject *obj = JSVAL_TO_OBJECT(v);
|
||||
Class *clasp = obj->getClass();
|
||||
|
@ -1126,9 +1126,6 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
|
||||
bool
|
||||
Compiler::defineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *script)
|
||||
{
|
||||
if (!globalScope.defs.length())
|
||||
return true;
|
||||
|
||||
JSObject *globalObj = globalScope.globalObj;
|
||||
|
||||
/* Define and update global properties. */
|
||||
@ -1181,18 +1178,29 @@ Compiler::defineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *scrip
|
||||
* object.
|
||||
*/
|
||||
while (worklist.length()) {
|
||||
JSScript *inner = worklist.back();
|
||||
JSScript *outer = worklist.back();
|
||||
worklist.popBack();
|
||||
|
||||
if (JSScript::isValidOffset(inner->objectsOffset)) {
|
||||
JSObjectArray *arr = inner->objects();
|
||||
for (size_t i = 0; i < arr->length; i++) {
|
||||
if (JSScript::isValidOffset(outer->objectsOffset)) {
|
||||
JSObjectArray *arr = outer->objects();
|
||||
|
||||
/*
|
||||
* If this is an eval script, don't treat the saved caller function
|
||||
* stored in the first object slot as an inner function.
|
||||
*/
|
||||
size_t start = outer->savedCallerFun ? 1 : 0;
|
||||
|
||||
for (size_t i = start; i < arr->length; i++) {
|
||||
JSObject *obj = arr->vector[i];
|
||||
if (!obj->isFunction())
|
||||
continue;
|
||||
JSFunction *fun = obj->getFunctionPrivate();
|
||||
JS_ASSERT(fun->isInterpreted());
|
||||
JSScript *inner = fun->script();
|
||||
if (outer->isHeavyweightFunction) {
|
||||
outer->isOuterFunction = true;
|
||||
inner->isInnerFunction = true;
|
||||
}
|
||||
if (!JSScript::isValidOffset(inner->globalsOffset) &&
|
||||
!JSScript::isValidOffset(inner->objectsOffset)) {
|
||||
continue;
|
||||
@ -1202,10 +1210,10 @@ Compiler::defineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *scrip
|
||||
}
|
||||
}
|
||||
|
||||
if (!JSScript::isValidOffset(inner->globalsOffset))
|
||||
if (!JSScript::isValidOffset(outer->globalsOffset))
|
||||
continue;
|
||||
|
||||
GlobalSlotArray *globalUses = inner->globals();
|
||||
GlobalSlotArray *globalUses = outer->globals();
|
||||
uint32 nGlobalUses = globalUses->length;
|
||||
for (uint32 i = 0; i < nGlobalUses; i++) {
|
||||
uint32 index = globalUses->vector[i].slot;
|
||||
|
@ -1212,15 +1212,6 @@ JSScript::NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
|
||||
cg->upvarMap.clear();
|
||||
}
|
||||
|
||||
/* Set global for compileAndGo scripts. */
|
||||
if (script->compileAndGo) {
|
||||
GlobalScope *globalScope = cg->compiler()->globalScope;
|
||||
if (globalScope->globalObj && globalScope->globalObj->isGlobal())
|
||||
script->where.global = globalScope->globalObj->asGlobal();
|
||||
else if (cx->globalObject->isGlobal())
|
||||
script->where.global = cx->globalObject->asGlobal();
|
||||
}
|
||||
|
||||
if (cg->globalUses.length()) {
|
||||
memcpy(script->globals()->vector, &cg->globalUses[0],
|
||||
cg->globalUses.length() * sizeof(GlobalSlotArray::Entry));
|
||||
|
@ -511,12 +511,18 @@ struct JSScript : public js::gc::Cell {
|
||||
undefined properties in this
|
||||
script */
|
||||
bool hasSingletons:1; /* script has singleton objects */
|
||||
bool hasFunction:1; /* function is active in 'where' union */
|
||||
bool hasFunction:1; /* script has an associated function */
|
||||
bool isHeavyweightFunction:1; /* function is heavyweight */
|
||||
bool isOuterFunction:1; /* function is heavyweight, with inner functions */
|
||||
bool isInnerFunction:1; /* function is directly nested in a heavyweight
|
||||
* outer function */
|
||||
bool isActiveEval:1; /* script came from eval(), and is still active */
|
||||
bool isCachedEval:1; /* script came from eval(), and is in eval cache */
|
||||
bool usedLazyArgs:1; /* script has used lazy arguments at some point */
|
||||
bool createdArgs:1; /* script has had arguments objects created */
|
||||
bool uninlineable:1; /* script is considered uninlineable by analysis */
|
||||
bool reentrantOuterFunction:1; /* outer function marked reentrant */
|
||||
bool typesPurged:1; /* TypeScript has been purged at some point */
|
||||
#ifdef JS_METHODJIT
|
||||
bool debugMode:1; /* script was compiled in debug mode */
|
||||
bool failedBoundsCheck:1; /* script has had hoisted bounds checks fail */
|
||||
@ -535,8 +541,10 @@ struct JSScript : public js::gc::Cell {
|
||||
* the script with 4 bytes. We use them to store tiny scripts like empty
|
||||
* scripts.
|
||||
*/
|
||||
#if JS_BITS_PER_WORD == 64
|
||||
#define JS_SCRIPT_INLINE_DATA_LIMIT 4
|
||||
uint8 inlineData[JS_SCRIPT_INLINE_DATA_LIMIT];
|
||||
#endif
|
||||
|
||||
const char *filename; /* source filename or null */
|
||||
JSAtom **atoms; /* maps immediate index to literal struct */
|
||||
@ -572,19 +580,6 @@ struct JSScript : public js::gc::Cell {
|
||||
/* array of execution counters for every JSOp in the script, by runmode */
|
||||
JSPCCounters pcCounters;
|
||||
|
||||
union {
|
||||
/* Function this script is the body for, if there is one. */
|
||||
JSFunction *fun;
|
||||
|
||||
/* Global object for this script, if compileAndGo. */
|
||||
js::GlobalObject *global;
|
||||
} where;
|
||||
|
||||
inline JSFunction *function() const {
|
||||
JS_ASSERT(hasFunction);
|
||||
return where.fun;
|
||||
}
|
||||
|
||||
#ifdef JS_CRASH_DIAGNOSTICS
|
||||
JSObject *ownerObject;
|
||||
|
||||
@ -594,17 +589,6 @@ struct JSScript : public js::gc::Cell {
|
||||
|
||||
void setOwnerObject(JSObject *owner);
|
||||
|
||||
/*
|
||||
* Associates this script with a specific function, constructing a new type
|
||||
* object for the function.
|
||||
*/
|
||||
bool typeSetFunction(JSContext *cx, JSFunction *fun, bool singleton = false);
|
||||
|
||||
inline bool hasGlobal() const;
|
||||
inline js::GlobalObject *global() const;
|
||||
|
||||
inline bool hasClearedGlobal() const;
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Unique identifier within the compartment for this script, used for
|
||||
@ -620,17 +604,41 @@ struct JSScript : public js::gc::Cell {
|
||||
/* Persistent type information retained across GCs. */
|
||||
js::types::TypeScript *types;
|
||||
|
||||
/* Ensure the script has types, bytecode and/or type inference results. */
|
||||
inline bool ensureHasTypes(JSContext *cx);
|
||||
inline bool ensureRanBytecode(JSContext *cx);
|
||||
/* Ensure the script has a TypeScript. */
|
||||
inline bool ensureHasTypes(JSContext *cx, JSFunction *fun = NULL);
|
||||
|
||||
/*
|
||||
* Ensure the script has scope and bytecode analysis information.
|
||||
* Performed when the script first runs, or first runs after a TypeScript
|
||||
* GC purge. If fun/scope are NULL then the script must already have types
|
||||
* with scope information.
|
||||
*/
|
||||
inline bool ensureRanAnalysis(JSContext *cx, JSFunction *fun = NULL, JSObject *scope = NULL);
|
||||
|
||||
/* Ensure the script has type inference analysis information. */
|
||||
inline bool ensureRanInference(JSContext *cx);
|
||||
|
||||
/* Filled in by one of the above. */
|
||||
inline bool hasAnalysis();
|
||||
inline void clearAnalysis();
|
||||
inline js::analyze::ScriptAnalysis *analysis();
|
||||
|
||||
/*
|
||||
* Associates this script with a specific function, constructing a new type
|
||||
* object for the function if necessary.
|
||||
*/
|
||||
bool typeSetFunction(JSContext *cx, JSFunction *fun, bool singleton = false);
|
||||
|
||||
inline bool hasGlobal() const;
|
||||
inline bool hasClearedGlobal() const;
|
||||
|
||||
inline JSFunction *function() const;
|
||||
inline js::GlobalObject *global() const;
|
||||
inline js::types::TypeScriptNesting *nesting() const;
|
||||
|
||||
inline void clearNesting();
|
||||
|
||||
private:
|
||||
bool makeTypes(JSContext *cx);
|
||||
bool makeTypes(JSContext *cx, JSFunction *fun);
|
||||
bool makeAnalysis(JSContext *cx);
|
||||
public:
|
||||
|
||||
|
@ -177,9 +177,8 @@ JSScript::hasGlobal() const
|
||||
* which have had their scopes cleared. compileAndGo code should not run
|
||||
* anymore against such globals.
|
||||
*/
|
||||
if (!compileAndGo)
|
||||
return false;
|
||||
js::GlobalObject *obj = hasFunction ? function()->getGlobal() : where.global;
|
||||
JS_ASSERT(types && types->hasScope());
|
||||
js::GlobalObject *obj = types->global;
|
||||
return obj && !obj->isCleared();
|
||||
}
|
||||
|
||||
@ -187,16 +186,39 @@ inline js::GlobalObject *
|
||||
JSScript::global() const
|
||||
{
|
||||
JS_ASSERT(hasGlobal());
|
||||
return hasFunction ? function()->getGlobal() : where.global;
|
||||
return types->global;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScript::hasClearedGlobal() const
|
||||
{
|
||||
if (!compileAndGo)
|
||||
return false;
|
||||
js::GlobalObject *obj = hasFunction ? function()->getGlobal() : where.global;
|
||||
JS_ASSERT(types && types->hasScope());
|
||||
js::GlobalObject *obj = types->global;
|
||||
return obj && obj->isCleared();
|
||||
}
|
||||
|
||||
inline JSFunction *
|
||||
JSScript::function() const
|
||||
{
|
||||
JS_ASSERT(hasFunction && types);
|
||||
return types->function;
|
||||
}
|
||||
|
||||
inline js::types::TypeScriptNesting *
|
||||
JSScript::nesting() const
|
||||
{
|
||||
JS_ASSERT(hasFunction && types && types->hasScope());
|
||||
return types->nesting;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSScript::clearNesting()
|
||||
{
|
||||
js::types::TypeScriptNesting *nesting = this->nesting();
|
||||
if (nesting) {
|
||||
js::Foreground::delete_(nesting);
|
||||
types->nesting = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* jsscriptinlines_h___ */
|
||||
|
@ -133,6 +133,7 @@ mjit::Compiler::Compiler(JSContext *cx, JSScript *outerScript, bool isConstructi
|
||||
inlining_(false),
|
||||
hasGlobalReallocation(false),
|
||||
oomInVector(false),
|
||||
gcNumber(cx->runtime->gcNumber),
|
||||
applyTricks(NoApplyTricks),
|
||||
pcLengths(NULL)
|
||||
{
|
||||
@ -188,7 +189,7 @@ mjit::Compiler::checkAnalysis(JSScript *script)
|
||||
return Compile_Abort;
|
||||
}
|
||||
|
||||
if (!script->ensureRanBytecode(cx))
|
||||
if (!script->ensureRanAnalysis(cx))
|
||||
return Compile_Error;
|
||||
if (cx->typeInferenceEnabled() && !script->ensureRanInference(cx))
|
||||
return Compile_Error;
|
||||
@ -338,6 +339,11 @@ mjit::Compiler::scanInlineCalls(uint32 index, uint32 depth)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!script->types || !script->types->hasScope()) {
|
||||
okay = false;
|
||||
break;
|
||||
}
|
||||
|
||||
CompileStatus status = checkAnalysis(script);
|
||||
if (status != Compile_Okay)
|
||||
return status;
|
||||
@ -742,27 +748,60 @@ mjit::Compiler::generatePrologue()
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the call object. */
|
||||
types::TypeScriptNesting *nesting = script->nesting();
|
||||
|
||||
/*
|
||||
* Run the function prologue if necessary. This is always done in a
|
||||
* stub for heavyweight functions (including nesting outer functions).
|
||||
*/
|
||||
JS_ASSERT_IF(nesting && nesting->children, script->function()->isHeavyweight());
|
||||
if (script->function()->isHeavyweight()) {
|
||||
prepareStubCall(Uses(0));
|
||||
INLINE_STUBCALL(stubs::CreateFunCallObject, REJOIN_CREATE_CALL_OBJECT);
|
||||
}
|
||||
|
||||
j.linkTo(masm.label(), &masm);
|
||||
|
||||
if (analysis->usesScopeChain() && !script->function()->isHeavyweight()) {
|
||||
INLINE_STUBCALL(stubs::FunctionFramePrologue, REJOIN_FUNCTION_PROLOGUE);
|
||||
} else {
|
||||
/*
|
||||
* Load the scope chain into the frame if necessary. The scope chain
|
||||
* is always set for global and eval frames, and will have been set by
|
||||
* Load the scope chain into the frame if it will be needed by NAME
|
||||
* opcodes or by the nesting prologue below. The scope chain is
|
||||
* always set for global and eval frames, and will have been set by
|
||||
* CreateFunCallObject for heavyweight function frames.
|
||||
*/
|
||||
RegisterID t0 = Registers::ReturnReg;
|
||||
Jump hasScope = masm.branchTest32(Assembler::NonZero,
|
||||
FrameFlagsAddress(), Imm32(StackFrame::HAS_SCOPECHAIN));
|
||||
masm.loadPayload(Address(JSFrameReg, StackFrame::offsetOfCallee(script->function())), t0);
|
||||
masm.loadPtr(Address(t0, offsetof(JSObject, parent)), t0);
|
||||
masm.storePtr(t0, Address(JSFrameReg, StackFrame::offsetOfScopeChain()));
|
||||
hasScope.linkTo(masm.label(), &masm);
|
||||
if (analysis->usesScopeChain() || nesting) {
|
||||
RegisterID t0 = Registers::ReturnReg;
|
||||
Jump hasScope = masm.branchTest32(Assembler::NonZero,
|
||||
FrameFlagsAddress(), Imm32(StackFrame::HAS_SCOPECHAIN));
|
||||
masm.loadPayload(Address(JSFrameReg, StackFrame::offsetOfCallee(script->function())), t0);
|
||||
masm.loadPtr(Address(t0, offsetof(JSObject, parent)), t0);
|
||||
masm.storePtr(t0, Address(JSFrameReg, StackFrame::offsetOfScopeChain()));
|
||||
hasScope.linkTo(masm.label(), &masm);
|
||||
}
|
||||
|
||||
if (nesting) {
|
||||
/*
|
||||
* Inline the common case for the nesting prologue: the
|
||||
* function is a non-heavyweight inner function with no
|
||||
* children of its own. We ensure during inference that the
|
||||
* outer function does not add scope objects for 'let' or
|
||||
* 'with', so that the frame's scope chain will be
|
||||
* the parent's call object, and if it differs from the
|
||||
* parent's current activation then the parent is reentrant.
|
||||
*/
|
||||
JSScript *parent = nesting->parent;
|
||||
JS_ASSERT(parent);
|
||||
JS_ASSERT_IF(parent->hasAnalysis() && parent->analysis()->ranBytecode(),
|
||||
!parent->analysis()->addsScopeObjects());
|
||||
|
||||
RegisterID t0 = Registers::ReturnReg;
|
||||
masm.move(ImmPtr(&parent->nesting()->activeCall), t0);
|
||||
masm.loadPtr(Address(t0), t0);
|
||||
|
||||
Address scopeChain(JSFrameReg, StackFrame::offsetOfScopeChain());
|
||||
Jump mismatch = masm.branchPtr(Assembler::NotEqual, t0, scopeChain);
|
||||
masm.add32(Imm32(1), AbsoluteAddress(&nesting->activeFrames));
|
||||
|
||||
stubcc.linkExitDirect(mismatch, stubcc.masm.label());
|
||||
OOL_STUBCALL(stubs::FunctionFramePrologue, REJOIN_FUNCTION_PROLOGUE);
|
||||
stubcc.crossJump(stubcc.masm.jump(), masm.label());
|
||||
}
|
||||
}
|
||||
|
||||
if (outerScript->usesArguments && !script->function()->isHeavyweight()) {
|
||||
@ -780,6 +819,8 @@ mjit::Compiler::generatePrologue()
|
||||
Address(JSFrameReg, StackFrame::offsetOfArgs()));
|
||||
hasArgs.linkTo(masm.label(), &masm);
|
||||
}
|
||||
|
||||
j.linkTo(masm.label(), &masm);
|
||||
}
|
||||
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
@ -846,6 +887,13 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
|
||||
if (globalSlots && globalObj->getRawSlots() != globalSlots)
|
||||
return Compile_Retry;
|
||||
|
||||
/*
|
||||
* Watch for GCs which occurred during compilation. These may have
|
||||
* renumbered shapes baked into the jitcode.
|
||||
*/
|
||||
if (cx->runtime->gcNumber != gcNumber)
|
||||
return Compile_Retry;
|
||||
|
||||
for (size_t i = 0; i < branchPatches.length(); i++) {
|
||||
Label label = labelOf(branchPatches[i].pc, branchPatches[i].inlineIndex);
|
||||
branchPatches[i].jump.linkTo(label, &masm);
|
||||
@ -2701,9 +2749,8 @@ mjit::Compiler::generateMethod()
|
||||
END_CASE(JSOP_UNBRAND)
|
||||
|
||||
BEGIN_CASE(JSOP_UNBRANDTHIS)
|
||||
jsop_this();
|
||||
jsop_unbrand();
|
||||
frame.pop();
|
||||
prepareStubCall(Uses(1));
|
||||
INLINE_STUBCALL(stubs::UnbrandThis, REJOIN_FALLTHROUGH);
|
||||
END_CASE(JSOP_UNBRANDTHIS)
|
||||
|
||||
BEGIN_CASE(JSOP_GETGLOBAL)
|
||||
@ -3112,22 +3159,31 @@ mjit::Compiler::emitReturn(FrameEntry *fe)
|
||||
* even on the entry frame. To avoid double-putting, EnterMethodJIT clears
|
||||
* out the entry frame's activation objects.
|
||||
*/
|
||||
if (script->hasFunction && script->function()->isHeavyweight()) {
|
||||
/* There will always be a call object. */
|
||||
prepareStubCall(Uses(fe ? 1 : 0));
|
||||
INLINE_STUBCALL(stubs::PutActivationObjects, REJOIN_NONE);
|
||||
} else {
|
||||
/* if (hasCallObj() || hasArgsObj()) */
|
||||
Jump putObjs = masm.branchTest32(Assembler::NonZero,
|
||||
Address(JSFrameReg, StackFrame::offsetOfFlags()),
|
||||
Imm32(StackFrame::HAS_CALL_OBJ | StackFrame::HAS_ARGS_OBJ));
|
||||
stubcc.linkExit(putObjs, Uses(frame.frameSlots()));
|
||||
if (script->hasFunction) {
|
||||
types::TypeScriptNesting *nesting = script->nesting();
|
||||
if (script->function()->isHeavyweight() || (nesting && nesting->children)) {
|
||||
prepareStubCall(Uses(fe ? 1 : 0));
|
||||
INLINE_STUBCALL(stubs::FunctionFrameEpilogue, REJOIN_NONE);
|
||||
} else {
|
||||
/* if (hasCallObj() || hasArgsObj()) */
|
||||
Jump putObjs = masm.branchTest32(Assembler::NonZero,
|
||||
Address(JSFrameReg, StackFrame::offsetOfFlags()),
|
||||
Imm32(StackFrame::HAS_CALL_OBJ | StackFrame::HAS_ARGS_OBJ));
|
||||
stubcc.linkExit(putObjs, Uses(frame.frameSlots()));
|
||||
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stubs::PutActivationObjects, REJOIN_NONE);
|
||||
stubcc.leave();
|
||||
OOL_STUBCALL(stubs::FunctionFrameEpilogue, REJOIN_NONE);
|
||||
|
||||
emitReturnValue(&stubcc.masm, fe);
|
||||
emitFinalReturn(stubcc.masm);
|
||||
emitReturnValue(&stubcc.masm, fe);
|
||||
emitFinalReturn(stubcc.masm);
|
||||
|
||||
/*
|
||||
* Do frame count balancing inline for inner functions in a nesting
|
||||
* with no children of their own.
|
||||
*/
|
||||
if (nesting)
|
||||
masm.sub32(Imm32(1), AbsoluteAddress(&nesting->activeFrames));
|
||||
}
|
||||
}
|
||||
|
||||
emitReturnValue(&masm, fe);
|
||||
@ -5039,6 +5095,22 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache, bool popGuaranteed
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a SETNAME to a variable of a non-reentrant outer function,
|
||||
* set the variable's slot directly for the active call object.
|
||||
*/
|
||||
if (cx->typeInferenceEnabled() && js_CodeSpec[*PC].format & JOF_NAME) {
|
||||
ScriptAnalysis::NameAccess access =
|
||||
analysis->resolveNameAccess(cx, ATOM_TO_JSID(atom), true);
|
||||
if (access.nesting) {
|
||||
Address address = frame.loadNameAddress(access);
|
||||
frame.storeTo(rhs, address, popGuaranteed);
|
||||
frame.shimmy(1);
|
||||
frame.freeReg(address.base);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the property directly if we are accessing a known object which
|
||||
* always has the property in a particular inline slot.
|
||||
@ -5201,6 +5273,26 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache, bool popGuaranteed
|
||||
void
|
||||
mjit::Compiler::jsop_name(JSAtom *atom, JSValueType type, bool isCall)
|
||||
{
|
||||
/*
|
||||
* If this is a NAME for a variable of a non-reentrant outer function, get
|
||||
* the variable's slot directly for the active call object. We always need
|
||||
* to check for undefined, however.
|
||||
*/
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
ScriptAnalysis::NameAccess access =
|
||||
analysis->resolveNameAccess(cx, ATOM_TO_JSID(atom), true);
|
||||
if (access.nesting) {
|
||||
Address address = frame.loadNameAddress(access);
|
||||
JSValueType type = knownPushedType(0);
|
||||
BarrierState barrier = pushAddressMaybeBarrier(address, type, true,
|
||||
/* testUndefined = */ true);
|
||||
finishBarrier(barrier, REJOIN_GETTER, 0);
|
||||
if (isCall)
|
||||
jsop_callgname_epilogue();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PICGenInfo pic(isCall ? ic::PICInfo::CALLNAME : ic::PICInfo::NAME, JSOp(*PC), true);
|
||||
|
||||
RESERVE_IC_SPACE(masm);
|
||||
@ -5258,6 +5350,24 @@ mjit::Compiler::jsop_name(JSAtom *atom, JSValueType type, bool isCall)
|
||||
bool
|
||||
mjit::Compiler::jsop_xname(JSAtom *atom)
|
||||
{
|
||||
/*
|
||||
* If this is a GETXPROP for a variable of a non-reentrant outer function,
|
||||
* treat in the same way as a NAME.
|
||||
*/
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
ScriptAnalysis::NameAccess access =
|
||||
analysis->resolveNameAccess(cx, ATOM_TO_JSID(atom), true);
|
||||
if (access.nesting) {
|
||||
frame.pop();
|
||||
Address address = frame.loadNameAddress(access);
|
||||
JSValueType type = knownPushedType(0);
|
||||
BarrierState barrier = pushAddressMaybeBarrier(address, type, true,
|
||||
/* testUndefined = */ true);
|
||||
finishBarrier(barrier, REJOIN_GETTER, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
PICGenInfo pic(ic::PICInfo::XNAME, JSOp(*PC), true);
|
||||
|
||||
FrameEntry *fe = frame.peek(-1);
|
||||
@ -5317,6 +5427,23 @@ mjit::Compiler::jsop_xname(JSAtom *atom)
|
||||
void
|
||||
mjit::Compiler::jsop_bindname(JSAtom *atom, bool usePropCache)
|
||||
{
|
||||
/*
|
||||
* If this is a BINDNAME for a variable of a non-reentrant outer function,
|
||||
* the object is definitely the outer function's active call object.
|
||||
*/
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
ScriptAnalysis::NameAccess access =
|
||||
analysis->resolveNameAccess(cx, ATOM_TO_JSID(atom), true);
|
||||
if (access.nesting) {
|
||||
RegisterID reg = frame.allocReg();
|
||||
JSObject **pobj = &access.nesting->activeCall;
|
||||
masm.move(ImmPtr(pobj), reg);
|
||||
masm.loadPtr(Address(reg), reg);
|
||||
frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PICGenInfo pic(ic::PICInfo::BIND, JSOp(*PC), usePropCache);
|
||||
|
||||
// This code does not check the frame flags to see if scopeChain has been
|
||||
@ -5458,6 +5585,16 @@ mjit::Compiler::jsop_this()
|
||||
stubcc.rejoin(Changes(1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Watch out for an obscure case where we don't know we are pushing
|
||||
* an object: the script has not yet had a 'this' value assigned,
|
||||
* so no pushed 'this' type has been inferred. Don't mark the type
|
||||
* as known in this case, preserving the invariant that compiler
|
||||
* types reflect inferred types.
|
||||
*/
|
||||
if (cx->typeInferenceEnabled() && knownPushedType(0) != JSVAL_TYPE_OBJECT)
|
||||
return;
|
||||
|
||||
// Now we know that |this| is an object.
|
||||
frame.pop();
|
||||
frame.learnThisIsObject(type != JSVAL_TYPE_OBJECT);
|
||||
@ -5908,7 +6045,7 @@ mjit::Compiler::jsop_callgname_epilogue()
|
||||
/* Paths for known object callee. */
|
||||
if (fval->isConstant()) {
|
||||
JSObject *obj = &fval->getValue().toObject();
|
||||
if (obj->getParent() == globalObj) {
|
||||
if (obj->getGlobal() == globalObj) {
|
||||
frame.push(UndefinedValue());
|
||||
} else {
|
||||
prepareStubCall(Uses(1));
|
||||
@ -5918,6 +6055,20 @@ mjit::Compiler::jsop_callgname_epilogue()
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fast path for functions whose global is statically known to be the
|
||||
* current global. This is primarily for calls on inner functions within
|
||||
* nestings, whose direct parent is a call object rather than the global
|
||||
* and which will make a stub call in the path below.
|
||||
*/
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
types::TypeSet *types = analysis->pushedTypes(PC, 0);
|
||||
if (types->hasGlobalObject(cx, globalObj)) {
|
||||
frame.push(UndefinedValue());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Optimized version. This inlines the common case, calling a
|
||||
* (non-proxied) function that has the same global as the current
|
||||
@ -6942,7 +7093,7 @@ mjit::Compiler::fixDoubleTypes(jsbytecode *target)
|
||||
} else {
|
||||
JS_ASSERT(vt.type == JSVAL_TYPE_DOUBLE);
|
||||
}
|
||||
} else if (fe->isType(JSVAL_TYPE_DOUBLE)) {
|
||||
} else if (vt.type == JSVAL_TYPE_DOUBLE) {
|
||||
fixedDoubleToAnyEntries.append(newv->slot);
|
||||
frame.syncAndForgetFe(fe);
|
||||
frame.forgetLoopReg(fe);
|
||||
|
@ -468,6 +468,7 @@ class Compiler : public BaseCompiler
|
||||
bool inlining_;
|
||||
bool hasGlobalReallocation;
|
||||
bool oomInVector; // True if we have OOM'd appending to a vector.
|
||||
uint32 gcNumber;
|
||||
enum { NoApplyTricks, LazyArgsObj } applyTricks;
|
||||
PCLengthEntry *pcLengths;
|
||||
|
||||
|
@ -878,6 +878,19 @@ FrameState::syncAndForgetFe(FrameEntry *fe, bool markSynced)
|
||||
fe->data.setMemory();
|
||||
}
|
||||
|
||||
inline JSC::MacroAssembler::Address
|
||||
FrameState::loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access)
|
||||
{
|
||||
JS_ASSERT(access.script && access.nesting);
|
||||
|
||||
RegisterID reg = allocReg();
|
||||
Value **pbase = access.arg ? &access.nesting->argArray : &access.nesting->varArray;
|
||||
masm.move(ImmPtr(pbase), reg);
|
||||
masm.loadPtr(Address(reg), reg);
|
||||
|
||||
return Address(reg, access.index * sizeof(Value));
|
||||
}
|
||||
|
||||
inline void
|
||||
FrameState::forgetLoopReg(FrameEntry *fe)
|
||||
{
|
||||
|
@ -1949,9 +1949,6 @@ FrameState::pushCopyOf(FrameEntry *backing)
|
||||
FrameEntry *
|
||||
FrameState::walkTrackerForUncopy(FrameEntry *original)
|
||||
{
|
||||
/* Temporary entries are immutable and should never be uncopied. */
|
||||
JS_ASSERT(!isTemporary(original));
|
||||
|
||||
uint32 firstCopy = InvalidIndex;
|
||||
FrameEntry *bestFe = NULL;
|
||||
uint32 ncopies = 0;
|
||||
@ -1978,7 +1975,7 @@ FrameState::walkTrackerForUncopy(FrameEntry *original)
|
||||
|
||||
JS_ASSERT(firstCopy != InvalidIndex);
|
||||
JS_ASSERT(bestFe);
|
||||
JS_ASSERT(bestFe > original);
|
||||
JS_ASSERT_IF(!isTemporary(original), bestFe > original);
|
||||
|
||||
/* Mark all extra copies as copies of the new backing index. */
|
||||
bestFe->setCopyOf(NULL);
|
||||
@ -2873,6 +2870,8 @@ FrameState::clearTemporaries()
|
||||
for (FrameEntry *fe = temporaries; fe < temporariesTop; fe++) {
|
||||
if (!fe->isTracked())
|
||||
continue;
|
||||
if (fe->isCopied())
|
||||
uncopy(fe);
|
||||
forgetAllRegs(fe);
|
||||
fe->resetSynced();
|
||||
}
|
||||
|
@ -953,6 +953,12 @@ class FrameState
|
||||
inline void syncAndForgetFe(FrameEntry *fe, bool markSynced = false);
|
||||
inline void forgetLoopReg(FrameEntry *fe);
|
||||
|
||||
/*
|
||||
* Get an address for the specified name access in another script.
|
||||
* The compiler owns the result's base register.
|
||||
*/
|
||||
inline Address loadNameAddress(const analyze::ScriptAnalysis::NameAccess &access);
|
||||
|
||||
private:
|
||||
inline AnyRegisterID allocAndLoadReg(FrameEntry *fe, bool fp, RematInfo::RematType type);
|
||||
inline void forgetReg(AnyRegisterID reg);
|
||||
|
@ -361,7 +361,7 @@ UncachedInlineCall(VMFrame &f, InitialFrameFlags initial,
|
||||
PreserveRegsGuard regsGuard(cx, regs);
|
||||
|
||||
/* Scope with a call object parented by callee's parent. */
|
||||
if (newfun->isHeavyweight() && !js::CreateFunCallObject(cx, regs.fp()))
|
||||
if (!regs.fp()->functionPrologue(cx))
|
||||
return false;
|
||||
|
||||
/*
|
||||
@ -497,13 +497,6 @@ stubs::UncachedCallHelper(VMFrame &f, uint32 argc, bool lowered, UncachedCallRes
|
||||
return;
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::PutActivationObjects(VMFrame &f)
|
||||
{
|
||||
JS_ASSERT(f.fp()->hasCallObj() || f.fp()->hasArgsObj());
|
||||
f.fp()->putActivationObjects();
|
||||
}
|
||||
|
||||
static void
|
||||
RemoveOrphanedNative(JSContext *cx, StackFrame *fp)
|
||||
{
|
||||
@ -634,7 +627,7 @@ js_InternalThrow(VMFrame &f)
|
||||
*/
|
||||
cx->compartment->jaegerCompartment()->setLastUnfinished(Jaeger_Unfinished);
|
||||
|
||||
if (!script->ensureRanBytecode(cx)) {
|
||||
if (!script->ensureRanAnalysis(cx)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
@ -670,14 +663,6 @@ js_InternalThrow(VMFrame &f)
|
||||
return script->nativeCodeForPC(fp->isConstructing(), pc);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::CreateFunCallObject(VMFrame &f)
|
||||
{
|
||||
JS_ASSERT(f.fp()->fun()->isHeavyweight());
|
||||
if (!js::CreateFunCallObject(f.cx, f.fp()))
|
||||
THROW();
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::CreateThis(VMFrame &f, JSObject *proto)
|
||||
{
|
||||
@ -1251,7 +1236,7 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
|
||||
JSOp op = JSOp(*pc);
|
||||
const JSCodeSpec *cs = &js_CodeSpec[op];
|
||||
|
||||
if (!script->ensureRanBytecode(cx)) {
|
||||
if (!script->ensureRanAnalysis(cx)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return js_InternalThrow(f);
|
||||
}
|
||||
@ -1395,7 +1380,7 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
|
||||
break;
|
||||
}
|
||||
|
||||
case REJOIN_CHECK_ARGUMENTS: {
|
||||
case REJOIN_CHECK_ARGUMENTS:
|
||||
/*
|
||||
* Do all the work needed in arity check JIT prologues after the
|
||||
* arguments check occurs (FixupArity has been called if needed, but
|
||||
@ -1406,22 +1391,17 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
|
||||
|
||||
SetValueRangeToUndefined(fp->slots(), script->nfixed);
|
||||
|
||||
if (fp->fun()->isHeavyweight()) {
|
||||
if (!js::CreateFunCallObject(cx, fp))
|
||||
return js_InternalThrow(f);
|
||||
}
|
||||
|
||||
if (!fp->functionPrologue(cx))
|
||||
return js_InternalThrow(f);
|
||||
/* FALLTHROUGH */
|
||||
}
|
||||
|
||||
case REJOIN_CREATE_CALL_OBJECT: {
|
||||
case REJOIN_FUNCTION_PROLOGUE:
|
||||
fp->scopeChain();
|
||||
|
||||
/* Construct the 'this' object for the frame if necessary. */
|
||||
if (!ScriptPrologueOrGeneratorResume(cx, fp, types::UseNewTypeAtEntry(cx, fp)))
|
||||
return js_InternalThrow(f);
|
||||
break;
|
||||
}
|
||||
|
||||
case REJOIN_CALL_PROLOGUE:
|
||||
case REJOIN_CALL_PROLOGUE_LOWERED_CALL:
|
||||
@ -1493,6 +1473,7 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
|
||||
break;
|
||||
|
||||
case JSOP_CALLGNAME:
|
||||
case JSOP_CALLNAME:
|
||||
if (!ComputeImplicitThis(cx, &fp->scopeChain(), nextsp[-2], &nextsp[-1]))
|
||||
return js_InternalThrow(f);
|
||||
f.regs.pc = nextpc;
|
||||
|
@ -576,11 +576,16 @@ LoopState::hoistArrayLengthCheck(InvariantArrayKind arrayKind, const CrossSSAVal
|
||||
|
||||
if (indexSlot == UNASSIGNED) {
|
||||
/* Hoist checks on x[n] accesses for constant n. */
|
||||
if (indexConstant < 0) {
|
||||
JaegerSpew(JSpew_Analysis, "Constant index is negative\n");
|
||||
return false;
|
||||
}
|
||||
return addHoistedCheck(arrayKind, objSlot, UNASSIGNED, UNASSIGNED, indexConstant);
|
||||
}
|
||||
|
||||
if (loopInvariantEntry(indexSlot)) {
|
||||
/* Hoist checks on x[y] accesses when y is loop invariant. */
|
||||
addNegativeCheck(indexSlot, indexConstant);
|
||||
return addHoistedCheck(arrayKind, objSlot, indexSlot, UNASSIGNED, indexConstant);
|
||||
}
|
||||
|
||||
|
@ -925,7 +925,8 @@ mjit::EnterMethodJIT(JSContext *cx, StackFrame *fp, void *code, Value *stackLimi
|
||||
}
|
||||
|
||||
/* See comment in mjit::Compiler::emitReturn. */
|
||||
fp->markActivationObjectsAsPut();
|
||||
if (fp->isFunctionFrame())
|
||||
fp->markFunctionEpilogueDone();
|
||||
|
||||
return ok ? Jaeger_Returned : Jaeger_Throwing;
|
||||
}
|
||||
|
@ -285,12 +285,15 @@ enum RejoinState {
|
||||
|
||||
/*
|
||||
* Type check on arguments failed during prologue, need stack check and
|
||||
* call object creation before script can execute.
|
||||
* the rest of the JIT prologue before the script can execute.
|
||||
*/
|
||||
REJOIN_CHECK_ARGUMENTS,
|
||||
|
||||
/* A GC while making a call object occurred, discarding the script's jitcode. */
|
||||
REJOIN_CREATE_CALL_OBJECT,
|
||||
/*
|
||||
* The script's jitcode was discarded after marking an outer function as
|
||||
* reentrant or due to a GC while creating a call object.
|
||||
*/
|
||||
REJOIN_FUNCTION_PROLOGUE,
|
||||
|
||||
/*
|
||||
* State after calling a stub which returns a JIT code pointer for a call
|
||||
|
@ -691,9 +691,10 @@ class SetPropCompiler : public PICStubCompiler
|
||||
* objects may differ due to eval(), DEFFUN, etc.).
|
||||
*/
|
||||
RecompilationMonitor monitor(cx);
|
||||
JSScript *script = obj->getCallObjCalleeFunction()->script();
|
||||
JSFunction *fun = obj->getCallObjCalleeFunction();
|
||||
JSScript *script = fun->script();
|
||||
uint16 slot = uint16(shape->shortid);
|
||||
if (!script->ensureHasTypes(cx))
|
||||
if (!script->ensureHasTypes(cx, fun))
|
||||
return error();
|
||||
{
|
||||
types::AutoEnterTypeInference enter(cx);
|
||||
|
@ -2194,6 +2194,19 @@ stubs::Unbrand(VMFrame &f)
|
||||
obj->unbrand(f.cx);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::UnbrandThis(VMFrame &f)
|
||||
{
|
||||
if (!ComputeThis(f.cx, f.fp()))
|
||||
THROW();
|
||||
Value &thisv = f.fp()->thisValue();
|
||||
if (!thisv.isObject())
|
||||
return;
|
||||
JSObject *obj = &thisv.toObject();
|
||||
if (obj->isNative())
|
||||
obj->unbrand(f.cx);
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::Pos(VMFrame &f)
|
||||
{
|
||||
@ -2520,6 +2533,27 @@ stubs::Exception(VMFrame &f)
|
||||
f.cx->clearPendingException();
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::FunctionFramePrologue(VMFrame &f)
|
||||
{
|
||||
if (!f.fp()->functionPrologue(f.cx))
|
||||
THROW();
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::FunctionFrameEpilogue(VMFrame &f)
|
||||
{
|
||||
f.fp()->functionEpilogue();
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::AnyFrameEpilogue(VMFrame &f)
|
||||
{
|
||||
if (f.fp()->isNonEvalFunctionFrame())
|
||||
f.fp()->functionEpilogue();
|
||||
stubs::ScriptDebugEpilogue(f);
|
||||
}
|
||||
|
||||
template <bool Clamped>
|
||||
int32 JS_FASTCALL
|
||||
stubs::ConvertToTypedInt(JSContext *cx, Value *vp)
|
||||
|
@ -113,8 +113,6 @@ void UncachedNewHelper(VMFrame &f, uint32 argc, UncachedCallResult *ucr);
|
||||
|
||||
void JS_FASTCALL CreateThis(VMFrame &f, JSObject *proto);
|
||||
void JS_FASTCALL Throw(VMFrame &f);
|
||||
void JS_FASTCALL PutActivationObjects(VMFrame &f);
|
||||
void JS_FASTCALL CreateFunCallObject(VMFrame &f);
|
||||
#if JS_MONOIC
|
||||
void * JS_FASTCALL InvokeTracer(VMFrame &f, ic::TraceICInfo *tic);
|
||||
#else
|
||||
@ -202,6 +200,7 @@ JSBool JS_FASTCALL InstanceOf(VMFrame &f);
|
||||
void JS_FASTCALL FastInstanceOf(VMFrame &f);
|
||||
void JS_FASTCALL ArgCnt(VMFrame &f);
|
||||
void JS_FASTCALL Unbrand(VMFrame &f);
|
||||
void JS_FASTCALL UnbrandThis(VMFrame &f);
|
||||
|
||||
/*
|
||||
* Helper for triggering recompilation should a name read miss a type barrier,
|
||||
@ -227,6 +226,11 @@ void JS_FASTCALL ConvertToTypedFloat(JSContext *cx, Value *vp);
|
||||
|
||||
void JS_FASTCALL Exception(VMFrame &f);
|
||||
|
||||
void JS_FASTCALL FunctionFramePrologue(VMFrame &f);
|
||||
void JS_FASTCALL FunctionFrameEpilogue(VMFrame &f);
|
||||
|
||||
void JS_FASTCALL AnyFrameEpilogue(VMFrame &f);
|
||||
|
||||
JSObject * JS_FASTCALL
|
||||
NewDenseUnallocatedArray(VMFrame &f, uint32 length);
|
||||
|
||||
|
@ -110,7 +110,8 @@ TrampolineCompiler::compileTrampoline(Trampolines::TrampolinePtr *where,
|
||||
/*
|
||||
* This is shamelessly copied from emitReturn, but with several changes:
|
||||
* - There was always at least one inline call.
|
||||
* - We don't know if there is a call object, so we always check.
|
||||
* - We don't know if there are activation objects or a script with nesting
|
||||
* state whose active frames need adjustment, so we always stub the epilogue.
|
||||
* - We don't know where we came from, so we don't know frame depth or PC.
|
||||
* - There is no stub buffer.
|
||||
*/
|
||||
@ -120,13 +121,8 @@ TrampolineCompiler::generateForceReturn(Assembler &masm)
|
||||
/* The JSStackFrame register may have been clobbered while returning, reload it. */
|
||||
masm.loadPtr(FrameAddress(VMFrame::offsetOfFp), JSFrameReg);
|
||||
|
||||
masm.fallibleVMCall(true, JS_FUNC_TO_DATA_PTR(void *, stubs::ScriptDebugEpilogue), NULL, NULL, 0);
|
||||
|
||||
/* if (hasArgsObj() || hasCallObj()) stubs::PutActivationObjects() */
|
||||
Jump noActObjs = masm.branchTest32(Assembler::Zero, FrameFlagsAddress(),
|
||||
Imm32(StackFrame::HAS_CALL_OBJ | StackFrame::HAS_ARGS_OBJ));
|
||||
masm.fallibleVMCall(true, JS_FUNC_TO_DATA_PTR(void *, stubs::PutActivationObjects), NULL, NULL, 0);
|
||||
noActObjs.linkTo(masm.label(), &masm);
|
||||
/* Perform the frame epilogue. */
|
||||
masm.fallibleVMCall(true, JS_FUNC_TO_DATA_PTR(void *, stubs::AnyFrameEpilogue), NULL, NULL, 0);
|
||||
|
||||
/* Store any known return value */
|
||||
masm.loadValueAsComponents(UndefinedValue(), JSReturnReg_Type, JSReturnReg_Data);
|
||||
|
@ -225,7 +225,10 @@ BreakpointSite::clearTrap(JSContext *cx, BreakpointSiteMap::Enum *e,
|
||||
trapClosure.setUndefined();
|
||||
if (enabledCount == 0) {
|
||||
*pc = realOpcode;
|
||||
recompile(cx, true); /* ignore failure */
|
||||
if (!cx->runtime->gcRunning) {
|
||||
/* If the GC is running then the script is being destroyed. */
|
||||
recompile(cx, true); /* ignore failure */
|
||||
}
|
||||
destroyIfEmpty(cx->runtime, e);
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,7 @@
|
||||
|
||||
#include "Stack.h"
|
||||
|
||||
#include "jsscriptinlines.h"
|
||||
#include "ArgumentsObject-inl.h"
|
||||
#include "methodjit/MethodJIT.h"
|
||||
|
||||
@ -130,11 +131,6 @@ StackFrame::resetCallFrame(JSScript *script)
|
||||
{
|
||||
JS_ASSERT(script == this->script());
|
||||
|
||||
/* Undo changes to frame made during execution; see also initCallFrame */
|
||||
|
||||
putActivationObjects();
|
||||
markActivationObjectsAsPut();
|
||||
|
||||
if (flags_ & UNDERFLOW_ARGS)
|
||||
SetValueRangeToUndefined(formalArgs() + numActualArgs(), formalArgsEnd());
|
||||
|
||||
@ -365,9 +361,44 @@ StackFrame::callObj() const
|
||||
return *pobj;
|
||||
}
|
||||
|
||||
inline void
|
||||
StackFrame::putActivationObjects()
|
||||
inline bool
|
||||
StackFrame::maintainNestingState() const
|
||||
{
|
||||
/*
|
||||
* Whether to invoke the nesting epilogue/prologue to maintain active
|
||||
* frame counts and check for reentrant outer functions.
|
||||
*/
|
||||
return isNonEvalFunctionFrame() && !isGeneratorFrame() && script()->nesting();
|
||||
}
|
||||
|
||||
inline bool
|
||||
StackFrame::functionPrologue(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(isNonEvalFunctionFrame());
|
||||
|
||||
JSFunction *fun = this->fun();
|
||||
|
||||
if (fun->isHeavyweight()) {
|
||||
if (!CreateFunCallObject(cx, this))
|
||||
return false;
|
||||
} else {
|
||||
/* Force instantiation of the scope chain, for JIT frames. */
|
||||
scopeChain();
|
||||
}
|
||||
|
||||
if (script()->nesting()) {
|
||||
JS_ASSERT(maintainNestingState());
|
||||
types::NestingPrologue(cx, this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void
|
||||
StackFrame::functionEpilogue(bool objectsOnly)
|
||||
{
|
||||
JS_ASSERT(isNonEvalFunctionFrame());
|
||||
|
||||
if (flags_ & (HAS_ARGS_OBJ | HAS_CALL_OBJ)) {
|
||||
/* NB: there is an ordering dependency here. */
|
||||
if (hasCallObj())
|
||||
@ -375,10 +406,13 @@ StackFrame::putActivationObjects()
|
||||
else if (hasArgsObj())
|
||||
js_PutArgsObject(this);
|
||||
}
|
||||
|
||||
if (!objectsOnly && maintainNestingState())
|
||||
types::NestingEpilogue(this);
|
||||
}
|
||||
|
||||
inline void
|
||||
StackFrame::markActivationObjectsAsPut()
|
||||
StackFrame::markFunctionEpilogueDone(bool activationOnly)
|
||||
{
|
||||
if (flags_ & (HAS_ARGS_OBJ | HAS_CALL_OBJ)) {
|
||||
if (hasArgsObj() && !argsObj().getPrivate()) {
|
||||
@ -399,6 +433,14 @@ StackFrame::markActivationObjectsAsPut()
|
||||
flags_ &= ~HAS_CALL_OBJ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For outer/inner function frames, undo the active frame balancing so that
|
||||
* when we redo it in the epilogue we get the right final value. The other
|
||||
* nesting epilogue changes (update active args/vars) are idempotent.
|
||||
*/
|
||||
if (!activationOnly && maintainNestingState())
|
||||
script()->nesting()->activeFrames++;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -547,7 +589,7 @@ ContextStack::popInlineFrame(FrameRegs ®s)
|
||||
JS_ASSERT(®s == &seg_->regs());
|
||||
|
||||
StackFrame *fp = regs.fp();
|
||||
fp->putActivationObjects();
|
||||
fp->functionEpilogue();
|
||||
|
||||
Value *newsp = fp->actualArgs() - 1;
|
||||
JS_ASSERT(newsp >= fp->prev()->base());
|
||||
|
@ -779,7 +779,8 @@ ContextStack::popFrame(const FrameGuard &fg)
|
||||
JS_ASSERT(space().firstUnused() == fg.regs_.sp);
|
||||
JS_ASSERT(&fg.regs_ == &seg_->regs());
|
||||
|
||||
fg.regs_.fp()->putActivationObjects();
|
||||
if (fg.regs_.fp()->isNonEvalFunctionFrame())
|
||||
fg.regs_.fp()->functionEpilogue();
|
||||
|
||||
seg_->popRegs(fg.prevRegs_);
|
||||
if (fg.pushedSeg_)
|
||||
|
@ -856,11 +856,28 @@ class StackFrame
|
||||
inline void setScopeChainWithOwnCallObj(JSObject &obj);
|
||||
|
||||
/*
|
||||
* NB: putActivationObjects does not mark activation objects as having been
|
||||
* put (since the frame is about to be popped).
|
||||
* Prologue for function frames: make a call object for heavyweight
|
||||
* functions, and maintain type nesting invariants.
|
||||
*/
|
||||
inline void putActivationObjects();
|
||||
inline void markActivationObjectsAsPut();
|
||||
inline bool functionPrologue(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Epilogue for function frames: put any args or call object for the frame
|
||||
* which may still be live, and maintain type nesting invariants. Only the
|
||||
* args/call objects are put if activationOnly is set. Note: this does not
|
||||
* mark the epilogue as having been completed, since the frame is about to
|
||||
* be popped. Use markFunctionEpilogueDone for this.
|
||||
*/
|
||||
inline void functionEpilogue(bool activationOnly = false);
|
||||
|
||||
/*
|
||||
* Mark any work needed in the function's epilogue as done. Only the args
|
||||
* and call objects are reset if activationOnly is set. If activationOnly
|
||||
* is *NOT* set, this call must be followed by a later functionEpilogue.
|
||||
*/
|
||||
inline void markFunctionEpilogueDone(bool activationOnly = false);
|
||||
|
||||
inline bool maintainNestingState() const;
|
||||
|
||||
/*
|
||||
* Variables object
|
||||
|
@ -1366,7 +1366,10 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
||||
case JSTRACE_SCRIPT:
|
||||
{
|
||||
JSScript *script = static_cast<JSScript *>(thing);
|
||||
if (script->data != script->inlineData) {
|
||||
#if JS_SCRIPT_INLINE_DATA_LIMIT
|
||||
if (script->data != script->inlineData)
|
||||
#endif
|
||||
{
|
||||
size_t usable = moz_malloc_usable_size(script->data);
|
||||
curr->scriptData += usable ? usable : script->dataSize();
|
||||
}
|
||||
|
@ -62,6 +62,11 @@ HTTP(..) == weightmapping-478.html weightmapping-478-ref.html
|
||||
HTTP(..) == weightmapping-7.html weightmapping-7-ref.html
|
||||
HTTP(..) == weightmapping-12579.html weightmapping-12579-ref.html
|
||||
|
||||
HTTP(..) == stretchmapping-all.html stretchmapping-all-ref.html
|
||||
HTTP(..) == stretchmapping-reverse.html stretchmapping-reverse-ref.html
|
||||
HTTP(..) == stretchmapping-35.html stretchmapping-35-ref.html
|
||||
HTTP(..) == stretchmapping-137.html stretchmapping-137-ref.html
|
||||
|
||||
# test for font-stretch using @font-face
|
||||
HTTP(..) == font-stretch-1.html font-stretch-1-ref.html
|
||||
|
||||
|
348
layout/reftests/font-matching/stretchmapping-137-ref.html
Normal file
348
layout/reftests/font-matching/stretchmapping-137-ref.html
Normal file
@ -0,0 +1,348 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>font-stretch mapping tests</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
body {
|
||||
margin: 50px;
|
||||
font-family: Verdana, sans-serif;
|
||||
}
|
||||
|
||||
h3, h4 { font-weight: normal; }
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0; margin: 0;
|
||||
font-family: test;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
p { width: 300px; }
|
||||
|
||||
.red { color: red; }
|
||||
|
||||
thead { font-weight: 400; font-size: 75%; }
|
||||
|
||||
/* make all the spans blocks to avoid influence of what's outside them
|
||||
on line-height calculations */
|
||||
span { display: block; }
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-thin.ttf);
|
||||
font-weight: 100;
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-regular.ttf);
|
||||
font-weight: 400;
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-light.ttf);
|
||||
font-weight: 200;
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-heavy.ttf);
|
||||
font-weight: 800;
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-medium.ttf);
|
||||
font-weight: 500;
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-black.ttf);
|
||||
font-weight: 900;
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test100;
|
||||
src: url(../fonts/mplus/mplus-1p-thin.ttf);
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test200;
|
||||
src: url(../fonts/mplus/mplus-1p-light.ttf);
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test400;
|
||||
src: url(../fonts/mplus/mplus-1p-regular.ttf);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test500;
|
||||
src: url(../fonts/mplus/mplus-1p-medium.ttf);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test800;
|
||||
src: url(../fonts/mplus/mplus-1p-heavy.ttf);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test900;
|
||||
src: url(../fonts/mplus/mplus-1p-black.ttf);
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.w1 { font-weight: 100; }
|
||||
.w2 { font-weight: 200; }
|
||||
.w3 { font-weight: 300; }
|
||||
.w4 { font-weight: 400; }
|
||||
.w5 { font-weight: 500; }
|
||||
.w6 { font-weight: 600; }
|
||||
.w7 { font-weight: 700; }
|
||||
.w8 { font-weight: 800; }
|
||||
.w9 { font-weight: 900; }
|
||||
|
||||
.w1 .fs1 { font-family: test100; }
|
||||
.w2 .fs1 { font-family: test100; }
|
||||
.w3 .fs1 { font-family: test100; }
|
||||
.w4 .fs1 { font-family: test400; }
|
||||
.w5 .fs1 { font-family: test400; }
|
||||
.w6 .fs1 { font-family: test400; }
|
||||
.w7 .fs1 { font-family: test400; }
|
||||
.w8 .fs1 { font-family: test400; }
|
||||
.w9 .fs1 { font-family: test400; }
|
||||
|
||||
.w1 .fs2 { font-family: test100; }
|
||||
.w2 .fs2 { font-family: test100; }
|
||||
.w3 .fs2 { font-family: test100; }
|
||||
.w4 .fs2 { font-family: test400; }
|
||||
.w5 .fs2 { font-family: test400; }
|
||||
.w6 .fs2 { font-family: test400; }
|
||||
.w7 .fs2 { font-family: test400; }
|
||||
.w8 .fs2 { font-family: test400; }
|
||||
.w9 .fs2 { font-family: test400; }
|
||||
|
||||
.w1 .fs3 { font-family: test200; }
|
||||
.w2 .fs3 { font-family: test200; }
|
||||
.w3 .fs3 { font-family: test200; }
|
||||
.w4 .fs3 { font-family: test200; }
|
||||
.w5 .fs3 { font-family: test200; }
|
||||
.w6 .fs3 { font-family: test800; }
|
||||
.w7 .fs3 { font-family: test800; }
|
||||
.w8 .fs3 { font-family: test800; }
|
||||
.w9 .fs3 { font-family: test800; }
|
||||
|
||||
.w1 .fs4 { font-family: test200; }
|
||||
.w2 .fs4 { font-family: test200; }
|
||||
.w3 .fs4 { font-family: test200; }
|
||||
.w4 .fs4 { font-family: test200; }
|
||||
.w5 .fs4 { font-family: test200; }
|
||||
.w6 .fs4 { font-family: test800; }
|
||||
.w7 .fs4 { font-family: test800; }
|
||||
.w8 .fs4 { font-family: test800; }
|
||||
.w9 .fs4 { font-family: test800; }
|
||||
|
||||
.w1 .fs5 { font-family: test200; }
|
||||
.w2 .fs5 { font-family: test200; }
|
||||
.w3 .fs5 { font-family: test200; }
|
||||
.w4 .fs5 { font-family: test200; }
|
||||
.w5 .fs5 { font-family: test200; }
|
||||
.w6 .fs5 { font-family: test800; }
|
||||
.w7 .fs5 { font-family: test800; }
|
||||
.w8 .fs5 { font-family: test800; }
|
||||
.w9 .fs5 { font-family: test800; }
|
||||
|
||||
.w1 .fs6 { font-family: test500; }
|
||||
.w2 .fs6 { font-family: test500; }
|
||||
.w3 .fs6 { font-family: test500; }
|
||||
.w4 .fs6 { font-family: test500; }
|
||||
.w5 .fs6 { font-family: test500; }
|
||||
.w6 .fs6 { font-family: test900; }
|
||||
.w7 .fs6 { font-family: test900; }
|
||||
.w8 .fs6 { font-family: test900; }
|
||||
.w9 .fs6 { font-family: test900; }
|
||||
|
||||
.w1 .fs7 { font-family: test500; }
|
||||
.w2 .fs7 { font-family: test500; }
|
||||
.w3 .fs7 { font-family: test500; }
|
||||
.w4 .fs7 { font-family: test500; }
|
||||
.w5 .fs7 { font-family: test500; }
|
||||
.w6 .fs7 { font-family: test900; }
|
||||
.w7 .fs7 { font-family: test900; }
|
||||
.w8 .fs7 { font-family: test900; }
|
||||
.w9 .fs7 { font-family: test900; }
|
||||
|
||||
.w1 .fs8 { font-family: test500; }
|
||||
.w2 .fs8 { font-family: test500; }
|
||||
.w3 .fs8 { font-family: test500; }
|
||||
.w4 .fs8 { font-family: test500; }
|
||||
.w5 .fs8 { font-family: test500; }
|
||||
.w6 .fs8 { font-family: test900; }
|
||||
.w7 .fs8 { font-family: test900; }
|
||||
.w8 .fs8 { font-family: test900; }
|
||||
.w9 .fs8 { font-family: test900; }
|
||||
|
||||
.w1 .fs9 { font-family: test500; }
|
||||
.w2 .fs9 { font-family: test500; }
|
||||
.w3 .fs9 { font-family: test500; }
|
||||
.w4 .fs9 { font-family: test500; }
|
||||
.w5 .fs9 { font-family: test500; }
|
||||
.w6 .fs9 { font-family: test900; }
|
||||
.w7 .fs9 { font-family: test900; }
|
||||
.w8 .fs9 { font-family: test900; }
|
||||
.w9 .fs9 { font-family: test900; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>Font family with ultra-condensed 100, 400, condensed 200, 800 and expanded 500, 900</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<th></th>
|
||||
<th class="red">1</th>
|
||||
<th>2</th>
|
||||
<th class="red">3</th>
|
||||
<th>4</th>
|
||||
<th>5</th>
|
||||
<th>6</th>
|
||||
<th class="red">7</th>
|
||||
<th>8</th>
|
||||
<th>9</th>
|
||||
</thead>
|
||||
<tr class="w1">
|
||||
<th>100</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w2">
|
||||
<th>200</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w3">
|
||||
<th>300</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w4">
|
||||
<th>400</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w5">
|
||||
<th>500</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w6">
|
||||
<th>600</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w7">
|
||||
<th>700</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w8">
|
||||
<th>800</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w9">
|
||||
<th>900</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
268
layout/reftests/font-matching/stretchmapping-137.html
Normal file
268
layout/reftests/font-matching/stretchmapping-137.html
Normal file
@ -0,0 +1,268 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>font-stretch mapping tests</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
body {
|
||||
margin: 50px;
|
||||
font-family: Verdana, sans-serif;
|
||||
}
|
||||
|
||||
h3, h4 { font-weight: normal; }
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0; margin: 0;
|
||||
font-family: test;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
p { width: 300px; }
|
||||
|
||||
.red { color: red; }
|
||||
|
||||
thead { font-weight: 400; font-size: 75%; }
|
||||
|
||||
/* make all the spans blocks to avoid influence of what's outside them
|
||||
on line-height calculations */
|
||||
span { display: block; }
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-thin.ttf);
|
||||
font-weight: 100;
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-regular.ttf);
|
||||
font-weight: 400;
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-light.ttf);
|
||||
font-weight: 200;
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-heavy.ttf);
|
||||
font-weight: 800;
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-medium.ttf);
|
||||
font-weight: 500;
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-black.ttf);
|
||||
font-weight: 900;
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test100;
|
||||
src: url(../fonts/mplus/mplus-1p-thin.ttf);
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test200;
|
||||
src: url(../fonts/mplus/mplus-1p-light.ttf);
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test400;
|
||||
src: url(../fonts/mplus/mplus-1p-regular.ttf);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test500;
|
||||
src: url(../fonts/mplus/mplus-1p-medium.ttf);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test800;
|
||||
src: url(../fonts/mplus/mplus-1p-heavy.ttf);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test900;
|
||||
src: url(../fonts/mplus/mplus-1p-black.ttf);
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.w1 { font-weight: 100; }
|
||||
.w2 { font-weight: 200; }
|
||||
.w3 { font-weight: 300; }
|
||||
.w4 { font-weight: 400; }
|
||||
.w5 { font-weight: 500; }
|
||||
.w6 { font-weight: 600; }
|
||||
.w7 { font-weight: 700; }
|
||||
.w8 { font-weight: 800; }
|
||||
.w9 { font-weight: 900; }
|
||||
|
||||
.fs1 { font-stretch: ultra-condensed; }
|
||||
.fs2 { font-stretch: extra-condensed; }
|
||||
.fs3 { font-stretch: condensed; }
|
||||
.fs4 { font-stretch: semi-condensed; }
|
||||
.fs5 { font-stretch: normal; }
|
||||
.fs6 { font-stretch: semi-expanded; }
|
||||
.fs7 { font-stretch: expanded; }
|
||||
.fs8 { font-stretch: extra-expanded; }
|
||||
.fs9 { font-stretch: ultra-expanded; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>Font family with ultra-condensed 100, 400, condensed 200, 800 and expanded 500, 900</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<th></th>
|
||||
<th class="red">1</th>
|
||||
<th>2</th>
|
||||
<th class="red">3</th>
|
||||
<th>4</th>
|
||||
<th>5</th>
|
||||
<th>6</th>
|
||||
<th class="red">7</th>
|
||||
<th>8</th>
|
||||
<th>9</th>
|
||||
</thead>
|
||||
<tr class="w1">
|
||||
<th>100</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w2">
|
||||
<th>200</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w3">
|
||||
<th>300</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w4">
|
||||
<th>400</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w5">
|
||||
<th>500</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w6">
|
||||
<th>600</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w7">
|
||||
<th>700</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w8">
|
||||
<th>800</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
<tr class="w9">
|
||||
<th>900</th>
|
||||
<td class="fs1"><span>か</span></td>
|
||||
<td class="fs2"><span>か</span></td>
|
||||
<td class="fs3"><span>か</span></td>
|
||||
<td class="fs4"><span>か</span></td>
|
||||
<td class="fs5"><span>か</span></td>
|
||||
<td class="fs6"><span>か</span></td>
|
||||
<td class="fs7"><span>か</span></td>
|
||||
<td class="fs8"><span>か</span></td>
|
||||
<td class="fs9"><span>か</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
320
layout/reftests/font-matching/stretchmapping-35-ref.html
Normal file
320
layout/reftests/font-matching/stretchmapping-35-ref.html
Normal file
@ -0,0 +1,320 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>font-stretch mapping tests</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
body {
|
||||
margin: 50px;
|
||||
font-family: Verdana, sans-serif;
|
||||
}
|
||||
|
||||
h3, h4 { font-weight: normal; }
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0; margin: 0;
|
||||
font-family: test;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
p { width: 300px; }
|
||||
|
||||
.red { color: red; }
|
||||
|
||||
thead { font-weight: 400; font-size: 75%; }
|
||||
|
||||
/* make all the spans blocks to avoid influence of what's outside them
|
||||
on line-height calculations */
|
||||
span { display: block; }
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-light.ttf);
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-medium.ttf);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-thin.ttf);
|
||||
font-weight: 100;
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-black.ttf);
|
||||
font-weight: 900;
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test100;
|
||||
src: url(../fonts/mplus/mplus-1p-thin.ttf);
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test200;
|
||||
src: url(../fonts/mplus/mplus-1p-light.ttf);
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test500;
|
||||
src: url(../fonts/mplus/mplus-1p-medium.ttf);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test900;
|
||||
src: url(../fonts/mplus/mplus-1p-black.ttf);
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.w1 { font-weight: 100; }
|
||||
.w2 { font-weight: 200; }
|
||||
.w3 { font-weight: 300; }
|
||||
.w4 { font-weight: 400; }
|
||||
.w5 { font-weight: 500; }
|
||||
.w6 { font-weight: 600; }
|
||||
.w7 { font-weight: 700; }
|
||||
.w8 { font-weight: 800; }
|
||||
.w9 { font-weight: 900; }
|
||||
|
||||
.w1 .fs1 { font-family: test100; }
|
||||
.w2 .fs1 { font-family: test100; }
|
||||
.w3 .fs1 { font-family: test100; }
|
||||
.w4 .fs1 { font-family: test100; }
|
||||
.w5 .fs1 { font-family: test100; }
|
||||
.w6 .fs1 { font-family: test900; }
|
||||
.w7 .fs1 { font-family: test900; }
|
||||
.w8 .fs1 { font-family: test900; }
|
||||
.w9 .fs1 { font-family: test900; }
|
||||
|
||||
.w1 .fs2 { font-family: test100; }
|
||||
.w2 .fs2 { font-family: test100; }
|
||||
.w3 .fs2 { font-family: test100; }
|
||||
.w4 .fs2 { font-family: test100; }
|
||||
.w5 .fs2 { font-family: test100; }
|
||||
.w6 .fs2 { font-family: test900; }
|
||||
.w7 .fs2 { font-family: test900; }
|
||||
.w8 .fs2 { font-family: test900; }
|
||||
.w9 .fs2 { font-family: test900; }
|
||||
|
||||
.w1 .fs3 { font-family: test100; }
|
||||
.w2 .fs3 { font-family: test100; }
|
||||
.w3 .fs3 { font-family: test100; }
|
||||
.w4 .fs3 { font-family: test100; }
|
||||
.w5 .fs3 { font-family: test100; }
|
||||
.w6 .fs3 { font-family: test900; }
|
||||
.w7 .fs3 { font-family: test900; }
|
||||
.w8 .fs3 { font-family: test900; }
|
||||
.w9 .fs3 { font-family: test900; }
|
||||
|
||||
.w1 .fs4 { font-family: test100; }
|
||||
.w2 .fs4 { font-family: test100; }
|
||||
.w3 .fs4 { font-family: test100; }
|
||||
.w4 .fs4 { font-family: test100; }
|
||||
.w5 .fs4 { font-family: test100; }
|
||||
.w6 .fs4 { font-family: test900; }
|
||||
.w7 .fs4 { font-family: test900; }
|
||||
.w8 .fs4 { font-family: test900; }
|
||||
.w9 .fs4 { font-family: test900; }
|
||||
|
||||
.w1 .fs5 { font-family: test200; }
|
||||
.w2 .fs5 { font-family: test200; }
|
||||
.w3 .fs5 { font-family: test200; }
|
||||
.w4 .fs5 { font-family: test500; }
|
||||
.w5 .fs5 { font-family: test500; }
|
||||
.w6 .fs5 { font-family: test500; }
|
||||
.w7 .fs5 { font-family: test500; }
|
||||
.w8 .fs5 { font-family: test500; }
|
||||
.w9 .fs5 { font-family: test500; }
|
||||
|
||||
.w1 .fs6 { font-family: test200; }
|
||||
.w2 .fs6 { font-family: test200; }
|
||||
.w3 .fs6 { font-family: test200; }
|
||||
.w4 .fs6 { font-family: test500; }
|
||||
.w5 .fs6 { font-family: test500; }
|
||||
.w6 .fs6 { font-family: test500; }
|
||||
.w7 .fs6 { font-family: test500; }
|
||||
.w8 .fs6 { font-family: test500; }
|
||||
.w9 .fs6 { font-family: test500; }
|
||||
|
||||
.w1 .fs7 { font-family: test200; }
|
||||
.w2 .fs7 { font-family: test200; }
|
||||
.w3 .fs7 { font-family: test200; }
|
||||
.w4 .fs7 { font-family: test500; }
|
||||
.w5 .fs7 { font-family: test500; }
|
||||
.w6 .fs7 { font-family: test500; }
|
||||
.w7 .fs7 { font-family: test500; }
|
||||
.w8 .fs7 { font-family: test500; }
|
||||
.w9 .fs7 { font-family: test500; }
|
||||
|
||||
.w1 .fs8 { font-family: test200; }
|
||||
.w2 .fs8 { font-family: test200; }
|
||||
.w3 .fs8 { font-family: test200; }
|
||||
.w4 .fs8 { font-family: test500; }
|
||||
.w5 .fs8 { font-family: test500; }
|
||||
.w6 .fs8 { font-family: test500; }
|
||||
.w7 .fs8 { font-family: test500; }
|
||||
.w8 .fs8 { font-family: test500; }
|
||||
.w9 .fs8 { font-family: test500; }
|
||||
|
||||
.w1 .fs9 { font-family: test200; }
|
||||
.w2 .fs9 { font-family: test200; }
|
||||
.w3 .fs9 { font-family: test200; }
|
||||
.w4 .fs9 { font-family: test500; }
|
||||
.w5 .fs9 { font-family: test500; }
|
||||
.w6 .fs9 { font-family: test500; }
|
||||
.w7 .fs9 { font-family: test500; }
|
||||
.w8 .fs9 { font-family: test500; }
|
||||
.w9 .fs9 { font-family: test500; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>Font family with normal width 200, 500 and condensed 100, 900</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<th></th>
|
||||
<th>1</th>
|
||||
<th>2</th>
|
||||
<th class="red">3</th>
|
||||
<th>4</th>
|
||||
<th class="red">5</th>
|
||||
<th>6</th>
|
||||
<th>7</th>
|
||||
<th>8</th>
|
||||
<th>9</th>
|
||||
</thead>
|
||||
<tr class="w1">
|
||||
<th>100</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w2">
|
||||
<th>200</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w3">
|
||||
<th>300</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w4">
|
||||
<th>400</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w5">
|
||||
<th>500</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w6">
|
||||
<th>600</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w7">
|
||||
<th>700</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w8">
|
||||
<th>800</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w9">
|
||||
<th>900</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
240
layout/reftests/font-matching/stretchmapping-35.html
Normal file
240
layout/reftests/font-matching/stretchmapping-35.html
Normal file
@ -0,0 +1,240 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>font-stretch mapping tests</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
body {
|
||||
margin: 50px;
|
||||
font-family: Verdana, sans-serif;
|
||||
}
|
||||
|
||||
h3, h4 { font-weight: normal; }
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0; margin: 0;
|
||||
font-family: test;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
p { width: 300px; }
|
||||
|
||||
.red { color: red; }
|
||||
|
||||
thead { font-weight: 400; font-size: 75%; }
|
||||
|
||||
/* make all the spans blocks to avoid influence of what's outside them
|
||||
on line-height calculations */
|
||||
span { display: block; }
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-light.ttf);
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-medium.ttf);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-thin.ttf);
|
||||
font-weight: 100;
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(../fonts/mplus/mplus-1p-black.ttf);
|
||||
font-weight: 900;
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test100;
|
||||
src: url(../fonts/mplus/mplus-1p-thin.ttf);
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test200;
|
||||
src: url(../fonts/mplus/mplus-1p-light.ttf);
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test500;
|
||||
src: url(../fonts/mplus/mplus-1p-medium.ttf);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: test900;
|
||||
src: url(../fonts/mplus/mplus-1p-black.ttf);
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.w1 { font-weight: 100; }
|
||||
.w2 { font-weight: 200; }
|
||||
.w3 { font-weight: 300; }
|
||||
.w4 { font-weight: 400; }
|
||||
.w5 { font-weight: 500; }
|
||||
.w6 { font-weight: 600; }
|
||||
.w7 { font-weight: 700; }
|
||||
.w8 { font-weight: 800; }
|
||||
.w9 { font-weight: 900; }
|
||||
|
||||
.fs1 { font-stretch: ultra-condensed; }
|
||||
.fs2 { font-stretch: extra-condensed; }
|
||||
.fs3 { font-stretch: condensed; }
|
||||
.fs4 { font-stretch: semi-condensed; }
|
||||
.fs5 { font-stretch: normal; }
|
||||
.fs6 { font-stretch: semi-expanded; }
|
||||
.fs7 { font-stretch: expanded; }
|
||||
.fs8 { font-stretch: extra-expanded; }
|
||||
.fs9 { font-stretch: ultra-expanded; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>Font family with normal width 200, 500 and condensed 100, 900</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<th></th>
|
||||
<th>1</th>
|
||||
<th>2</th>
|
||||
<th class="red">3</th>
|
||||
<th>4</th>
|
||||
<th class="red">5</th>
|
||||
<th>6</th>
|
||||
<th>7</th>
|
||||
<th>8</th>
|
||||
<th>9</th>
|
||||
</thead>
|
||||
<tr class="w1">
|
||||
<th>100</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w2">
|
||||
<th>200</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w3">
|
||||
<th>300</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w4">
|
||||
<th>400</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w5">
|
||||
<th>500</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w6">
|
||||
<th>600</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w7">
|
||||
<th>700</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w8">
|
||||
<th>800</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
<tr class="w9">
|
||||
<th>900</th>
|
||||
<td class="fs1"><span>あ</span></td>
|
||||
<td class="fs2"><span>あ</span></td>
|
||||
<td class="fs3"><span>あ</span></td>
|
||||
<td class="fs4"><span>あ</span></td>
|
||||
<td class="fs5"><span>あ</span></td>
|
||||
<td class="fs6"><span>あ</span></td>
|
||||
<td class="fs7"><span>あ</span></td>
|
||||
<td class="fs8"><span>あ</span></td>
|
||||
<td class="fs9"><span>あ</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
366
layout/reftests/font-matching/stretchmapping-all-ref.html
Normal file
366
layout/reftests/font-matching/stretchmapping-all-ref.html
Normal file
@ -0,0 +1,366 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>font-stretch matching tests</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
body {
|
||||
margin: 50px;
|
||||
font-family: Calibri, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
p { margin: 0; padding: 0; }
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: normal;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
th, td { width: 3em; text-align: left; }
|
||||
tr th { text-align: left; }
|
||||
|
||||
.fstest-full { font-family: fstest-full; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd1.ttf);
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd2.ttf);
|
||||
font-stretch: extra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd3.ttf);
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd4.ttf);
|
||||
font-stretch: semi-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd5.ttf);
|
||||
font-stretch: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd6.ttf);
|
||||
font-stretch: semi-expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd7.ttf);
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd8.ttf);
|
||||
font-stretch: extra-expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd9.ttf);
|
||||
font-stretch: ultra-expanded;
|
||||
}
|
||||
|
||||
.fstest-1-3 { font-family: fstest-1-3; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-3;
|
||||
src: url(../fonts/csstest-widths-wd1.ttf);
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-3;
|
||||
src: url(../fonts/csstest-widths-wd3.ttf);
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
.fstest-1-4 { font-family: fstest-1-4; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-4;
|
||||
src: url(../fonts/csstest-widths-wd1.ttf);
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-4;
|
||||
src: url(../fonts/csstest-widths-wd4.ttf);
|
||||
font-stretch: semi-condensed;
|
||||
}
|
||||
|
||||
.fstest-1-5 { font-family: fstest-1-5; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-5;
|
||||
src: url(../fonts/csstest-widths-wd1.ttf);
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-5;
|
||||
src: url(../fonts/csstest-widths-wd5.ttf);
|
||||
font-stretch: normal;
|
||||
}
|
||||
|
||||
.fstest-2-6 { font-family: fstest-2-6; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-2-6;
|
||||
src: url(../fonts/csstest-widths-wd2.ttf);
|
||||
font-stretch: extra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-2-6;
|
||||
src: url(../fonts/csstest-widths-wd6.ttf);
|
||||
font-stretch: semi-expanded;
|
||||
}
|
||||
|
||||
.fstest-4-6 { font-family: fstest-4-6; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-4-6;
|
||||
src: url(../fonts/csstest-widths-wd4.ttf);
|
||||
font-stretch: semi-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-4-6;
|
||||
src: url(../fonts/csstest-widths-wd6.ttf);
|
||||
font-stretch: semi-expanded;
|
||||
}
|
||||
|
||||
.fstest-4-7 { font-family: fstest-4-7; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-4-7;
|
||||
src: url(../fonts/csstest-widths-wd4.ttf);
|
||||
font-stretch: semi-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-4-7;
|
||||
src: url(../fonts/csstest-widths-wd7.ttf);
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
.fstest-6-7 { font-family: fstest-6-7; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-6-7;
|
||||
src: url(../fonts/csstest-widths-wd6.ttf);
|
||||
font-stretch: semi-expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-6-7;
|
||||
src: url(../fonts/csstest-widths-wd7.ttf);
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
.fstest-7-9 { font-family: fstest-7-9; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-7-9;
|
||||
src: url(../fonts/csstest-widths-wd7.ttf);
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-7-9;
|
||||
src: url(../fonts/csstest-widths-wd9.ttf);
|
||||
font-stretch: ultra-expanded;
|
||||
}
|
||||
|
||||
.fstest-8-9 { font-family: fstest-8-9; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-8-9;
|
||||
src: url(../fonts/csstest-widths-wd8.ttf);
|
||||
font-stretch: extra-expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-8-9;
|
||||
src: url(../fonts/csstest-widths-wd9.ttf);
|
||||
font-stretch: ultra-expanded;
|
||||
}
|
||||
|
||||
.fs1 { font-stretch: ultra-condensed; }
|
||||
.fs2 { font-stretch: extra-condensed; }
|
||||
.fs3 { font-stretch: condensed; }
|
||||
.fs4 { font-stretch: semi-condensed; }
|
||||
.fs5 { font-stretch: normal; }
|
||||
.fs6 { font-stretch: semi-expanded; }
|
||||
.fs7 { font-stretch: expanded; }
|
||||
.fs8 { font-stretch: extra-expanded; }
|
||||
.fs9 { font-stretch: ultra-expanded; }
|
||||
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>font-stretch mapping with different font family sets</p>
|
||||
<p>(only numbers should appear in the body of the table)</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<th>width</th>
|
||||
<th>full</th>
|
||||
<th>1-3</th>
|
||||
<th>1-4</th>
|
||||
<th>1-5</th>
|
||||
<th>2-6</th>
|
||||
<th>4-6</th>
|
||||
<th>4-7</th>
|
||||
<th>6-7</th>
|
||||
<th>7-9</th>
|
||||
<th>8-9</th>
|
||||
</thead>
|
||||
<tr class="fs1">
|
||||
<th>1</th>
|
||||
<td class="fstest-full">1</td>
|
||||
<td class="fstest-1-3">1</td>
|
||||
<td class="fstest-1-4">1</td>
|
||||
<td class="fstest-1-5">1</td>
|
||||
<td class="fstest-2-6">2</td>
|
||||
<td class="fstest-4-6">4</td>
|
||||
<td class="fstest-4-7">4</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs2">
|
||||
<th>2</th>
|
||||
<td class="fstest-full">2</td>
|
||||
<td class="fstest-1-3">1</td>
|
||||
<td class="fstest-1-4">1</td>
|
||||
<td class="fstest-1-5">1</td>
|
||||
<td class="fstest-2-6">2</td>
|
||||
<td class="fstest-4-6">4</td>
|
||||
<td class="fstest-4-7">4</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs3">
|
||||
<th>3</th>
|
||||
<td class="fstest-full">3</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">1</td>
|
||||
<td class="fstest-1-5">1</td>
|
||||
<td class="fstest-2-6">2</td>
|
||||
<td class="fstest-4-6">4</td>
|
||||
<td class="fstest-4-7">4</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs4">
|
||||
<th>4</th>
|
||||
<td class="fstest-full">4</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">1</td>
|
||||
<td class="fstest-2-6">2</td>
|
||||
<td class="fstest-4-6">4</td>
|
||||
<td class="fstest-4-7">4</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs5">
|
||||
<th>5</th>
|
||||
<td class="fstest-full">5</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">5</td>
|
||||
<td class="fstest-2-6">2</td>
|
||||
<td class="fstest-4-6">4</td>
|
||||
<td class="fstest-4-7">4</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs6">
|
||||
<th>6</th>
|
||||
<td class="fstest-full">6</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">5</td>
|
||||
<td class="fstest-2-6">6</td>
|
||||
<td class="fstest-4-6">6</td>
|
||||
<td class="fstest-4-7">7</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs7">
|
||||
<th>7</th>
|
||||
<td class="fstest-full">7</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">5</td>
|
||||
<td class="fstest-2-6">6</td>
|
||||
<td class="fstest-4-6">6</td>
|
||||
<td class="fstest-4-7">7</td>
|
||||
<td class="fstest-6-7">7</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs8">
|
||||
<th>8</th>
|
||||
<td class="fstest-full">8</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">5</td>
|
||||
<td class="fstest-2-6">6</td>
|
||||
<td class="fstest-4-6">6</td>
|
||||
<td class="fstest-4-7">7</td>
|
||||
<td class="fstest-6-7">7</td>
|
||||
<td class="fstest-7-9">9</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs9">
|
||||
<th>9</th>
|
||||
<td class="fstest-full">9</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">5</td>
|
||||
<td class="fstest-2-6">6</td>
|
||||
<td class="fstest-4-6">6</td>
|
||||
<td class="fstest-4-7">7</td>
|
||||
<td class="fstest-6-7">7</td>
|
||||
<td class="fstest-7-9">9</td>
|
||||
<td class="fstest-8-9">9</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
505
layout/reftests/font-matching/stretchmapping-all.html
Normal file
505
layout/reftests/font-matching/stretchmapping-all.html
Normal file
@ -0,0 +1,505 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>font-stretch matching tests</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
body {
|
||||
margin: 50px;
|
||||
font-family: Calibri, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
p { margin: 0; padding: 0; }
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: normal;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
th, td { width: 3em; text-align: left; }
|
||||
tr th { text-align: left; }
|
||||
|
||||
.fstest-full { font-family: fstest-full; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd1.ttf);
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd2.ttf);
|
||||
font-stretch: extra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd3.ttf);
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd4.ttf);
|
||||
font-stretch: semi-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd5.ttf);
|
||||
font-stretch: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd6.ttf);
|
||||
font-stretch: semi-expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd7.ttf);
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd8.ttf);
|
||||
font-stretch: extra-expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd9.ttf);
|
||||
font-stretch: ultra-expanded;
|
||||
}
|
||||
|
||||
.fstest-1-3 { font-family: fstest-1-3; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-3;
|
||||
src: url(../fonts/csstest-widths-wd1.ttf);
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-3;
|
||||
src: url(../fonts/csstest-widths-wd3.ttf);
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
.fstest-1-4 { font-family: fstest-1-4; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-4;
|
||||
src: url(../fonts/csstest-widths-wd1.ttf);
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-4;
|
||||
src: url(../fonts/csstest-widths-wd4.ttf);
|
||||
font-stretch: semi-condensed;
|
||||
}
|
||||
|
||||
.fstest-1-5 { font-family: fstest-1-5; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-5;
|
||||
src: url(../fonts/csstest-widths-wd1.ttf);
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-1-5;
|
||||
src: url(../fonts/csstest-widths-wd5.ttf);
|
||||
font-stretch: normal;
|
||||
}
|
||||
|
||||
.fstest-2-6 { font-family: fstest-2-6; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-2-6;
|
||||
src: url(../fonts/csstest-widths-wd2.ttf);
|
||||
font-stretch: extra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-2-6;
|
||||
src: url(../fonts/csstest-widths-wd6.ttf);
|
||||
font-stretch: semi-expanded;
|
||||
}
|
||||
|
||||
.fstest-4-6 { font-family: fstest-4-6; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-4-6;
|
||||
src: url(../fonts/csstest-widths-wd4.ttf);
|
||||
font-stretch: semi-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-4-6;
|
||||
src: url(../fonts/csstest-widths-wd6.ttf);
|
||||
font-stretch: semi-expanded;
|
||||
}
|
||||
|
||||
.fstest-4-7 { font-family: fstest-4-7; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-4-7;
|
||||
src: url(../fonts/csstest-widths-wd4.ttf);
|
||||
font-stretch: semi-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-4-7;
|
||||
src: url(../fonts/csstest-widths-wd7.ttf);
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
.fstest-6-7 { font-family: fstest-6-7; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-6-7;
|
||||
src: url(../fonts/csstest-widths-wd6.ttf);
|
||||
font-stretch: semi-expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-6-7;
|
||||
src: url(../fonts/csstest-widths-wd7.ttf);
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
.fstest-7-9 { font-family: fstest-7-9; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-7-9;
|
||||
src: url(../fonts/csstest-widths-wd7.ttf);
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-7-9;
|
||||
src: url(../fonts/csstest-widths-wd9.ttf);
|
||||
font-stretch: ultra-expanded;
|
||||
}
|
||||
|
||||
.fstest-8-9 { font-family: fstest-8-9; }
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-8-9;
|
||||
src: url(../fonts/csstest-widths-wd8.ttf);
|
||||
font-stretch: extra-expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-8-9;
|
||||
src: url(../fonts/csstest-widths-wd9.ttf);
|
||||
font-stretch: ultra-expanded;
|
||||
}
|
||||
|
||||
.fs1 { font-stretch: ultra-condensed; }
|
||||
.fs2 { font-stretch: extra-condensed; }
|
||||
.fs3 { font-stretch: condensed; }
|
||||
.fs4 { font-stretch: semi-condensed; }
|
||||
.fs5 { font-stretch: normal; }
|
||||
.fs6 { font-stretch: semi-expanded; }
|
||||
.fs7 { font-stretch: expanded; }
|
||||
.fs8 { font-stretch: extra-expanded; }
|
||||
.fs9 { font-stretch: ultra-expanded; }
|
||||
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>font-stretch mapping with different font family sets</p>
|
||||
<p>(only numbers should appear in the body of the table)</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<th>width</th>
|
||||
<th>full</th>
|
||||
<th>1-3</th>
|
||||
<th>1-4</th>
|
||||
<th>1-5</th>
|
||||
<th>2-6</th>
|
||||
<th>4-6</th>
|
||||
<th>4-7</th>
|
||||
<th>6-7</th>
|
||||
<th>7-9</th>
|
||||
<th>8-9</th>
|
||||
</thead>
|
||||
<tr class="fs1">
|
||||
<th>1</th>
|
||||
<td class="fstest-full">F</td>
|
||||
<td class="fstest-1-3">F</td>
|
||||
<td class="fstest-1-4">F</td>
|
||||
<td class="fstest-1-5">F</td>
|
||||
<td class="fstest-2-6">F</td>
|
||||
<td class="fstest-4-6">F</td>
|
||||
<td class="fstest-4-7">F</td>
|
||||
<td class="fstest-6-7">F</td>
|
||||
<td class="fstest-7-9">F</td>
|
||||
<td class="fstest-8-9">F</td>
|
||||
</tr>
|
||||
<tr class="fs2">
|
||||
<th>2</th>
|
||||
<td class="fstest-full">F</td>
|
||||
<td class="fstest-1-3">F</td>
|
||||
<td class="fstest-1-4">F</td>
|
||||
<td class="fstest-1-5">F</td>
|
||||
<td class="fstest-2-6">F</td>
|
||||
<td class="fstest-4-6">F</td>
|
||||
<td class="fstest-4-7">F</td>
|
||||
<td class="fstest-6-7">F</td>
|
||||
<td class="fstest-7-9">F</td>
|
||||
<td class="fstest-8-9">F</td>
|
||||
</tr>
|
||||
<tr class="fs3">
|
||||
<th>3</th>
|
||||
<td class="fstest-full">F</td>
|
||||
<td class="fstest-1-3">F</td>
|
||||
<td class="fstest-1-4">F</td>
|
||||
<td class="fstest-1-5">F</td>
|
||||
<td class="fstest-2-6">F</td>
|
||||
<td class="fstest-4-6">F</td>
|
||||
<td class="fstest-4-7">F</td>
|
||||
<td class="fstest-6-7">F</td>
|
||||
<td class="fstest-7-9">F</td>
|
||||
<td class="fstest-8-9">F</td>
|
||||
</tr>
|
||||
<tr class="fs4">
|
||||
<th>4</th>
|
||||
<td class="fstest-full">F</td>
|
||||
<td class="fstest-1-3">F</td>
|
||||
<td class="fstest-1-4">F</td>
|
||||
<td class="fstest-1-5">F</td>
|
||||
<td class="fstest-2-6">F</td>
|
||||
<td class="fstest-4-6">F</td>
|
||||
<td class="fstest-4-7">F</td>
|
||||
<td class="fstest-6-7">F</td>
|
||||
<td class="fstest-7-9">F</td>
|
||||
<td class="fstest-8-9">F</td>
|
||||
</tr>
|
||||
<tr class="fs5">
|
||||
<th>5</th>
|
||||
<td class="fstest-full">F</td>
|
||||
<td class="fstest-1-3">F</td>
|
||||
<td class="fstest-1-4">F</td>
|
||||
<td class="fstest-1-5">F</td>
|
||||
<td class="fstest-2-6">F</td>
|
||||
<td class="fstest-4-6">F</td>
|
||||
<td class="fstest-4-7">F</td>
|
||||
<td class="fstest-6-7">F</td>
|
||||
<td class="fstest-7-9">F</td>
|
||||
<td class="fstest-8-9">F</td>
|
||||
</tr>
|
||||
<tr class="fs6">
|
||||
<th>6</th>
|
||||
<td class="fstest-full">F</td>
|
||||
<td class="fstest-1-3">F</td>
|
||||
<td class="fstest-1-4">F</td>
|
||||
<td class="fstest-1-5">F</td>
|
||||
<td class="fstest-2-6">F</td>
|
||||
<td class="fstest-4-6">F</td>
|
||||
<td class="fstest-4-7">F</td>
|
||||
<td class="fstest-6-7">F</td>
|
||||
<td class="fstest-7-9">F</td>
|
||||
<td class="fstest-8-9">F</td>
|
||||
</tr>
|
||||
<tr class="fs7">
|
||||
<th>7</th>
|
||||
<td class="fstest-full">F</td>
|
||||
<td class="fstest-1-3">F</td>
|
||||
<td class="fstest-1-4">F</td>
|
||||
<td class="fstest-1-5">F</td>
|
||||
<td class="fstest-2-6">F</td>
|
||||
<td class="fstest-4-6">F</td>
|
||||
<td class="fstest-4-7">F</td>
|
||||
<td class="fstest-6-7">F</td>
|
||||
<td class="fstest-7-9">F</td>
|
||||
<td class="fstest-8-9">F</td>
|
||||
</tr>
|
||||
<tr class="fs8">
|
||||
<th>8</th>
|
||||
<td class="fstest-full">F</td>
|
||||
<td class="fstest-1-3">F</td>
|
||||
<td class="fstest-1-4">F</td>
|
||||
<td class="fstest-1-5">F</td>
|
||||
<td class="fstest-2-6">F</td>
|
||||
<td class="fstest-4-6">F</td>
|
||||
<td class="fstest-4-7">F</td>
|
||||
<td class="fstest-6-7">F</td>
|
||||
<td class="fstest-7-9">F</td>
|
||||
<td class="fstest-8-9">F</td>
|
||||
</tr>
|
||||
<tr class="fs9">
|
||||
<th>9</th>
|
||||
<td class="fstest-full">F</td>
|
||||
<td class="fstest-1-3">F</td>
|
||||
<td class="fstest-1-4">F</td>
|
||||
<td class="fstest-1-5">F</td>
|
||||
<td class="fstest-2-6">F</td>
|
||||
<td class="fstest-4-6">F</td>
|
||||
<td class="fstest-4-7">F</td>
|
||||
<td class="fstest-6-7">F</td>
|
||||
<td class="fstest-7-9">F</td>
|
||||
<td class="fstest-8-9">F</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!--
|
||||
|
||||
<p>Results based on spec logic:</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<th>width</th>
|
||||
<th>full</th>
|
||||
<th>1-3</th>
|
||||
<th>1-4</th>
|
||||
<th>1-5</th>
|
||||
<th>2-6</th>
|
||||
<th>4-6</th>
|
||||
<th>4-7</th>
|
||||
<th>6-7</th>
|
||||
<th>7-9</th>
|
||||
<th>8-9</th>
|
||||
</thead>
|
||||
<tr class="fs1">
|
||||
<th>1</th>
|
||||
<td class="fstest-full">1</td>
|
||||
<td class="fstest-1-3">1</td>
|
||||
<td class="fstest-1-4">1</td>
|
||||
<td class="fstest-1-5">1</td>
|
||||
<td class="fstest-2-6">2</td>
|
||||
<td class="fstest-4-6">4</td>
|
||||
<td class="fstest-4-7">4</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs2">
|
||||
<th>2</th>
|
||||
<td class="fstest-full">2</td>
|
||||
<td class="fstest-1-3">1</td>
|
||||
<td class="fstest-1-4">1</td>
|
||||
<td class="fstest-1-5">1</td>
|
||||
<td class="fstest-2-6">2</td>
|
||||
<td class="fstest-4-6">4</td>
|
||||
<td class="fstest-4-7">4</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs3">
|
||||
<th>3</th>
|
||||
<td class="fstest-full">3</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">1</td>
|
||||
<td class="fstest-1-5">1</td>
|
||||
<td class="fstest-2-6">2</td>
|
||||
<td class="fstest-4-6">4</td>
|
||||
<td class="fstest-4-7">4</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs4">
|
||||
<th>4</th>
|
||||
<td class="fstest-full">4</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">1</td>
|
||||
<td class="fstest-2-6">2</td>
|
||||
<td class="fstest-4-6">4</td>
|
||||
<td class="fstest-4-7">4</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs5">
|
||||
<th>5</th>
|
||||
<td class="fstest-full">5</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">5</td>
|
||||
<td class="fstest-2-6">2</td>
|
||||
<td class="fstest-4-6">4</td>
|
||||
<td class="fstest-4-7">4</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs6">
|
||||
<th>6</th>
|
||||
<td class="fstest-full">6</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">5</td>
|
||||
<td class="fstest-2-6">6</td>
|
||||
<td class="fstest-4-6">6</td>
|
||||
<td class="fstest-4-7">7</td>
|
||||
<td class="fstest-6-7">6</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs7">
|
||||
<th>7</th>
|
||||
<td class="fstest-full">7</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">5</td>
|
||||
<td class="fstest-2-6">6</td>
|
||||
<td class="fstest-4-6">6</td>
|
||||
<td class="fstest-4-7">7</td>
|
||||
<td class="fstest-6-7">7</td>
|
||||
<td class="fstest-7-9">7</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs8">
|
||||
<th>8</th>
|
||||
<td class="fstest-full">8</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">5</td>
|
||||
<td class="fstest-2-6">6</td>
|
||||
<td class="fstest-4-6">6</td>
|
||||
<td class="fstest-4-7">7</td>
|
||||
<td class="fstest-6-7">7</td>
|
||||
<td class="fstest-7-9">9</td>
|
||||
<td class="fstest-8-9">8</td>
|
||||
</tr>
|
||||
<tr class="fs9">
|
||||
<th>9</th>
|
||||
<td class="fstest-full">9</td>
|
||||
<td class="fstest-1-3">3</td>
|
||||
<td class="fstest-1-4">4</td>
|
||||
<td class="fstest-1-5">5</td>
|
||||
<td class="fstest-2-6">6</td>
|
||||
<td class="fstest-4-6">6</td>
|
||||
<td class="fstest-4-7">7</td>
|
||||
<td class="fstest-6-7">7</td>
|
||||
<td class="fstest-7-9">9</td>
|
||||
<td class="fstest-8-9">9</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
-->
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Assure OS/2 usWidthClass isn't referenced</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd5.ttf);
|
||||
font-stretch: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 50px;
|
||||
}
|
||||
|
||||
p.test {
|
||||
font-family: fstest-full;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.fs9 { font-stretch: ultra-condensed; }
|
||||
.fs8 { font-stretch: extra-condensed; }
|
||||
.fs7 { font-stretch: condensed; }
|
||||
.fs6 { font-stretch: semi-condensed; }
|
||||
.fs5 { font-stretch: normal; }
|
||||
.fs4 { font-stretch: semi-expanded; }
|
||||
.fs3 { font-stretch: expanded; }
|
||||
.fs2 { font-stretch: extra-expanded; }
|
||||
.fs1 { font-stretch: ultra-expanded; }
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>The numbers below should appear in ascending sequence:</p>
|
||||
|
||||
<p class="test">
|
||||
<span class="fs1">1</span>
|
||||
<span class="fs2">2</span>
|
||||
<span class="fs3">3</span>
|
||||
<span class="fs4">4</span>
|
||||
<span class="fs5">5</span>
|
||||
<span class="fs6">6</span>
|
||||
<span class="fs7">7</span>
|
||||
<span class="fs8">8</span>
|
||||
<span class="fs9">9</span>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
102
layout/reftests/font-matching/stretchmapping-reverse.html
Normal file
102
layout/reftests/font-matching/stretchmapping-reverse.html
Normal file
@ -0,0 +1,102 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Assure OS/2 usWidthClass isn't referenced</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd9.ttf);
|
||||
font-stretch: ultra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd8.ttf);
|
||||
font-stretch: extra-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd7.ttf);
|
||||
font-stretch: condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd6.ttf);
|
||||
font-stretch: semi-condensed;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd5.ttf);
|
||||
font-stretch: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd4.ttf);
|
||||
font-stretch: semi-expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd3.ttf);
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd2.ttf);
|
||||
font-stretch: extra-expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: fstest-full;
|
||||
src: url(../fonts/csstest-widths-wd1.ttf);
|
||||
font-stretch: ultra-expanded;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 50px;
|
||||
}
|
||||
|
||||
p.test {
|
||||
font-family: fstest-full;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.fs9 { font-stretch: ultra-condensed; }
|
||||
.fs8 { font-stretch: extra-condensed; }
|
||||
.fs7 { font-stretch: condensed; }
|
||||
.fs6 { font-stretch: semi-condensed; }
|
||||
.fs5 { font-stretch: normal; }
|
||||
.fs4 { font-stretch: semi-expanded; }
|
||||
.fs3 { font-stretch: expanded; }
|
||||
.fs2 { font-stretch: extra-expanded; }
|
||||
.fs1 { font-stretch: ultra-expanded; }
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>The numbers below should appear in ascending sequence:</p>
|
||||
|
||||
<p class="test">
|
||||
<span class="fs1">F</span>
|
||||
<span class="fs2">F</span>
|
||||
<span class="fs3">F</span>
|
||||
<span class="fs4">F</span>
|
||||
<span class="fs5">F</span>
|
||||
<span class="fs6">F</span>
|
||||
<span class="fs7">F</span>
|
||||
<span class="fs8">F</span>
|
||||
<span class="fs9">F</span>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -401,6 +401,12 @@ SpecialPowers.prototype = {
|
||||
closeLogFile: function() {
|
||||
this._mfl.close();
|
||||
},
|
||||
|
||||
addCategoryEntry: function(category, entry, value, persists, replace) {
|
||||
Cc["@mozilla.org/categorymanager;1"].
|
||||
getService(Components.interfaces.nsICategoryManager).
|
||||
addCategoryEntry(category, entry, value, persists, replace);
|
||||
},
|
||||
};
|
||||
|
||||
// Expose everything but internal APIs (starting with underscores) to
|
||||
|
Loading…
Reference in New Issue
Block a user