commit | c2ba2ac888052d3ee5dbdd47e04c5db68df625db | [log] [tgz] |
---|---|---|
author | ticaiolima@gmail.com <ticaiolima@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc> | Tue Feb 09 16:30:24 2021 +0000 |
committer | ticaiolima@gmail.com <ticaiolima@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc> | Tue Feb 09 16:30:24 2021 +0000 |
tree | b4b8ba1ce872f35445556221127a96fb1e69d692 | |
parent | 5177b6edca8012ed4dfcdd6c12bcb2b3214d734c [diff] |
[ESNext] Implement private methods https://bugs.webkit.org/show_bug.cgi?id=194434 Reviewed by Filip Pizlo. JSTests: * stress/private-brand-installed-after-super-call-from-arrow-function.js: Added. * stress/private-brand-installed-after-super-call-from-eval.js: Added. * stress/private-method-brand-check.js: Added. * stress/private-method-change-attribute-from-branded-structure.js: Added. * stress/private-method-change-prototype-from-branded-structure.js: Added. * stress/private-method-check-private-brand-ic.js: Added. * stress/private-method-check-structure-miss.js: Added. * stress/private-method-comparison.js: Added. * stress/private-method-delete-property-from-branded-structure.js: Added. * stress/private-method-extends-brand-check.js: Added. * stress/private-method-get-and-call.js: Added. * stress/private-method-invalid-multiple-brand-installation.js: Added. * stress/private-method-invalidate-compiled-with-constant-symbol.js: Added. * stress/private-method-nested-class.js: Added. * stress/private-method-on-sealed-objects.js: Added. * stress/private-method-on-uncacheable-dictionary.js: Added. * stress/private-method-polymorphic-with-constant-symbol.js: Added. * stress/private-method-set-brand-should-have-write-barrier.js: Added. * stress/private-method-untyped-use.js: Added. * stress/private-method-with-uncacheable-dictionary-transition.js: Added. * stress/private-methods-inline-cache.js: Added. * stress/private-methods-megamorphic-ic.js: Added. * stress/private-methods-on-proxy.js: Added. * stress/private-methods-poly-ic-multiple-classes.js: Added. * stress/private-methods-poly-ic-single-class.js: Added. * stress/private-names-available-on-direct-eval.js: Added. * test262/config.yaml: Source/JavaScriptCore: This patch is adding support to private methods following the specification on https://tc39.es/proposal-private-methods/. This is introducing a new way to declare private methods on class syntax. Private methods are only accessible within classes they were declared, and only can be called from objects that are instance of these classes. To guarantee such rules, the proposal presents the concept of Brand Check. During class evaluation, if a private method is present, a `brand` is installed in this class. Every instance of such class then gets this brand installed during `[[Construct]]` operation. It means that an object can have multiple brands (e.g when there is also private methods declared on super class). Before accessing a private method, there is a check to validate if the target of the call has the brand of callee method. The brand check mechanism is implemented using a `@privateBrand` stored on class scope. Here is a representation of how this mechanism works: ``` class C { #m() { return 3; } method() { return this.#m(); } } let c = new C(); console.log(c.method()); // prints 3 ``` Generated bytecode for the following representation: ``` { // class lexical scope const @privateBrand = @createPrivateSymbol(); const #m = function () { return 3; } C.prototype.method = function() { @check_private_brand(this, @privateBrand); return #m.call(this); } C = function() { @set_private_brand(this, @privateBrand); } } let c = new C(); console.log(c.method()); // prints 3 ``` # Resolving correct brand to check In the case of shadowing or nested scope, we need to emit brand checks to the right private brand. See code below: ``` class C { #m() { return 3; } method() { return this.#m();} A = class { #m2() { return 3; } foo(o) { return o.#m(); } } } ``` The call of "#m" in `foo` refers to "C::#m". In such case, we need to check C's private brand, instead of A's private brand. To perform the proper check, we first resolve scope of "#m" and then check the private brand of this scope (the scope where the private method and brand are stored is the same). So the bytecode to lookup the right brand is: ``` mov loc9, arg1 resolve_scope loc10, "#m" get_from_scope loc11, loc10, "@privateBrand" check_private_brand loc9, loc11 get_from_scope loc11, loc10, "#m" // setup call frame call loc11, ... // ... ``` # Brand check mechanism We are introducing in this patch 2 new bytecodes to allow brand check of objects: `op_set_brand` and `op_check_brand`. `op_set_brand` sets a new brand in an object, so we can perform the brand check later when accessing private methods. This operations throws when trying to add the same brand twice in an Object. `op_check_brand` checks if the given object contains the brand we are looking for. It traverses the brand chain to verify if the brand is present, and throws `TypeError` otherwise. We are also introducing a subclass for Structure called BrandedStructure. It is used to store brands and to allow brand check mechanism. BrandedStructure stores a brand and a parent pointer to another BrandedStructure that allow us traverse the brand chain. With `BrandedStructure`, we can then infer that a given object has the brand we are looking for just checking its structureId. This is a very good optimization, since we can reduce most of brand checks to structure checks. We created a new kind of transition called `SetBrand` that happens when `op_set_brand` is executed. This allow us to cache such kind of trasitions on trasition table using the key `<brand->uid, 0, TransitionKind::SetBrand>`. During this transition, we take previous structure and apply one of the following rules: 1. If it's a BrandedStructure, we then set it to `m_parentBrand`, to allow proper brand chain check. 2. If it's not a BrandedStructure, we set `m_parentBrand` to `nullptr`, meaning that this is the first brand being added to the object with this structure. For now, we are using the flag `isBrandedStructure` to identify that a given Structure is a BrandedStructure. This is done to avoid changes on places where we are checking for `vm.structureStructure()`. However, if we ever need space on Structure, this flag is a good candidate to be deleted and we can move to a solution that uses `vm.brandedStructureStructure()`; # JIT Support This patch also includes initial JIT support for `set_private_brand` and `check_private_brand`. On Baseline JIT, we are using `JITPravateBrandAccessGenerator` to support IC for both operands. On `DFGByteCodeParser` we are trying to inline brand access whenever possible, and fallbacking to `SetPrivateBrand` and `CheckPrivateBrand` otherwise. Those nodes are not being optimized at their full potential, but the code generated by them is also relying on `JITPrivateBrandAccessGenerator` to have IC support for both DFG and FTL. During DFG parsing, we try to reduce those access to `CheckIsConstant` and `CheckStructure` (with `PutStructure` for `set_private_brand` cases) based on available profiled data. This is meant to make brand checks almost free on DFG/FTL tiers when we have a single evaluation of a class, since the `CheckIsConstant` can be eliminated by the constant-folded scope load, and the `CheckStructure` is very likely to be redundant to any other `CheckStructure` that can be performed on receiver when we have a finite structure set. For instance, when we have a brand check on a path-of-no-return to a `GetByOffset` sequence on the same receiver, the `CheckStructure` for the brand check will enable CSE of the `CheckStructure` that would happen for that `GetByOffset`. Such design is possible because brand checks supports polymorphic access very similr to what we have for `GetByOffset` sequences. * CMakeLists.txt: * JavaScriptCore.xcodeproj/project.pbxproj: * Sources.txt: * builtins/BuiltinExecutables.cpp: (JSC::BuiltinExecutables::createDefaultConstructor): (JSC::BuiltinExecutables::createExecutable): * builtins/BuiltinExecutables.h: We are adding a new parameter `PrivateBrandRequirement` to propagate when a default constructor needs to emit code to setup private brand on instances. * builtins/BuiltinNames.h: Adding `@privateBrand` that we use to store private brand on class's scope. * bytecode/AccessCase.cpp: (JSC::AccessCase::createCheckPrivateBrand): (JSC::AccessCase::createSetPrivateBrand): (JSC::AccessCase::requiresIdentifierNameMatch const): (JSC::AccessCase::requiresInt32PropertyCheck const): (JSC::AccessCase::needsScratchFPR const): (JSC::AccessCase::forEachDependentCell const): (JSC::AccessCase::doesCalls const): (JSC::AccessCase::canReplace const): (JSC::AccessCase::dump const): (JSC::AccessCase::generateWithGuard): (JSC::AccessCase::generateImpl): * bytecode/AccessCase.h: (JSC::AccessCase::structure const): (JSC::AccessCase::newStructure const): * bytecode/BytecodeList.rb: * bytecode/BytecodeUseDef.cpp: (JSC::computeUsesForBytecodeIndexImpl): (JSC::computeDefsForBytecodeIndexImpl): * bytecode/CheckPrivateBrandStatus.cpp: Added. (JSC::CheckPrivateBrandStatus::appendVariant): (JSC::CheckPrivateBrandStatus::computeForBaseline): (JSC::CheckPrivateBrandStatus::CheckPrivateBrandStatus): (JSC::CheckPrivateBrandStatus::computeForStubInfoWithoutExitSiteFeedback): (JSC::CheckPrivateBrandStatus::computeFor): (JSC::CheckPrivateBrandStatus::slowVersion const): (JSC::CheckPrivateBrandStatus::merge): (JSC::CheckPrivateBrandStatus::filter): (JSC::CheckPrivateBrandStatus::singleIdentifier const): (JSC::CheckPrivateBrandStatus::visitAggregate): (JSC::CheckPrivateBrandStatus::markIfCheap): (JSC::CheckPrivateBrandStatus::finalize): (JSC::CheckPrivateBrandStatus::dump const): * bytecode/CheckPrivateBrandStatus.h: Added. * bytecode/CheckPrivateBrandVariant.cpp: Added. (JSC::CheckPrivateBrandVariant::CheckPrivateBrandVariant): (JSC::CheckPrivateBrandVariant::~CheckPrivateBrandVariant): (JSC::CheckPrivateBrandVariant::attemptToMerge): (JSC::CheckPrivateBrandVariant::markIfCheap): (JSC::CheckPrivateBrandVariant::finalize): (JSC::CheckPrivateBrandVariant::visitAggregate): (JSC::CheckPrivateBrandVariant::dump const): (JSC::CheckPrivateBrandVariant::dumpInContext const): * bytecode/CheckPrivateBrandVariant.h: Added. (JSC::CheckPrivateBrandVariant::structureSet const): (JSC::CheckPrivateBrandVariant::structureSet): (JSC::CheckPrivateBrandVariant::identifier const): (JSC::CheckPrivateBrandVariant::overlaps): * bytecode/CodeBlock.cpp: (JSC::CodeBlock::finishCreation): (JSC::CodeBlock::finalizeLLIntInlineCaches): * bytecode/ExecutableInfo.h: (JSC::ExecutableInfo::ExecutableInfo): (JSC::ExecutableInfo::privateBrandRequirement const): * bytecode/PolymorphicAccess.cpp: (JSC::PolymorphicAccess::regenerate): (WTF::printInternal): * bytecode/RecordedStatuses.cpp: (JSC::RecordedStatuses::operator=): (JSC::RecordedStatuses::addCheckPrivateBrandStatus): (JSC::RecordedStatuses::addSetPrivateBrandStatus): (JSC::RecordedStatuses::visitAggregate): (JSC::RecordedStatuses::markIfCheap): * bytecode/RecordedStatuses.h: (JSC::RecordedStatuses::forEachVector): * bytecode/SetPrivateBrandStatus.cpp: Added. (JSC::SetPrivateBrandStatus::appendVariant): (JSC::SetPrivateBrandStatus::computeForBaseline): (JSC::SetPrivateBrandStatus::SetPrivateBrandStatus): (JSC::SetPrivateBrandStatus::computeForStubInfoWithoutExitSiteFeedback): (JSC::SetPrivateBrandStatus::computeFor): (JSC::SetPrivateBrandStatus::slowVersion const): (JSC::SetPrivateBrandStatus::merge): (JSC::SetPrivateBrandStatus::filter): (JSC::SetPrivateBrandStatus::singleIdentifier const): (JSC::SetPrivateBrandStatus::visitAggregate): (JSC::SetPrivateBrandStatus::markIfCheap): (JSC::SetPrivateBrandStatus::finalize): (JSC::SetPrivateBrandStatus::dump const): * bytecode/SetPrivateBrandStatus.h: Added. * bytecode/SetPrivateBrandVariant.cpp: Added. (JSC::SetPrivateBrandVariant::SetPrivateBrandVariant): (JSC::SetPrivateBrandVariant::~SetPrivateBrandVariant): (JSC::SetPrivateBrandVariant::attemptToMerge): (JSC::SetPrivateBrandVariant::markIfCheap): (JSC::SetPrivateBrandVariant::finalize): (JSC::SetPrivateBrandVariant::visitAggregate): (JSC::SetPrivateBrandVariant::dump const): (JSC::SetPrivateBrandVariant::dumpInContext const): * bytecode/SetPrivateBrandVariant.h: Added. (JSC::SetPrivateBrandVariant::oldStructure const): (JSC::SetPrivateBrandVariant::newStructure const): (JSC::SetPrivateBrandVariant::identifier const): (JSC::SetPrivateBrandVariant::overlaps): * bytecode/StructureStubInfo.cpp: (JSC::StructureStubInfo::reset): * bytecode/StructureStubInfo.h: * bytecode/UnlinkedCodeBlock.cpp: (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock): * bytecode/UnlinkedCodeBlock.h: (JSC::UnlinkedCodeBlock::privateBrandRequirement const): * bytecode/UnlinkedCodeBlockGenerator.h: (JSC::UnlinkedCodeBlockGenerator::privateBrandRequirement const): * bytecode/UnlinkedFunctionExecutable.cpp: (JSC::generateUnlinkedFunctionCodeBlock): (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::BytecodeGenerator): We changed BytecodeGenerator for FunctionNode and EvalNode to propagate parentScope PrivateNameEnvironment. These environments stores private name entries that are visible into the scope of the function/eval. This is required to identify the kind of access a private name is referring to, since it can be a private field or a private method. (JSC::BytecodeGenerator::instantiateLexicalVariables): (JSC::BytecodeGenerator::emitGetPrivateName): (JSC::BytecodeGenerator::emitCreatePrivateBrand): The process to create a private brand is as follows: 1. Create a PrivateSymbol using `@createPrivateSymbol`. 2. Store this symbol into a given scope (i.e class lexical scope) on `@privateBrand` variable. (JSC::BytecodeGenerator::emitInstallPrivateBrand): (JSC::BytecodeGenerator::emitGetPrivateBrand): We added `m_privateNamesStack` to BytecodeGenerator to represent the scope chain of available private names while generating bytecode. (JSC::BytecodeGenerator::emitCheckPrivateBrand): (JSC::BytecodeGenerator::isPrivateMethod): (JSC::BytecodeGenerator::pushPrivateAccessNames): (JSC::BytecodeGenerator::popPrivateAccessNames): (JSC::BytecodeGenerator::getAvailablePrivateAccessNames): (JSC::BytecodeGenerator::emitNewDefaultConstructor): (JSC::BytecodeGenerator::emitNewClassFieldInitializerFunction): (JSC::BytecodeGenerator::emitDirectGetByVal): Deleted. * bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::privateBrandRequirement const): (JSC::BytecodeGenerator::generate): (JSC::BytecodeGenerator::makeFunction): This change is required to properly propagate PrivateBrandRequirement to arrow functions that can potentially call `super()`. * bytecompiler/NodesCodegen.cpp: (JSC::PropertyListNode::emitDeclarePrivateFieldNames): (JSC::PropertyListNode::emitBytecode): (JSC::PropertyListNode::emitPutConstantProperty): (JSC::BaseDotNode::emitGetPropertyValue): Adding support to properly access private method. Since we store private methods on class lexical scope, we need a different set of instructions to access a private method. (JSC::BaseDotNode::emitPutProperty): In the case of we trying to write in a private method, we need to throw a TypeError according to specification (https://tc39.es/proposal-private-methods/#sec-privatefieldset). (JSC::FunctionCallValueNode::emitBytecode): (JSC::PostfixNode::emitDot): (JSC::PrefixNode::emitDot): (JSC::ClassExprNode::emitBytecode): * debugger/DebuggerCallFrame.cpp: (JSC::DebuggerCallFrame::evaluateWithScopeExtension): * dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): (JSC::DFG::AbstractInterpreter<AbstractStateType>::filterICStatus): * dfg/DFGArgumentsEliminationPhase.cpp: * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::parseBlock): * dfg/DFGCapabilities.cpp: (JSC::DFG::capabilityLevel): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGClobbersExitState.cpp: (JSC::DFG::clobbersExitState): * dfg/DFGDoesGC.cpp: (JSC::DFG::doesGC): * dfg/DFGFixupPhase.cpp: (JSC::DFG::FixupPhase::fixupNode): * dfg/DFGGraph.h: * dfg/DFGJITCompiler.cpp: (JSC::DFG::JITCompiler::link): * dfg/DFGJITCompiler.h: (JSC::DFG::JITCompiler::addPrivateBrandAccess): * dfg/DFGMayExit.cpp: * dfg/DFGNode.h: (JSC::DFG::Node::hasCheckPrivateBrandStatus): (JSC::DFG::Node::checkPrivateBrandStatus): (JSC::DFG::Node::hasSetPrivateBrandStatus): (JSC::DFG::Node::setPrivateBrandStatus): * dfg/DFGNodeType.h: * dfg/DFGObjectAllocationSinkingPhase.cpp: * dfg/DFGPredictionPropagationPhase.cpp: * dfg/DFGSafeToExecute.h: (JSC::DFG::safeToExecute): * dfg/DFGSpeculativeJIT.cpp: (JSC::DFG::SpeculativeJIT::compileCheckPrivateBrand): (JSC::DFG::SpeculativeJIT::compileSetPrivateBrand): * dfg/DFGSpeculativeJIT.h: * dfg/DFGSpeculativeJIT32_64.cpp: (JSC::DFG::SpeculativeJIT::compile): * dfg/DFGSpeculativeJIT64.cpp: (JSC::DFG::SpeculativeJIT::compile): * dfg/DFGStoreBarrierInsertionPhase.cpp: * dfg/DFGVarargsForwardingPhase.cpp: * ftl/FTLCapabilities.cpp: (JSC::FTL::canCompile): * ftl/FTLLowerDFGToB3.cpp: (JSC::FTL::DFG::LowerDFGToB3::compileNode): (JSC::FTL::DFG::LowerDFGToB3::compilePrivateBrandAccess): (JSC::FTL::DFG::LowerDFGToB3::compileCheckPrivateBrand): (JSC::FTL::DFG::LowerDFGToB3::compileSetPrivateBrand): * interpreter/Interpreter.cpp: (JSC::eval): * jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases): (JSC::JIT::link): * jit/JIT.h: * jit/JITInlineCacheGenerator.cpp: (JSC::JITPrivateBrandAccessGenerator::JITPrivateBrandAccessGenerator): (JSC::JITPrivateBrandAccessGenerator::generateFastPath): (JSC::JITPrivateBrandAccessGenerator::finalize): * jit/JITInlineCacheGenerator.h: (JSC::JITPrivateBrandAccessGenerator::JITPrivateBrandAccessGenerator): (JSC::JITPrivateBrandAccessGenerator::slowPathJump const): * jit/JITOperations.cpp: (JSC::JSC_DEFINE_JIT_OPERATION): (JSC::getPrivateName): * jit/JITOperations.h: * jit/JITPropertyAccess.cpp: (JSC::JIT::emit_op_set_private_brand): (JSC::JIT::emitSlow_op_set_private_brand): (JSC::JIT::emit_op_check_private_brand): (JSC::JIT::emitSlow_op_check_private_brand): * jit/JITPropertyAccess32_64.cpp: (JSC::JIT::emit_op_set_private_brand): (JSC::JIT::emitSlow_op_set_private_brand): (JSC::JIT::emit_op_check_private_brand): (JSC::JIT::emitSlow_op_check_private_brand): * jit/Repatch.cpp: (JSC::tryCacheCheckPrivateBrand): (JSC::repatchCheckPrivateBrand): (JSC::tryCacheSetPrivateBrand): (JSC::repatchSetPrivateBrand): (JSC::resetCheckPrivateBrand): (JSC::resetSetPrivateBrand): * jit/Repatch.h: * llint/LLIntSlowPaths.cpp: (JSC::LLInt::LLINT_SLOW_PATH_DECL): * llint/LLIntSlowPaths.h: * llint/LowLevelInterpreter32_64.asm: * llint/LowLevelInterpreter64.asm: * parser/Nodes.cpp: (JSC::FunctionMetadataNode::FunctionMetadataNode): * parser/Nodes.h: (JSC::BaseDotNode::isPrivateMember const): (JSC::BaseDotNode::isPrivateField const): Deleted. * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClass): (JSC::Parser<LexerType>::parseMemberExpression): * parser/Parser.h: (JSC::Scope::declarePrivateMethod): (JSC::Scope::declarePrivateField): (JSC::Parser<LexerType>::parse): (JSC::parse): (JSC::Scope::declarePrivateName): Deleted. * parser/ParserModes.h: * parser/SyntaxChecker.h: (JSC::SyntaxChecker::createDotAccess): * parser/VariableEnvironment.cpp: (JSC::VariableEnvironment::declarePrivateMethod): * parser/VariableEnvironment.h: (JSC::VariableEnvironmentEntry::isPrivateField const): (JSC::VariableEnvironmentEntry::isPrivateMethod const): (JSC::VariableEnvironmentEntry::setIsPrivateField): (JSC::VariableEnvironmentEntry::setIsPrivateMethod): (JSC::PrivateNameEntry::isMethod const): (JSC::PrivateNameEntry::isPrivateMethodOrAcessor const): (JSC::VariableEnvironment::addPrivateName): (JSC::VariableEnvironment::declarePrivateField): (JSC::VariableEnvironment::declarePrivateMethod): (JSC::VariableEnvironment::privateNameEnvironment const): (JSC::VariableEnvironment::hasPrivateMethodOrAccessor const): (JSC::VariableEnvironment::addPrivateNamesFrom): (JSC::VariableEnvironmentEntry::isPrivateName const): Deleted. (JSC::VariableEnvironmentEntry::setIsPrivateName): Deleted. (JSC::VariableEnvironment::declarePrivateName): Deleted. * runtime/CachedTypes.cpp: (JSC::CachedCodeBlockRareData::encode): (JSC::CachedCodeBlockRareData::decode const): (JSC::CachedFunctionExecutableRareData::encode): (JSC::CachedFunctionExecutableRareData::decode const): (JSC::CachedFunctionExecutable::privateBrandRequirement const): (JSC::CachedCodeBlock::derivedContextType const): (JSC::CachedFunctionExecutable::encode): (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): (JSC::CachedCodeBlock::needsClassFieldInitializer const): Deleted. * runtime/CodeCache.cpp: (JSC::generateUnlinkedCodeBlockImpl): (JSC::generateUnlinkedCodeBlock): (JSC::generateUnlinkedCodeBlockForDirectEval): (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable): * runtime/CodeCache.h: * runtime/DirectEvalExecutable.cpp: (JSC::DirectEvalExecutable::create): (JSC::DirectEvalExecutable::DirectEvalExecutable): * runtime/DirectEvalExecutable.h: * runtime/EvalExecutable.cpp: (JSC::EvalExecutable::EvalExecutable): * runtime/EvalExecutable.h: (JSC::EvalExecutable::executableInfo const): (JSC::EvalExecutable::privateBrandRequirement const): * runtime/ExceptionHelpers.cpp: (JSC::createInvalidPrivateNameError): * runtime/IndirectEvalExecutable.cpp: (JSC::IndirectEvalExecutable::IndirectEvalExecutable): * runtime/JSObject.h: * runtime/JSObjectInlines.h: (JSC::JSObject::checkPrivateBrand): (JSC::JSObject::setPrivateBrand): * runtime/JSScope.cpp: (JSC::JSScope::collectClosureVariablesUnderTDZ): * runtime/JSScope.h: * runtime/ModuleProgramExecutable.h: * runtime/Options.cpp: (JSC::Options::recomputeDependentOptions): * runtime/OptionsList.h: * runtime/ProgramExecutable.h: * runtime/Structure.cpp: (JSC::Structure::materializePropertyTable): (JSC::BrandedStructure::BrandedStructure): (JSC::BrandedStructure::create): (JSC::BrandedStructure::checkBrand): (JSC::Structure::setBrandTransitionFromExistingStructureImpl): (JSC::Structure::setBrandTransitionFromExistingStructureConcurrently): (JSC::Structure::setBrandTransition): * runtime/Structure.h: (JSC::Structure::finishCreation): * runtime/StructureInlines.h: (JSC::Structure::create): (JSC::Structure::forEachPropertyConcurrently): * runtime/StructureTransitionTable.h: * runtime/SymbolTable.cpp: (JSC::SymbolTable::cloneScopePart): * runtime/SymbolTable.h: * runtime/VM.cpp: (JSC::VM::VM): * runtime/VM.h: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@272580 268f45cc-cd09-0410-ab3c-d52691b4dbfc
WebKit is a cross-platform web browser engine. On iOS and macOS, it powers Safari, Mail, iBooks, and many other applications.
Visit WebKit Feature Status page to see which Web API has been implemented, in development, or under consideration.
On macOS, download Safari Technology Preview to test the latest version of WebKit. On Linux, download Epiphany Technology Preview. On Windows, you'll have to build it yourself.
Once your bug is filed, you will receive email when it is updated at each stage in the bug life cycle. After the bug is considered fixed, you may be asked to download the latest nightly and confirm that the fix works for you.
On Windows, follow the instructions on our website.
Run the following command to clone WebKit's Git SVN repository:
git clone git@github.com:WebKit/WebKit.git WebKit
or
git clone https://github.com/WebKit/WebKit.git WebKit
If you want to be able to track Subversion revision from your git checkout, you can run the following command to do so:
Tools/Scripts/git-webkit setup-git-svn
For information about this, and other aspects of using Git with WebKit, read the wiki page.
If you don‘t want to use Git, run the following command to check out WebKit’s Subversion repository:
svn checkout https://svn.webkit.org/repository/webkit/trunk WebKit
Install Xcode and its command line tools if you haven't done so already:
xcode-select --install
Run the following command to build a debug build with debugging symbols and assertions:
Tools/Scripts/build-webkit --debug
For performance testing, and other purposes, use --release
instead.
You can open WebKit.xcworkspace
to build and debug WebKit within Xcode.
If you don't use a custom build location in Xcode preferences, you have to update the workspace settings to use WebKitBuild
directory. In menu bar, choose File > Workspace Settings, then click the Advanced button, select “Custom”, “Relative to Workspace”, and enter WebKitBuild
for both Products and Intermediates.
iOS, tvOS and watchOS are all considered embedded builds. The first time after you install a new Xcode, you will need to run:
sudo Tools/Scripts/configure-xcode-for-embedded-development
Without this step, you will see the error message: “target specifies product type ‘com.apple.product-type.tool’, but there’s no such product type for the ‘iphonesimulator’ platform.
” when building target JSCLLIntOffsetsExtractor
of project JavaScriptCore
.
Run the following command to build a debug build with debugging symbols and assertions for embededded simulators:
Tools/Scripts/build-webkit --debug --<platform>-simulator
or embedded devices:
Tools/Scripts/build-webkit --debug --<platform>-device
where platform
is ios
, tvos
or watchos
.
For production builds:
cmake -DPORT=GTK -DCMAKE_BUILD_TYPE=RelWithDebInfo -GNinja ninja sudo ninja install
For development builds:
Tools/gtk/install-dependencies Tools/Scripts/update-webkitgtk-libs Tools/Scripts/build-webkit --gtk --debug
For more information on building WebKitGTK+, see the wiki page.
For production builds:
cmake -DPORT=WPE -DCMAKE_BUILD_TYPE=RelWithDebInfo -GNinja ninja sudo ninja install
For development builds:
Tools/wpe/install-dependencies Tools/Scripts/update-webkitwpe-libs Tools/Scripts/build-webkit --wpe --debug
For building WebKit on Windows, see the wiki page.
Run the following command to launch Safari with your local build of WebKit:
Tools/Scripts/run-safari --debug
The run-safari
script sets the DYLD_FRAMEWORK_PATH
environment variable to point to your build products, and then launches /Applications/Safari.app
. DYLD_FRAMEWORK_PATH
tells the system loader to prefer your build products over the frameworks installed in /System/Library/Frameworks
.
To run other applications with your local build of WebKit, run the following command:
Tools/Scripts/run-webkit-app <application-path>
Run the following command to launch iOS simulator with your local build of WebKit:
run-safari --debug --ios-simulator
In both cases, if you have built release builds instead, use --release
instead of --debug
.
If you have a development build, you can use the run-minibrowser script, e.g.:
run-minibrowser --debug --wpe
Pass one of --gtk
, --jsc-only
, or --wpe
to indicate the port to use.
Congratulations! You’re up and running. Now you can begin coding in WebKit and contribute your fixes and new features to the project. For details on submitting your code to the project, read Contributing Code.