Merge inbound to m-c

This commit is contained in:
Wes Kocher 2014-03-07 17:07:37 -08:00
commit ffa3b0216a
11 changed files with 319 additions and 108 deletions

View File

@ -4580,7 +4580,20 @@ gfxFontGroup::MakeSpaceTextRun(const Parameters *aParams, uint32_t aFlags)
textRun->AddGlyphRun(font, gfxTextRange::kFontGroup, 0, false);
}
else {
textRun->SetSpaceGlyph(font, aParams->mContext, 0);
if (font->GetSpaceGlyph()) {
// Normally, the font has a cached space glyph, so we can avoid
// the cost of calling FindFontForChar.
textRun->SetSpaceGlyph(font, aParams->mContext, 0);
} else {
// In case the primary font doesn't have <space> (bug 970891),
// find one that does.
uint8_t matchType;
nsRefPtr<gfxFont> spaceFont =
FindFontForChar(' ', 0, MOZ_SCRIPT_LATIN, nullptr, &matchType);
if (spaceFont) {
textRun->SetSpaceGlyph(spaceFont, aParams->mContext, 0);
}
}
}
// Note that the gfxGlyphExtents glyph bounds storage for the font will

View File

@ -265,12 +265,6 @@ struct JSStringFinalizer {
void (*finalize)(const JSStringFinalizer *fin, jschar *chars);
};
// Return whether the first principal subsumes the second. The exact meaning of
// 'subsumes' is left up to the browser. Subsumption is checked inside the JS
// engine when determining, e.g., which stack frames to display in a backtrace.
typedef bool
(* JSSubsumesOp)(JSPrincipals *first, JSPrincipals *second);
// Check whether v is an instance of obj. Return false on error or exception,
// true on success with true in *bp if v is an instance of obj, false in
// *bp otherwise.

100
js/public/Principals.h Normal file
View File

@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* JSPrincipals and related interfaces. */
#ifndef js_Principals_h
#define js_Principals_h
#include "mozilla/Atomics.h"
#include <stdint.h>
#include "jspubtd.h"
struct JSPrincipals {
/* Don't call "destroy"; use reference counting macros below. */
#ifdef JS_THREADSAFE
mozilla::Atomic<int32_t> refcount;
#else
int32_t refcount;
#endif
#ifdef JS_DEBUG
/* A helper to facilitate principals debugging. */
uint32_t debugToken;
#endif
void setDebugToken(uint32_t token) {
# ifdef JS_DEBUG
debugToken = token;
# endif
}
/*
* This is not defined by the JS engine but should be provided by the
* embedding.
*/
JS_PUBLIC_API(void) dump();
};
extern JS_PUBLIC_API(void)
JS_HoldPrincipals(JSPrincipals *principals);
extern JS_PUBLIC_API(void)
JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals);
// Return whether the first principal subsumes the second. The exact meaning of
// 'subsumes' is left up to the browser. Subsumption is checked inside the JS
// engine when determining, e.g., which stack frames to display in a backtrace.
typedef bool
(* JSSubsumesOp)(JSPrincipals *first, JSPrincipals *second);
/*
* Used to check if a CSP instance wants to disable eval() and friends.
* See js_CheckCSPPermitsJSAction() in jsobj.
*/
typedef bool
(* JSCSPEvalChecker)(JSContext *cx);
struct JSSecurityCallbacks {
JSCSPEvalChecker contentSecurityPolicyAllows;
JSSubsumesOp subsumes;
};
extern JS_PUBLIC_API(void)
JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *callbacks);
extern JS_PUBLIC_API(const JSSecurityCallbacks *)
JS_GetSecurityCallbacks(JSRuntime *rt);
/*
* Code running with "trusted" principals will be given a deeper stack
* allocation than ordinary scripts. This allows trusted script to run after
* untrusted script has exhausted the stack. This function sets the
* runtime-wide trusted principal.
*
* This principals is not held (via JS_HoldPrincipals/JS_DropPrincipals) since
* there is no available JSContext. Instead, the caller must ensure that the
* given principals stays valid for as long as 'rt' may point to it. If the
* principals would be destroyed before 'rt', JS_SetTrustedPrincipals must be
* called again, passing nullptr for 'prin'.
*/
extern JS_PUBLIC_API(void)
JS_SetTrustedPrincipals(JSRuntime *rt, const JSPrincipals *prin);
typedef void
(* JSDestroyPrincipalsOp)(JSPrincipals *principals);
/*
* Initialize the callback that is called to destroy JSPrincipals instance
* when its reference counter drops to zero. The initialization can be done
* only once per JS runtime.
*/
extern JS_PUBLIC_API(void)
JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPrincipals);
#endif /* js_Principals_h */

View File

@ -0,0 +1,52 @@
// Test the JS shell's toy principals.
var count = 0;
// Given a string of letters |expected|, say "abc", assert that the stack
// contains calls to a series of functions named by the next letter from
// the string, say a, b, and then c. Younger frames appear earlier in
// |expected| than older frames.
function check(expected, stack) {
print("check(" + uneval(expected) + ") against:\n" + stack);
count++;
// Extract only the function names from the stack trace. Omit the frames
// for the top-level evaluation, if it is present.
var split = stack.split(/(.)?@.*\n/).slice(0, -1);
if (split[split.length - 1] === undefined)
split = split.slice(0, -2);
// Check the function names against the expected sequence.
assertEq(split.length, expected.length * 2);
for (var i = 0; i < expected.length; i++)
assertEq(split[i * 2 + 1], expected[i]);
}
var low = newGlobal({ principal: 0 });
var mid = newGlobal({ principal: 0xffff });
var high = newGlobal({ principal: 0xfffff });
eval('function a() { check("a", Error().stack); b(); }');
low .eval('function b() { check("b", Error().stack); c(); }');
mid .eval('function c() { check("cba", Error().stack); d(); }');
high.eval('function d() { check("dcba", Error().stack); e(); }');
eval('function e() { check("edcba", Error().stack); f(); }'); // no principal, so checks skipped
low .eval('function f() { check("fb", Error().stack); g(); }');
mid .eval('function g() { check("gfecba", Error().stack); h(); }');
high.eval('function h() { check("hgfedcba", Error().stack); }');
// Make everyone's functions visible to each other, as needed.
b = low .b;
low .c = mid .c;
mid .d = high.d;
high.e = e;
f = low .f;
low .g = mid .g;
mid .h = high.h;
low.check = mid.check = high.check = check;
// Kick the whole process off.
a();
assertEq(count, 8);

View File

@ -9,7 +9,6 @@
#ifndef jsapi_h
#define jsapi_h
#include "mozilla/Atomics.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/RangedPtr.h"
@ -26,6 +25,7 @@
#include "js/Class.h"
#include "js/HashTable.h"
#include "js/Id.h"
#include "js/Principals.h"
#include "js/RootingAPI.h"
#include "js/Utility.h"
#include "js/Value.h"
@ -779,20 +779,6 @@ typedef bool
typedef bool
(* JSLocaleToUnicode)(JSContext *cx, const char *src, JS::MutableHandleValue rval);
/*
* Security protocol types.
*/
typedef void
(* JSDestroyPrincipalsOp)(JSPrincipals *principals);
/*
* Used to check if a CSP instance wants to disable eval() and friends.
* See js_CheckCSPPermitsJSAction() in jsobj.
*/
typedef bool
(* JSCSPEvalChecker)(JSContext *cx);
/*
* Callback used to ask the embedding for the cross compartment wrapper handler
* that implements the desired prolicy for this kind of object in the
@ -3202,77 +3188,6 @@ JS_SetReservedSlot(JSObject *obj, uint32_t index, jsval v);
/************************************************************************/
/*
* Security protocol.
*/
struct JSPrincipals {
/* Don't call "destroy"; use reference counting macros below. */
#ifdef JS_THREADSAFE
mozilla::Atomic<int32_t> refcount;
#else
int32_t refcount;
#endif
#ifdef JS_DEBUG
/* A helper to facilitate principals debugging. */
uint32_t debugToken;
#endif
void setDebugToken(uint32_t token) {
# ifdef JS_DEBUG
debugToken = token;
# endif
}
/*
* This is not defined by the JS engine but should be provided by the
* embedding.
*/
JS_PUBLIC_API(void) dump();
};
extern JS_PUBLIC_API(void)
JS_HoldPrincipals(JSPrincipals *principals);
extern JS_PUBLIC_API(void)
JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals);
struct JSSecurityCallbacks {
JSCSPEvalChecker contentSecurityPolicyAllows;
JSSubsumesOp subsumes;
};
extern JS_PUBLIC_API(void)
JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *callbacks);
extern JS_PUBLIC_API(const JSSecurityCallbacks *)
JS_GetSecurityCallbacks(JSRuntime *rt);
/*
* Code running with "trusted" principals will be given a deeper stack
* allocation than ordinary scripts. This allows trusted script to run after
* untrusted script has exhausted the stack. This function sets the
* runtime-wide trusted principal.
*
* This principals is not held (via JS_HoldPrincipals/JS_DropPrincipals) since
* there is no available JSContext. Instead, the caller must ensure that the
* given principals stays valid for as long as 'rt' may point to it. If the
* principals would be destroyed before 'rt', JS_SetTrustedPrincipals must be
* called again, passing nullptr for 'prin'.
*/
extern JS_PUBLIC_API(void)
JS_SetTrustedPrincipals(JSRuntime *rt, const JSPrincipals *prin);
/*
* Initialize the callback that is called to destroy JSPrincipals instance
* when its reference counter drops to zero. The initialization can be done
* only once per JS runtime.
*/
extern JS_PUBLIC_API(void)
JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPrincipals);
/************************************************************************/
/*
* Functions and scripts.
*/

View File

@ -77,6 +77,7 @@ EXPORTS.js += [
'../public/LegacyIntTypes.h',
'../public/MemoryMetrics.h',
'../public/OldDebugAPI.h',
'../public/Principals.h',
'../public/ProfilingStack.h',
'../public/PropertyKey.h',
'../public/RequiredDefines.h',

View File

@ -190,11 +190,65 @@ static void
DestroyContext(JSContext *cx, bool withGC);
static JSObject *
NewGlobalObject(JSContext *cx, JS::CompartmentOptions &options);
NewGlobalObject(JSContext *cx, JS::CompartmentOptions &options,
JSPrincipals *principals);
static const JSErrorFormatString *
my_GetErrorMessage(void *userRef, const char *locale, const unsigned errorNumber);
/*
* A toy principals type for the shell.
*
* In the shell, a principal is simply a 32-bit mask: P subsumes Q if the
* set bits in P are a superset of those in Q. Thus, the principal 0 is
* subsumed by everything, and the principal ~0 subsumes everything.
*
* As a special case, a null pointer as a principal is treated like 0xffff.
*
* The 'newGlobal' function takes an option indicating which principal the
* new global should have; 'evaluate' does for the new code.
*/
class ShellPrincipals: public JSPrincipals {
uint32_t bits;
static uint32_t getBits(JSPrincipals *p) {
if (!p)
return 0xffff;
return static_cast<ShellPrincipals *>(p)->bits;
}
public:
ShellPrincipals(uint32_t bits, int32_t refcount = 0) : bits(bits) {
this->refcount = refcount;
}
static void destroy(JSPrincipals *principals) {
MOZ_ASSERT(principals != &fullyTrusted);
MOZ_ASSERT(principals->refcount == 0);
js_free(static_cast<ShellPrincipals *>(principals));
}
static bool subsumes(JSPrincipals *first, JSPrincipals *second) {
uint32_t firstBits = getBits(first);
uint32_t secondBits = getBits(second);
return (firstBits | secondBits) == firstBits;
}
static JSSecurityCallbacks securityCallbacks;
// Fully-trusted principals singleton.
static ShellPrincipals fullyTrusted;
};
JSSecurityCallbacks ShellPrincipals::securityCallbacks = {
nullptr, // contentSecurityPolicyAllows
subsumes
};
// The fully-trusted principal subsumes all other principals.
ShellPrincipals ShellPrincipals::fullyTrusted(-1, 1);
#ifdef EDITLINE
extern "C" {
extern JS_EXPORT_API(char *) readline(const char *prompt);
@ -2829,7 +2883,7 @@ WorkerMain(void *arg)
JS::CompartmentOptions compartmentOptions;
compartmentOptions.setVersion(JSVERSION_LATEST);
RootedObject global(cx, NewGlobalObject(cx, compartmentOptions));
RootedObject global(cx, NewGlobalObject(cx, compartmentOptions, nullptr));
if (!global)
break;
@ -4104,6 +4158,7 @@ WrapWithProto(JSContext *cx, unsigned argc, jsval *vp)
static bool
NewGlobal(JSContext *cx, unsigned argc, jsval *vp)
{
JSPrincipals *principals = nullptr;
JS::CompartmentOptions options;
options.setVersion(JSVERSION_LATEST);
@ -4121,9 +4176,23 @@ NewGlobal(JSContext *cx, unsigned argc, jsval *vp)
return false;
if (v.isBoolean())
options.setInvisibleToDebugger(v.toBoolean());
if (!JS_GetProperty(cx, opts, "principal", &v))
return false;
if (!v.isUndefined()) {
uint32_t bits;
if (!ToUint32(cx, v, &bits))
return false;
principals = cx->new_<ShellPrincipals>(bits);
if (!principals)
return false;
JS_HoldPrincipals(principals);
}
}
RootedObject global(cx, NewGlobalObject(cx, options));
RootedObject global(cx, NewGlobalObject(cx, options, principals));
if (principals)
JS_DropPrincipals(cx->runtime(), principals);
if (!global)
return false;
@ -4601,7 +4670,15 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
" Return a new global object in a new compartment. If options\n"
" is given, it may have any of the following properties:\n"
" sameZoneAs: the compartment will be in the same zone as the given object (defaults to a new zone)\n"
" invisibleToDebugger: the global will be invisible to the debugger (default false)"),
" invisibleToDebugger: the global will be invisible to the debugger (default false)\n"
" principal: if present, its value converted to a number must be an\n"
" integer that fits in 32 bits; use that as the new compartment's\n"
" principal. Shell principals are toys, meant only for testing; one\n"
" shell principal subsumes another if its set bits are a superset of\n"
" the other's. Thus, a principal of 0 subsumes nothing, while a\n"
" principals of ~0 subsumes all other principals. The absence of a\n"
" principal is treated as if its bits were 0xffff, for subsumption\n"
" purposes. If this property is omitted, supply no principal."),
JS_FN_HELP("enableStackWalkingAssertion", EnableStackWalkingAssertion, 1, 0,
"enableStackWalkingAssertion(enabled)",
@ -5520,9 +5597,10 @@ DestroyContext(JSContext *cx, bool withGC)
}
static JSObject *
NewGlobalObject(JSContext *cx, JS::CompartmentOptions &options)
NewGlobalObject(JSContext *cx, JS::CompartmentOptions &options,
JSPrincipals *principals)
{
RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, nullptr,
RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, principals,
JS::DontFireOnNewGlobalHook, options));
if (!glob)
return nullptr;
@ -5849,7 +5927,7 @@ Shell(JSContext *cx, OptionParser *op, char **envp)
RootedObject glob(cx);
JS::CompartmentOptions options;
options.setVersion(JSVERSION_LATEST);
glob = NewGlobalObject(cx, options);
glob = NewGlobalObject(cx, options, nullptr);
if (!glob)
return 1;
@ -6103,11 +6181,10 @@ main(int argc, char **argv, char **envp)
if (availMem > 0)
JS_SetGCParametersBasedOnAvailableMemory(rt, availMem);
/* Set the initial counter to 1 so the principal will never be destroyed. */
JSPrincipals shellTrustedPrincipals;
shellTrustedPrincipals.refcount = 1;
JS_SetTrustedPrincipals(rt, &ShellPrincipals::fullyTrusted);
JS_SetSecurityCallbacks(rt, &ShellPrincipals::securityCallbacks);
JS_InitDestroyPrincipalsCallback(rt, ShellPrincipals::destroy);
JS_SetTrustedPrincipals(rt, &shellTrustedPrincipals);
JS_SetOperationCallback(rt, ShellOperationCallback);
JS::SetAsmJSCacheOps(rt, &asmJSCacheOps);

View File

@ -295,3 +295,6 @@ pref(layout.css.text-align-true-value.enabled,true) == text-align-true.html text
!= control-chars-02.html control-chars-02-notref.html
== control-chars-03a.html control-chars-03-ref.html
== control-chars-03b.html control-chars-03-ref.html
# font fallback for <space> when not supported in the primary font family - bug 970891
HTTP(..) == space-font-1.html space-font-1-ref.html

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 970891</title>
<style type="text/css">
@font-face {
font-family: "test";
src: url(../fonts/markA.ttf);
}
div {
font-family: test, monospace;
font-size: 16px;
line-height: 32px;
}
span {
font-family: monospace;
}
</style>
</head>
<body>
<div><b>A</b><span> </span><b>A</b><span> </span><i>A</i><span> </span><i>A</i></div>
</body>
</html>

View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 970891</title>
<style type="text/css">
@font-face {
font-family: "test";
src: url(../fonts/markA.ttf);
}
div {
font-family: test, monospace;
font-size: 16px;
line-height: 32px;
}
span {
font-family: monospace;
}
</style>
</head>
<body>
<!-- markA does not have a glyph for the <space> character,
so the spaces should fall back to 'monospace'. -->
<div><b>A</b> <b>A</b> <i>A</i> <i>A</i><span>&nbsp;</span></div>
</body>
</html>

View File

@ -253,9 +253,7 @@ CPROJECT_TEMPLATE_FOOTER = """ </configuration>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
<resource resourceType="PROJECT" workspacePath="/Gecko"/>
</configuration>
<configuration configurationName="Default"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
</cproject>
@ -298,6 +296,10 @@ LANGUAGE_SETTINGS_TEMPLATE = """<?xml version="1.0" encoding="UTF-8" standalone=
</resource>
</language>
</provider>
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-859273372804152468" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot; -std=c++11" prefer-non-shared="true" store-entries-with-project="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
</extension>
</configuration>
@ -325,7 +327,7 @@ LAUNCH_CONFIG_TEMPLATE = """<?xml version="1.0" encoding="UTF-8" standalone="no"
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN_SYMBOL" value="main"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_ARGUMENTS" value="@LAUNCH_ARGS@"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="@LAUNCH_PROGRAM@"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="Gecko"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="gecko"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value=""/>
<booleanAttribute key="org.eclipse.cdt.launch.use_terminal" value="true"/>