Chrome 63 roll with specific FIXMEDART Changes.
diff --git a/bindings/IDLExtendedAttributes.txt b/bindings/IDLExtendedAttributes.txt
index 58e04ee..e6a6cf3 100644
--- a/bindings/IDLExtendedAttributes.txt
+++ b/bindings/IDLExtendedAttributes.txt
@@ -5,7 +5,7 @@
 # If you would like to add a new extended attribute or value, please:
 #     (1) add the extended attribute or value to this file
 #     (2) add an explanation to the Blink IDL extended attributes document:
-#         idl-extended-attributes.md (in this directory)
+#         IDLExtendedAttributes.md (in this directory)
 #     (3) add appropriate test cases to run-bindings-tests
 #
 # The syntax of this file is as follows:
@@ -31,18 +31,24 @@
 #       arbitrary, but that "X" is standard, e.g. [Attr=X], [Attr=Foo].
 #
 
+ActiveScriptWrappable
+AllowShared
+CEReactions
+CachedAccessor
 CachedAttribute=*
-CallWith=ExecutionContext|ScriptState|ScriptArguments|ActiveWindow|FirstWindow|ThisValue
+CallWith=ExecutionContext|ScriptState|ScriptArguments|CurrentWindow|EnteredWindow|ThisValue
 CheckSecurity=Receiver|ReturnValue
 Clamp
 Constructor
 # FIXME: remove [ConstructorCallWith=Document], as can instead use
 # [ConstructorCallWith=ExecutionContext] + toDocument(executionContext)
 ConstructorCallWith=ExecutionContext|ScriptState|Document
-Custom=|Getter|Setter|LegacyCallAsFunction|VisitDOMWrapper|PropertyGetter|PropertyEnumerator|PropertyQuery|CallPrologue|CallEpilogue
+ContextEnabled=*
+CrossOrigin=|Getter|Setter
+Custom=|Getter|Setter|LegacyCallAsFunction|PropertyGetter|PropertyEnumerator|PropertyQuery|CallPrologue|CallEpilogue
 CustomConstructor
 CustomElementCallbacks
-# Dartium specific attributes.
+# FIXMEDART: Dartium specific attributes.
 # DartCustom can have no value or New if New an additional method is added (V8 will not see this method)
 DartCustom=|New|Setter|Getter
 # DartName should have the alias name to be used to resolve.
@@ -65,18 +71,18 @@
 DependentLifetime
 DeprecateAs=*
 DoNotCheckConstants
-DoNotCheckSecurity=|Setter
-DoNotCheckSignature
+DoNotTestNewObject
 EnforceRange
 Exposed=*
+FeaturePolicy=*
 FlexibleArrayBufferView
-GarbageCollected
 Global=|*
+HTMLConstructor
+ImmutablePrototype
 ImplementedAs=*
-ImplementedInPrivateScript
-Iterable
 LegacyInterfaceTypeChecking
 LegacyTreatAsPartialInterface
+LegacyUnenumerableNamedProperties
 LenientThis
 LogActivity=|GetterOnly|SetterOnly
 LogAllWorlds
@@ -84,10 +90,8 @@
 Measure
 MeasureAs=*
 NamedConstructor=*
-NoImplHeader
 NoInterfaceObject
 NotEnumerable
-OnlyExposedToPrivateScript
 OriginTrialEnabled=*
 OverrideBuiltins
 PartialInterfaceImplementedAs=*
@@ -104,15 +108,17 @@
 ReflectOnly=*
 Replaceable
 # Valid values for [RuntimeEnabled] are the Runtime Enabled Features, listed in
-# Source/core/page/RuntimeEnabledFeatures.in
+# Source/platform/runtime_enabled_features.json5
 RuntimeEnabled=*
+# Valid values for [RuntimeCallStatsCounter] are counters defined in
+# Source/platform/bindings/RuntimeCallStats.h
+RuntimeCallStatsCounter=*
 SameObject
-SetWrapperReferenceFrom=*
-SetWrapperReferenceTo=*
-SetterCallWith=ExecutionContext|ScriptArguments|ActiveWindow|FirstWindow
+SaveSameObject
+SecureContext
+SetterCallWith=ExecutionContext|ScriptArguments|CurrentWindow|EnteredWindow
 TreatNullAs=NullString|EmptyString
-TreatUndefinedAs=NullString
 URL
 Unforgeable
-Unscopeable
-WillBeGarbageCollected
+Unscopable
+WebAgentAPI
diff --git a/bindings/PRESUBMIT.py b/bindings/PRESUBMIT.py
index 605322d..32d9c44 100644
--- a/bindings/PRESUBMIT.py
+++ b/bindings/PRESUBMIT.py
@@ -32,6 +32,9 @@
 for more details about the presubmit API built into gcl.
 """
 
+# Make sure binding templates are considered as source files.
+WHITE_LIST = (r'.+\.tmpl$',)
+
 # Changes to v8/ do not change generated code or tests, so exclude from
 # _RunBindingsTests
 BLACK_LIST = (r'.*\bv8[\\\/].*',)
@@ -39,7 +42,8 @@
 def _RunBindingsTests(input_api, output_api):
     # Skip if nothing to do
     source_filter = lambda x: input_api.FilterSourceFile(
-                x, black_list=input_api.DEFAULT_BLACK_LIST + BLACK_LIST)
+        x, white_list=input_api.DEFAULT_WHITE_LIST + WHITE_LIST,
+        black_list=input_api.DEFAULT_BLACK_LIST + BLACK_LIST)
     if not input_api.AffectedFiles(file_filter=source_filter):
         return []
 
@@ -56,6 +60,8 @@
         cmd = [input_api.python_executable, run_bindings_tests_path]
     else:
         cmd = [run_bindings_tests_path]
+    if not input_api.verbose:
+        cmd.append('--suppress-diff')
     test_cmd = input_api.Command(
       name=cmd_name,
       cmd=cmd,
diff --git a/bindings/dart/gyp/scripts/build_dart_snapshot.py b/bindings/dart/gyp/scripts/build_dart_snapshot.py
deleted file mode 100755
index e9e677c..0000000
--- a/bindings/dart/gyp/scripts/build_dart_snapshot.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2011 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# build_dart_snapshot.py generates two C++ files: DartSnapshot.cpp
-# with a constant which is a snapshot of major DOM libs an
-# DartResolver.cpp which is a resolver for dart:html library.
-
-import os.path
-import subprocess
-import sys
-
-
-def main(args):
-    assert(len(args) >= 4)
-    dartPath = args[1]
-    dartSnapshotTemplateFile = args[2]
-    outputFilePath = args[3]
-    genSnapshotBinPath = args[4]
-    snapshottedLibPaths = args[5:]
-
-    def path(*components):
-        return os.path.abspath(os.path.join(*components))
-
-    def dartName(path):
-        # Translates <dirs>/foo_dartium.dart into foo.
-        return (os.path.splitext(os.path.split(path)[1])[0]
-                .replace('_dartium', ''))
-
-    snapshottedLibs = [(dartName(p), path(p))
-                       for p in snapshottedLibPaths]
-
-    # Generate a Dart script to build the snapshot from.
-    snapshotScriptName = os.path.join(outputFilePath, 'snapshotScript.dart')
-    with file(snapshotScriptName, 'w') as snapshotScript:
-        snapshotScript.write('library snapshot;\n')
-        for name, _ in snapshottedLibs:
-            # Skip internal libraries - they should be indirectly imported via the public ones.
-            if not name.startswith('_'):
-                snapshotScript.write('import \'dart:%(name)s\' as %(name)s;\n' % {'name': name})
-        snapshotScript.write('import \'dart:vmserviceio\';\n')
-
-    binaryVmIsolateSnapshotFile = path(outputFilePath, 'DartVmIsolateSnapshot.bin')
-    binaryIsolateSnapshotFile = path(outputFilePath, 'DartIsolateSnapshot.bin')
-
-    # Build a command to generate the snapshot bin file.
-    command = [
-        'python',
-        path(dartPath, 'runtime', 'tools', 'create_snapshot_bin.py'),
-        '--executable=%s' % path(genSnapshotBinPath),
-        '--snapshot_kind=core',
-        '--vm_output_bin=%s' % binaryVmIsolateSnapshotFile,
-        '--isolate_output_bin=%s' % binaryIsolateSnapshotFile,
-        '--script=%s' % snapshotScriptName,
-    ]
-    command.extend(['--url_mapping=dart:%s,%s' % lib for lib in snapshottedLibs])
-
-    pipe = subprocess.Popen(command,
-                            stdout=subprocess.PIPE,
-                            stderr=subprocess.PIPE)
-    out, error = pipe.communicate()
-    if (pipe.returncode != 0):
-        raise Exception('Snapshot bin generation failed: %s/%s' % (out, error))
-
-    # Build a command to generate the snapshot file.
-    command = [
-        'python',
-        path(dartPath, 'runtime', 'tools', 'create_snapshot_file.py'),
-        '--input_cc=%s' % dartSnapshotTemplateFile,
-        '--vm_input_bin=%s' % binaryVmIsolateSnapshotFile,
-        '--input_bin=%s' % binaryIsolateSnapshotFile,
-        '--output=%s' % path(outputFilePath, 'DartSnapshot.bytes'),
-    ]
-
-    pipe = subprocess.Popen(command,
-                            stdout=subprocess.PIPE,
-                            stderr=subprocess.PIPE)
-    out, error = pipe.communicate()
-    if (pipe.returncode != 0):
-        raise Exception('Snapshot file generation failed: %s/%s' % (out, error))
-
-    snapshotSizeInBytes = os.path.getsize(binaryIsolateSnapshotFile)
-    productDir = os.path.dirname(genSnapshotBinPath)
-    snapshotSizeOutputPath = os.path.join(productDir, 'snapshot-size.txt')
-    with file(snapshotSizeOutputPath, 'w') as snapshotSizeFile:
-        snapshotSizeFile.write('%d\n' % snapshotSizeInBytes)
-
-    return 0
-
-if __name__ == '__main__':
-    sys.exit(main(sys.argv))
diff --git a/bindings/dart/gyp/scripts/create_resources.py b/bindings/dart/gyp/scripts/create_resources.py
deleted file mode 100644
index 3b6b992..0000000
--- a/bindings/dart/gyp/scripts/create_resources.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-#
-# This python script creates string literals in a C++ source file from a C++
-# source template and one or more resource files.
-
-import os
-import sys
-from os.path import join
-import time
-from optparse import OptionParser
-import re
-from datetime import date
-
-
-def makeResources(root_dir, input_files):
-    result = ''
-    resources = []
-
-    # Write each file's contents as a byte string constant.
-    for resource_file in input_files:
-        if root_dir and resource_file.startswith(root_dir):
-            resource_file_name = resource_file[len(root_dir):]
-        else:
-            resource_file_name = resource_file
-        resource_url = '/%s' % resource_file_name
-        result += '// %s\n' % resource_file
-        result += 'const char '
-        resource_name = re.sub(r'(/|\.|-)', '_', resource_file_name) + '_'
-        result += resource_name
-        result += '[] = {\n   '
-        fileHandle = open(resource_file, 'rb')
-        lineCounter = 0
-        for byte in fileHandle.read():
-            result += r" '\x%02x'," % ord(byte)
-            lineCounter += 1
-            if lineCounter == 10:
-                result += '\n   '
-                lineCounter = 0
-        if lineCounter != 0:
-            result += '\n   '
-        result += ' 0\n};\n\n'
-        resources.append(
-            (resource_url, resource_name, os.stat(resource_file).st_size))
-
-    # Write the resource table.
-    result += 'Resources::resource_map_entry Resources::builtin_resources_[] = '
-    result += '{\n'
-    for res in resources:
-        result += '   { "%s", %s, %d },\n' % res
-    result += '};\n\n'
-    result += 'const intptr_t Resources::builtin_resources_count_ '
-    result += '= %d;\n' % len(resources)
-    return result
-
-
-def makeFile(output_file, root_dir, input_files):
-    cc_text = '''
-// Copyright (c) %d, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-''' % date.today().year
-    cc_text += '#if defined(new)\n'
-    cc_text += '#undef new\n'
-    cc_text += '#endif\n\n'
-    cc_text += '#if defined(delete)\n'
-    cc_text += '#undef delete\n'
-    cc_text += '#endif\n\n'
-    cc_text += '#ifndef NDEBUG\n'
-    cc_text += '#define DEBUG\n'
-    cc_text += '#endif\n'
-    cc_text += '#include "bin/resources.h"\n\n'
-    cc_text += 'namespace dart {\n'
-    cc_text += 'namespace bin {\n'
-    cc_text += makeResources(root_dir, input_files)
-    cc_text += '}  // namespace bin\n} // namespace dart\n'
-    open(output_file, 'w').write(cc_text)
-    return True
-
-
-def main(args):
-    try:
-        # Parse input.
-        parser = OptionParser()
-        parser.add_option("--output",
-                          action="store", type="string",
-                          help="output file name")
-        parser.add_option("--root_prefix",
-                          action="store", type="string",
-                          help="root directory for resources")
-        (options, args) = parser.parse_args()
-        if not options.output:
-            sys.stderr.write('--output not specified\n')
-            return -1
-        if len(args) == 0:
-            sys.stderr.write('No input files specified\n')
-            return -1
-
-        files = []
-        for arg in args:
-            files.append(arg)
-
-        if not makeFile(options.output, options.root_prefix, files):
-            return -1
-
-        return 0
-    except Exception, inst:
-        sys.stderr.write('create_resources.py exception\n')
-        sys.stderr.write(str(inst))
-        sys.stderr.write('\n')
-        return -1
-
-if __name__ == '__main__':
-    sys.exit(main(sys.argv))
diff --git a/bindings/dart/gyp/scripts/dart_action_derivedsourcesallinone.py b/bindings/dart/gyp/scripts/dart_action_derivedsourcesallinone.py
deleted file mode 100644
index 969ffa6..0000000
--- a/bindings/dart/gyp/scripts/dart_action_derivedsourcesallinone.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2011 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# dart_action_derivedsourceslist.py generates a single or several cpp files
-# that include all Dart bindings cpp files generated from idls.
-#
-# usage: dart_action_derivedsourceslist.py IDL_FILES_LIST -- OUTPUT_FILE1 OUTPUT_FILE2 ...
-#
-# Note that IDL_FILES_LIST is a text file containing the IDL file paths.
-
-import os.path
-import re
-import sys
-
-v8scriptPath = os.path.join(sys.path[0], '../../../../WebCore.gyp/scripts')
-sys.path.append(v8scriptPath)
-
-# FIXME: there are couple of very ugly hacks like duplication of main code and
-# regexp to rewrite V8 prefix to Dart. It all can be easily solved with minimal
-# modifications to action_derivedsourcesallinone.py.
-import action_derivedsourcesallinone as base
-
-
-def main(args):
-    assert(len(args) > 3)
-    inOutBreakIndex = args.index('--')
-    inputFileName = args[1]
-    outputFileNames = args[inOutBreakIndex + 1:]
-
-    inputFile = open(inputFileName, 'r')
-    idlFileNames = inputFile.read().split('\n')
-    inputFile.close()
-
-    filesMetaData = base.extractMetaData(idlFileNames)
-    for fileName in outputFileNames:
-        partition = outputFileNames.index(fileName)
-        fileContents = base.generateContent(filesMetaData, partition, len(outputFileNames))
-        # FIXME: ugly hack---change V8 prefix to Dart.
-        fileContents = re.sub('\n#include "bindings/V8', '\n#include "bindings/Dart', fileContents)
-        base.writeContent(fileContents, fileName)
-
-    return 0
-
-
-if __name__ == '__main__':
-    sys.exit(main(sys.argv))
diff --git a/bindings/dart/gyp/scripts/dart_html_lib_deps.py b/bindings/dart/gyp/scripts/dart_html_lib_deps.py
deleted file mode 100644
index ff534f0..0000000
--- a/bindings/dart/gyp/scripts/dart_html_lib_deps.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2012 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-import fnmatch
-import os
-import sys
-
-
-def printAllFilesRecursively(directory, pattern):
-  def matches(basename): return fnmatch.fnmatch(basename, pattern)
-  for root, _, files in os.walk(directory):
-    for basename in filter(matches, files):
-      # gyp operates correctly only on /, not Windows \.
-      print os.path.join(root, basename).replace(os.sep, '/')
-
-
-
-def main(args):
-  dart_html_lib_dir = args[1]
-
-  deps = [
-      ('idl', '*.idl'),
-      ('scripts', '*.py'),
-      ('src', '*.dart'),
-      ('templates', '*.*template'),
-  ]
-
-  for directory, pattern in deps:
-    printAllFilesRecursively(os.path.join(dart_html_lib_dir, directory), pattern)
-
-
-if __name__ == '__main__':
-    sys.exit(main(sys.argv))
diff --git a/bindings/dart/gyp/scripts/generate_dart_bindings.py b/bindings/dart/gyp/scripts/generate_dart_bindings.py
deleted file mode 100755
index a57881d..0000000
--- a/bindings/dart/gyp/scripts/generate_dart_bindings.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2012 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import glob
-import os.path
-import sys
-import tempfile
-
-def main(args):
-    assert(len(args) == 6)
-    idlListFileName = args[1]
-    dartiumScriptDir = args[2]
-    dartScriptDir = args[3]
-    outputFilePath = args[4]
-    featureDefines = args[5]
-
-    # Clear out any stale dart/lib/html/scripts/.pyc files that are lurking.
-    for f in glob.glob(os.path.join(dartScriptDir, '*.pyc')):
-      os.remove(f)
-
-    baseDir = os.path.dirname(dartiumScriptDir)
-    idlListFile = open(idlListFileName, 'r')
-    idlFiles = [os.path.join(baseDir, fileName.strip()) for fileName in idlListFile]
-    idlListFile.close()
-
-    def analyse(featureDef):
-      featureDef = featureDef.strip('"')
-      if '=' not in featureDef: return None
-      feature, status = featureDef.split('=')
-      if status == '1':
-        return feature
-      return None
-
-    featureDefines = filter(None, map(analyse, featureDefines.split()))
-
-    sys.path.insert(0, dartScriptDir)
-    import fremontcutbuilder
-    import dartdomgenerator
-
-    database = fremontcutbuilder.build_database(idlFiles, tempfile.mkdtemp(), feature_defines=featureDefines)
-    database.Load()
-    dartdomgenerator.GenerateFromDatabase(database, None, outputFilePath)
-    database.Delete()
-
-    return 0
-
-if __name__ == '__main__':
-    sys.exit(main(sys.argv))
diff --git a/bindings/scripts/aggregate_generated_bindings.py b/bindings/scripts/aggregate_generated_bindings.py
index 4b71743..5619f48 100755
--- a/bindings/scripts/aggregate_generated_bindings.py
+++ b/bindings/scripts/aggregate_generated_bindings.py
@@ -32,28 +32,29 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-"""Generate aggregate .cpp files that include multiple V8 binding .cpp files.
+"""Generates a .cpp file that includes all V8 binding .cpp files for interfaces.
 
-This can be a single output file, to preserve symbol space; or multiple output
-files, to reduce maximum compilation unit size and allow parallel compilation.
+It is expected to preserve symbol space, and to be acceptable to make static
+build on Windows.
 
 Usage:
-aggregate_generated_bindings.py COMPONENT_DIR IDL_FILES_LIST -- OUTPUT_FILE1 OUTPUT_FILE2 ...
+ $ aggregate_generated_bindings.py --component COMPONENT IDL_FILES_LIST OUTPUT_FILE
 
-COMPONENT_DIR is the relative directory of a component, e.g., 'core', 'modules'.
-IDL_FILES_LIST is a text file containing the IDL file paths, so the command
-line doesn't exceed OS length limits.
-OUTPUT_FILE1 etc. are filenames of output files.
+ COMPONENT is the relative directory of a component, e.g., 'core', 'modules'.
+ IDL_FILES_LIST is a text file containing the IDL file paths
+ OUTPUT_FILE is the filename of output file.
 
-Design doc: http://www.chromium.org/developers/design-documents/idl-build
+ Design doc: http://www.chromium.org/developers/design-documents/idl-build
 """
 
 import errno
+import optparse
 import os
 import re
 import sys
-
-from utilities import should_generate_impl_file_from_idl, get_file_contents, idl_filename_to_component, idl_filename_to_interface_name, read_idl_files_list_from_file
+from utilities import idl_filename_to_basename
+from utilities import read_idl_files_list_from_file
+from utilities import to_snake_case
 
 COPYRIGHT_TEMPLATE = """/*
  * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT.
@@ -85,49 +86,32 @@
  */
 """
 
+def parse_options():
+    parser = optparse.OptionParser()
+    parser.add_option('--component')
+    # TODO(tkent): Remove the option after the great mv. crbug.com/760462
+    parser.add_option('--snake-case-generated-files',
+                      action='store_true', default=False)
 
-def extract_meta_data(file_paths):
-    """Extracts interface name from each IDL file."""
-    meta_data_list = []
+    options, args = parser.parse_args()
+    if len(args) < 2:
+        raise Exception('Expected 2 filenames; one is for input, and the other is for output.')
 
-    for file_path in file_paths:
-        if not file_path.endswith('.idl'):
-            print 'WARNING: non-IDL file passed: "%s"' % file_path
-            continue
-        if not os.path.exists(file_path):
-            print 'WARNING: file not found: "%s"' % file_path
-            continue
-
-        idl_file_contents = get_file_contents(file_path)
-        if not should_generate_impl_file_from_idl(idl_file_contents):
-            continue
-
-        # Extract interface name from file name
-        interface_name = idl_filename_to_interface_name(file_path)
-
-        meta_data = {
-            'name': interface_name,
-        }
-        meta_data_list.append(meta_data)
-
-    return meta_data_list
+    return options, args
 
 
-def generate_content(component_dir, aggregate_partial_interfaces, files_meta_data_this_partition):
+def generate_content(component, basenames, snake_case_generated_files):
     # Add fixed content.
     output = [COPYRIGHT_TEMPLATE,
               '#define NO_IMPLICIT_ATOMICSTRING\n\n']
 
-    # List all includes.
-    files_meta_data_this_partition.sort()
-    for meta_data in files_meta_data_this_partition:
-        if aggregate_partial_interfaces:
-            cpp_filename = 'V8%sPartial.cpp' % meta_data['name']
-        else:
-            cpp_filename = 'V8%s.cpp' % meta_data['name']
-
-        output.append('#include "bindings/%s/v8/%s"\n' %
-                      (component_dir, cpp_filename))
+    basenames.sort()
+    if snake_case_generated_files:
+        output.extend('#include "bindings/%s/v8/v8_%s.cc"\n' % (component, to_snake_case(basename))
+                      for basename in basenames)
+    else:
+        output.extend('#include "bindings/%s/v8/V8%s.cpp"\n' % (component, basename)
+                      for basename in basenames)
 
     return ''.join(output)
 
@@ -141,33 +125,16 @@
         f.write(content)
 
 
-def main(args):
-    if len(args) <= 4:
-        raise Exception('Expected at least 5 arguments.')
-    component_dir = args[1]
-    input_file_name = args[2]
-    in_out_break_index = args.index('--')
-    output_file_names = args[in_out_break_index + 1:]
-
-    idl_file_names = read_idl_files_list_from_file(input_file_name,
-                                                   is_gyp_format=True)
-    components = set([idl_filename_to_component(filename)
-                      for filename in idl_file_names])
-    if len(components) != 1:
-        raise Exception('Cannot aggregate generated codes in different components')
-    aggregate_partial_interfaces = component_dir not in components
-
-    files_meta_data = extract_meta_data(idl_file_names)
-    total_partitions = len(output_file_names)
-    for partition, file_name in enumerate(output_file_names):
-        files_meta_data_this_partition = [
-                meta_data for meta_data in files_meta_data
-                if hash(meta_data['name']) % total_partitions == partition]
-        file_contents = generate_content(component_dir,
-                                         aggregate_partial_interfaces,
-                                         files_meta_data_this_partition)
-        write_content(file_contents, file_name)
+def main():
+    options, filenames = parse_options()
+    component = options.component
+    idl_filenames = read_idl_files_list_from_file(filenames[0],
+                                                  is_gyp_format=False)
+    basenames = [idl_filename_to_basename(file_path)
+                 for file_path in idl_filenames]
+    file_contents = generate_content(component, basenames, options.snake_case_generated_files)
+    write_content(file_contents, filenames[1])
 
 
 if __name__ == '__main__':
-    sys.exit(main(sys.argv))
+    sys.exit(main())
diff --git a/bindings/scripts/blink_idl_lexer.py b/bindings/scripts/blink_idl_lexer.py
index 31a71ff..c14b145 100644
--- a/bindings/scripts/blink_idl_lexer.py
+++ b/bindings/scripts/blink_idl_lexer.py
@@ -70,25 +70,9 @@
 from idl_parser.idl_lexer import IDLLexer
 
 LEXTAB = 'lextab'
-REMOVE_TOKENS = ['COMMENT']
 
 
 class BlinkIDLLexer(IDLLexer):
-    # ignore comments
-    def t_COMMENT(self, t):
-        r'(/\*(.|\n)*?\*/)|(//.*(\n[ \t]*//.*)*)'
-        self.AddLines(t.value.count('\n'))
-
-    # Analogs to _AddToken/_AddTokens in base lexer
-    # Needed to remove COMMENT token, since comments ignored
-    def _RemoveToken(self, token):
-        if token in self.tokens:
-            self.tokens.remove(token)
-
-    def _RemoveTokens(self, tokens):
-        for token in tokens:
-            self._RemoveToken(token)
-
     def __init__(self, debug=False, optimize=True, outputdir=None,
                  rewrite_tables=False):
         if debug:
@@ -115,8 +99,6 @@
             lextab = None
 
         IDLLexer.__init__(self)
-        # Overrides to parent class
-        self._RemoveTokens(REMOVE_TOKENS)
         # Optimized mode substantially decreases startup time (by disabling
         # error checking), and also allows use of Python's optimized mode.
         # See: Optimized Mode
diff --git a/bindings/scripts/blink_idl_parser.py b/bindings/scripts/blink_idl_parser.py
index 55c3e5f..be8030c 100644
--- a/bindings/scripts/blink_idl_parser.py
+++ b/bindings/scripts/blink_idl_parser.py
@@ -53,6 +53,7 @@
 #
 # Disable attribute validation, as lint can't import parent class to check
 # pylint: disable=E1101
+#
 
 import os.path
 import sys
@@ -67,315 +68,14 @@
 # Base parser is in Chromium src/tools/idl_parser
 tools_dir = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, 'tools')
 sys.path.append(tools_dir)
-from idl_parser.idl_parser import IDLParser, ListFromConcat
+from idl_parser.idl_parser import IDLParser  # pylint: disable=import-error
 from idl_parser.idl_parser import ParseFile as parse_file
 
 from blink_idl_lexer import BlinkIDLLexer
 import blink_idl_lexer
 
 
-# Explicitly set starting symbol to rule defined only in base parser.
-# BEWARE that the starting symbol should NOT be defined in both the base parser
-# and the derived one, as otherwise which is used depends on which line number
-# is lower, which is fragile. Instead, either use one in base parser or
-# create a new symbol, so that this is unambiguous.
-# FIXME: unfortunately, this doesn't work in PLY 3.4, so need to duplicate the
-# rule below.
-STARTING_SYMBOL = 'Definitions'
-
-# We ignore comments (and hence don't need 'Top') but base parser preserves them
-# FIXME: Upstream: comments should be removed in base parser
-REMOVED_RULES = ['Top',  # [0]
-                 'Comments',  # [0.1]
-                 'CommentsRest',  # [0.2]
-                ]
-
-# Remove rules from base class
-# FIXME: add a class method upstream: @classmethod IDLParser._RemoveRules
-for rule in REMOVED_RULES:
-    production_name = 'p_' + rule
-    delattr(IDLParser, production_name)
-
-
 class BlinkIDLParser(IDLParser):
-    # [1]
-    # FIXME: Need to duplicate rule for starting symbol here, with line number
-    # *lower* than in the base parser (idl_parser.py).
-    # This is a bug in PLY: it determines starting symbol by lowest line number.
-    # This can be overridden by the 'start' parameter, but as of PLY 3.4 this
-    # doesn't work correctly.
-    def p_Definitions(self, p):
-        """Definitions : ExtendedAttributeList Definition Definitions
-                       | """
-        if len(p) > 1:
-            p[2].AddChildren(p[1])
-            p[0] = ListFromConcat(p[2], p[3])
-
-    # Below are grammar rules used by yacc, given by functions named p_<RULE>.
-    # * The docstring is the production rule in BNF (grammar).
-    # * The body is the yacc action (semantics).
-    #
-    # The PLY framework builds the actual low-level parser by introspecting this
-    # parser object, selecting all attributes named p_<RULE> as grammar rules.
-    # It extracts the docstrings and uses them as the production rules, building
-    # the table of a LALR parser, and uses the body of the functions as actions.
-    #
-    # Reference:
-    # http://www.dabeaz.com/ply/ply.html#ply_nn23
-    #
-    # Review of yacc:
-    # Yacc parses a token stream, internally producing a Concrete Syntax Tree
-    # (CST), where each node corresponds to a production rule in the grammar.
-    # At each node, it runs an action, which is usually "produce a node in the
-    # Abstract Syntax Tree (AST)" or "ignore this node" (for nodes in the CST
-    # that aren't included in the AST, since only needed for parsing).
-    #
-    # The rules use pseudo-variables; in PLY syntax:
-    # p[0] is the left side: assign return value to p[0] instead of returning,
-    # p[1] ... p[n] are the right side: the values can be accessed, and they
-    # can be modified.
-    # (In yacc these are $$ and $1 ... $n.)
-    #
-    # The rules can look cryptic at first, but there are a few standard
-    # transforms from the CST to AST. With these in mind, the actions should
-    # be reasonably legible.
-    #
-    # * Ignore production
-    #   Discard this branch. Primarily used when one alternative is empty.
-    #
-    #   Sample code:
-    #   if len(p) > 1:
-    #       p[0] = ...
-    #   # Note no assignment if len(p) == 1
-    #
-    # * Eliminate singleton production
-    #   Discard this node in the CST, pass the next level down up the tree.
-    #   Used to ignore productions only necessary for parsing, but not needed
-    #   in the AST.
-    #
-    #   Sample code:
-    #   p[0] = p[1]
-    #
-    # * Build node
-    #   The key type of rule. In this parser, produces object of class IDLNode.
-    #   There are several helper functions:
-    #   * BuildProduction: actually builds an IDLNode, based on a production.
-    #   * BuildAttribute: builds an IDLAttribute, which is a temporary
-    #                     object to hold a name-value pair, which is then
-    #                     set as a Property of the IDLNode when the IDLNode
-    #                     is built.
-    #   * BuildNamed: Same as BuildProduction, and sets the 'NAME' property.
-    #   * BuildTrue: BuildAttribute with value True, for flags.
-    #   See base idl_parser.py for definitions and more examples of use.
-    #
-    #   Sample code:
-    #   # Build node of type NodeType, with value p[1], and children.
-    #   p[0] = self.BuildProduction('NodeType', p, 1, children)
-    #
-    #   # Build named node of type NodeType, with name and value p[1].
-    #   # (children optional)
-    #   p[0] = self.BuildNamed('NodeType', p, 1)
-    #
-    #   # Make a list
-    #   # Used if one node has several children.
-    #   children = ListFromConcat(p[2], p[3])
-    #   p[0] = self.BuildProduction('NodeType', p, 1, children)
-    #
-    #   # Also used to collapse the right-associative tree
-    #   # produced by parsing a list back into a single list.
-    #   """Foos : Foo Foos
-    #           |"""
-    #   if len(p) > 1:
-    #       p[0] = ListFromConcat(p[1], p[2])
-    #
-    #   # Add children.
-    #   # Primarily used to add attributes, produced via BuildTrue.
-    #   # p_StaticAttribute
-    #   """StaticAttribute : STATIC Attribute"""
-    #   p[2].AddChildren(self.BuildTrue('STATIC'))
-    #   p[0] = p[2]
-    #
-    # Numbering scheme for the rules is:
-    # [1] for Web IDL spec (or additions in base parser)
-    #     These should all be upstreamed to the base parser.
-    # [b1] for Blink IDL changes (overrides Web IDL)
-    # [b1.1] for Blink IDL additions, auxiliary rules for [b1]
-    # Numbers are as per Candidate Recommendation 19 April 2012:
-    # http://www.w3.org/TR/2012/CR-WebIDL-20120419/
-
-    # [3] Override action, since we distinguish callbacks
-    # FIXME: Upstream
-    def p_CallbackOrInterface(self, p):
-        """CallbackOrInterface : CALLBACK CallbackRestOrInterface
-                               | Interface"""
-        if len(p) > 2:
-            p[2].AddChildren(self.BuildTrue('CALLBACK'))
-            p[0] = p[2]
-        else:
-            p[0] = p[1]
-
-    # [b27] Add strings, more 'Literal' productions
-    # 'Literal's needed because integers and strings are both internally strings
-    def p_ConstValue(self, p):
-        """ConstValue : BooleanLiteral
-                      | FloatLiteral
-                      | IntegerLiteral
-                      | StringLiteral
-                      | null"""
-        # Standard is (no 'string', fewer 'Literal's):
-        # ConstValue : BooleanLiteral
-        #            | FloatLiteral
-        #            | integer
-        #            | NULL
-        p[0] = p[1]
-
-    # [b27.1]
-    def p_IntegerLiteral(self, p):
-        """IntegerLiteral : integer"""
-        p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'integer'),
-                              self.BuildAttribute('NAME', p[1]))
-
-    # [b27.2]
-    def p_StringLiteral(self, p):
-        """StringLiteral : string"""
-        p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'DOMString'),
-                              self.BuildAttribute('NAME', p[1]))
-
-    # [b47]
-    def p_ExceptionMember(self, p):
-        """ExceptionMember : Const
-                           | ExceptionField
-                           | Attribute
-                           | ExceptionOperation"""
-        # Standard is (no Attribute, no ExceptionOperation):
-        # ExceptionMember : Const
-        #                 | ExceptionField
-        # FIXME: In DOMException.idl, Attributes should be changed to
-        # ExceptionFields, and Attribute removed from this rule.
-        p[0] = p[1]
-
-    # [b47.1] FIXME: rename to ExceptionAttribute
-    def p_Attribute(self, p):
-        """Attribute : ReadOnly ATTRIBUTE Type identifier ';'"""
-        p[0] = self.BuildNamed('Attribute', p, 4,
-                               ListFromConcat(p[1], p[3]))
-
-    # [b47.2]
-    def p_ExceptionOperation(self, p):
-        """ExceptionOperation : Type identifier '(' ')' ';'"""
-        # Needed to handle one case in DOMException.idl:
-        # // Override in a Mozilla compatible format
-        # [NotEnumerable] DOMString toString();
-        # Limited form of Operation to prevent others from being added.
-        # FIXME: Should be a stringifier instead.
-        p[0] = self.BuildNamed('ExceptionOperation', p, 2, p[1])
-
-    # Extended attributes
-    # [b49] Override base parser: remove comment field, since comments stripped
-    # FIXME: Upstream
-    def p_ExtendedAttributeList(self, p):
-        """ExtendedAttributeList : '[' ExtendedAttribute ExtendedAttributes ']'
-                                 | '[' ']'
-                                 | """
-        if len(p) > 3:
-            items = ListFromConcat(p[2], p[3])
-            p[0] = self.BuildProduction('ExtAttributes', p, 1, items)
-
-    # Error handling for ExtendedAttributeList.
-    # We can't upstream this because we override ExtendedAttributeList.
-    def p_ExtendedAttributeListError(self, p):
-        """ExtendedAttributeList : '[' ExtendedAttribute ',' error"""
-        p[0] = self.BuildError(p, "ExtendedAttributeList")
-
-    # [b50] Allow optional trailing comma
-    # Blink-only, marked as WONTFIX in Web IDL spec:
-    # https://www.w3.org/Bugs/Public/show_bug.cgi?id=22156
-    def p_ExtendedAttributes(self, p):
-        """ExtendedAttributes : ',' ExtendedAttribute ExtendedAttributes
-                              | ','
-                              |"""
-        if len(p) > 3:
-            p[0] = ListFromConcat(p[2], p[3])
-
-    # [b51] Add ExtendedAttributeStringLiteral and ExtendedAttributeStringLiteralList
-    def p_ExtendedAttribute(self, p):
-        """ExtendedAttribute : ExtendedAttributeNoArgs
-                             | ExtendedAttributeArgList
-                             | ExtendedAttributeIdent
-                             | ExtendedAttributeIdentList
-                             | ExtendedAttributeNamedArgList
-                             | ExtendedAttributeStringLiteral
-                             | ExtendedAttributeStringLiteralList"""
-        p[0] = p[1]
-
-    # [59]
-    # FIXME: Upstream UnionType
-    def p_UnionType(self, p):
-        """UnionType : '(' UnionMemberType OR UnionMemberType UnionMemberTypes ')'"""
-        members = ListFromConcat(p[2], p[4], p[5])
-        p[0] = self.BuildProduction('UnionType', p, 1, members)
-
-    # [60]
-    def p_UnionMemberType(self, p):
-        """UnionMemberType : NonAnyType
-                           | UnionType TypeSuffix
-                           | ANY '[' ']' TypeSuffix"""
-        if len(p) == 2:
-            p[0] = self.BuildProduction('Type', p, 1, p[1])
-        elif len(p) == 3:
-            p[0] = self.BuildProduction('Type', p, 1, ListFromConcat(p[1], p[2]))
-        else:
-            any_node = ListFromConcat(self.BuildProduction('Any', p, 1), p[4])
-            p[0] = self.BuildProduction('Type', p, 1, any_node)
-
-    # [61]
-    def p_UnionMemberTypes(self, p):
-        """UnionMemberTypes : OR UnionMemberType UnionMemberTypes
-                            |"""
-        if len(p) > 2:
-            p[0] = ListFromConcat(p[2], p[3])
-
-    # [70] Override base parser to remove non-standard sized array
-    # FIXME: Upstream
-    def p_TypeSuffix(self, p):
-        """TypeSuffix : '[' ']' TypeSuffix
-                      | '?' TypeSuffixStartingWithArray
-                      |"""
-        if len(p) == 4:
-            p[0] = self.BuildProduction('Array', p, 1, p[3])
-        elif len(p) == 3:
-            p[0] = ListFromConcat(self.BuildTrue('NULLABLE'), p[2])
-
-    # Blink extension: Add support for string literal Extended Attribute values
-    def p_ExtendedAttributeStringLiteral(self, p):
-        """ExtendedAttributeStringLiteral : identifier '=' StringLiteral """
-        def unwrap_string(ls):
-            """Reach in and grab the string literal's "NAME"."""
-            return ls[1].value
-
-        value = self.BuildAttribute('VALUE', unwrap_string(p[3]))
-        p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
-
-    # Blink extension: Add support for compound Extended Attribute values over string literals ("A","B")
-    def p_ExtendedAttributeStringLiteralList(self, p):
-        """ExtendedAttributeStringLiteralList : identifier '=' '(' StringLiteralList ')' """
-        value = self.BuildAttribute('VALUE', p[4])
-        p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
-
-    # Blink extension: one or more string literals. The values aren't propagated as literals,
-    # but their by their value only.
-    def p_StringLiteralList(self, p):
-        """StringLiteralList : StringLiteral ',' StringLiteralList
-                             | StringLiteral"""
-        def unwrap_string(ls):
-            """Reach in and grab the string literal's "NAME"."""
-            return ls[1].value
-
-        if len(p) > 3:
-            p[0] = ListFromConcat(unwrap_string(p[1]), p[3])
-        else:
-            p[0] = ListFromConcat(unwrap_string(p[1]))
-
     def __init__(self,
                  # common parameters
                  debug=False,
@@ -406,10 +106,6 @@
                                        optimize=optimize)
         self.lexer = lexer
         self.tokens = lexer.KnownTokens()
-        # Using SLR (instead of LALR) generates the table faster,
-        # but produces the same output. This is ok b/c Web IDL (and Blink IDL)
-        # is an SLR grammar (as is often the case for simple LL(1) grammars).
-        #
         # Optimized mode substantially decreases startup time (by disabling
         # error checking), and also allows use of Python's optimized mode.
         # See: Using Python's Optimized Mode
@@ -420,8 +116,6 @@
         # See: CHANGES, Version 3.2
         # http://ply.googlecode.com/svn/trunk/CHANGES
         self.yaccobj = yacc.yacc(module=self,
-                                 start=STARTING_SYMBOL,
-                                 method='SLR',
                                  debug=debug,
                                  optimize=optimize,
                                  write_tables=write_tables,
diff --git a/bindings/scripts/blink_idl_parser_test.py b/bindings/scripts/blink_idl_parser_test.py
new file mode 100644
index 0000000..309b463
--- /dev/null
+++ b/bindings/scripts/blink_idl_parser_test.py
@@ -0,0 +1,21 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# pylint: disable=no-member,relative-import
+
+"""Unit tests for blink_idl_parser.py."""
+
+import unittest
+
+from blink_idl_parser import BlinkIDLParser
+
+
+class BlinkIDLParserTest(unittest.TestCase):
+
+    def test_missing_semicolon_between_definitions(self):
+        # No semicolon after enum definition.
+        text = '''enum TestEnum { "value" } dictionary TestDictionary {};'''
+        parser = BlinkIDLParser()
+        parser.ParseText(filename='', data=text)
+        self.assertGreater(parser.GetErrors(), 0)
diff --git a/bindings/scripts/code_generator.py b/bindings/scripts/code_generator.py
new file mode 100644
index 0000000..66838f8
--- /dev/null
+++ b/bindings/scripts/code_generator.py
@@ -0,0 +1,201 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# pylint: disable=import-error,print-statement,relative-import
+
+"""Plumbing for a Jinja-based code generator, including CodeGeneratorBase, a base class for all generators."""
+
+import os
+import posixpath
+import re
+import sys
+
+from idl_types import set_ancestors, IdlType
+from v8_globals import includes
+from v8_interface import constant_filters
+from v8_types import set_component_dirs
+from v8_methods import method_filters
+import v8_utilities
+from v8_utilities import capitalize
+from utilities import (idl_filename_to_component, is_valid_component_dependency,
+                       format_remove_duplicates, format_blink_cpp_source_code,
+                       to_snake_case)
+
+# Path handling for libraries and templates
+# Paths have to be normalized because Jinja uses the exact template path to
+# determine the hash used in the cache filename, and we need a pre-caching step
+# to be concurrency-safe. Use absolute path because __file__ is absolute if
+# module is imported, and relative if executed directly.
+# If paths differ between pre-caching and individual file compilation, the cache
+# is regenerated, which causes a race condition and breaks concurrent build,
+# since some compile processes will try to read the partially written cache.
+MODULE_PATH, _ = os.path.split(os.path.realpath(__file__))
+THIRD_PARTY_DIR = os.path.normpath(os.path.join(
+    MODULE_PATH, os.pardir, os.pardir, os.pardir, os.pardir))
+TEMPLATES_DIR = os.path.normpath(os.path.join(
+    MODULE_PATH, os.pardir, 'templates'))
+
+# jinja2 is in chromium's third_party directory.
+# Insert at 1 so at front to override system libraries, and
+# after path[0] == invoking script dir
+sys.path.insert(1, THIRD_PARTY_DIR)
+import jinja2
+
+
+def generate_indented_conditional(code, conditional):
+    # Indent if statement to level of original code
+    indent = re.match(' *', code).group(0)
+    return ('%sif (%s) {\n' % (indent, conditional) +
+            '  %s\n' % '\n  '.join(code.splitlines()) +
+            '%s}\n' % indent)
+
+
+# [Exposed]
+def exposed_if(code, exposed_test):
+    if not exposed_test:
+        return code
+    return generate_indented_conditional(code, 'executionContext && (%s)' % exposed_test)
+
+
+# [SecureContext]
+def secure_context_if(code, secure_context_test, test_result=None):
+    if not secure_context_test:
+        return code
+    if test_result:
+        return generate_indented_conditional(code, test_result)
+    return generate_indented_conditional(code, 'executionContext && (%s)' % secure_context_test)
+
+
+# [RuntimeEnabled]
+def runtime_enabled_if(code, name):
+    if not name:
+        return code
+
+    function = v8_utilities.runtime_enabled_function(name)
+    return generate_indented_conditional(code, function)
+
+def initialize_jinja_env(cache_dir):
+    jinja_env = jinja2.Environment(
+        loader=jinja2.FileSystemLoader(TEMPLATES_DIR),
+        # Bytecode cache is not concurrency-safe unless pre-cached:
+        # if pre-cached this is read-only, but writing creates a race condition.
+        bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
+        keep_trailing_newline=True,  # newline-terminate generated files
+        lstrip_blocks=True,  # so can indent control flow tags
+        trim_blocks=True)
+    jinja_env.filters.update({
+        'blink_capitalize': capitalize,
+        'exposed': exposed_if,
+        'format_blink_cpp_source_code': format_blink_cpp_source_code,
+        'format_remove_duplicates': format_remove_duplicates,
+        'runtime_enabled': runtime_enabled_if,
+        'runtime_enabled_function': v8_utilities.runtime_enabled_function,
+        'secure_context': secure_context_if})
+    jinja_env.filters.update(constant_filters())
+    jinja_env.filters.update(method_filters())
+    return jinja_env
+
+
+def normalize_and_sort_includes(include_paths, snake_case):
+    normalized_include_paths = []
+    for include_path in include_paths:
+        match = re.search(r'/gen/blink/(.*)$', posixpath.abspath(include_path))
+        if match:
+            include_path = match.group(1)
+        if snake_case:
+            match = re.search(r'/([^/]+)\.h$', include_path)
+            if match:
+                name = match.group(1)
+                if name.lower() != name:
+                    include_path = include_path[0:match.start(1)] + to_snake_case(name) + '.h'
+        normalized_include_paths.append(include_path)
+    return sorted(normalized_include_paths)
+
+
+def render_template(template, context):
+    filename = str(template.filename)
+    filename = filename[filename.rfind('third_party'):]
+    context['jinja_template_filename'] = filename
+    return template.render(context)
+
+
+class CodeGeneratorBase(object):
+    """Base class for jinja-powered jinja template generation.
+    """
+    def __init__(self, generator_name, info_provider, cache_dir, output_dir, snake_case):
+        self.generator_name = generator_name
+        self.info_provider = info_provider
+        self.jinja_env = initialize_jinja_env(cache_dir)
+        self.output_dir = output_dir
+        self.snake_case_generated_files = snake_case
+        self.set_global_type_info()
+
+    def should_generate_code(self, definitions):
+        return definitions.interfaces or definitions.dictionaries
+
+    def set_global_type_info(self):
+        interfaces_info = self.info_provider.interfaces_info
+        set_ancestors(interfaces_info['ancestors'])
+        IdlType.set_callback_interfaces(interfaces_info['callback_interfaces'])
+        IdlType.set_dictionaries(interfaces_info['dictionaries'])
+        IdlType.set_enums(self.info_provider.enumerations)
+        IdlType.set_callback_functions(self.info_provider.callback_functions)
+        IdlType.set_implemented_as_interfaces(interfaces_info['implemented_as_interfaces'])
+        IdlType.set_garbage_collected_types(interfaces_info['garbage_collected_interfaces'])
+        set_component_dirs(interfaces_info['component_dirs'])
+
+    def render_template(self, include_paths, header_template, cpp_template,
+                        template_context, component=None):
+        template_context['code_generator'] = self.generator_name
+
+        # Add includes for any dependencies
+        template_context['header_includes'] = normalize_and_sort_includes(
+            template_context['header_includes'], self.snake_case_generated_files)
+
+        for include_path in include_paths:
+            if component:
+                dependency = idl_filename_to_component(include_path)
+                assert is_valid_component_dependency(component, dependency)
+            includes.add(include_path)
+
+        template_context['cpp_includes'] = normalize_and_sort_includes(includes, self.snake_case_generated_files)
+
+        header_text = render_template(header_template, template_context)
+        cpp_text = render_template(cpp_template, template_context)
+        return header_text, cpp_text
+
+    def generate_code(self, definitions, definition_name):
+        """Invokes code generation. The [definitions] argument is a list of definitions,
+        and the [definition_name] is the name of the definition
+        """
+        # This should be implemented in subclasses.
+        raise NotImplementedError()
+
+
+def main(argv):
+    # If file itself executed, cache templates
+    try:
+        cache_dir = argv[1]
+        dummy_filename = argv[2]
+    except IndexError:
+        print 'Usage: %s CACHE_DIR DUMMY_FILENAME' % argv[0]
+        return 1
+
+    # Cache templates
+    jinja_env = initialize_jinja_env(cache_dir)
+    template_filenames = [filename for filename in os.listdir(TEMPLATES_DIR)
+                          # Skip .svn, directories, etc.
+                          if filename.endswith(('.tmpl', '.txt'))]
+    for template_filename in template_filenames:
+        jinja_env.get_template(template_filename)
+
+    # Create a dummy file as output for the build system,
+    # since filenames of individual cache files are unpredictable and opaque
+    # (they are hashes of the template path, which varies based on environment)
+    with open(dummy_filename, 'w') as dummy_file:
+        pass  # |open| creates or touches the file
+
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
diff --git a/bindings/scripts/code_generator_v8.py b/bindings/scripts/code_generator_v8.py
index 381d321..c971aa9 100644
--- a/bindings/scripts/code_generator_v8.py
+++ b/bindings/scripts/code_generator_v8.py
@@ -26,6 +26,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# pylint: disable=import-error,print-statement,relative-import
+
 """Generate Blink V8 bindings (.h and .cpp files).
 
 If run itself, caches Jinja templates (and creates dummy file for build,
@@ -45,121 +47,65 @@
 
 import os
 import posixpath
-import re
-import sys
 
-# Path handling for libraries and templates
-# Paths have to be normalized because Jinja uses the exact template path to
-# determine the hash used in the cache filename, and we need a pre-caching step
-# to be concurrency-safe. Use absolute path because __file__ is absolute if
-# module is imported, and relative if executed directly.
-# If paths differ between pre-caching and individual file compilation, the cache
-# is regenerated, which causes a race condition and breaks concurrent build,
-# since some compile processes will try to read the partially written cache.
-module_path, module_filename = os.path.split(os.path.realpath(__file__))
-third_party_dir = os.path.normpath(os.path.join(
-    module_path, os.pardir, os.pardir, os.pardir, os.pardir))
-templates_dir = os.path.normpath(os.path.join(
-    module_path, os.pardir, 'templates'))
-# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
-module_pyname = os.path.splitext(module_filename)[0] + '.py'
-
-# jinja2 is in chromium's third_party directory.
-# Insert at 1 so at front to override system libraries, and
-# after path[0] == invoking script dir
-sys.path.insert(1, third_party_dir)
-import jinja2
-
+from code_generator import CodeGeneratorBase, render_template, normalize_and_sort_includes
 from idl_definitions import Visitor
-import idl_types
 from idl_types import IdlType
+import v8_callback_function
 import v8_callback_interface
 import v8_dictionary
-from v8_globals import includes, interfaces
+from v8_globals import includes
 import v8_interface
 import v8_types
 import v8_union
-from v8_utilities import capitalize, cpp_name, v8_class_name
-from utilities import KNOWN_COMPONENTS, idl_filename_to_component, is_valid_component_dependency, is_testing_target
+from v8_utilities import build_basename, cpp_name
+from utilities import idl_filename_to_component, is_testing_target, shorten_union_name, to_snake_case
 
 
-def normalize_and_sort_includes(include_paths):
-    normalized_include_paths = []
-    for include_path in include_paths:
-        match = re.search(r'/gen/blink/(.*)$', posixpath.abspath(include_path))
-        if match:
-            include_path = match.group(1)
-        normalized_include_paths.append(include_path)
-    return sorted(normalized_include_paths)
+# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
+MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py'
 
-
-def render_template(include_paths, header_template, cpp_template,
-                    template_context, component=None):
-    template_context['code_generator'] = module_pyname
-
-    # Add includes for any dependencies
-    template_context['header_includes'] = normalize_and_sort_includes(
-        template_context['header_includes'])
-
-    for include_path in include_paths:
-        if component:
-            dependency = idl_filename_to_component(include_path)
-            assert is_valid_component_dependency(component, dependency)
-        includes.add(include_path)
-
-    template_context['cpp_includes'] = normalize_and_sort_includes(includes)
-
-    header_text = header_template.render(template_context)
-    cpp_text = cpp_template.render(template_context)
-    return header_text, cpp_text
-
-
-def set_global_type_info(info_provider):
-    interfaces_info = info_provider.interfaces_info
-    idl_types.set_ancestors(interfaces_info['ancestors'])
-    IdlType.set_callback_interfaces(interfaces_info['callback_interfaces'])
-    IdlType.set_dictionaries(interfaces_info['dictionaries'])
-    IdlType.set_enums(info_provider.enumerations)
-    IdlType.set_implemented_as_interfaces(interfaces_info['implemented_as_interfaces'])
-    IdlType.set_garbage_collected_types(interfaces_info['garbage_collected_interfaces'])
-    IdlType.set_will_be_garbage_collected_types(interfaces_info['will_be_garbage_collected_interfaces'])
-    v8_types.set_component_dirs(interfaces_info['component_dirs'])
-
-
-def should_generate_code(definitions):
-    return definitions.interfaces or definitions.dictionaries
-
-
-def depends_on_union_types(idl_type):
-    """Returns true when a given idl_type depends on union containers
-    directly.
+def depending_union_type(idl_type):
+    """Returns the union type name if the given idl_type depends on a
+    union type.
     """
-    if idl_type.is_union_type:
-        return True
-    if idl_type.is_array_or_sequence_type:
-        return idl_type.element_type.is_union_type
-    return False
+    def find_base_type(current_type):
+        if current_type.is_array_or_sequence_type:
+            return find_base_type(current_type.element_type)
+        if current_type.is_record_type:
+            # IdlRecordType.key_type is always a string type, so we only need
+            # to looking into value_type.
+            return find_base_type(current_type.value_type)
+        if current_type.is_nullable:
+            return find_base_type(current_type.inner_type)
+        return current_type
+    base_type = find_base_type(idl_type)
+    if base_type.is_union_type:
+        return base_type
+    return None
 
 
 class TypedefResolver(Visitor):
     def __init__(self, info_provider):
         self.info_provider = info_provider
+        self.additional_header_includes = set()
+        self.typedefs = {}
 
     def resolve(self, definitions, definition_name):
         """Traverse definitions and resolves typedefs with the actual types."""
         self.typedefs = {}
         for name, typedef in self.info_provider.typedefs.iteritems():
             self.typedefs[name] = typedef.idl_type
-        self.additional_includes = set()
+        self.additional_header_includes = set()
         definitions.accept(self)
         self._update_dependencies_include_paths(definition_name)
 
     def _update_dependencies_include_paths(self, definition_name):
+        if definition_name not in self.info_provider.interfaces_info:
+            return
         interface_info = self.info_provider.interfaces_info[definition_name]
-        dependencies_include_paths = interface_info['dependencies_include_paths']
-        for include_path in self.additional_includes:
-            if include_path not in dependencies_include_paths:
-                dependencies_include_paths.append(include_path)
+        interface_info['additional_header_includes'] = set(
+            self.additional_header_includes)
 
     def _resolve_typedefs(self, typed_object):
         """Resolve typedefs to actual types in the object."""
@@ -171,9 +117,12 @@
             if not idl_type:
                 continue
             resolved_idl_type = idl_type.resolve_typedefs(self.typedefs)
-            if depends_on_union_types(resolved_idl_type):
-                self.additional_includes.add(
-                    self.info_provider.include_path_for_union_types)
+            # TODO(bashi): Dependency resolution shouldn't happen here.
+            # Move this into includes_for_type() families.
+            union_type = depending_union_type(resolved_idl_type)
+            if union_type:
+                self.additional_header_includes.add(
+                    self.info_provider.include_path_for_union_types(union_type))
             # Need to re-assign the attribute, not just mutate idl_type, since
             # type(idl_type) may change.
             setattr(typed_object, attribute_name, resolved_idl_type)
@@ -182,23 +131,19 @@
         self._resolve_typedefs(typed_object)
 
 
-class CodeGeneratorBase(object):
+class CodeGeneratorV8Base(CodeGeneratorBase):
     """Base class for v8 bindings generator and IDL dictionary impl generator"""
 
-    def __init__(self, info_provider, cache_dir, output_dir):
-        self.info_provider = info_provider
-        self.jinja_env = initialize_jinja_env(cache_dir)
-        self.output_dir = output_dir
+    def __init__(self, info_provider, cache_dir, output_dir, snake_case):
+        CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, cache_dir, output_dir, snake_case)
         self.typedef_resolver = TypedefResolver(info_provider)
-        set_global_type_info(info_provider)
 
     def generate_code(self, definitions, definition_name):
         """Returns .h/.cpp code as ((path, content)...)."""
         # Set local type info
-        if not should_generate_code(definitions):
+        if not self.should_generate_code(definitions):
             return set()
 
-        IdlType.set_callback_functions(definitions.callback_functions.keys())
         # Resolve typedefs
         self.typedef_resolver.resolve(definitions, definition_name)
         return self.generate_code_internal(definitions, definition_name)
@@ -207,15 +152,19 @@
         # This should be implemented in subclasses.
         raise NotImplementedError()
 
+    def get_output_basename(self, definition_name, ext, prefix=None):
+        return build_basename(definition_name, self.snake_case_generated_files, prefix=prefix, ext=ext)
 
-class CodeGeneratorV8(CodeGeneratorBase):
-    def __init__(self, info_provider, cache_dir, output_dir):
-        CodeGeneratorBase.__init__(self, info_provider, cache_dir, output_dir)
+
+class CodeGeneratorV8(CodeGeneratorV8Base):
+    def __init__(self, info_provider, cache_dir, output_dir, snake_case):
+        CodeGeneratorV8Base.__init__(self, info_provider, cache_dir, output_dir, snake_case)
 
     def output_paths(self, definition_name):
-        header_path = posixpath.join(self.output_dir,
-                                     'V8%s.h' % definition_name)
-        cpp_path = posixpath.join(self.output_dir, 'V8%s.cpp' % definition_name)
+        header_path = posixpath.join(self.output_dir, self.get_output_basename(
+            definition_name, '.h', prefix='V8'))
+        cpp_path = posixpath.join(self.output_dir, self.get_output_basename(
+            definition_name, '.cpp', prefix='V8'))
         return header_path, cpp_path
 
     def generate_code_internal(self, definitions, definition_name):
@@ -230,49 +179,55 @@
         raise ValueError('%s is not in IDL definitions' % definition_name)
 
     def generate_interface_code(self, definitions, interface_name, interface):
-        # Store other interfaces for introspection
-        interfaces.update(definitions.interfaces)
-
         interface_info = self.info_provider.interfaces_info[interface_name]
         full_path = interface_info.get('full_path')
         component = idl_filename_to_component(full_path)
         include_paths = interface_info.get('dependencies_include_paths')
 
         # Select appropriate Jinja template and contents function
-        if interface.is_callback:
-            header_template_filename = 'callback_interface.h'
-            cpp_template_filename = 'callback_interface.cpp'
+        #
+        # A callback interface with constants needs a special handling.
+        # https://heycam.github.io/webidl/#legacy-callback-interface-object
+        if interface.is_callback and len(interface.constants) > 0:
+            header_template_filename = 'legacy_callback_interface.h.tmpl'
+            cpp_template_filename = 'legacy_callback_interface.cpp.tmpl'
+            interface_context = v8_callback_interface.legacy_callback_interface_context
+        elif interface.is_callback:
+            header_template_filename = 'callback_interface.h.tmpl'
+            cpp_template_filename = 'callback_interface.cpp.tmpl'
             interface_context = v8_callback_interface.callback_interface_context
         elif interface.is_partial:
             interface_context = v8_interface.interface_context
-            header_template_filename = 'partial_interface.h'
-            cpp_template_filename = 'partial_interface.cpp'
+            header_template_filename = 'partial_interface.h.tmpl'
+            cpp_template_filename = 'partial_interface.cpp.tmpl'
             interface_name += 'Partial'
             assert component == 'core'
             component = 'modules'
             include_paths = interface_info.get('dependencies_other_component_include_paths')
         else:
-            header_template_filename = 'interface.h'
-            cpp_template_filename = 'interface.cpp'
+            header_template_filename = 'interface.h.tmpl'
+            cpp_template_filename = 'interface.cpp.tmpl'
             interface_context = v8_interface.interface_context
 
-        template_context = interface_context(interface)
+        template_context = interface_context(interface, definitions.interfaces)
         includes.update(interface_info.get('cpp_includes', {}).get(component, set()))
         if not interface.is_partial and not is_testing_target(full_path):
             template_context['header_includes'].add(self.info_provider.include_path_for_export)
             template_context['exported'] = self.info_provider.specifier_for_export
         # Add the include for interface itself
         if IdlType(interface_name).is_typed_array:
-            template_context['header_includes'].add('core/dom/DOMTypedArray.h')
-        elif interface_info['include_path']:
+            template_context['header_includes'].add('core/typed_arrays/DOMTypedArray.h')
+        else:
             template_context['header_includes'].add(interface_info['include_path'])
-
+        template_context['header_includes'].update(
+            interface_info.get('additional_header_includes', []))
+        header_path, cpp_path = self.output_paths(interface_name)
+        template_context['this_include_header_name'] = posixpath.basename(header_path)
         header_template = self.jinja_env.get_template(header_template_filename)
         cpp_template = self.jinja_env.get_template(cpp_template_filename)
-        header_text, cpp_text = render_template(
+        header_text, cpp_text = self.render_template(
             include_paths, header_template, cpp_template, template_context,
             component)
-        header_path, cpp_path = self.output_paths(interface_name)
         return (
             (header_path, header_text),
             (cpp_path, cpp_text),
@@ -280,187 +235,181 @@
 
     def generate_dictionary_code(self, definitions, dictionary_name,
                                  dictionary):
+        # pylint: disable=unused-argument
         interfaces_info = self.info_provider.interfaces_info
-        header_template = self.jinja_env.get_template('dictionary_v8.h')
-        cpp_template = self.jinja_env.get_template('dictionary_v8.cpp')
+        header_template = self.jinja_env.get_template('dictionary_v8.h.tmpl')
+        cpp_template = self.jinja_env.get_template('dictionary_v8.cpp.tmpl')
         interface_info = interfaces_info[dictionary_name]
         template_context = v8_dictionary.dictionary_context(
             dictionary, interfaces_info)
         include_paths = interface_info.get('dependencies_include_paths')
         # Add the include for interface itself
-        if interface_info['include_path']:
-            template_context['header_includes'].add(interface_info['include_path'])
+        template_context['header_includes'].add(interface_info['include_path'])
         if not is_testing_target(interface_info.get('full_path')):
             template_context['header_includes'].add(self.info_provider.include_path_for_export)
             template_context['exported'] = self.info_provider.specifier_for_export
-        header_text, cpp_text = render_template(
-            include_paths, header_template, cpp_template, template_context)
         header_path, cpp_path = self.output_paths(dictionary_name)
+        template_context['this_include_header_name'] = posixpath.basename(header_path)
+        header_text, cpp_text = self.render_template(
+            include_paths, header_template, cpp_template, template_context)
         return (
             (header_path, header_text),
             (cpp_path, cpp_text),
         )
 
 
-class CodeGeneratorDictionaryImpl(CodeGeneratorBase):
-    def __init__(self, info_provider, cache_dir, output_dir):
-        CodeGeneratorBase.__init__(self, info_provider, cache_dir, output_dir)
+class CodeGeneratorDictionaryImpl(CodeGeneratorV8Base):
+    def __init__(self, info_provider, cache_dir, output_dir, snake_case):
+        CodeGeneratorV8Base.__init__(self, info_provider, cache_dir, output_dir, snake_case)
 
     def output_paths(self, definition_name, interface_info):
         output_dir = posixpath.join(self.output_dir,
                                     interface_info['relative_dir'])
-        header_path = posixpath.join(output_dir, '%s.h' % definition_name)
-        cpp_path = posixpath.join(output_dir, '%s.cpp' % definition_name)
+        header_path = posixpath.join(output_dir,
+                                     self.get_output_basename(definition_name, '.h'))
+        cpp_path = posixpath.join(output_dir,
+                                  self.get_output_basename(definition_name, '.cpp'))
         return header_path, cpp_path
 
     def generate_code_internal(self, definitions, definition_name):
         if not definition_name in definitions.dictionaries:
-            raise ValueError('%s is not an IDL dictionary')
+            raise ValueError('%s is not an IDL dictionary' % definition_name)
         interfaces_info = self.info_provider.interfaces_info
         dictionary = definitions.dictionaries[definition_name]
         interface_info = interfaces_info[definition_name]
-        header_template = self.jinja_env.get_template('dictionary_impl.h')
-        cpp_template = self.jinja_env.get_template('dictionary_impl.cpp')
+        header_template = self.jinja_env.get_template('dictionary_impl.h.tmpl')
+        cpp_template = self.jinja_env.get_template('dictionary_impl.cpp.tmpl')
         template_context = v8_dictionary.dictionary_impl_context(
             dictionary, interfaces_info)
         include_paths = interface_info.get('dependencies_include_paths')
-        # Add union containers header file to header_includes rather than
-        # cpp file so that union containers can be used in dictionary headers.
-        union_container_headers = [header for header in include_paths
-                                   if header.find('UnionTypes') > 0]
-        include_paths = [header for header in include_paths
-                         if header not in union_container_headers]
-        template_context['header_includes'].update(union_container_headers)
         if not is_testing_target(interface_info.get('full_path')):
             template_context['exported'] = self.info_provider.specifier_for_export
             template_context['header_includes'].add(self.info_provider.include_path_for_export)
-        header_text, cpp_text = render_template(
-            include_paths, header_template, cpp_template, template_context)
+        template_context['header_includes'].update(
+            interface_info.get('additional_header_includes', []))
         header_path, cpp_path = self.output_paths(
             cpp_name(dictionary), interface_info)
+        template_context['this_include_header_name'] = posixpath.basename(header_path)
+        header_text, cpp_text = self.render_template(
+            include_paths, header_template, cpp_template, template_context)
         return (
             (header_path, header_text),
             (cpp_path, cpp_text),
         )
 
 
-class CodeGeneratorUnionType(object):
+class CodeGeneratorUnionType(CodeGeneratorBase):
     """Generates union type container classes.
     This generator is different from CodeGeneratorV8 and
     CodeGeneratorDictionaryImpl. It assumes that all union types are already
     collected. It doesn't process idl files directly.
     """
-    def __init__(self, info_provider, cache_dir, output_dir, target_component):
-        self.info_provider = info_provider
-        self.jinja_env = initialize_jinja_env(cache_dir)
-        self.output_dir = output_dir
+    def __init__(self, info_provider, cache_dir, output_dir, snake_case, target_component):
+        CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, cache_dir, output_dir, snake_case)
         self.target_component = target_component
-        set_global_type_info(info_provider)
+        # The code below duplicates parts of TypedefResolver. We do not use it
+        # directly because IdlUnionType is not a type defined in
+        # idl_definitions.py. What we do instead is to resolve typedefs in
+        # _generate_container_code() whenever a new union file is generated.
+        self.typedefs = {}
+        for name, typedef in self.info_provider.typedefs.iteritems():
+            self.typedefs[name] = typedef.idl_type
 
-    def generate_code(self):
-        union_types = self.info_provider.union_types
-        if not union_types:
-            return ()
-        header_template = self.jinja_env.get_template('union.h')
-        cpp_template = self.jinja_env.get_template('union.cpp')
-        template_context = v8_union.union_context(
-            union_types, self.info_provider.interfaces_info)
-        template_context['code_generator'] = module_pyname
-        capitalized_component = self.target_component.capitalize()
-        template_context['exported'] = self.info_provider.specifier_for_export
-        template_context['header_filename'] = 'bindings/%s/v8/UnionTypes%s.h' % (
-            self.target_component, capitalized_component)
-        template_context['macro_guard'] = 'UnionType%s_h' % capitalized_component
-        additional_header_includes = [self.info_provider.include_path_for_export]
-
-        # Add UnionTypesCore.h as a dependency when we generate modules union types
-        # because we only generate union type containers which are used by both
-        # core and modules in UnionTypesCore.h.
-        # FIXME: This is an ad hoc workaround and we need a general way to
-        # handle core <-> modules dependency.
-        if self.target_component == 'modules':
-            additional_header_includes.append(
-                'bindings/core/v8/UnionTypesCore.h')
-
+    def _generate_container_code(self, union_type):
+        union_type = union_type.resolve_typedefs(self.typedefs)
+        header_template = self.jinja_env.get_template('union_container.h.tmpl')
+        cpp_template = self.jinja_env.get_template('union_container.cpp.tmpl')
+        template_context = v8_union.container_context(
+            union_type, self.info_provider)
+        template_context['header_includes'].append(
+            self.info_provider.include_path_for_export)
         template_context['header_includes'] = normalize_and_sort_includes(
-            template_context['header_includes'] + additional_header_includes)
-
-        header_text = header_template.render(template_context)
-        cpp_text = cpp_template.render(template_context)
-        header_path = posixpath.join(self.output_dir,
-                                     'UnionTypes%s.h' % capitalized_component)
-        cpp_path = posixpath.join(self.output_dir,
-                                  'UnionTypes%s.cpp' % capitalized_component)
+            template_context['header_includes'], self.snake_case_generated_files)
+        template_context['cpp_includes'] = normalize_and_sort_includes(
+            template_context['cpp_includes'], self.snake_case_generated_files)
+        template_context['code_generator'] = self.generator_name
+        template_context['exported'] = self.info_provider.specifier_for_export
+        snake_base_name = to_snake_case(shorten_union_name(union_type))
+        template_context['this_include_header_name'] = snake_base_name
+        header_text = render_template(header_template, template_context)
+        cpp_text = render_template(cpp_template, template_context)
+        header_path = posixpath.join(self.output_dir, '%s.h' % snake_base_name)
+        cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
         return (
             (header_path, header_text),
             (cpp_path, cpp_text),
         )
 
+    def _get_union_types_for_containers(self):
+        union_types = self.info_provider.union_types
+        if not union_types:
+            return None
+        # For container classes we strip nullable wrappers. For example,
+        # both (A or B)? and (A? or B) will become AOrB. This should be OK
+        # because container classes can handle null and it seems that
+        # distinguishing (A or B)? and (A? or B) doesn't make sense.
+        container_cpp_types = set()
+        union_types_for_containers = set()
+        for union_type in union_types:
+            cpp_type = union_type.cpp_type
+            if cpp_type not in container_cpp_types:
+                union_types_for_containers.add(union_type)
+                container_cpp_types.add(cpp_type)
+        return union_types_for_containers
 
-def initialize_jinja_env(cache_dir):
-    jinja_env = jinja2.Environment(
-        loader=jinja2.FileSystemLoader(templates_dir),
-        # Bytecode cache is not concurrency-safe unless pre-cached:
-        # if pre-cached this is read-only, but writing creates a race condition.
-        bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
-        keep_trailing_newline=True,  # newline-terminate generated files
-        lstrip_blocks=True,  # so can indent control flow tags
-        trim_blocks=True)
-    jinja_env.filters.update({
-        'blink_capitalize': capitalize,
-        'exposed': exposed_if,
-        'runtime_enabled': runtime_enabled_if,
-        })
-    return jinja_env
+    def generate_code(self):
+        union_types = self._get_union_types_for_containers()
+        if not union_types:
+            return ()
+        outputs = set()
+        for union_type in union_types:
+            outputs.update(self._generate_container_code(union_type))
+        return outputs
 
 
-def generate_indented_conditional(code, conditional):
-    # Indent if statement to level of original code
-    indent = re.match(' *', code).group(0)
-    return ('%sif (%s) {\n' % (indent, conditional) +
-            '    %s\n' % '\n    '.join(code.splitlines()) +
-            '%s}\n' % indent)
+class CodeGeneratorCallbackFunction(CodeGeneratorBase):
+    def __init__(self, info_provider, cache_dir, output_dir, snake_case, target_component):
+        CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, cache_dir, output_dir, snake_case)
+        self.target_component = target_component
+        self.typedef_resolver = TypedefResolver(info_provider)
 
+    def generate_code_internal(self, callback_function, path):
+        self.typedef_resolver.resolve(callback_function, callback_function.name)
+        header_template = self.jinja_env.get_template('callback_function.h.tmpl')
+        cpp_template = self.jinja_env.get_template('callback_function.cpp.tmpl')
+        template_context = v8_callback_function.callback_function_context(
+            callback_function)
+        if not is_testing_target(path):
+            template_context['exported'] = self.info_provider.specifier_for_export
+            template_context['header_includes'].append(
+                self.info_provider.include_path_for_export)
+        template_context['header_includes'] = normalize_and_sort_includes(
+            template_context['header_includes'], self.snake_case_generated_files)
+        template_context['cpp_includes'] = normalize_and_sort_includes(
+            template_context['cpp_includes'], self.snake_case_generated_files)
+        template_context['code_generator'] = MODULE_PYNAME
+        header_text = render_template(header_template, template_context)
+        cpp_text = render_template(cpp_template, template_context)
+        snake_base_name = to_snake_case('V8%s' % callback_function.name)
+        header_path = posixpath.join(self.output_dir, '%s.h' % snake_base_name)
+        cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
+        return (
+            (header_path, header_text),
+            (cpp_path, cpp_text),
+        )
 
-# [Exposed]
-def exposed_if(code, exposed_test):
-    if not exposed_test:
-        return code
-    return generate_indented_conditional(code, 'executionContext && (%s)' % exposed_test)
-
-
-# [RuntimeEnabled]
-def runtime_enabled_if(code, runtime_enabled_function_name):
-    if not runtime_enabled_function_name:
-        return code
-    return generate_indented_conditional(code, '%s()' % runtime_enabled_function_name)
-
-
-################################################################################
-
-def main(argv):
-    # If file itself executed, cache templates
-    try:
-        cache_dir = argv[1]
-        dummy_filename = argv[2]
-    except IndexError as err:
-        print 'Usage: %s CACHE_DIR DUMMY_FILENAME' % argv[0]
-        return 1
-
-    # Cache templates
-    jinja_env = initialize_jinja_env(cache_dir)
-    template_filenames = [filename for filename in os.listdir(templates_dir)
-                          # Skip .svn, directories, etc.
-                          if filename.endswith(('.cpp', '.h'))]
-    for template_filename in template_filenames:
-        jinja_env.get_template(template_filename)
-
-    # Create a dummy file as output for the build system,
-    # since filenames of individual cache files are unpredictable and opaque
-    # (they are hashes of the template path, which varies based on environment)
-    with open(dummy_filename, 'w') as dummy_file:
-        pass  # |open| creates or touches the file
-
-
-if __name__ == '__main__':
-    sys.exit(main(sys.argv))
+    # pylint: disable=W0221
+    def generate_code(self):
+        callback_functions = self.info_provider.callback_functions
+        if not callback_functions:
+            return ()
+        outputs = set()
+        for callback_function_dict in callback_functions.itervalues():
+            if callback_function_dict['component_dir'] != self.target_component:
+                continue
+            callback_function = callback_function_dict['callback_function']
+            if 'Custom' in callback_function.extended_attributes:
+                continue
+            path = callback_function_dict['full_path']
+            outputs.update(self.generate_code_internal(callback_function, path))
+        return outputs
diff --git a/bindings/scripts/code_generator_web_agent_api.py b/bindings/scripts/code_generator_web_agent_api.py
new file mode 100644
index 0000000..69d4aff
--- /dev/null
+++ b/bindings/scripts/code_generator_web_agent_api.py
@@ -0,0 +1,285 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# pylint: disable=import-error,print-statement,relative-import
+
+"""Generates Web Agent API bindings.
+
+The Web Agent API bindings provide a stable, IDL-generated interface for the
+Web Agents.
+
+The Web Agents are the high-level services like Autofill,
+Autocomplete, Translate, Distiller, Phishing Detector, and others. Web Agents
+typically want to introspec the document and rendering infromation to implement
+browser features.
+
+The bindings are meant to be as simple and as ephemeral as possible, mostly just
+wrapping existing DOM classes. Their primary goal is to avoid leaking the actual
+DOM classes to the Web Agents layer.
+"""
+
+import os
+import posixpath
+import sys
+
+from code_generator import CodeGeneratorBase, render_template
+# TODO(dglazkov): Move TypedefResolver to code_generator.py
+from code_generator_v8 import TypedefResolver
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', '..',
+                             'third_party', 'blink', 'tools'))
+from blinkpy.common.name_style_converter import NameStyleConverter
+
+MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py'
+
+STRING_INCLUDE_PATH = 'platform/wtf/text/WTFString.h'
+WEB_AGENT_API_IDL_ATTRIBUTE = 'WebAgentAPI'
+
+
+def interface_context(idl_interface, type_resolver):
+    builder = InterfaceContextBuilder(MODULE_PYNAME, type_resolver)
+    builder.set_class_name(idl_interface.name)
+    builder.set_inheritance(idl_interface.parent)
+
+    for idl_attribute in idl_interface.attributes:
+        builder.add_attribute(idl_attribute)
+
+    for idl_operation in idl_interface.operations:
+        builder.add_operation(idl_operation)
+
+    return builder.build()
+
+
+class TypeResolver(object):
+    """Resolves Web IDL types into corresponding C++ types and include paths
+       to the generated and existing files."""
+
+    def __init__(self, interfaces_info):
+        self.interfaces_info = interfaces_info
+
+    def includes_from_interface(self, interface_name):
+        interface_info = self.interfaces_info.get(interface_name)
+        if interface_info is None:
+            raise KeyError('Unknown interface "%s".' % interface_name)
+        return set([interface_info['include_path']])
+
+    def _includes_from_type(self, idl_type):
+        if idl_type.is_void:
+            return set()
+        if idl_type.is_primitive_type:
+            return set()
+        if idl_type.is_string_type:
+            return set([STRING_INCLUDE_PATH])
+
+        # TODO(dglazkov): Handle complex/weird types.
+        return self.includes_from_interface(idl_type.base_type)
+
+    def includes_from_definition(self, idl_definition):
+        return self._includes_from_type(idl_definition.idl_type)
+
+    def type_from_definition(self, idl_definition):
+        # TODO(dglazkov): The output of this method must be a reasonable C++
+        # type that can be used directly in the jinja2 template.
+        return idl_definition.idl_type.base_type
+
+    def base_class_includes(self):
+        return set(['platform/heap/Handle.h'])
+
+
+class MethodOverloadSplitter(object):
+    """Because of union and optional types being used as arguments, some
+       operations may result in more than one generated method. This class
+       contains the logic for spliting an operation into multiple C++ overloads.
+    """
+
+    def __init__(self, idl_operation):
+        self.idl_operation = idl_operation
+
+    def _update_argument_lists(self, argument_lists, idl_types):
+        """Given a list of IdlTypes and an existing list of argument lists (yes,
+           this is a list of lists), produces a next generation of the list of
+           lists. This is where the actual splitting into overloads happens.
+        """
+        result = []
+        for argument_list in argument_lists:
+            for idl_type in idl_types:
+                new_argument_list = list(argument_list)
+                if idl_type is not None:
+                    new_argument_list.append(idl_type)
+                result.append(new_argument_list)
+        return result
+
+    def _enumerate_argument_types(self, idl_argument):
+        """Given an IdlArgument, returns a list of types that are included
+           in this argument. If optional, the list will include a 'None'."""
+        argument_type = idl_argument.idl_type
+        # TODO(dglazkov): What should we do with primitive nullable args?
+        if (argument_type.is_nullable and
+                argument_type.inner_type.is_primitive_type):
+            raise ValueError('Primitive nullable types are not supported.')
+
+        idl_types = []
+        if idl_argument.is_optional:
+            idl_types.append(None)  # None is used to convey optionality.
+        if argument_type.is_union_type:
+            idl_types = idl_types + argument_type.member_types
+        else:
+            idl_types.append(argument_type)
+        return idl_types
+
+    def split_into_overloads(self):
+        """Splits an operation into one or more overloads that correctly reflect
+           the WebIDL semantics of the operation arguments. For example,
+           running this method on an IdlOperation that represents this WebIDL
+           definition:
+
+           void addEventListener(
+                DOMString type,
+                EventListener? listener,
+                optional (AddEventListenerOptions or boolean) options)
+
+            will produce a list of 3 argument lists:
+
+            1) [DOMString, EventListener], since the third argument is optional,
+            2) [DOMString, EventListener, AddEventListenerOptions], since the
+               third argument is a union type with AddEventListenerOptions as
+               one of its member types, and
+            3) [DOMString, EventListener, boolean], since the other union member
+               type of the third argument is boolean.
+
+            This example is also captured as test in
+            MethodOverloadSplitterTest.test_split_add_event_listener.
+        """
+
+        argument_lists = [[]]
+        for idl_argument in self.idl_operation.arguments:
+            idl_types = self._enumerate_argument_types(idl_argument)
+            argument_lists = self._update_argument_lists(argument_lists,
+                                                         idl_types)
+        return argument_lists
+
+
+class InterfaceContextBuilder(object):
+    def __init__(self, code_generator, type_resolver):
+        self.result = {'code_generator': code_generator}
+        self.type_resolver = type_resolver
+
+    def set_class_name(self, class_name):
+        converter = NameStyleConverter(class_name)
+        self.result['class_name'] = converter.to_all_cases()
+        self._ensure_set('cpp_includes').update(
+            self.type_resolver.includes_from_interface(class_name))
+
+    def set_inheritance(self, base_interface):
+        if base_interface is None:
+            self._ensure_set('header_includes').update(
+                self.type_resolver.base_class_includes())
+            return
+        self.result['base_class'] = base_interface
+        self._ensure_set('header_includes').update(
+            self.type_resolver.includes_from_interface(base_interface))
+
+    def _ensure_set(self, name):
+        return self.result.setdefault(name, set())
+
+    def _ensure_list(self, name):
+        return self.result.setdefault(name, [])
+
+    def add_attribute(self, idl_attribute):
+        self._ensure_list('attributes').append(
+            self.create_attribute(idl_attribute))
+        self._ensure_set('cpp_includes').update(
+            self.type_resolver.includes_from_definition(idl_attribute))
+
+    def add_operation(self, idl_operation):
+        if not idl_operation.name:
+            return
+        overload_splitter = MethodOverloadSplitter(idl_operation)
+        overloads = overload_splitter.split_into_overloads()
+        argument_names = [argument.name for argument
+                          in idl_operation.arguments]
+        for argument_types in overloads:
+            arguments = []
+            for position, argument_type in enumerate(argument_types):
+                arguments.append(
+                    self.create_argument(argument_names[position],
+                                         argument_type))
+            self._ensure_list('methods').append(
+                self.create_method(idl_operation, arguments))
+            self._ensure_set('cpp_includes').update(
+                self.type_resolver.includes_from_definition(idl_operation))
+
+    def create_argument(self, argument_name, argument_type):
+        name_converter = NameStyleConverter(argument_name)
+        return {
+            'name': name_converter.to_snake_case(),
+            'type': argument_type.base_type,
+        }
+
+    def create_method(self, idl_operation, arguments):
+        name_converter = NameStyleConverter(idl_operation.name)
+        return_type = self.type_resolver.type_from_definition(idl_operation)
+        return {
+            'name': name_converter.to_upper_camel_case(),
+            'type': return_type,
+            'arguments': arguments
+        }
+
+    def create_attribute(self, idl_attribute):
+        name = idl_attribute.name
+        return_type = self.type_resolver.type_from_definition(idl_attribute)
+        return {
+            'name': name,
+            'type': return_type
+        }
+
+    def build(self):
+        return self.result
+
+
+class CodeGeneratorWebAgentAPI(CodeGeneratorBase):
+    def __init__(self, info_provider, cache_dir, output_dir, snake_case):
+        CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider,
+                                   cache_dir, output_dir, snake_case)
+        self.type_resolver = TypeResolver(info_provider.interfaces_info)
+        self.typedef_resolver = TypedefResolver(info_provider)
+
+    def get_template(self, file_extension):
+        template_filename = 'web_agent_api_interface.%s.tmpl' % file_extension
+        return self.jinja_env.get_template(template_filename)
+
+    def generate_file(self, template_context, file_extension):
+        template = self.get_template(file_extension)
+        path = posixpath.join(
+            self.output_dir,
+            '%s.%s' % (template_context['class_name']['snake_case'],
+                       file_extension))
+        text = render_template(template, template_context)
+        return (path, text)
+
+    def generate_interface_code(self, interface):
+        # TODO(dglazkov): Implement callback interfaces.
+        # TODO(dglazkov): Make sure partial interfaces are handled.
+        if interface.is_callback or interface.is_partial:
+            raise ValueError('Partial or callback interfaces are not supported')
+
+        template_context = interface_context(interface, self.type_resolver)
+
+        return (
+            self.generate_file(template_context, 'h'),
+            self.generate_file(template_context, 'cc')
+        )
+
+    def generate_code(self, definitions, definition_name):
+        self.typedef_resolver.resolve(definitions, definition_name)
+
+        # TODO(dglazkov): Implement dictionaries
+        if definition_name not in definitions.interfaces:
+            return None
+
+        interface = definitions.interfaces[definition_name]
+        if WEB_AGENT_API_IDL_ATTRIBUTE not in interface.extended_attributes:
+            return None
+
+        return self.generate_interface_code(interface)
diff --git a/bindings/scripts/code_generator_web_agent_api_test.py b/bindings/scripts/code_generator_web_agent_api_test.py
new file mode 100644
index 0000000..7f7b96e
--- /dev/null
+++ b/bindings/scripts/code_generator_web_agent_api_test.py
@@ -0,0 +1,337 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# pylint: disable=import-error,print-statement,relative-import,protected-access
+
+"""Unit tests for code_generator_web_agent_api.py."""
+
+import unittest
+
+from code_generator_web_agent_api import InterfaceContextBuilder
+from code_generator_web_agent_api import MethodOverloadSplitter
+from code_generator_web_agent_api import STRING_INCLUDE_PATH
+from code_generator_web_agent_api import TypeResolver
+from idl_definitions import IdlArgument
+from idl_definitions import IdlAttribute
+from idl_definitions import IdlOperation
+from idl_types import IdlType
+from idl_types import IdlNullableType
+from idl_types import IdlUnionType
+from idl_types import PRIMITIVE_TYPES
+from idl_types import STRING_TYPES
+
+
+# TODO(dglazkov): Convert to use actual objects, not stubs.
+# See http://crbug.com/673214 for more details.
+class IdlTestingHelper(object):
+    """A collection of stub makers and helper utils to make testing code
+    generation easy."""
+
+    def make_stub_idl_argument(self, name, idl_type, is_optional=False):
+        idl_argument = IdlArgument()
+        idl_argument.name = name
+        idl_argument.idl_type = idl_type
+        idl_argument.is_optional = is_optional
+        return idl_argument
+
+    def make_stub_idl_attribute(self, name, return_type):
+        idl_attribute_stub = IdlAttribute()
+        idl_attribute_stub.name = name
+        idl_attribute_stub.idl_type = IdlType(return_type)
+        return idl_attribute_stub
+
+    def make_stub_idl_operation(self, name, return_type):
+        idl_operation_stub = IdlOperation()
+        idl_operation_stub.name = name
+        idl_operation_stub.idl_type = IdlType(return_type)
+        return idl_operation_stub
+
+    def make_stub_idl_type(self, base_type):
+        return IdlType(base_type)
+
+    def make_stub_interfaces_info(self, classes_to_paths):
+        result = {}
+        for class_name, path in classes_to_paths.iteritems():
+            result[class_name] = {'include_path': path}
+        return result
+
+
+class TypeResolverTest(unittest.TestCase):
+
+    def test_includes_from_type_should_filter_primitive_types(self):
+        helper = IdlTestingHelper()
+        type_resolver = TypeResolver({})
+        for primitive_type in PRIMITIVE_TYPES:
+            idl_type = helper.make_stub_idl_type(primitive_type)
+            self.assertEqual(
+                type_resolver._includes_from_type(idl_type), set())
+
+    def test_includes_from_type_should_filter_void(self):
+        type_resolver = TypeResolver({})
+        helper = IdlTestingHelper()
+        idl_type = helper.make_stub_idl_type('void')
+        self.assertEqual(
+            type_resolver._includes_from_type(idl_type), set())
+
+    def test_includes_from_type_should_handle_string(self):
+        type_resolver = TypeResolver({})
+        helper = IdlTestingHelper()
+        for string_type in STRING_TYPES:
+            idl_type = helper.make_stub_idl_type(string_type)
+            self.assertEqual(
+                type_resolver._includes_from_type(idl_type),
+                set([STRING_INCLUDE_PATH]))
+
+
+class MethodOverloadSplitterTest(unittest.TestCase):
+
+    def test_enumerate_argument_types(self):
+        splitter = MethodOverloadSplitter(IdlOperation())
+        nullable_and_primitive = IdlArgument()
+        nullable_and_primitive.idl_type = IdlNullableType(IdlType('double'))
+        with self.assertRaises(ValueError):
+            splitter._enumerate_argument_types(nullable_and_primitive)
+
+        argument = IdlArgument()
+        foo_type = IdlType('Foo')
+        bar_type = IdlType('Bar')
+
+        argument.idl_type = foo_type
+        self.assertEqual(
+            splitter._enumerate_argument_types(argument), [foo_type])
+
+        argument.is_optional = True
+        self.assertEqual(
+            splitter._enumerate_argument_types(argument), [None, foo_type])
+
+        argument.is_optional = False
+        argument.idl_type = IdlUnionType([foo_type, bar_type])
+        self.assertEqual(
+            splitter._enumerate_argument_types(argument), [foo_type, bar_type])
+
+        argument.is_optional = True
+        self.assertEqual(
+            splitter._enumerate_argument_types(argument),
+            [None, foo_type, bar_type])
+
+    def test_update_argument_lists(self):
+        splitter = MethodOverloadSplitter(IdlOperation())
+        foo_type = IdlType('Foo')
+        bar_type = IdlType('Bar')
+        baz_type = IdlType('Baz')
+        qux_type = IdlType('Qux')
+
+        result = splitter._update_argument_lists([[]], [foo_type])
+        self.assertEqual(result, [[foo_type]])
+
+        result = splitter._update_argument_lists([[]], [foo_type, bar_type])
+        self.assertEqual(result, [[foo_type], [bar_type]])
+
+        existing_list = [[foo_type]]
+        result = splitter._update_argument_lists(existing_list, [bar_type])
+        self.assertEqual(result, [[foo_type, bar_type]])
+
+        existing_list = [[foo_type]]
+        result = splitter._update_argument_lists(existing_list,
+                                                 [None, bar_type])
+        self.assertEqual(result, [[foo_type], [foo_type, bar_type]])
+
+        existing_list = [[foo_type]]
+        result = splitter._update_argument_lists(existing_list,
+                                                 [bar_type, baz_type])
+        self.assertEqual(result, [[foo_type, bar_type], [foo_type, baz_type]])
+
+        existing_list = [[foo_type], [qux_type]]
+        result = splitter._update_argument_lists(existing_list,
+                                                 [bar_type, baz_type])
+        self.assertEqual(result, [
+            [foo_type, bar_type],
+            [foo_type, baz_type],
+            [qux_type, bar_type],
+            [qux_type, baz_type],
+        ])
+
+        existing_list = [[foo_type], [qux_type]]
+        result = splitter._update_argument_lists(existing_list,
+                                                 [None, bar_type, baz_type])
+        self.assertEqual(result, [
+            [foo_type],
+            [foo_type, bar_type],
+            [foo_type, baz_type],
+            [qux_type],
+            [qux_type, bar_type],
+            [qux_type, baz_type],
+        ])
+
+        existing_list = [[foo_type, qux_type]]
+        result = splitter._update_argument_lists(existing_list,
+                                                 [bar_type, baz_type])
+        self.assertEqual(result, [
+            [foo_type, qux_type, bar_type],
+            [foo_type, qux_type, baz_type],
+        ])
+
+    def test_split_into_overloads(self):
+        helper = IdlTestingHelper()
+        type_double = IdlType('double')
+        type_foo = IdlType('foo')
+        type_double_or_foo = IdlUnionType([type_double, type_foo])
+        idl_operation = IdlOperation()
+
+        idl_operation.arguments = []
+        splitter = MethodOverloadSplitter(idl_operation)
+        result = splitter.split_into_overloads()
+        self.assertEqual(result, [[]])
+
+        idl_operation.arguments = [
+            helper.make_stub_idl_argument(None, type_double, True)
+        ]
+        splitter = MethodOverloadSplitter(idl_operation)
+        result = splitter.split_into_overloads()
+        self.assertEqual(result, [[], [type_double]])
+
+        idl_operation.arguments = [
+            helper.make_stub_idl_argument(None, type_double_or_foo)
+        ]
+        splitter = MethodOverloadSplitter(idl_operation)
+        result = splitter.split_into_overloads()
+        self.assertEqual(result, [[type_double], [type_foo]])
+
+    def test_split_add_event_listener(self):
+        """Tests how EventTarget.addEventListener is split into respective
+           overloads. From:
+
+           void addEventListener(
+                DOMString type,
+                EventListener? listener,
+                optional (AddEventListenerOptions or boolean) options)
+
+           produces: """
+
+        helper = IdlTestingHelper()
+        type_dom_string = IdlType('DOMString')
+        type_listener = IdlType('EventListener')
+        type_options = IdlType('AddEventListenerOptions')
+        type_boolean = IdlType('boolean')
+        type_union = IdlUnionType([type_options, type_boolean])
+        idl_operation = IdlOperation()
+        idl_operation.arguments = [
+            helper.make_stub_idl_argument('type', type_dom_string),
+            helper.make_stub_idl_argument('listener', type_listener),
+            helper.make_stub_idl_argument('options', type_union,
+                                          is_optional=True)]
+        splitter = MethodOverloadSplitter(idl_operation)
+        result = splitter.split_into_overloads()
+        self.assertEqual(
+            result,
+            [[type_dom_string, type_listener],
+             [type_dom_string, type_listener, type_options],
+             [type_dom_string, type_listener, type_boolean]])
+
+
+class InterfaceContextBuilderTest(unittest.TestCase):
+
+    def test_empty(self):
+        builder = InterfaceContextBuilder('test', TypeResolver({}))
+
+        self.assertEqual({'code_generator': 'test'}, builder.build())
+
+    def test_set_name(self):
+        helper = IdlTestingHelper()
+        builder = InterfaceContextBuilder(
+            'test', TypeResolver(helper.make_stub_interfaces_info({
+                'foo': 'path_to_foo',
+            })))
+
+        builder.set_class_name('foo')
+        self.assertEqual({
+            'code_generator': 'test',
+            'cpp_includes': set(['path_to_foo']),
+            'class_name': {
+                'snake_case': 'foo',
+                'macro_case': 'FOO',
+                'upper_camel_case': 'Foo'
+            },
+        }, builder.build())
+
+    def test_set_inheritance(self):
+        helper = IdlTestingHelper()
+        builder = InterfaceContextBuilder(
+            'test', TypeResolver(helper.make_stub_interfaces_info({
+                'foo': 'path_to_foo',
+            })))
+        builder.set_inheritance('foo')
+        self.assertEqual({
+            'base_class': 'foo',
+            'code_generator': 'test',
+            'header_includes': set(['path_to_foo']),
+        }, builder.build())
+
+        builder = InterfaceContextBuilder('test', TypeResolver({}))
+        builder.set_inheritance(None)
+        self.assertEqual({
+            'code_generator': 'test',
+            'header_includes': set(['platform/heap/Handle.h']),
+        }, builder.build())
+
+    def test_add_attribute(self):
+        helper = IdlTestingHelper()
+        builder = InterfaceContextBuilder(
+            'test', TypeResolver(helper.make_stub_interfaces_info({
+                'foo': 'path_to_foo',
+                'bar': 'path_to_bar'
+            })))
+
+        attribute = helper.make_stub_idl_attribute('foo', 'bar')
+        builder.add_attribute(attribute)
+        self.assertEqual({
+            'code_generator': 'test',
+            'cpp_includes': set(['path_to_bar']),
+            'attributes': [{'name': 'foo', 'type': 'bar'}],
+        }, builder.build())
+
+    def test_add_method(self):
+        helper = IdlTestingHelper()
+        builder = InterfaceContextBuilder(
+            'test', TypeResolver(helper.make_stub_interfaces_info({
+                'foo': 'path_to_foo',
+                'bar': 'path_to_bar',
+                'garply': 'path_to_garply',
+            })))
+
+        operation = helper.make_stub_idl_operation('foo', 'bar')
+        builder.add_operation(operation)
+        self.assertEqual({
+            'code_generator': 'test',
+            'cpp_includes': set(['path_to_bar']),
+            'methods': [{
+                'arguments': [],
+                'name': 'Foo',
+                'type': 'bar'
+            }],
+        }, builder.build())
+
+        operation = helper.make_stub_idl_operation('quux', 'garply')
+        operation.arguments = [
+            helper.make_stub_idl_argument('barBaz', IdlType('qux'))
+        ]
+        builder.add_operation(operation)
+        self.assertEqual({
+            'code_generator': 'test',
+            'cpp_includes': set(['path_to_bar', 'path_to_garply']),
+            'methods': [
+                {
+                    'arguments': [],
+                    'name': 'Foo',
+                    'type': 'bar'
+                },
+                {
+                    'arguments': [
+                        {'name': 'bar_baz', 'type': 'qux'}
+                    ],
+                    'name': 'Quux',
+                    'type': 'garply'
+                }
+            ],
+        }, builder.build())
diff --git a/bindings/scripts/collect_idls_into_json.py b/bindings/scripts/collect_idls_into_json.py
deleted file mode 100644
index a03026f..0000000
--- a/bindings/scripts/collect_idls_into_json.py
+++ /dev/null
@@ -1,432 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Usage: collect_idls_into_json.py path_file.txt json_file.json
-This script collects and organizes interface information and that information dumps into json file.
-"""
-
-import json
-import os
-import sys
-import utilities
-
-
-from blink_idl_parser import parse_file, BlinkIDLParser
-
-_INTERFACE = 'Interface'
-_IMPLEMENT = 'Implements'
-_PARTIAL = 'Partial'
-_NAME = 'Name'
-_TYPE = 'Type'
-_UNIONTYPE = 'UnionType'
-_ARRAY = 'Array'
-_ANY = 'Any'
-_SEQUENCE = 'Sequence'
-_PROP_VALUE = 'VALUE'
-_VALUE = 'Value'
-_PARENT = 'Parent'
-_FILEPATH = 'FilePath'
-_PROP_FILENAME = 'FILENAME'
-_PROP_READONLY = 'READONLY'
-_READONLY = 'Readonly'
-_PROP_STATIC = 'STATIC'
-_STATIC = 'Static'
-_CONSTS = 'Consts'
-_CONST = 'Const'
-_ATTRIBUTES = 'Attributes'
-_ATTRIBUTE = 'Attribute'
-_OPERATIONS = 'Operations'
-_OPERATION = 'Operation'
-_PROP_GETTER = 'GETTER'
-_NAMED_GETTER = '__getter__'
-_PROP_SETTER = 'SETTER'
-_NAMED_SETTER = '__setter__'
-_PROP_DELETER = 'DELETER'
-_NAMED_DELETER = '__deleter__'
-_ARGUMENTS = 'Arguments'
-_ARGUMENT = 'Argument'
-_EXTATTRIBUTES = 'ExtAttributes'
-_EXTATTRIBUTE = 'ExtAttribute'
-_INHERIT = 'Inherit'
-_PROP_REFERENCE = 'REFERENCE'
-_PARTIAL_FILEPATH = 'Partial_FilePaths'
-_MEMBERS = [_CONSTS, _ATTRIBUTES, _OPERATIONS]
-
-
-def get_definitions(paths):
-    """Returns a generator of IDL node.
-    Args:
-      paths: list of IDL file path
-    Returns:
-      a generator which yields IDL node objects
-    """
-    parser = BlinkIDLParser()
-    for path in paths:
-        definitions = parse_file(parser, path)
-        for definition in definitions.GetChildren():
-            yield definition
-
-
-def is_implements(definition):
-    """Returns True if class of |definition| is Implements, otherwise False.
-    Args:
-      definition: IDL node
-    Returns:
-      True if class of |definition| is Implements, otherwise False.
-    """
-    return definition.GetClass() == _IMPLEMENT
-
-
-def is_partial(definition):
-    """Returns True if |definition| is 'partial interface' class, otherwise False.
-    Args:
-      definition: IDL node
-    Return:
-      True if |definition| is 'partial interface' class, otherwise False.
-    """
-    return definition.GetClass() == _INTERFACE and definition.GetProperty(_PARTIAL)
-
-
-def get_filepath(interface_node):
-    """Returns relative path to the IDL in which |interface_node| is defined.
-    Args:
-      interface_node: IDL interface
-    Returns:
-      str which is |interface_node|'s file path
-    """
-    filename = interface_node.GetProperty(_PROP_FILENAME)
-    return os.path.relpath(filename)
-
-
-def get_const_node_list(interface_node):
-    """Returns a list of Const node.
-    Args:
-      interface_node: interface node
-    Returns:
-      A list of const node
-    """
-    return interface_node.GetListOf(_CONST)
-
-
-def get_const_type(const_node):
-    """Returns const's type.
-    Args:
-      const_node: const node
-    Returns:
-      str which is constant type.
-    """
-    return const_node.GetChildren()[0].GetName()
-
-
-def get_const_value(const_node):
-    """Returns const's value.
-    This function only supports primitive types.
-
-    Args:
-      const_node: const node
-    Returns:
-      str which is name of constant's value.
-    """
-    if const_node.GetChildren()[1].GetName():
-        return const_node.GetChildren()[1].GetName()
-    else:
-        for const_child in const_node.GetChildren():
-            if const_child.GetClass() == _VALUE and not const_child.GetName():
-                return const_child.GetProperty(_PROP_VALUE)
-        raise Exception('Constant value is empty')
-
-
-def const_node_to_dict(const_node):
-    """Returns dictionary of const's information.
-    Args:
-      const_node: const node
-    Returns:
-      dictionary of const's information
-    """
-    return {
-        _NAME: const_node.GetName(),
-        _TYPE: get_const_type(const_node),
-        _VALUE: get_const_value(const_node),
-        _EXTATTRIBUTES: [extattr_node_to_dict(extattr) for extattr in get_extattribute_node_list(const_node)],
-    }
-
-
-def get_attribute_node_list(interface_node):
-    """Returns list of Attribute if the interface have one.
-    Args:
-      interface_node: interface node
-    Returns:
-      list of attribute node
-    """
-    return interface_node.GetListOf(_ATTRIBUTE)
-
-
-def get_attribute_type(attribute_node):
-    """Returns type of attribute.
-    Args:
-      attribute_node: attribute node
-    Returns:
-      name of attribute's type
-    """
-    attr_type = attribute_node.GetOneOf(_TYPE).GetChildren()[0]
-    type_list = []
-    if attr_type.GetClass() == _UNIONTYPE:
-        union_member_list = attr_type.GetListOf(_TYPE)
-        for union_member in union_member_list:
-            for type_component in union_member.GetChildren():
-                if type_component.GetClass() == _ARRAY:
-                    type_list[-1] += '[]'
-                elif type_component.GetClass() == _SEQUENCE:
-                    for seq_type in type_component.GetOneOf(_TYPE).GetChildren():
-                        type_list.append('<' + seq_type.GetName() + '>')
-                else:
-                    type_list.append(type_component.GetName())
-        return type_list
-    elif attr_type.GetClass() == _SEQUENCE:
-        union_member_types = []
-        if attr_type.GetOneOf(_TYPE).GetChildren()[0].GetClass() == _UNIONTYPE:
-            for union_member in attr_type.GetOneOf(_TYPE).GetOneOf(_UNIONTYPE).GetListOf(_TYPE):
-                if len(union_member.GetChildren()) != 1:
-                    raise Exception('Complex type in a union in a sequence is not yet supported')
-                type_component = union_member.GetChildren()[0]
-                union_member_types.append(type_component.GetName())
-            return '<' + str(union_member_types) + '>'
-        else:
-            for type_component in attr_type.GetOneOf(_TYPE).GetChildren():
-                if type_component.GetClass() == _SEQUENCE:
-                    raise Exception('Sequence in another sequence is not yet supported')
-                else:
-                    if type_component.GetClass() == _ARRAY:
-                        type_list[-1] += []
-                    else:
-                        type_list.append(type_component.GetName())
-            return '<' + type_list[0] + '>'
-    elif attr_type.GetClass() == _ANY:
-        return _ANY
-    else:
-        for type_component in attribute_node.GetOneOf(_TYPE).GetChildren():
-            if type_component.GetClass() == _ARRAY:
-                type_list[-1] += '[]'
-            else:
-                type_list.append(type_component.GetName())
-        return type_list[0]
-
-
-get_operation_type = get_attribute_type
-get_argument_type = get_attribute_type
-
-
-def attribute_node_to_dict(attribute_node):
-    """Returns dictioary of attribute's information.
-    Args:
-      attribute_node: attribute node
-    Returns:
-      dictionary of attribute's information
-    """
-    return {
-        _NAME: attribute_node.GetName(),
-        _TYPE: get_attribute_type(attribute_node),
-        _EXTATTRIBUTES: [extattr_node_to_dict(extattr) for extattr in get_extattribute_node_list(attribute_node)],
-        _READONLY: attribute_node.GetProperty(_PROP_READONLY, default=False),
-        _STATIC: attribute_node.GetProperty(_PROP_STATIC, default=False),
-    }
-
-
-def get_operation_node_list(interface_node):
-    """Returns operations node list.
-    Args:
-      interface_node: interface node
-    Returns:
-      list of oparation node
-    """
-    return interface_node.GetListOf(_OPERATION)
-
-
-def get_argument_node_list(operation_node):
-    """Returns list of argument.
-    Args:
-      operation_node: operation node
-    Returns:
-      list of argument node
-    """
-    return operation_node.GetOneOf(_ARGUMENTS).GetListOf(_ARGUMENT)
-
-
-def argument_node_to_dict(argument_node):
-    """Returns dictionary of argument's information.
-    Args:
-      argument_node: argument node
-    Returns:
-      dictionary of argument's information
-    """
-    return {
-        _NAME: argument_node.GetName(),
-        _TYPE: get_argument_type(argument_node),
-    }
-
-
-def get_operation_name(operation_node):
-    """Returns openration's name.
-    Args:
-      operation_node: operation node
-    Returns:
-      name of operation
-    """
-    if operation_node.GetProperty(_PROP_GETTER):
-        return _NAMED_GETTER
-    elif operation_node.GetProperty(_PROP_SETTER):
-        return _NAMED_SETTER
-    elif operation_node.GetProperty(_PROP_DELETER):
-        return _NAMED_DELETER
-    else:
-        return operation_node.GetName()
-
-
-def operation_node_to_dict(operation_node):
-    """Returns dictionary of operation's information.
-    Args:
-      operation_node: operation node
-    Returns:
-      dictionary of operation's informantion
-    """
-    return {
-        _NAME: get_operation_name(operation_node),
-        _ARGUMENTS: [argument_node_to_dict(argument) for argument in get_argument_node_list(operation_node) if argument_node_to_dict(argument)],
-        _TYPE: get_operation_type(operation_node),
-        _EXTATTRIBUTES: [extattr_node_to_dict(extattr) for extattr in get_extattribute_node_list(operation_node)],
-        _STATIC: operation_node.GetProperty(_PROP_STATIC, default=False),
-    }
-
-
-def get_extattribute_node_list(node):
-    """Returns list of ExtAttribute.
-    Args:
-      node: IDL node
-    Returns:
-      list of ExtAttrbute
-    """
-    if node.GetOneOf(_EXTATTRIBUTES):
-        return node.GetOneOf(_EXTATTRIBUTES).GetListOf(_EXTATTRIBUTE)
-    else:
-        return []
-
-
-def extattr_node_to_dict(extattr):
-    """Returns dictionary of ExtAttribute's information.
-    Args:
-      extattr: ExtAttribute node
-    Returns:
-      dictionary of ExtAttribute's information
-    """
-    return {
-        _NAME: extattr.GetName(),
-    }
-
-
-def inherit_node_to_dict(interface_node):
-    """Returns a dictionary of inheritance information.
-    Args:
-      interface_node: interface node
-    Returns:
-      A dictioanry of inheritance information.
-    """
-    inherit = interface_node.GetOneOf(_INHERIT)
-    if inherit:
-        return {_PARENT: inherit.GetName()}
-    else:
-        return {_PARENT: None}
-
-
-def interface_node_to_dict(interface_node):
-    """Returns a dictioary of interface information.
-    Args:
-      interface_node: interface node
-    Returns:
-      A dictionary of the interface information.
-    """
-    return {
-        _NAME: interface_node.GetName(),
-        _FILEPATH: get_filepath(interface_node),
-        _CONSTS: [const_node_to_dict(const) for const in get_const_node_list(interface_node)],
-        _ATTRIBUTES: [attribute_node_to_dict(attr) for attr in get_attribute_node_list(interface_node) if attr],
-        _OPERATIONS: [operation_node_to_dict(operation) for operation in get_operation_node_list(interface_node) if operation],
-        _EXTATTRIBUTES: [extattr_node_to_dict(extattr) for extattr in get_extattribute_node_list(interface_node)],
-        _INHERIT: inherit_node_to_dict(interface_node)
-    }
-
-
-def merge_partial_dicts(interfaces_dict, partials_dict):
-    """Merges partial interface into non-partial interface.
-    Args:
-      interfaces_dict: A dict of the non-partial interfaces.
-      partial_dict: A dict of partial interfaces.
-    Returns:
-      A merged dictionary of |interface_dict| with |partial_dict|.
-    """
-    for interface_name, partial in partials_dict.iteritems():
-        interface = interfaces_dict.get(interface_name)
-        if not interface:
-            raise Exception('There is a partial interface, but the corresponding non-partial interface was not found.')
-        for member in _MEMBERS:
-            interface[member].extend(partial.get(member))
-            interface.setdefault(_PARTIAL_FILEPATH, []).append(partial[_FILEPATH])
-    return interfaces_dict
-
-
-def merge_implement_nodes(interfaces_dict, implement_node_list):
-    """Combines a dict of interface information with referenced interface information.
-    Args:
-      interfaces_dict: dict of interface information
-      implement_nodes: list of implemented interface node
-    Returns:
-      A dict of interface information combined with implements nodes.
-    """
-    for implement in implement_node_list:
-        reference = implement.GetProperty(_PROP_REFERENCE)
-        implement = implement.GetName()
-        if reference not in interfaces_dict.keys() or implement not in interfaces_dict.keys():
-            raise Exception('There is not corresponding implement or reference interface.')
-        for member in _MEMBERS:
-            interfaces_dict[implement][member].extend(interfaces_dict[reference].get(member))
-    return interfaces_dict
-
-
-def export_to_jsonfile(dictionary, json_file):
-    """Writes a Python dict into a JSON file.
-    Args:
-      dictioary: interface dictionary
-      json_file: json file for output
-    """
-    with open(json_file, 'w') as f:
-        json.dump(dictionary, f, sort_keys=True)
-
-
-def usage():
-    sys.stdout.write('Usage: collect_idls_into_json.py <path_file.txt> <output_file.json>\n')
-
-
-def main(args):
-    if len(args) != 2:
-        usage()
-        exit(1)
-    path_file = args[0]
-    json_file = args[1]
-    path_list = utilities.read_file_to_list(path_file)
-    implement_node_list = [definition
-                           for definition in get_definitions(path_list)
-                           if is_implements(definition)]
-    interfaces_dict = {definition.GetName(): interface_node_to_dict(definition)
-                       for definition in get_definitions(path_list)
-                       if not is_partial(definition)}
-    partials_dict = {definition.GetName(): interface_node_to_dict(definition)
-                     for definition in get_definitions(path_list)
-                     if is_partial(definition)}
-    dictionary = merge_partial_dicts(interfaces_dict, partials_dict)
-    interfaces_dict = merge_implement_nodes(interfaces_dict, implement_node_list)
-    export_to_jsonfile(dictionary, json_file)
-
-
-if __name__ == '__main__':
-    main(sys.argv[1:])
diff --git a/bindings/scripts/compute_global_objects.py b/bindings/scripts/compute_global_objects.py
index 2e83e46..ececf61 100755
--- a/bindings/scripts/compute_global_objects.py
+++ b/bindings/scripts/compute_global_objects.py
@@ -12,12 +12,18 @@
 Design document: http://www.chromium.org/developers/design-documents/idl-build
 """
 
+# pylint: disable=relative-import
+
 import optparse
 import os
-import cPickle as pickle
 import sys
 
-from utilities import get_file_contents, idl_filename_to_interface_name, get_interface_extended_attributes_from_idl, read_file_to_list, read_pickle_files, write_pickle_file
+from utilities import get_file_contents
+from utilities import get_interface_extended_attributes_from_idl
+from utilities import get_first_interface_name_from_idl
+from utilities import read_file_to_list
+from utilities import read_pickle_files
+from utilities import write_pickle_file
 
 GLOBAL_EXTENDED_ATTRIBUTES = frozenset([
     'Global',
@@ -26,21 +32,20 @@
 
 
 def parse_options():
-    usage = 'Usage: %prog [options] [GlobalObjectsComponent.pickle]... [GlobalObjects.pickle]'
+    usage = 'Usage: %prog [options]  [GlobalObjects.pickle]'
     parser = optparse.OptionParser(usage=usage)
     parser.add_option('--idl-files-list', help='file listing IDL files')
-    parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja')
+    parser.add_option('--global-objects-component-files', action='append',
+                      help='optionally preceeded input pickle filename.')
 
     options, args = parser.parse_args()
 
     if options.idl_files_list is None:
         parser.error('Must specify a file listing IDL files using --idl-files-list.')
-    if options.write_file_only_if_changed is None:
-        parser.error('Must specify whether output files are only written if changed using --write-file-only-if-changed.')
-    options.write_file_only_if_changed = bool(options.write_file_only_if_changed)
-    if not args:
-        parser.error('Must specify an output pickle filename as argument, '
-                     'optionally preceeded by input pickle filenames.')
+    if options.global_objects_component_files is None:
+        options.global_objects_component_files = []
+    if len(args) != 1:
+        parser.error('Must specify an output pickle filename as an argument')
 
     return options, args
 
@@ -57,10 +62,10 @@
     names; otherwise, the interface has a single global name, which is the
     interface's identifier (http://heycam.github.io/webidl/#Global).
     """
-    interface_name = idl_filename_to_interface_name(idl_filename)
     full_path = os.path.realpath(idl_filename)
     idl_file_contents = get_file_contents(full_path)
     extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents)
+    interface_name = get_first_interface_name_from_idl(idl_file_contents)
 
     global_keys = GLOBAL_EXTENDED_ATTRIBUTES.intersection(
         extended_attributes.iterkeys())
@@ -80,7 +85,7 @@
 def idl_files_to_interface_name_global_names(idl_files):
     """Yields pairs (interface_name, global_names) found in IDL files."""
     for idl_filename in idl_files:
-        interface_name = idl_filename_to_interface_name(idl_filename)
+        interface_name = get_first_interface_name_from_idl(get_file_contents(idl_filename))
         global_names = idl_file_to_global_names(idl_filename)
         if global_names:
             yield interface_name, global_names
@@ -90,11 +95,11 @@
 
 def main():
     options, args = parse_options()
-    # args = Input1, Input2, ..., Output
     output_global_objects_filename = args.pop()
     interface_name_global_names = dict_union(
         existing_interface_name_global_names
-        for existing_interface_name_global_names in read_pickle_files(args))
+        for existing_interface_name_global_names
+        in read_pickle_files(options.global_objects_component_files))
 
     # Input IDL files are passed in a file, due to OS command line length
     # limits. This is generated at GYP time, which is ok b/c files are static.
@@ -103,8 +108,7 @@
             idl_files_to_interface_name_global_names(idl_files))
 
     write_pickle_file(output_global_objects_filename,
-                      interface_name_global_names,
-                      options.write_file_only_if_changed)
+                      interface_name_global_names)
 
 
 if __name__ == '__main__':
diff --git a/bindings/scripts/compute_interfaces_info_individual.py b/bindings/scripts/compute_interfaces_info_individual.py
index 26af9fe..98fee87 100755
--- a/bindings/scripts/compute_interfaces_info_individual.py
+++ b/bindings/scripts/compute_interfaces_info_individual.py
@@ -47,10 +47,16 @@
 import posixpath
 import sys
 
-from idl_compiler import idl_filename_to_interface_name
 from idl_definitions import Visitor
 from idl_reader import IdlReader
-from utilities import get_file_contents, read_file_to_list, idl_filename_to_interface_name, idl_filename_to_component, write_pickle_file, get_interface_extended_attributes_from_idl, is_callback_interface_from_idl, merge_dict_recursively
+from utilities import idl_filename_to_component
+from utilities import idl_filename_to_basename
+from utilities import merge_dict_recursively
+from utilities import read_idl_files_list_from_file
+from utilities import shorten_union_name
+from utilities import to_snake_case
+from utilities import write_pickle_file
+
 
 module_path = os.path.dirname(__file__)
 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir))
@@ -63,22 +69,20 @@
 
 
 def parse_options():
-    usage = 'Usage: %prog [options] [generated1.idl]...'
+    usage = 'Usage: %prog [options]'
     parser = optparse.OptionParser(usage=usage)
     parser.add_option('--cache-directory', help='cache directory')
     parser.add_option('--idl-files-list', help='file listing IDL files')
     parser.add_option('--interfaces-info-file', help='interface info pickle file')
     parser.add_option('--component-info-file', help='component wide info pickle file')
-    parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja')
+    # TODO(tkent): Remove the option after the great mv. crbug.com/760462
+    parser.add_option('--snake-case-generated-files', action='store_true', default=False)
 
     options, args = parser.parse_args()
     if options.interfaces_info_file is None:
         parser.error('Must specify an output file using --interfaces-info-file.')
     if options.idl_files_list is None:
         parser.error('Must specify a file listing IDL files using --idl-files-list.')
-    if options.write_file_only_if_changed is None:
-        parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.')
-    options.write_file_only_if_changed = bool(options.write_file_only_if_changed)
     return options, args
 
 
@@ -93,7 +97,7 @@
     return relative_dir_local.replace(os.path.sep, posixpath.sep)
 
 
-def include_path(idl_filename, implemented_as=None):
+def include_path(idl_filename, snake_case_generated_files, implemented_as=None):
     """Returns relative path to header file in POSIX format; used in includes.
 
     POSIX format is used for consistency of output, so reference tests are
@@ -105,9 +109,10 @@
         relative_dir = relative_dir_posix(idl_filename, source_path)
 
     # IDL file basename is used even if only a partial interface file
-    cpp_class_name = implemented_as or idl_filename_to_interface_name(idl_filename)
-
-    return posixpath.join(relative_dir, cpp_class_name + '.h')
+    output_file_basename = implemented_as or idl_filename_to_basename(idl_filename)
+    if snake_case_generated_files:
+        output_file_basename = to_snake_case(output_file_basename)
+    return posixpath.join(relative_dir, output_file_basename + '.h')
 
 
 def get_implements_from_definitions(definitions, definition_name):
@@ -170,9 +175,10 @@
             'full_paths': [],
             'include_paths': [],
         })
-        self.enumerations = set()
+        self.enumerations = {}
         self.union_types = set()
         self.typedefs = {}
+        self.callback_functions = {}
 
     def add_paths_to_partials_dict(self, partial_interface_name, full_path,
                                    include_paths):
@@ -180,17 +186,24 @@
         paths_dict['full_paths'].append(full_path)
         paths_dict['include_paths'].extend(include_paths)
 
-    def collect_info(self, idl_filename):
+    def check_enum_consistency(self, enum):
+        existing_enum = self.enumerations.get(enum.name)
+        if not existing_enum:
+            return True
+        # TODO(bashi): Ideally we should not allow multiple enum declarations
+        # but we allow them to work around core/module separation.
+        if len(existing_enum.values) != len(enum.values):
+            return False
+        return all(value in existing_enum.values for value in enum.values)
+
+    def collect_info(self, idl_filename, snake_case_generated_files=False):
         """Reads an idl file and collects information which is required by the
         binding code generation."""
         def collect_unforgeable_attributes(definition, idl_filename):
             """Collects [Unforgeable] attributes so that we can define them on
             sub-interfaces later.  The resulting structure is as follows.
                 interfaces_info[interface_name] = {
-                    'unforgeable_attributes': {
-                        'core': [IdlAttribute, ...],
-                        'modules': [IdlAttribute, ...],
-                    },
+                    'unforgeable_attributes': [IdlAttribute, ...],
                     ...
                 }
             """
@@ -206,9 +219,7 @@
                 # Come up with a better way to keep them consistent.
                 for attr in unforgeable_attributes:
                     attr.extended_attributes['PartialInterfaceImplementedAs'] = definition.extended_attributes.get('ImplementedAs', interface_basename)
-            component = idl_filename_to_component(idl_filename)
-            interface_info['unforgeable_attributes'] = {}
-            interface_info['unforgeable_attributes'][component] = unforgeable_attributes
+            interface_info['unforgeable_attributes'] = unforgeable_attributes
             return interface_info
 
         definitions = self.reader.read_idl_file(idl_filename)
@@ -216,12 +227,19 @@
         this_union_types = collect_union_types_from_definitions(definitions)
         self.union_types.update(this_union_types)
         self.typedefs.update(definitions.typedefs)
+        for callback_function_name, callback_function in definitions.callback_functions.iteritems():
+            # Set 'component_dir' to specify a directory that callback function files belong to
+            self.callback_functions[callback_function_name] = {
+                'callback_function': callback_function,
+                'component_dir': idl_filename_to_component(idl_filename),
+                'full_path': os.path.realpath(idl_filename),
+            }
         # Check enum duplication.
-        for enum_name in definitions.enumerations.keys():
-            for defined_enum in self.enumerations:
-                if defined_enum.name == enum_name:
-                    raise Exception('Enumeration %s has multiple definitions' % enum_name)
-        self.enumerations.update(definitions.enumerations.values())
+        for enum in definitions.enumerations.values():
+            if not self.check_enum_consistency(enum):
+                raise Exception('Enumeration "%s" is defined more than once '
+                                'with different valid values' % enum.name)
+        self.enumerations.update(definitions.enumerations)
 
         if definitions.interfaces:
             definition = next(definitions.interfaces.itervalues())
@@ -259,16 +277,13 @@
         extended_attributes = definition.extended_attributes
         implemented_as = extended_attributes.get('ImplementedAs')
         full_path = os.path.realpath(idl_filename)
-        this_include_path = None if 'NoImplHeader' in extended_attributes else include_path(idl_filename, implemented_as)
+        this_include_path = include_path(idl_filename, snake_case_generated_files, implemented_as)
         if definition.is_partial:
             # We don't create interface_info for partial interfaces, but
             # adds paths to another dict.
             partial_include_paths = []
             if this_include_path:
                 partial_include_paths.append(this_include_path)
-            if this_union_types:
-                partial_include_paths.append(
-                    'bindings/%s/v8/UnionTypes%s.h' % (component, component.capitalize()))
             self.add_paths_to_partials_dict(definition.name, full_path, partial_include_paths)
             # Collects C++ header paths which should be included from generated
             # .cpp files.  The resulting structure is as follows.
@@ -295,7 +310,7 @@
         interface_info.update({
             'extended_attributes': extended_attributes,
             'full_path': full_path,
-            'has_union_types': bool(this_union_types),
+            'union_types': this_union_types,
             'implemented_as': implemented_as,
             'implemented_by_interfaces': left_interfaces,
             'implements_interfaces': right_interfaces,
@@ -320,8 +335,9 @@
     def get_component_info_as_dict(self):
         """Returns component wide information as a dict."""
         return {
+            'callback_functions': self.callback_functions,
             'enumerations': dict((enum.name, enum.values)
-                                 for enum in self.enumerations),
+                                 for enum in self.enumerations.values()),
             'typedefs': self.typedefs,
             'union_types': self.union_types,
         }
@@ -330,29 +346,22 @@
 ################################################################################
 
 def main():
-    options, args = parse_options()
+    options, _ = parse_options()
 
-    # Static IDL files are passed in a file (generated at GYP time), due to OS
-    # command line length limits
-    idl_files = read_file_to_list(options.idl_files_list)
-    # Generated IDL files are passed at the command line, since these are in the
-    # build directory, which is determined at build time, not GYP time, so these
-    # cannot be included in the file listing static files
-    idl_files.extend(args)
+    # IDL files are passed in a file, due to OS command line length limits
+    idl_files = read_idl_files_list_from_file(options.idl_files_list, is_gyp_format=False)
 
     # Compute information for individual files
     # Information is stored in global variables interfaces_info and
     # partial_interface_files.
     info_collector = InterfaceInfoCollector(options.cache_directory)
     for idl_filename in idl_files:
-        info_collector.collect_info(idl_filename)
+        info_collector.collect_info(idl_filename, options.snake_case_generated_files)
 
     write_pickle_file(options.interfaces_info_file,
-                      info_collector.get_info_as_dict(),
-                      options.write_file_only_if_changed)
+                      info_collector.get_info_as_dict())
     write_pickle_file(options.component_info_file,
-                      info_collector.get_component_info_as_dict(),
-                      options.write_file_only_if_changed)
+                      info_collector.get_component_info_as_dict())
 
 if __name__ == '__main__':
     sys.exit(main())
diff --git a/bindings/scripts/compute_interfaces_info_overall.py b/bindings/scripts/compute_interfaces_info_overall.py
index f038b76..2791a9a 100755
--- a/bindings/scripts/compute_interfaces_info_overall.py
+++ b/bindings/scripts/compute_interfaces_info_overall.py
@@ -81,17 +81,22 @@
 Design doc: http://www.chromium.org/developers/design-documents/idl-build
 """
 
-from collections import defaultdict
-import cPickle as pickle
+# pylint: disable=relative-import
+
 import optparse
 import sys
 
-from utilities import idl_filename_to_component, read_pickle_files, write_pickle_file, merge_dict_recursively
+from collections import defaultdict
+from utilities import idl_filename_to_component
+from utilities import merge_dict_recursively
+from utilities import read_pickle_files
+from utilities import shorten_union_name
+from utilities import write_pickle_file
 
 INHERITED_EXTENDED_ATTRIBUTES = set([
+    'ActiveScriptWrappable',
     'DependentLifetime',
-    'GarbageCollected',
-    'WillBeGarbageCollected',
+    'LegacyUnenumerableNamedProperties',
 ])
 
 # Main variable (filled in and exported)
@@ -114,13 +119,8 @@
 def parse_options():
     usage = 'Usage: %prog [InfoIndividual.pickle]... [Info.pickle]'
     parser = optparse.OptionParser(usage=usage)
-    parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja')
 
-    options, args = parser.parse_args()
-    if options.write_file_only_if_changed is None:
-        parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.')
-    options.write_file_only_if_changed = bool(options.write_file_only_if_changed)
-    return options, args
+    return parser.parse_args()
 
 
 def dict_of_dicts_of_lists_update_or_append(existing, other):
@@ -168,7 +168,6 @@
     dictionaries = {}
     component_dirs = {}
     implemented_as_interfaces = {}
-    will_be_garbage_collected_interfaces = set()
     garbage_collected_interfaces = set()
     callback_interfaces = set()
 
@@ -185,17 +184,13 @@
             implemented_as_interfaces[interface_name] = interface_info['implemented_as']
 
         inherited_extended_attributes = interface_info['inherited_extended_attributes']
-        if 'WillBeGarbageCollected' in inherited_extended_attributes:
-            will_be_garbage_collected_interfaces.add(interface_name)
-        if 'GarbageCollected' in inherited_extended_attributes:
-            garbage_collected_interfaces.add(interface_name)
+        garbage_collected_interfaces.add(interface_name)
 
     interfaces_info['ancestors'] = ancestors
     interfaces_info['callback_interfaces'] = callback_interfaces
     interfaces_info['dictionaries'] = dictionaries
     interfaces_info['implemented_as_interfaces'] = implemented_as_interfaces
     interfaces_info['garbage_collected_interfaces'] = garbage_collected_interfaces
-    interfaces_info['will_be_garbage_collected_interfaces'] = will_be_garbage_collected_interfaces
     interfaces_info['component_dirs'] = component_dirs
 
 
@@ -266,12 +261,10 @@
         # However, they are needed for legacy implemented interfaces that
         # are being treated as partial interfaces, until we remove these.
         # http://crbug.com/360435
-        implemented_interfaces_include_paths = []
-        for implemented_interface_info in implemented_interfaces_info:
-            if (implemented_interface_info['is_legacy_treat_as_partial_interface'] and
-                implemented_interface_info['include_path']):
-                implemented_interfaces_include_paths.append(
-                    implemented_interface_info['include_path'])
+        implemented_interfaces_include_paths = [
+            implemented_interface_info['include_path']
+            for implemented_interface_info in implemented_interfaces_info
+            if implemented_interface_info['is_legacy_treat_as_partial_interface']]
 
         dependencies_full_paths = implemented_interfaces_full_paths
         dependencies_include_paths = implemented_interfaces_include_paths
@@ -293,10 +286,6 @@
             else:
                 dependencies_other_component_include_paths.append(include_path)
 
-        if interface_info['has_union_types']:
-            dependencies_include_paths.append(
-                'bindings/%s/v8/UnionTypes%s.h' % (component, component.capitalize()))
-
         interface_info.update({
             'dependencies_full_paths': dependencies_full_paths,
             'dependencies_include_paths': dependencies_include_paths,
@@ -309,7 +298,7 @@
     # Clean up temporary private information
     for interface_info in interfaces_info.itervalues():
         del interface_info['extended_attributes']
-        del interface_info['has_union_types']
+        del interface_info['union_types']
         del interface_info['is_legacy_treat_as_partial_interface']
 
     # Compute global_type_info to interfaces_info so that idl_compiler does
@@ -320,15 +309,13 @@
 ################################################################################
 
 def main():
-    options, args = parse_options()
+    _, args = parse_options()
     # args = Input1, Input2, ..., Output
     interfaces_info_filename = args.pop()
     info_individuals = read_pickle_files(args)
 
     compute_interfaces_info_overall(info_individuals)
-    write_pickle_file(interfaces_info_filename,
-                      interfaces_info,
-                      options.write_file_only_if_changed)
+    write_pickle_file(interfaces_info_filename, interfaces_info)
 
 
 if __name__ == '__main__':
diff --git a/bindings/scripts/generate_conditional_features.py b/bindings/scripts/generate_conditional_features.py
new file mode 100644
index 0000000..0028e8a
--- /dev/null
+++ b/bindings/scripts/generate_conditional_features.py
@@ -0,0 +1,250 @@
+#!/usr/bin/python
+#
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script reads the global interface data collected by
+# compute_interfaces_info_overall.py, and writes out the code which adds
+# bindings for origin-trial-enabled features at runtime.
+
+import optparse
+import os
+import posixpath
+import sys
+from collections import defaultdict, namedtuple
+
+from code_generator import (initialize_jinja_env, normalize_and_sort_includes,
+                            render_template)
+from idl_reader import IdlReader
+from utilities import (create_component_info_provider, write_file,
+                       idl_filename_to_component)
+from v8_utilities import (binding_header_basename, v8_class_name,
+                          v8_class_name_or_partial, uncapitalize)
+
+# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
+MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py'
+
+
+ConditionalInterfaceInfo = namedtuple('ConditionalInterfaceInfo', [
+    'name', 'v8_class', 'v8_class_or_partial', 'is_global'])
+
+
+def get_install_functions(interfaces, feature_names):
+    """Construct a list of V8 bindings installation functions for each feature
+    on each interface.
+
+    interfaces is a list of ConditionalInterfaceInfo tuples
+    feature_names is a list of strings, containing names of features which can
+        be installed on those interfaces.
+    """
+    return [
+        {'condition': 'OriginTrials::%sEnabled' % uncapitalize(feature_name),
+         'name': feature_name,
+         'install_method': 'install%s' % feature_name,
+         'interface_is_global': interface_info.is_global,
+         'v8_class': interface_info.v8_class,
+         'v8_class_or_partial': interface_info.v8_class_or_partial}
+        for feature_name in feature_names
+        for interface_info in interfaces]
+
+
+def get_conditional_feature_names_from_interface(interface):
+    feature_names = set()
+    if ('OriginTrialEnabled' in interface.extended_attributes and
+            interface.is_partial):
+        feature_names.add(interface.extended_attributes['OriginTrialEnabled'])
+    for operation in interface.operations:
+        if 'OriginTrialEnabled' in operation.extended_attributes:
+            feature_names.add(
+                operation.extended_attributes['OriginTrialEnabled'])
+    for attribute in interface.attributes:
+        if 'OriginTrialEnabled' in attribute.extended_attributes:
+            feature_names.add(
+                attribute.extended_attributes['OriginTrialEnabled'])
+    return feature_names
+
+
+def read_idl_file(reader, idl_filename):
+    definitions = reader.read_idl_file(idl_filename)
+    interfaces = definitions.interfaces
+    implements = definitions.implements
+    # There should only be a single interface defined in an IDL file. Return it.
+    assert len(interfaces) == 1
+    return (interfaces.values()[0], implements)
+
+
+def interface_is_global(interface):
+    return ('Global' in interface.extended_attributes or
+            'PrimaryGlobal' in interface.extended_attributes)
+
+
+def conditional_features_info(info_provider, reader, idl_filenames, target_component, snake_case):
+    """Read a set of IDL files and compile the mapping between interfaces and
+    the conditional features defined on them.
+
+    Returns a tuple (features_for_type, types_for_feature, includes):
+      - features_for_type is a mapping of interface->feature
+      - types_for_feature is the reverse mapping: feature->interface
+      - includes is a set of header files which need to be included in the
+          generated implementation code.
+    """
+    features_for_type = defaultdict(set)
+    types_for_feature = defaultdict(set)
+    includes = set()
+
+    for idl_filename in idl_filenames:
+        interface, implements = read_idl_file(reader, idl_filename)
+        feature_names = get_conditional_feature_names_from_interface(interface)
+
+        # If this interface implements another one,
+        # it inherits any conditional features from it.
+        for implement in implements:
+            assert implement.left_interface == interface.name
+            implemented_interface, _ = read_idl_file(
+                reader,
+                info_provider.interfaces_info[implement.right_interface].get('full_path'))
+            feature_names |= get_conditional_feature_names_from_interface(implemented_interface)
+
+        feature_names = list(feature_names)
+        if feature_names:
+            is_global = interface_is_global(interface)
+            if interface.is_partial:
+                # For partial interfaces, we need to generate different
+                # includes if the parent interface is in a different
+                # component.
+                parent_interface_info = info_provider.interfaces_info[interface.name]
+                parent_interface, _ = read_idl_file(
+                    reader, parent_interface_info.get('full_path'))
+                is_global = is_global or interface_is_global(parent_interface)
+                parent_component = idl_filename_to_component(
+                    parent_interface_info.get('full_path'))
+            if interface.is_partial and target_component != parent_component:
+                includes.add('bindings/%s/v8/%s' %
+                             (parent_component, binding_header_basename(interface.name, snake_case)))
+                includes.add('bindings/%s/v8/%s' %
+                             (target_component, binding_header_basename(interface.name + 'Partial', snake_case)))
+            else:
+                includes.add('bindings/%s/v8/%s' %
+                             (target_component, binding_header_basename(interface.name, snake_case)))
+                # If this is a partial interface in the same component as
+                # its parent, then treat it as a non-partial interface.
+                interface.is_partial = False
+            interface_info = ConditionalInterfaceInfo(interface.name,
+                                                      v8_class_name(interface),
+                                                      v8_class_name_or_partial(
+                                                          interface),
+                                                      is_global)
+            for feature_name in feature_names:
+                features_for_type[interface_info].add(feature_name)
+                types_for_feature[feature_name].add(interface_info)
+
+    return features_for_type, types_for_feature, includes
+
+
+def conditional_features_context(generator_name, feature_info, snake_case):
+    context = {'code_generator': generator_name}
+
+    # Unpack the feature info tuple.
+    features_for_type, types_for_feature, includes = feature_info
+
+    # Add includes needed for cpp code and normalize.
+    includes.update([
+        'core/context_features/ContextFeatureSettings.h',
+        'core/dom/ExecutionContext.h',
+        'core/frame/Frame.h',
+        'core/origin_trials/origin_trials.h',
+        'platform/bindings/ConditionalFeatures.h',
+        'platform/bindings/ScriptState.h',
+        # TODO(iclelland): Remove the need to explicitly include this; it is
+        # here because the ContextFeatureSettings code needs it.
+        'bindings/core/v8/V8Window.h',
+    ])
+    context['includes'] = normalize_and_sort_includes(includes, snake_case)
+
+    # For each interface, collect a list of bindings installation functions to
+    # call, organized by conditional feature.
+    context['installers_by_interface'] = [
+        {'name': interface_info.name,
+         'is_global': interface_info.is_global,
+         'v8_class': interface_info.v8_class,
+         'installers': get_install_functions([interface_info], feature_names)}
+        for interface_info, feature_names in features_for_type.items()]
+    context['installers_by_interface'].sort(key=lambda x: x['name'])
+
+    # For each conditional feature, collect a list of bindings installation
+    # functions to call, organized by interface.
+    context['installers_by_feature'] = [
+        {'name': feature_name,
+         'name_constant': 'OriginTrials::k%sTrialName' % feature_name,
+         'installers': get_install_functions(interfaces, [feature_name])}
+        for feature_name, interfaces in types_for_feature.items()]
+    context['installers_by_feature'].sort(key=lambda x: x['name'])
+
+    return context
+
+
+def parse_options():
+    parser = optparse.OptionParser()
+    parser.add_option('--cache-directory',
+                      help='cache directory, defaults to output directory')
+    parser.add_option('--output-directory')
+    parser.add_option('--info-dir')
+    parser.add_option('--target-component',
+                      type='choice',
+                      choices=['Core', 'Modules'],
+                      help='target component to generate code')
+    parser.add_option('--idl-files-list')
+    # TODO(tkent): Remove the option after the great mv. crbug.com/760462
+    parser.add_option('--snake-case-generated-files',
+                      action='store_true', default=False)
+
+    options, _ = parser.parse_args()
+    if options.output_directory is None:
+        parser.error('Must specify output directory using --output-directory.')
+    return options
+
+
+def generate_conditional_features(info_provider, options, idl_filenames):
+    reader = IdlReader(info_provider.interfaces_info, options.cache_directory)
+    jinja_env = initialize_jinja_env(options.cache_directory)
+
+    # Extract the bidirectional mapping of conditional features <-> interfaces
+    # from the global info provider and the supplied list of IDL files.
+    feature_info = conditional_features_info(info_provider,
+                                             reader, idl_filenames,
+                                             options.target_component.lower(),
+                                             options.snake_case_generated_files)
+
+    # Convert that mapping into the context required for the Jinja2 templates.
+    template_context = conditional_features_context(
+        MODULE_PYNAME, feature_info, options.snake_case_generated_files)
+
+    # Generate and write out the header file
+    header_text = render_template(jinja_env.get_template(
+        'ConditionalFeaturesFor%s.h.tmpl' % options.target_component.title()), template_context)
+    header_path = posixpath.join(options.output_directory,
+                                 'ConditionalFeaturesFor%s.h' % options.target_component.title())
+    write_file(header_text, header_path)
+
+    # Generate and write out the implementation file
+    cpp_text = render_template(jinja_env.get_template(
+        'ConditionalFeaturesFor%s.cpp.tmpl' % options.target_component.title()), template_context)
+    cpp_path = posixpath.join(options.output_directory,
+                              'ConditionalFeaturesFor%s.cpp' % options.target_component.title())
+    write_file(cpp_text, cpp_path)
+
+
+def main():
+    options = parse_options()
+
+    info_provider = create_component_info_provider(
+        os.path.normpath(options.info_dir), options.target_component.lower())
+    idl_filenames = map(str.strip, open(options.idl_files_list))
+
+    generate_conditional_features(info_provider, options, idl_filenames)
+    return 0
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/bindings/scripts/generate_event_interfaces.py b/bindings/scripts/generate_event_interfaces.py
index 6a2cc6a..5cc29ae 100755
--- a/bindings/scripts/generate_event_interfaces.py
+++ b/bindings/scripts/generate_event_interfaces.py
@@ -28,16 +28,16 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-"""Generate event interfaces .in file (EventInterfaces.in).
+"""Generate event interfaces .json5 file (EventInterfaces.json5).
 
-The event interfaces .in file contains a list of all Event interfaces, i.e.,
+The event interfaces .json5 file contains a list of all Event interfaces, i.e.,
 all interfaces that inherit from Event, including Event itself,
 together with certain extended attributes.
 
 Paths are in POSIX format, and relative to Source/.
 
 This list is used in core/ to generate EventFactory and EventNames.
-The .in format is documented in build/scripts/in_file.py.
+The .json5 format is documented in build/scripts/json5_generator.py.
 """
 
 from optparse import OptionParser
@@ -45,7 +45,9 @@
 import posixpath
 import sys
 
-from utilities import get_file_contents, read_file_to_list, write_file, get_interface_extended_attributes_from_idl
+from utilities import (get_file_contents, get_first_interface_name_from_idl,
+                       read_file_to_list, write_file,
+                       get_interface_extended_attributes_from_idl)
 
 EXPORTED_EXTENDED_ATTRIBUTES = (
     'ImplementedAs',
@@ -59,7 +61,6 @@
     parser = OptionParser()
     parser.add_option('--event-idl-files-list', help='file listing event IDL files')
     parser.add_option('--event-interfaces-file', help='output file')
-    parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja')
     parser.add_option('--suffix', help='specify a suffix to the namespace, i.e., "Modules". Default is None.')
 
     options, args = parser.parse_args()
@@ -67,46 +68,59 @@
         parser.error('Must specify a file listing event IDL files using --event-idl-files-list.')
     if options.event_interfaces_file is None:
         parser.error('Must specify an output file using --event-interfaces-file.')
-    if options.write_file_only_if_changed is None:
-        parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.')
-    options.write_file_only_if_changed = bool(options.write_file_only_if_changed)
     if args:
         parser.error('No arguments allowed, but %d given.' % len(args))
     return options
 
 
-def write_event_interfaces_file(event_idl_files, destination_filename, only_if_changed, suffix):
-    def extended_attribute_string(name, value):
-        if name == 'RuntimeEnabled':
-            value += 'Enabled'
-        return name + '=' + value
-
+def write_event_interfaces_file(event_idl_files, destination_filename, suffix):
     def interface_line(full_path):
-        relative_path_local, _ = os.path.splitext(os.path.relpath(full_path, source_dir))
-        relative_path_posix = relative_path_local.replace(os.sep, posixpath.sep)
+        relative_dir_local = os.path.dirname(os.path.relpath(full_path, source_dir))
+        relative_dir_posix = relative_dir_local.replace(os.sep, posixpath.sep)
 
         idl_file_contents = get_file_contents(full_path)
+        interface_name = get_first_interface_name_from_idl(idl_file_contents)
         extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents)
         extended_attributes_list = [
-            extended_attribute_string(name, extended_attributes[name])
+            (name, extended_attributes[name])
             for name in EXPORTED_EXTENDED_ATTRIBUTES
             if name in extended_attributes]
 
-        return '%s %s\n' % (relative_path_posix,
-                            ', '.join(extended_attributes_list))
+        return (posixpath.join(relative_dir_posix, interface_name),
+                extended_attributes_list)
 
-    lines = ['namespace="Event"\n']
+    lines = [
+        '{',
+        'metadata: {',
+        '  namespace: "Event",'
+    ]
     if suffix:
-        lines.append('suffix="' + suffix + '"\n')
-        lines.append('export=%s_EXPORT\n' % suffix.upper())
+        lines.append('  suffix: "' + suffix + '",')
+        lines.append('  export: "%s_EXPORT",' % suffix.upper())
     else:
-        lines.append('export=CORE_EXPORT\n')
-    lines.append('\n')
+        lines.append('  export: "CORE_EXPORT",')
+    lines.extend([
+        '},',
+        'data: ['
+    ])
     interface_lines = [interface_line(event_idl_file)
                        for event_idl_file in event_idl_files]
     interface_lines.sort()
-    lines.extend(interface_lines)
-    write_file(''.join(lines), destination_filename, only_if_changed)
+    for name, attributes in interface_lines:
+        lines.extend([
+            '  {',
+            '    name: "%s",' % name
+        ])
+        for param, value in attributes:
+            if param == 'RuntimeEnabled':
+                value += 'Enabled'
+            lines.append('    %s: "%s",' % (param, value))
+        lines.append('  },')
+    lines.extend([
+        ']',
+        '}'
+    ])
+    write_file('\n'.join(lines), destination_filename)
 
 
 ################################################################################
@@ -116,7 +130,6 @@
     event_idl_files = read_file_to_list(options.event_idl_files_list)
     write_event_interfaces_file(event_idl_files,
                                 options.event_interfaces_file,
-                                options.write_file_only_if_changed,
                                 options.suffix)
 
 
diff --git a/bindings/scripts/generate_global_constructors.py b/bindings/scripts/generate_global_constructors.py
index 6965f9a..c068fbd 100755
--- a/bindings/scripts/generate_global_constructors.py
+++ b/bindings/scripts/generate_global_constructors.py
@@ -17,17 +17,25 @@
 Design document: http://www.chromium.org/developers/design-documents/idl-build
 """
 
+# pylint: disable=relative-import
+
 import itertools
 import optparse
 import os
-import cPickle as pickle
 import re
 import sys
 
-from v8_utilities import EXPOSED_EXECUTION_CONTEXT_METHOD
-
 from collections import defaultdict
-from utilities import should_generate_impl_file_from_idl, get_file_contents, idl_filename_to_interface_name, read_file_to_list, write_file, get_interface_extended_attributes_from_idl, get_interface_exposed_arguments, is_callback_interface_from_idl
+from utilities import get_file_contents
+from utilities import get_first_interface_name_from_idl
+from utilities import get_interface_exposed_arguments
+from utilities import get_interface_extended_attributes_from_idl
+from utilities import is_non_legacy_callback_interface_from_idl
+from utilities import read_file_to_list
+from utilities import read_pickle_file
+from utilities import should_generate_impl_file_from_idl
+from utilities import write_file
+from v8_utilities import EXPOSED_EXECUTION_CONTEXT_METHOD
 
 interface_name_to_global_names = {}
 global_name_to_constructors = defaultdict(list)
@@ -42,17 +50,12 @@
     parser = optparse.OptionParser()
     parser.add_option('--idl-files-list', help='file listing IDL files')
     parser.add_option('--global-objects-file', help='pickle file of global objects')
-    parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja')
-
     options, args = parser.parse_args()
 
     if options.idl_files_list is None:
         parser.error('Must specify a file listing IDL files using --idl-files-list.')
     if options.global_objects_file is None:
         parser.error('Must specify a pickle file of global objects using --global-objects-file.')
-    if options.write_file_only_if_changed is None:
-        parser.error('Must specify whether output files are only written if changed using --write-file-only-if-changed.')
-    options.write_file_only_if_changed = bool(options.write_file_only_if_changed)
 
     return options, args
 
@@ -69,18 +72,16 @@
 
 
 def record_global_constructors(idl_filename):
-    interface_name = idl_filename_to_interface_name(idl_filename)
     full_path = os.path.realpath(idl_filename)
     idl_file_contents = get_file_contents(full_path)
     extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents)
+    interface_name = get_first_interface_name_from_idl(idl_file_contents)
 
     # An interface property is produced for every non-callback interface
     # that does not have [NoInterfaceObject].
-    # Callback interfaces with constants also have interface properties,
-    # but there are none of these in Blink.
     # http://heycam.github.io/webidl/#es-interfaces
     if ((not should_generate_impl_file_from_idl(idl_file_contents)) or
-        is_callback_interface_from_idl(idl_file_contents) or
+        is_non_legacy_callback_interface_from_idl(idl_file_contents) or
         'NoInterfaceObject' in extended_attributes):
         return
 
@@ -104,9 +105,9 @@
 
 def generate_global_constructors_list(interface_name, extended_attributes):
     extended_attributes_list = [
-            name + '=' + extended_attributes[name]
-            for name in 'RuntimeEnabled', 'OriginTrialEnabled'
-            if name in extended_attributes]
+        name + (('=' + extended_attributes[name]) if extended_attributes[name] else '')
+        for name in 'RuntimeEnabled', 'OriginTrialEnabled', 'ContextEnabled', 'SecureContext'
+        if name in extended_attributes]
     if extended_attributes_list:
         extended_string = '[%s] ' % ', '.join(extended_attributes_list)
     else:
@@ -131,18 +132,20 @@
     return attributes_list
 
 
-def write_global_constructors_partial_interface(interface_name, idl_filename, constructor_attributes_list, only_if_changed):
+def write_global_constructors_partial_interface(interface_name, idl_filename, constructor_attributes_list):
+    idl_basename = os.path.basename(idl_filename)
+    basename = os.path.splitext(idl_basename)[0]
     # FIXME: replace this with a simple Jinja template
-    lines = (['partial interface %s {\n' % interface_name] +
+    lines = (['[\n',
+              '    ImplementedAs=%s\n' % basename,
+              '] partial interface %s {\n' % interface_name] +
              ['    %s;\n' % constructor_attribute
               # FIXME: sort by interface name (not first by extended attributes)
               for constructor_attribute in sorted(constructor_attributes_list)] +
              ['};\n'])
-    write_file(''.join(lines), idl_filename, only_if_changed)
+    write_file(''.join(lines), idl_filename)
     header_filename = os.path.splitext(idl_filename)[0] + '.h'
-    idl_basename = os.path.basename(idl_filename)
-    write_file(HEADER_FORMAT.format(idl_basename=idl_basename),
-               header_filename, only_if_changed)
+    write_file(HEADER_FORMAT.format(idl_basename=idl_basename), header_filename)
 
 
 ################################################################################
@@ -161,8 +164,7 @@
     interface_name_idl_filename = [(args[i], args[i + 1])
                                    for i in range(0, len(args), 2)]
 
-    with open(options.global_objects_file) as global_objects_file:
-        interface_name_to_global_names.update(pickle.load(global_objects_file))
+    interface_name_to_global_names.update(read_pickle_file(options.global_objects_file))
 
     for idl_filename in idl_files:
         record_global_constructors(idl_filename)
@@ -182,10 +184,7 @@
     for interface_name, idl_filename in interface_name_idl_filename:
         constructors = interface_name_to_constructors(interface_name)
         write_global_constructors_partial_interface(
-            interface_name,
-            idl_filename,
-            constructors,
-            options.write_file_only_if_changed)
+            interface_name, idl_filename, constructors)
 
 
 if __name__ == '__main__':
diff --git a/bindings/scripts/generate_idl_diff.py b/bindings/scripts/generate_idl_diff.py
deleted file mode 100644
index ae98695..0000000
--- a/bindings/scripts/generate_idl_diff.py
+++ /dev/null
@@ -1,184 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""generate_idl_diff.py is a script that generates a diff of two given IDL files.
-Usage: generate_idl_diff.py old_file.json new_file.json diff_file.json
-    old_file.json: An input json file including idl data of old Chrome version
-    new_file.json: An input json file including idl data of new Chrome version
-    diff_file.json: An output json file expressing a diff between old_file.json
-        and new_file.json
-"""
-
-import json
-import os
-import sys
-
-
-"""Data structure of input files of this script.
-The format of the json files is as follows. Each json file contains multiple
-"interface"s. Each "interface" contains 'ExtAttributes', 'Consts', 'Attributes'
-and 'Operations'. Each item in them are called a "member".
-    {'InterfaceName': {
-            'ExtAttributes': [{'Name': '...'},
-                               ...,
-                             ],
-            'Consts': [{'Type': '...',
-                        'Name': '...',
-                        'Value': '...'
-                       },
-                       ...,
-                      ],
-            'Attributes': [{'Type': '...',
-                            'Name': '...',
-                            'ExtAttributes':[{'Name': '...'},
-                                              ...,
-                                            ]
-                           },
-                           ...,
-                          ],
-            'Operations': [{'Type': '...',
-                            'Name': '...',
-                            'ExtAttributes': [{'Name': '...'},
-                                               ...,
-                                             ]
-                            'Arguments': [{'Type': '...',
-                                           'Name': '...'},
-                                           ...,
-                                         ]
-                           },
-                           ...,
-                          ],
-            'Name': '...'
-        },
-        ...,
-    }
-"""
-
-
-EXTATTRIBUTES_AND_MEMBER_TYPES = ['ExtAttributes', 'Consts', 'Attributes', 'Operations']
-DIFF_INSENSITIVE_FIELDS = ['Name']
-DIFF_TAG = 'diff_tag'
-DIFF_TAG_ADDED = 'added'
-DIFF_TAG_DELETED = 'deleted'
-
-
-def load_json_file(filepath):
-    """Load a json file into a dictionary.
-    Args:
-        filepath: A json file path of a json file that we want to load
-    Returns:
-        An "interfaces" object loaded from the json file
-    """
-    with open(filepath, 'r') as f:
-        return json.load(f)
-
-
-def members_diff(old_interface, new_interface):
-    """Create a diff between two "interface" objects by adding annotations to
-    "member" objects that are not common in them.
-    Args:
-        old_interface: An "interface" object
-        new_interface: An "interface" object
-    Returns:
-        (annotated, is_changed) where
-        annotated: An annotated "interface" object
-        is_changed: True if two interfaces are not identical, otherwise False
-    """
-    annotated = {}
-    is_changed = False
-    for member_type in EXTATTRIBUTES_AND_MEMBER_TYPES:
-        annotated_members = []
-        unannotated_members = []
-        for member in new_interface[member_type]:
-            if member in old_interface[member_type]:
-                unannotated_members.append(member)
-                old_interface[member_type].remove(member)
-            else:
-                is_changed = True
-                member[DIFF_TAG] = DIFF_TAG_ADDED
-                annotated_members.append(member)
-        annotated[member_type] = annotated_members
-        annotated[member_type].extend(unannotated_members)
-    for member_type in EXTATTRIBUTES_AND_MEMBER_TYPES:
-        for member in old_interface[member_type]:
-            is_changed = True
-            member[DIFF_TAG] = DIFF_TAG_DELETED
-        annotated[member_type].extend(old_interface[member_type])
-    for field in DIFF_INSENSITIVE_FIELDS:
-        annotated[field] = old_interface[field]
-    return (annotated, is_changed)
-
-
-def annotate_all_members(interface, diff_tag):
-    """Add annotations to all "member" objects of |interface|.
-    Args:
-        interface: An "interface" object whose members should be annotated with
-            |diff_tag|.
-        diff_tag: DIFF_TAG_ADDED or DIFF_TAG_DELETED
-    Returns:
-        Annotated "interface" object
-    """
-    for member_type in EXTATTRIBUTES_AND_MEMBER_TYPES:
-        for member in interface[member_type]:
-            member[DIFF_TAG] = diff_tag
-    return interface
-
-
-def interfaces_diff(old_interfaces, new_interfaces):
-    """Compare two "interfaces" objects and create a diff between them by
-    adding annotations (DIFF_TAG_ADDED or DIFF_TAG_DELETED) to each member
-    and/or interface.
-    Args:
-        old_interfaces: An "interfaces" object
-        new_interfaces: An "interfaces" object
-    Returns:
-        An "interfaces" object representing diff between |old_interfaces| and
-        |new_interfaces|
-    """
-    annotated = {}
-    for interface_name, interface in new_interfaces.items():
-        if interface_name in old_interfaces:
-            annotated_interface, is_changed = members_diff(old_interfaces[interface_name], interface)
-            if is_changed:
-                annotated[interface_name] = annotated_interface
-            del old_interfaces[interface_name]
-        else:
-            interface = annotate_all_members(interface, DIFF_TAG_ADDED)
-            interface[DIFF_TAG] = DIFF_TAG_ADDED
-            annotated[interface_name] = interface
-    for interface_name, interface in old_interfaces.items():
-        interface = annotate_all_members(interface, DIFF_TAG_DELETED)
-        interface[DIFF_TAG] = DIFF_TAG_DELETED
-    annotated.update(old_interfaces)
-    return annotated
-
-
-def write_diff(diff, filepath):
-    """Write a diff dictionary to a json file.
-    Args:
-        diff: An "interfaces" object that represents a diff
-        filepath: An output file path
-    """
-    with open(filepath, 'w') as f:
-        json.dump(diff, f, indent=4)
-
-
-def main(argv):
-    if len(argv) != 3:
-        sys.stdout.write(
-            'Usage: make_diff.py <old_file.json> <new_file.json> '
-            '<diff_file.json>\n')
-        exit(1)
-    old_json_file = argv[0]
-    new_json_file = argv[1]
-    output_file = argv[2]
-    old_interfaces = load_json_file(old_json_file)
-    new_interfaces = load_json_file(new_json_file)
-    diff = interfaces_diff(old_interfaces, new_interfaces)
-    write_diff(diff, output_file)
-
-
-if __name__ == '__main__':
-    main(sys.argv[1:])
diff --git a/bindings/scripts/generate_idl_diff_test.py b/bindings/scripts/generate_idl_diff_test.py
deleted file mode 100644
index c301dce..0000000
--- a/bindings/scripts/generate_idl_diff_test.py
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import generate_idl_diff
-import os
-import sys
-import unittest
-
-from generate_idl_diff import DIFF_TAG
-from generate_idl_diff import DIFF_TAG_DELETED
-from generate_idl_diff import DIFF_TAG_ADDED
-
-
-testdata_path = os.path.join(
-    os.path.dirname(os.path.realpath(__file__)), 'testdata')
-old_data_path = os.path.join(testdata_path, 'old_chrome.json')
-new_data_path = os.path.join(testdata_path, 'new_chrome.json')
-
-
-class TestGenerateIDLDiff(unittest.TestCase):
-
-    def setUp(self):
-        old = generate_idl_diff.load_json_file('old_chrome.json')
-        new = generate_idl_diff.load_json_file('new_chrome.json')
-        self.diff = generate_idl_diff.interfaces_diff(old, new)
-
-    def test_deleted_interface(self):
-        self.assertTrue('AnimationEffectReadOnly' in self.diff)
-        deleted_interface = self.diff.get('AnimationEffectReadOnly')
-        self.assertIsNotNone(deleted_interface)
-        self.assertEqual(deleted_interface.get(DIFF_TAG), DIFF_TAG_DELETED)
-
-    def test_added_interface(self):
-        self.assertTrue('AnimationEvent' in self.diff)
-        added_interface = self.diff.get('AnimationEvent')
-        self.assertIsNotNone(added_interface)
-        self.assertEqual(added_interface.get(DIFF_TAG), DIFF_TAG_ADDED)
-
-    def test_changed_interface(self):
-        self.assertTrue('ANGLEInstancedArrays' in self.diff)
-        changed_interface = self.diff.get('ANGLEInstancedArrays')
-        self.assertIsNotNone(changed_interface)
-        self.assertIsNone(changed_interface.get(DIFF_TAG))
-
-    def test_unchanged_interface(self):
-        self.assertFalse('AbstractWorker' in self.diff)
-
-    def test_unchanged_consts(self):
-        changed_interface = self.diff['ANGLEInstancedArrays']
-        members = changed_interface['Consts']
-        for member in members:
-            self.assertEqual(member['Name'], 'VERTEX_ATTRIB_ARRAY_DIVISOR')
-            self.assertEqual(member['Type'], 'unsigned long')
-            self.assertEqual(member['Value'], '0x88FE')
-
-    def test_changed_attribute(self):
-        changed_interface = self.diff['ANGLEInstancedArrays']
-        members = changed_interface['Attributes']
-        for member in members:
-            if member.get(DIFF_TAG) == DIFF_TAG_DELETED:
-                deleted = member
-            elif member.get(DIFF_TAG) == DIFF_TAG_ADDED:
-                added = member
-            else:
-                unchanged = member
-        self.assertEqual(deleted['Name'], 'animVal')
-        self.assertEqual(deleted['Type'], 'SVGAngle')
-        self.assertEqual(deleted['ExtAttributes'], [])
-        self.assertEqual(added['Name'], 'computedTiming')
-        self.assertEqual(added['Type'], 'ComputedTimingProperties')
-        self.assertEqual(added['ExtAttributes'], [{"Name": "maxChannelCount"}])
-        self.assertEqual(unchanged['Name'], 'timing')
-        self.assertEqual(unchanged['Type'], 'AnimationEffectTiming')
-        self.assertEqual(unchanged['ExtAttributes'], [])
-
-    def test_changed_operation(self):
-        changed_interface = self.diff['ANGLEInstancedArrays']
-        members = changed_interface['Operations']
-        deleted_arguments = [{"Type": "long", "Name": "primcount"}]
-        added_arguments = [{"Type": "unsigned long", "Name": "mode"}]
-        unchanged_arguments = [{"Type": "unsigned long", "Name": "mode"}]
-        for member in members:
-            if member.get(DIFF_TAG) == DIFF_TAG_DELETED:
-                deleted = member
-            elif member.get(DIFF_TAG) == DIFF_TAG_ADDED:
-                added = member
-            else:
-                unchanged = member
-        self.assertEqual(deleted['Name'], 'drawElementsInstancedANGLE')
-        self.assertEqual(deleted['Type'], 'void')
-        self.assertEqual(deleted['ExtAttributes'], [])
-        self.assertEqual(deleted['Arguments'], deleted_arguments)
-        self.assertEqual(added['Name'], 'drawElementsInstancedANGLE')
-        self.assertEqual(added['Type'], 'void')
-        self.assertEqual(added['ExtAttributes'], [])
-        self.assertEqual(added['Arguments'], added_arguments)
-        self.assertEqual(unchanged['Name'], 'drawArraysInstancedANGLE')
-        self.assertEqual(unchanged['Type'], 'void')
-        self.assertEqual(unchanged['ExtAttributes'], [])
-        self.assertEqual(unchanged['Arguments'], unchanged_arguments)
-
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/bindings/scripts/generate_init_partial_interfaces.py b/bindings/scripts/generate_init_partial_interfaces.py
index a604e57..63b782e 100755
--- a/bindings/scripts/generate_init_partial_interfaces.py
+++ b/bindings/scripts/generate_init_partial_interfaces.py
@@ -5,21 +5,24 @@
 
 """Generate initPartialInterfacesInModules(), which registers partial interfaces in modules to core interfaces."""
 
-import cPickle as pickle
+# pylint: disable=relative-import
+
 from optparse import OptionParser
 import os
 import posixpath
 import sys
-from utilities import write_file
 
-from aggregate_generated_bindings import extract_meta_data
+from utilities import get_file_contents
+from utilities import get_first_interface_name_from_idl
 from utilities import read_idl_files_list_from_file
+from utilities import should_generate_impl_file_from_idl
+from utilities import write_file
+from v8_utilities import build_basename
 
 
 _COPYRIGHT = """// Copyright 2014 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-
 """
 
 _INIT_PARTIAL_INTERFACE = """%s
@@ -27,8 +30,7 @@
 
 namespace blink {
 
-void initPartialInterfacesInModules()
-{
+void InitPartialInterfacesInModules() {
 %s
 }
 
@@ -39,35 +41,65 @@
 def parse_options():
     usage = 'Usage: %prog [options]'
     parser = OptionParser(usage=usage)
-    parser.add_option('--idl-files-list', help="a text file containing the IDL file paths, so the command line doesn't exceed OS length limits.")
-    parser.add_option('--gyp-format-list', default=False, action='store_true', help="if specified, idl-files-list is newline separated. When unspecified, it's formatted as a Posix command line.")
-    parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja')
+    parser.add_option('--idl-files-list',
+                      help='a text file containing the IDL file paths, so the command line doesn\'t exceed OS length limits.')
+    parser.add_option('--gyp-format-list', default=False, action='store_true',
+                      help='if specified, idl-files-list is newline separated. ' +
+                      'When unspecified, it\'s formatted as a Posix command line.')
     parser.add_option('--output')
+    # TODO(tkent): Remove the option after the great mv. crbug.com/760462
+    parser.add_option('--snake-case-generated-files',
+                      action='store_true', default=False)
 
     options, args = parser.parse_args()
     if options.output is None:
         parser.error('Must specify output file using --output.')
     if options.idl_files_list is None:
         parser.error('Must specify a list of IDL files using --idl-files-list.')
-    if options.write_file_only_if_changed is None:
-        parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.')
-    options.write_file_only_if_changed = bool(options.write_file_only_if_changed)
     return options
 
 
+def extract_meta_data(file_paths):
+    """Extracts interface name from each IDL file."""
+    meta_data_list = []
+
+    for file_path in file_paths:
+        if not file_path.endswith('.idl'):
+            print 'WARNING: non-IDL file passed: "%s"' % file_path
+            continue
+        if not os.path.exists(file_path):
+            print 'WARNING: file not found: "%s"' % file_path
+            continue
+
+        idl_file_contents = get_file_contents(file_path)
+        if not should_generate_impl_file_from_idl(idl_file_contents):
+            continue
+
+        # Extract interface name from file content
+        basename = get_first_interface_name_from_idl(idl_file_contents)
+
+        meta_data = {
+            'basename': basename,
+        }
+        meta_data_list.append(meta_data)
+
+    return meta_data_list
+
+
 def main():
     options = parse_options()
 
     idl_file_names = read_idl_files_list_from_file(options.idl_files_list, is_gyp_format=options.gyp_format_list)
 
     meta_data_list = extract_meta_data(idl_file_names)
-    interface_names = ['V8%sPartial' % meta_data['name']
+    interface_names = ['V8%sPartial' % meta_data['basename']
                        for meta_data in meta_data_list]
     interface_names.sort()
 
-    includes = ['#include "bindings/modules/v8/%s.h"' % interface_name
+    includes = ['#include "bindings/modules/v8/%s"' %
+                build_basename(interface_name, options.snake_case_generated_files, ext='.h')
                 for interface_name in interface_names]
-    initialize_calls = ['    %s::initialize();' % interface_name
+    initialize_calls = ['  %s::initialize();' % interface_name
                         for interface_name in interface_names]
 
     content = _INIT_PARTIAL_INTERFACE % (
@@ -75,8 +107,7 @@
         '\n'.join(includes),
         '\n'.join(initialize_calls))
 
-    write_file(content, options.output,
-               only_if_changed=options.write_file_only_if_changed)
+    write_file(content, options.output)
 
 
 if __name__ == '__main__':
diff --git a/bindings/scripts/generate_v8_context_snapshot_external_references.py b/bindings/scripts/generate_v8_context_snapshot_external_references.py
new file mode 100644
index 0000000..1fa3fae
--- /dev/null
+++ b/bindings/scripts/generate_v8_context_snapshot_external_references.py
@@ -0,0 +1,245 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# pylint: disable=relative-import
+
+import argparse
+import os
+import posixpath
+
+from code_generator import initialize_jinja_env
+from idl_reader import IdlReader
+from utilities import create_component_info_provider, write_file
+import utilities
+import v8_attributes
+import v8_interface
+import v8_types
+import v8_utilities
+
+
+INCLUDES = frozenset([
+    'bindings/core/v8/GeneratedCodeHelper.h',
+    'bindings/core/v8/V8HTMLDocument.h',
+    'bindings/core/v8/V8Initializer.h',
+    'bindings/core/v8/V8Window.h',
+    'platform/bindings/DOMWrapperWorld.h',
+    'platform/bindings/V8ObjectConstructor.h',
+    'platform/bindings/V8PerIsolateData.h',
+    'platform/bindings/V8PrivateProperty.h',
+    'v8/include/v8.h'])
+
+TEMPLATE_FILE = 'external_reference_table.cpp.tmpl'
+
+WHITE_LIST_INTERFACES = frozenset([
+    'DOMMatrix',  # crbug.com/733481
+])
+
+SNAPSHOTTED_INTERFACES = frozenset([
+    'Window',
+    'EventTarget',
+    'HTMLDocument',
+    'Document',
+    'Node',
+])
+
+
+def parse_args():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--idl-files-list', type=str, required=True,
+                        help='file listing IDL files')
+    parser.add_argument('--output', type=str, required=True,
+                        help='output file path')
+    parser.add_argument('--info-dir', type=str, required=True,
+                        help='directory contains component info')
+    parser.add_argument('--cache-dir', type=str, required=True,
+                        help='cache directory')
+    parser.add_argument('--target-component', type=str, required=True,
+                        help='target component')
+    parser.add_argument('--snake-case-generated-files', action='store_true',
+                        default=False)
+    return parser.parse_known_args()
+
+
+# This class creates a Jinja template context about an interface.
+class InterfaceTemplateContextBuilder(object):
+
+    def __init__(self, opts, info_provider):
+        self._opts = opts
+        self._info_provider = info_provider
+
+    def create_interface_context(self, interface, interfaces):
+        '''Creates a Jinja context which is based on an interface.'''
+
+        name = '%s%s' % (v8_utilities.cpp_name(interface), 'Partial' if interface.is_partial else '')
+
+        # Constructors
+        constructors = any(constructor.name == 'Constructor' for constructor in interface.constructors)
+        custom_constructors = interface.custom_constructors
+        html_constructor = 'HTMLConstructor' in interface.extended_attributes
+        has_constructor_callback = constructors or custom_constructors or html_constructor
+
+        attributes = []
+        methods = []
+        has_cross_origin_indexed_getter = False
+        has_cross_origin_named_enum = False
+        has_cross_origin_named_getter = False
+        has_cross_origin_named_setter = False
+        has_origin_safe_method_setter = False
+        has_security_check = False
+        indexed_property_getter = None
+        is_global = False
+        named_property_getter = None
+        if interface.name in SNAPSHOTTED_INTERFACES:
+            attributes = [v8_attributes.attribute_context(interface, attribute, interfaces)
+                          for attribute in interface.attributes]
+            methods = v8_interface.methods_context(interface)['methods']
+            is_global = ('PrimaryGlobal' in interface.extended_attributes or
+                         'Global' in interface.extended_attributes)
+
+            named_property_getter = v8_interface.property_getter(
+                interface.named_property_getter, ['name'])
+            indexed_property_getter = v8_interface.property_getter(
+                interface.indexed_property_getter, ['index'])
+
+            if not interface.is_partial:
+                has_origin_safe_method_setter = is_global and any(
+                    method['is_check_security_for_receiver'] and not method['is_unforgeable']
+                    for method in methods)
+                has_security_check = ('CheckSecurity' in interface.extended_attributes and
+                                      interface.name != 'EventTarget')
+                has_cross_origin_named_getter = (any(method['is_cross_origin'] for method in methods) or
+                                                 any(attribute['has_cross_origin_getter'] for attribute in attributes))
+                has_cross_origin_named_setter = any(attribute['has_cross_origin_setter'] for attribute in attributes)
+                has_cross_origin_indexed_getter = indexed_property_getter and indexed_property_getter['is_cross_origin']
+                has_cross_origin_named_enum = has_cross_origin_named_getter or has_cross_origin_named_setter
+                if named_property_getter and named_property_getter['is_cross_origin']:
+                    has_cross_origin_named_getter = True
+
+        return {
+            'attributes': attributes,
+            'has_origin_safe_method_setter': has_origin_safe_method_setter,
+            'has_constructor_callback': has_constructor_callback,
+            'has_cross_origin_named_getter': has_cross_origin_named_getter,
+            'has_cross_origin_named_setter': has_cross_origin_named_setter,
+            'has_cross_origin_named_enumerator': has_cross_origin_named_enum,
+            'has_cross_origin_indexed_getter': has_cross_origin_indexed_getter,
+            'has_security_check': has_security_check,
+            'indexed_property_getter': indexed_property_getter,
+            'indexed_property_setter': v8_interface.property_setter(interface.indexed_property_setter, interface),
+            'indexed_property_deleter': v8_interface.property_deleter(interface.indexed_property_deleter),
+            'is_array_buffer_or_view': interface.idl_type.is_array_buffer_or_view,
+            'is_callback': interface.is_callback,
+            'is_partial': interface.is_partial,
+            'is_snapshotted': interface in SNAPSHOTTED_INTERFACES,
+            'methods': methods,
+            'name': name,
+            'named_constructor': v8_interface.named_constructor_context(interface),
+            'named_property_getter': named_property_getter,
+            'named_property_setter': v8_interface.property_setter(interface.named_property_setter, interface),
+            'named_property_deleter': v8_interface.property_deleter(interface.named_property_deleter),
+            'v8_name': v8_utilities.v8_class_name_or_partial(interface),
+        }
+
+
+# This class applies a Jinja template and creates a .cpp file for the external reference table.
+class ExternalReferenceTableGenerator(object):
+    def __init__(self, opts, info_provider):
+        self._opts = opts
+        self._info_provider = info_provider
+        self._reader = IdlReader(
+            info_provider.interfaces_info, opts.cache_dir)
+        self._interface_contexts = {}
+        self._include_files = set(INCLUDES)
+        v8_types.set_component_dirs(info_provider.interfaces_info['component_dirs'])
+
+    # Creates a Jinja context from an IDL file.
+    def process_idl_file(self, idl_filename):
+        definitions = self._reader.read_idl_definitions(idl_filename)
+        for component in definitions:
+            target_definitions = definitions[component]
+            interfaces = target_definitions.interfaces
+            first_name = target_definitions.first_name
+            if first_name in interfaces.keys():
+                interface = interfaces[first_name]
+                self._process_interface(interface, component, interfaces)
+
+    # Creates a Jinja context from an interface. Some interfaces are not used
+    # in V8 context snapshot, so we can skip them.
+    def _process_interface(self, interface, component, interfaces):
+        def has_impl(interface):
+            if interface.name in WHITE_LIST_INTERFACES:
+                return True
+            # Non legacy callback interface does not provide V8 callbacks.
+            if interface.is_callback:
+                return len(interface.constants) > 0
+            if 'RuntimeEnabled' in interface.extended_attributes:
+                return False
+            return True
+
+        if not has_impl(interface):
+            return
+
+        context_builder = InterfaceTemplateContextBuilder(self._opts, self._info_provider)
+        context = context_builder.create_interface_context(interface, interfaces)
+        name = '%s%s' % (interface.name, 'Partial' if interface.is_partial else '')
+        self._interface_contexts[name] = context
+        if self._opts.snake_case_generated_files:
+            include_file = 'bindings/%s/v8/%s.h' % (component, utilities.to_snake_case(context['v8_name']))
+        else:
+            include_file = 'bindings/%s/v8/%s.h' % (component, context['v8_name'])
+        self._include_files.add(include_file)
+
+    # Gathers all interface-dependent information and returns as a Jinja template context.
+    def _create_template_context(self):
+        interfaces = []
+        for name in sorted(self._interface_contexts):
+            interfaces.append(self._interface_contexts[name])
+        header_name = 'V8ContextSnapshotExternalReferences.h'
+        if self._opts.snake_case_generated_files:
+            header_name = 'v8_context_snapshot_external_references.h'
+        include_files = list(self._include_files)
+        # TODO(tkent): Update INCLUDES after the great mv, and remove the
+        # following block. crbug.com/760462
+        if self._opts.snake_case_generated_files:
+            include_files = []
+            for include in self._include_files:
+                dirname, basename = posixpath.split(include)
+                name, ext = posixpath.splitext(basename)
+                include_files.append(posixpath.join(
+                    dirname, utilities.to_snake_case(name) + ext))
+        return {
+            'class': 'V8ContextSnapshotExternalReferences',
+            'interfaces': interfaces,
+            'include_files': sorted(include_files),
+            'this_include_header_name': header_name,
+            'code_generator': os.path.basename(__file__),
+            'jinja_template_filename': TEMPLATE_FILE
+        }
+
+    # Applies a Jinja template on a context and generates a C++ code.
+    def generate(self):
+        jinja_env = initialize_jinja_env(self._opts.cache_dir)
+        context = self._create_template_context()
+        cpp_template = jinja_env.get_template(TEMPLATE_FILE)
+        cpp_text = cpp_template.render(context)
+        return cpp_text
+
+
+def main():
+    opts, _ = parse_args()
+    # TODO(peria): get rid of |info_provider|
+    info_provider = create_component_info_provider(
+        opts.info_dir, opts.target_component)
+    generator = ExternalReferenceTableGenerator(opts, info_provider)
+
+    idl_files = utilities.read_idl_files_list_from_file(opts.idl_files_list, False)
+    for idl_file in idl_files:
+        generator.process_idl_file(idl_file)
+    output_code = generator.generate()
+    output_path = opts.output
+    write_file(output_code, output_path)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/bindings/scripts/idl_compiler.py b/bindings/scripts/idl_compiler.py
index baf2686..d876a0c 100755
--- a/bindings/scripts/idl_compiler.py
+++ b/bindings/scripts/idl_compiler.py
@@ -35,12 +35,16 @@
 import abc
 from optparse import OptionParser
 import os
-import cPickle as pickle
 import sys
 
-from code_generator_v8 import CodeGeneratorDictionaryImpl, CodeGeneratorV8, CodeGeneratorUnionType
+from code_generator_v8 import CodeGeneratorDictionaryImpl
+from code_generator_v8 import CodeGeneratorV8
+from code_generator_v8 import CodeGeneratorUnionType
+from code_generator_v8 import CodeGeneratorCallbackFunction
 from idl_reader import IdlReader
-from utilities import create_component_info_provider, read_idl_files_list_from_file, write_file, idl_filename_to_component
+from utilities import create_component_info_provider
+from utilities import read_idl_files_list_from_file
+from utilities import write_file
 
 
 def parse_options():
@@ -48,14 +52,20 @@
     parser.add_option('--cache-directory',
                       help='cache directory, defaults to output directory')
     parser.add_option('--generate-impl',
-                      action="store_true", default=False)
+                      action='store_true', default=False)
+    # TODO(tkent): Remove the option after the great mv. crbug.com/760462
+    parser.add_option('--snake-case-generated-files',
+                      action='store_true', default=False)
+    parser.add_option('--read-idl-list-from-file',
+                      action='store_true', default=False)
     parser.add_option('--output-directory')
     parser.add_option('--impl-output-directory')
     parser.add_option('--info-dir')
-    parser.add_option('--write-file-only-if-changed', type='int')
     # FIXME: We should always explicitly specify --target-component and
     # remove the default behavior.
     parser.add_option('--target-component',
+                      type='choice',
+                      choices=['core', 'modules'],
                       help='target component to generate code, defaults to '
                       'component of input idl file')
     # ensure output comes last, so command line easy to parse via regexes
@@ -64,139 +74,136 @@
     options, args = parser.parse_args()
     if options.output_directory is None:
         parser.error('Must specify output directory using --output-directory.')
-    options.write_file_only_if_changed = bool(options.write_file_only_if_changed)
     if len(args) != 1:
         parser.error('Must specify exactly 1 input file as argument, but %d given.' % len(args))
     idl_filename = os.path.realpath(args[0])
     return options, idl_filename
 
 
-def idl_filename_to_interface_name(idl_filename):
-    basename = os.path.basename(idl_filename)
-    interface_name, _ = os.path.splitext(basename)
-    return interface_name
-
-
 class IdlCompiler(object):
-    """Abstract Base Class for IDL compilers.
+    """The IDL Compiler.
 
-    In concrete classes:
-    * self.code_generator must be set, implementing generate_code()
-      (returning a list of output code), and
-    * compile_file() must be implemented (handling output filenames).
     """
     __metaclass__ = abc.ABCMeta
 
     def __init__(self, output_directory, cache_directory=None,
-                 code_generator=None, info_provider=None,
-                 only_if_changed=False, target_component=None):
+                 code_generator_class=None, snake_case_generated_files=False,
+                 info_provider=None, target_component=None):
         """
         Args:
           output_directory: directory to put output files.
           cache_directory: directory which contains PLY caches.
-          code_generator: code generator to be used.
+          code_generator_class: code generator class to be used.
           info_provider: component-specific information provider.
-          only_if_changed: True when the compiler should only write output files
-            when the contents are changed.
           target_component: component to be processed.
         """
         self.cache_directory = cache_directory
-        self.code_generator = code_generator
         self.info_provider = info_provider
-        self.only_if_changed = only_if_changed
         self.output_directory = output_directory
         self.target_component = target_component
         self.reader = IdlReader(info_provider.interfaces_info, cache_directory)
+        self.code_generator = code_generator_class(self.info_provider,
+                                                   self.cache_directory,
+                                                   self.output_directory,
+                                                   snake_case_generated_files)
 
     def compile_and_write(self, idl_filename):
-        interface_name = idl_filename_to_interface_name(idl_filename)
         definitions = self.reader.read_idl_definitions(idl_filename)
-        target_component = self.target_component or idl_filename_to_component(idl_filename)
-        target_definitions = definitions[target_component]
+        target_definitions = definitions[self.target_component]
+        interface_name = target_definitions.first_name
         output_code_list = self.code_generator.generate_code(
             target_definitions, interface_name)
+
+        # Generator may choose to omit the file.
+        if output_code_list is None:
+            return
+
         for output_path, output_code in output_code_list:
-            write_file(output_code, output_path, self.only_if_changed)
-
-    @abc.abstractmethod
-    def compile_file(self, idl_filename):
-        pass
-
-
-class IdlCompilerV8(IdlCompiler):
-    def __init__(self, *args, **kwargs):
-        IdlCompiler.__init__(self, *args, **kwargs)
-        self.code_generator = CodeGeneratorV8(self.info_provider,
-                                              self.cache_directory,
-                                              self.output_directory)
+            write_file(output_code, output_path)
 
     def compile_file(self, idl_filename):
         self.compile_and_write(idl_filename)
 
 
-class IdlCompilerDictionaryImpl(IdlCompiler):
-    def __init__(self, *args, **kwargs):
-        IdlCompiler.__init__(self, *args, **kwargs)
-        self.code_generator = CodeGeneratorDictionaryImpl(
-            self.info_provider, self.cache_directory, self.output_directory)
-
-    def compile_file(self, idl_filename):
-        self.compile_and_write(idl_filename)
-
-
-def generate_bindings(options, input_filename):
-    info_provider = create_component_info_provider(
-        options.info_dir, options.target_component)
-    idl_compiler = IdlCompilerV8(
-        options.output_directory,
+def generate_bindings(code_generator_class, info_provider, options,
+                      input_filenames):
+    idl_compiler = IdlCompiler(
+        output_directory=options.output_directory,
         cache_directory=options.cache_directory,
+        code_generator_class=code_generator_class,
+        snake_case_generated_files=options.snake_case_generated_files,
         info_provider=info_provider,
-        only_if_changed=options.write_file_only_if_changed,
         target_component=options.target_component)
-    idl_compiler.compile_file(input_filename)
 
-
-def generate_dictionary_impl(options, input_filename):
-    info_provider = create_component_info_provider(
-        options.info_dir, options.target_component)
-    idl_compiler = IdlCompilerDictionaryImpl(
-        options.impl_output_directory,
-        cache_directory=options.cache_directory,
-        info_provider=info_provider,
-        only_if_changed=options.write_file_only_if_changed)
-
-    idl_filenames = read_idl_files_list_from_file(input_filename,
-                                                  is_gyp_format=True)
-    for idl_filename in idl_filenames:
+    for idl_filename in input_filenames:
         idl_compiler.compile_file(idl_filename)
 
 
-def generate_union_type_containers(options):
-    info_provider = create_component_info_provider(
-        options.info_dir, options.target_component)
-    if not info_provider.interfaces_info:
-        raise Exception('Interfaces info is required to generate '
-                        'union types containers')
-    generator = CodeGeneratorUnionType(
+def generate_dictionary_impl(code_generator_class, info_provider, options,
+                             input_filenames):
+    idl_compiler = IdlCompiler(
+        output_directory=options.impl_output_directory,
+        cache_directory=options.cache_directory,
+        code_generator_class=code_generator_class,
+        snake_case_generated_files=options.snake_case_generated_files,
+        info_provider=info_provider,
+        target_component=options.target_component)
+
+    for idl_filename in input_filenames:
+        idl_compiler.compile_file(idl_filename)
+
+
+def generate_union_type_containers(code_generator_class, info_provider,
+                                   options):
+    generator = code_generator_class(
         info_provider,
         options.cache_directory,
         options.output_directory,
+        options.snake_case_generated_files,
         options.target_component)
     output_code_list = generator.generate_code()
     for output_path, output_code in output_code_list:
-        write_file(output_code, output_path, options.write_file_only_if_changed)
+        write_file(output_code, output_path)
+
+
+def generate_callback_function_impl(code_generator_class, info_provider,
+                                    options):
+    generator = code_generator_class(
+        info_provider,
+        options.cache_directory,
+        options.output_directory,
+        options.snake_case_generated_files,
+        options.target_component)
+    output_code_list = generator.generate_code()
+    for output_path, output_code in output_code_list:
+        write_file(output_code, output_path)
 
 
 def main():
     options, input_filename = parse_options()
-    if options.generate_impl:
+    info_provider = create_component_info_provider(
+        options.info_dir, options.target_component)
+    if options.generate_impl or options.read_idl_list_from_file:
         # |input_filename| should be a file which contains a list of IDL
         # dictionary paths.
-        generate_dictionary_impl(options, input_filename)
-        generate_union_type_containers(options)
+        input_filenames = read_idl_files_list_from_file(input_filename,
+                                                        is_gyp_format=True)
     else:
-        # |input_filename| should be a path of an IDL file.
-        generate_bindings(options, input_filename)
+        input_filenames = [input_filename]
+
+    if options.generate_impl:
+        if not info_provider.interfaces_info:
+            raise Exception('Interfaces info is required to generate '
+                            'impl classes')
+        generate_dictionary_impl(CodeGeneratorDictionaryImpl, info_provider,
+                                 options, input_filenames)
+        generate_union_type_containers(CodeGeneratorUnionType, info_provider,
+                                       options)
+        generate_callback_function_impl(CodeGeneratorCallbackFunction,
+                                        info_provider, options)
+    else:
+        generate_bindings(CodeGeneratorV8, info_provider, options,
+                          input_filenames)
 
 
 if __name__ == '__main__':
diff --git a/bindings/scripts/idl_definitions.py b/bindings/scripts/idl_definitions.py
index 16a8290..f2f0e54 100644
--- a/bindings/scripts/idl_definitions.py
+++ b/bindings/scripts/idl_definitions.py
@@ -26,6 +26,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# pylint: disable=relative-import
+
 """Blink IDL Intermediate Representation (IR) classes.
 
 Classes are primarily constructors, which build an IdlDefinitions object
@@ -52,8 +54,6 @@
         IdlIterable < IdlIterableOrMaplikeOrSetlike
         IdlMaplike < IdlIterableOrMaplikeOrSetlike
         IdlSetlike < IdlIterableOrMaplikeOrSetlike
-    IdlException < IdlInterface
-        (same contents as IdlInterface)
 
 TypedObject :: Object with one or more attributes that is a type.
 
@@ -64,9 +64,14 @@
 
 import abc
 
-from idl_types import IdlType, IdlUnionType, IdlArrayType, IdlSequenceType, IdlNullableType
+from idl_types import IdlFrozenArrayType
+from idl_types import IdlNullableType
+from idl_types import IdlRecordType
+from idl_types import IdlSequenceType
+from idl_types import IdlType
+from idl_types import IdlUnionType
 
-SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER']
+SPECIAL_KEYWORD_LIST = ['LEGACYCALLER', 'GETTER', 'SETTER', 'DELETER']
 
 
 ################################################################################
@@ -88,14 +93,14 @@
 ################################################################################
 
 class IdlDefinitions(object):
-    def __init__(self, idl_name, node):
+    def __init__(self, node):
         """Args: node: AST root node, class == 'File'"""
         self.callback_functions = {}
         self.dictionaries = {}
         self.enumerations = {}
         self.implements = []
         self.interfaces = {}
-        self.idl_name = idl_name
+        self.first_name = None
         self.typedefs = {}
 
         node_class = node.GetClass()
@@ -106,26 +111,26 @@
         for child in children:
             child_class = child.GetClass()
             if child_class == 'Interface':
-                interface = IdlInterface(idl_name, child)
+                interface = IdlInterface(child)
                 self.interfaces[interface.name] = interface
-            elif child_class == 'Exception':
-                exception = IdlException(idl_name, child)
-                # For simplicity, treat exceptions as interfaces
-                self.interfaces[exception.name] = exception
+                if not self.first_name:
+                    self.first_name = interface.name
             elif child_class == 'Typedef':
                 typedef = IdlTypedef(child)
                 self.typedefs[typedef.name] = typedef
             elif child_class == 'Enum':
-                enumeration = IdlEnum(idl_name, child)
+                enumeration = IdlEnum(child)
                 self.enumerations[enumeration.name] = enumeration
             elif child_class == 'Callback':
-                callback_function = IdlCallbackFunction(idl_name, child)
+                callback_function = IdlCallbackFunction(child)
                 self.callback_functions[callback_function.name] = callback_function
             elif child_class == 'Implements':
                 self.implements.append(IdlImplement(child))
             elif child_class == 'Dictionary':
-                dictionary = IdlDictionary(idl_name, child)
+                dictionary = IdlDictionary(child)
                 self.dictionaries[dictionary.name] = dictionary
+                if not self.first_name:
+                    self.first_name = dictionary.name
             else:
                 raise ValueError('Unrecognized node class: %s' % child_class)
 
@@ -137,6 +142,10 @@
             callback_function.accept(visitor)
         for dictionary in self.dictionaries.itervalues():
             dictionary.accept(visitor)
+        for enumeration in self.enumerations.itervalues():
+            enumeration.accept(visitor)
+        for implement in self.implements:
+            implement.accept(visitor)
         for typedef in self.typedefs.itervalues():
             typedef.accept(visitor)
 
@@ -166,20 +175,26 @@
 ################################################################################
 
 class IdlCallbackFunction(TypedObject):
-    def __init__(self, idl_name, node):
+    def __init__(self, node):
         children = node.GetChildren()
         num_children = len(children)
-        if num_children != 2:
-            raise ValueError('Expected 2 children, got %s' % num_children)
-        type_node, arguments_node = children
+        if num_children < 2 or num_children > 3:
+            raise ValueError('Expected 2 or 3 children, got %s' % num_children)
+        type_node = children[0]
+        arguments_node = children[1]
+        if num_children == 3:
+            ext_attributes_node = children[2]
+            self.extended_attributes = (
+                ext_attributes_node_to_extended_attributes(ext_attributes_node))
+        else:
+            self.extended_attributes = {}
         arguments_node_class = arguments_node.GetClass()
         if arguments_node_class != 'Arguments':
             raise ValueError('Expected Arguments node, got %s' % arguments_node_class)
 
-        self.idl_name = idl_name
         self.name = node.GetName()
         self.idl_type = type_node_to_type(type_node)
-        self.arguments = arguments_node_to_arguments(idl_name, arguments_node)
+        self.arguments = arguments_node_to_arguments(arguments_node)
 
     def accept(self, visitor):
         visitor.visit_callback_function(self)
@@ -192,10 +207,9 @@
 ################################################################################
 
 class IdlDictionary(object):
-    def __init__(self, idl_name, node):
+    def __init__(self, node):
         self.extended_attributes = {}
-        self.is_partial = bool(node.GetProperty('Partial'))
-        self.idl_name = idl_name
+        self.is_partial = bool(node.GetProperty('PARTIAL'))
         self.name = node.GetName()
         self.members = []
         self.parent = None
@@ -204,10 +218,10 @@
             if child_class == 'Inherit':
                 self.parent = child.GetName()
             elif child_class == 'Key':
-                self.members.append(IdlDictionaryMember(idl_name, child))
+                self.members.append(IdlDictionaryMember(child))
             elif child_class == 'ExtAttributes':
                 self.extended_attributes = (
-                    ext_attributes_node_to_extended_attributes(idl_name, child))
+                    ext_attributes_node_to_extended_attributes(child))
             else:
                 raise ValueError('Unrecognized node class: %s' % child_class)
 
@@ -218,11 +232,10 @@
 
 
 class IdlDictionaryMember(TypedObject):
-    def __init__(self, idl_name, node):
+    def __init__(self, node):
         self.default_value = None
         self.extended_attributes = {}
         self.idl_type = None
-        self.idl_name = idl_name
         self.is_required = bool(node.GetProperty('REQUIRED'))
         self.name = node.GetName()
         for child in node.GetChildren():
@@ -233,7 +246,7 @@
                 self.default_value = default_node_to_idl_literal(child)
             elif child_class == 'ExtAttributes':
                 self.extended_attributes = (
-                    ext_attributes_node_to_extended_attributes(idl_name, child))
+                    ext_attributes_node_to_extended_attributes(child))
             else:
                 raise ValueError('Unrecognized node class: %s' % child_class)
 
@@ -246,14 +259,15 @@
 ################################################################################
 
 class IdlEnum(object):
-    # FIXME: remove, just treat enums as a dictionary
-    def __init__(self, idl_name, node):
-        self.idl_name = idl_name
+    def __init__(self, node):
         self.name = node.GetName()
         self.values = []
         for child in node.GetChildren():
             self.values.append(child.GetName())
 
+    def accept(self, visitor):
+        visitor.visit_enumeration(self)
+
 
 ################################################################################
 # Typedefs
@@ -271,11 +285,11 @@
 
 
 ################################################################################
-# Interfaces and Exceptions
+# Interfaces
 ################################################################################
 
 class IdlInterface(object):
-    def __init__(self, idl_name, node=None):
+    def __init__(self, node):
         self.attributes = []
         self.constants = []
         self.constructors = []
@@ -287,67 +301,87 @@
         self.stringifier = None
         self.iterable = None
         self.has_indexed_elements = False
+        self.has_named_property_getter = False
         self.maplike = None
         self.setlike = None
         self.original_interface = None
         self.partial_interfaces = []
-        if not node:  # Early exit for IdlException.__init__
-            return
 
         self.is_callback = bool(node.GetProperty('CALLBACK'))
-        self.is_exception = False
-        # FIXME: uppercase 'Partial' => 'PARTIAL' in base IDL parser
-        self.is_partial = bool(node.GetProperty('Partial'))
-        self.idl_name = idl_name
+        self.is_partial = bool(node.GetProperty('PARTIAL'))
         self.name = node.GetName()
         self.idl_type = IdlType(self.name)
 
         has_indexed_property_getter = False
         has_integer_typed_length = False
 
+        def is_blacklisted_attribute_type(idl_type):
+            return idl_type.is_callback_function or \
+                idl_type.is_dictionary or \
+                idl_type.is_record_type or \
+                idl_type.is_sequence_type
+
         children = node.GetChildren()
         for child in children:
             child_class = child.GetClass()
             if child_class == 'Attribute':
-                attr = IdlAttribute(idl_name, child)
+                attr = IdlAttribute(child)
+                if is_blacklisted_attribute_type(attr.idl_type):
+                    raise ValueError('Type "%s" cannot be used as an attribute.' % attr.idl_type)
                 if attr.idl_type.is_integer_type and attr.name == 'length':
                     has_integer_typed_length = True
                 self.attributes.append(attr)
             elif child_class == 'Const':
-                self.constants.append(IdlConstant(idl_name, child))
+                self.constants.append(IdlConstant(child))
             elif child_class == 'ExtAttributes':
-                extended_attributes = ext_attributes_node_to_extended_attributes(idl_name, child)
+                extended_attributes = ext_attributes_node_to_extended_attributes(child)
                 self.constructors, self.custom_constructors = (
-                    extended_attributes_to_constructors(idl_name, extended_attributes))
+                    extended_attributes_to_constructors(extended_attributes))
                 clear_constructor_attributes(extended_attributes)
                 self.extended_attributes = extended_attributes
             elif child_class == 'Operation':
-                op = IdlOperation(idl_name, child)
-                if 'getter' in op.specials and str(op.arguments[0].idl_type) == 'unsigned long':
-                    has_indexed_property_getter = True
+                op = IdlOperation(child)
+                if 'getter' in op.specials:
+                    if str(op.arguments[0].idl_type) == 'unsigned long':
+                        has_indexed_property_getter = True
+                    elif str(op.arguments[0].idl_type) == 'DOMString':
+                        self.has_named_property_getter = True
                 self.operations.append(op)
             elif child_class == 'Inherit':
                 self.parent = child.GetName()
             elif child_class == 'Serializer':
-                self.serializer = IdlSerializer(idl_name, child)
+                self.serializer = IdlSerializer(child)
                 self.process_serializer()
             elif child_class == 'Stringifier':
-                self.stringifier = IdlStringifier(idl_name, child)
+                self.stringifier = IdlStringifier(child)
                 self.process_stringifier()
             elif child_class == 'Iterable':
-                self.iterable = IdlIterable(idl_name, child)
+                self.iterable = IdlIterable(child)
             elif child_class == 'Maplike':
-                self.maplike = IdlMaplike(idl_name, child)
+                self.maplike = IdlMaplike(child)
             elif child_class == 'Setlike':
-                self.setlike = IdlSetlike(idl_name, child)
+                self.setlike = IdlSetlike(child)
             else:
                 raise ValueError('Unrecognized node class: %s' % child_class)
 
         if len(filter(None, [self.iterable, self.maplike, self.setlike])) > 1:
             raise ValueError('Interface can only have one of iterable<>, maplike<> and setlike<>.')
 
+        # TODO(rakuco): This validation logic should be in v8_interface according to bashi@.
+        # At the moment, doing so does not work because several IDL files are partial Window
+        # interface definitions, and interface_dependency_resolver.py doesn't seem to have any logic
+        # to prevent these partial interfaces from resetting has_named_property to False.
+        if 'LegacyUnenumerableNamedProperties' in self.extended_attributes and \
+           not self.has_named_property_getter:
+            raise ValueError('[LegacyUnenumerableNamedProperties] can be used only in interfaces '
+                             'that support named properties.')
+
         if has_integer_typed_length and has_indexed_property_getter:
             self.has_indexed_elements = True
+        else:
+            if self.iterable is not None and self.iterable.key_type is None:
+                raise ValueError('Value iterators (iterable<V>) must be accompanied by an indexed '
+                                 'property getter and an integer-typed length attribute.')
 
     def accept(self, visitor):
         visitor.visit_interface(self)
@@ -387,43 +421,10 @@
         self.attributes.extend(other.attributes)
         self.constants.extend(other.constants)
         self.operations.extend(other.operations)
-
-
-class IdlException(IdlInterface):
-    # Properly exceptions and interfaces are distinct, and thus should inherit a
-    # common base class (say, "IdlExceptionOrInterface").
-    # However, there is only one exception (DOMException), and new exceptions
-    # are not expected. Thus it is easier to implement exceptions as a
-    # restricted subclass of interfaces.
-    # http://www.w3.org/TR/WebIDL/#idl-exceptions
-    def __init__(self, idl_name, node):
-        # Exceptions are similar to Interfaces, but simpler
-        IdlInterface.__init__(self, idl_name)
-        self.is_callback = False
-        self.is_exception = True
-        self.is_partial = False
-        self.idl_name = idl_name
-        self.name = node.GetName()
-        self.idl_type = IdlType(self.name)
-
-        children = node.GetChildren()
-        for child in children:
-            child_class = child.GetClass()
-            if child_class == 'Attribute':
-                attribute = IdlAttribute(idl_name, child)
-                self.attributes.append(attribute)
-            elif child_class == 'Const':
-                self.constants.append(IdlConstant(idl_name, child))
-            elif child_class == 'ExtAttributes':
-                extended_attributes = ext_attributes_node_to_extended_attributes(idl_name, child)
-                self.constructors, self.custom_constructors = (
-                    extended_attributes_to_constructors(idl_name, extended_attributes))
-                clear_constructor_attributes(extended_attributes)
-                self.extended_attributes = extended_attributes
-            elif child_class == 'ExceptionOperation':
-                self.operations.append(IdlOperation.from_exception_operation_node(idl_name, child))
-            else:
-                raise ValueError('Unrecognized node class: %s' % child_class)
+        if self.serializer is None:
+            self.serializer = other.serializer
+        if self.stringifier is None:
+            self.stringifier = other.stringifier
 
 
 ################################################################################
@@ -431,24 +432,23 @@
 ################################################################################
 
 class IdlAttribute(TypedObject):
-    def __init__(self, idl_name, node):
-        self.is_read_only = bool(node.GetProperty('READONLY'))
-        self.is_static = bool(node.GetProperty('STATIC'))
-        self.idl_name = idl_name
-        self.name = node.GetName()
-        # Defaults, overridden below
+    def __init__(self, node=None):
+        self.is_read_only = bool(node.GetProperty('READONLY')) if node else False
+        self.is_static = bool(node.GetProperty('STATIC')) if node else False
+        self.name = node.GetName() if node else None
         self.idl_type = None
         self.extended_attributes = {}
 
-        children = node.GetChildren()
-        for child in children:
-            child_class = child.GetClass()
-            if child_class == 'Type':
-                self.idl_type = type_node_to_type(child)
-            elif child_class == 'ExtAttributes':
-                self.extended_attributes = ext_attributes_node_to_extended_attributes(idl_name, child)
-            else:
-                raise ValueError('Unrecognized node class: %s' % child_class)
+        if node:
+            children = node.GetChildren()
+            for child in children:
+                child_class = child.GetClass()
+                if child_class == 'Type':
+                    self.idl_type = type_node_to_type(child)
+                elif child_class == 'ExtAttributes':
+                    self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
+                else:
+                    raise ValueError('Unrecognized node class: %s' % child_class)
 
     def accept(self, visitor):
         visitor.visit_attribute(self)
@@ -459,7 +459,7 @@
 ################################################################################
 
 class IdlConstant(TypedObject):
-    def __init__(self, idl_name, node):
+    def __init__(self, node):
         children = node.GetChildren()
         num_children = len(children)
         if num_children < 2 or num_children > 3:
@@ -470,22 +470,15 @@
         if value_node_class != 'Value':
             raise ValueError('Expected Value node, got %s' % value_node_class)
 
-        self.idl_name = idl_name
         self.name = node.GetName()
         # ConstType is more limited than Type, so subtree is smaller and
         # we don't use the full type_node_to_type function.
         self.idl_type = type_node_inner_to_type(type_node)
-        # FIXME: This code is unnecessarily complicated due to the rather
-        # inconsistent way the upstream IDL parser outputs default values.
-        # http://crbug.com/374178
-        if value_node.GetProperty('TYPE') == 'float':
-            self.value = value_node.GetProperty('VALUE')
-        else:
-            self.value = value_node.GetName()
+        self.value = value_node.GetProperty('VALUE')
 
         if num_children == 3:
             ext_attributes_node = children[2]
-            self.extended_attributes = ext_attributes_node_to_extended_attributes(idl_name, ext_attributes_node)
+            self.extended_attributes = ext_attributes_node_to_extended_attributes(ext_attributes_node)
         else:
             self.extended_attributes = {}
 
@@ -505,7 +498,10 @@
 
     def __str__(self):
         if self.idl_type == 'DOMString':
-            return 'String("%s")' % self.value
+            if self.value:
+                return '"%s"' % self.value
+            else:
+                return 'WTF::g_empty_string'
         if self.idl_type == 'integer':
             return '%d' % self.value
         if self.idl_type == 'float':
@@ -526,21 +522,18 @@
 
 
 def default_node_to_idl_literal(node):
-    # FIXME: This code is unnecessarily complicated due to the rather
-    # inconsistent way the upstream IDL parser outputs default values.
-    # http://crbug.com/374178
     idl_type = node.GetProperty('TYPE')
+    value = node.GetProperty('VALUE')
     if idl_type == 'DOMString':
-        value = node.GetProperty('NAME')
         if '"' in value or '\\' in value:
             raise ValueError('Unsupported string value: %r' % value)
         return IdlLiteral(idl_type, value)
     if idl_type == 'integer':
-        return IdlLiteral(idl_type, int(node.GetProperty('NAME'), base=0))
+        return IdlLiteral(idl_type, int(value, base=0))
     if idl_type == 'float':
-        return IdlLiteral(idl_type, float(node.GetProperty('VALUE')))
+        return IdlLiteral(idl_type, float(value))
     if idl_type in ['boolean', 'sequence']:
-        return IdlLiteral(idl_type, node.GetProperty('VALUE'))
+        return IdlLiteral(idl_type, value)
     if idl_type == 'NULL':
         return IdlLiteralNull()
     raise ValueError('Unrecognized default value type: %s' % idl_type)
@@ -551,22 +544,18 @@
 ################################################################################
 
 class IdlOperation(TypedObject):
-    def __init__(self, idl_name, node=None):
+    def __init__(self, node=None):
         self.arguments = []
         self.extended_attributes = {}
         self.specials = []
         self.is_constructor = False
-        self.idl_name = idl_name
         self.idl_type = None
         self.is_static = False
 
         if not node:
             return
 
-        self.name = node.GetName()  # FIXME: should just be: or ''
-        # FIXME: AST should use None internally
-        if self.name == '_unnamed_':
-            self.name = ''
+        self.name = node.GetName()
 
         self.is_static = bool(node.GetProperty('STATIC'))
         property_dictionary = node.GetProperties()
@@ -578,40 +567,19 @@
         for child in children:
             child_class = child.GetClass()
             if child_class == 'Arguments':
-                self.arguments = arguments_node_to_arguments(idl_name, child)
+                self.arguments = arguments_node_to_arguments(child)
             elif child_class == 'Type':
                 self.idl_type = type_node_to_type(child)
             elif child_class == 'ExtAttributes':
-                self.extended_attributes = ext_attributes_node_to_extended_attributes(idl_name, child)
+                self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
             else:
                 raise ValueError('Unrecognized node class: %s' % child_class)
 
     @classmethod
-    def from_exception_operation_node(cls, idl_name, node):
-        # Needed to handle one case in DOMException.idl:
-        # // Override in a Mozilla compatible format
-        # [NotEnumerable] DOMString toString();
-        # FIXME: can we remove this? replace with a stringifier?
-        operation = cls(idl_name)
-        operation.name = node.GetName()
-        children = node.GetChildren()
-        if len(children) < 1 or len(children) > 2:
-            raise ValueError('ExceptionOperation node with %s children, expected 1 or 2' % len(children))
-
-        type_node = children[0]
-        operation.idl_type = type_node_to_type(type_node)
-
-        if len(children) > 1:
-            ext_attributes_node = children[1]
-            operation.extended_attributes = ext_attributes_node_to_extended_attributes(idl_name, ext_attributes_node)
-
-        return operation
-
-    @classmethod
-    def constructor_from_arguments_node(cls, name, idl_name, arguments_node):
-        constructor = cls(idl_name)
+    def constructor_from_arguments_node(cls, name, arguments_node):
+        constructor = cls()
         constructor.name = name
-        constructor.arguments = arguments_node_to_arguments(idl_name, arguments_node)
+        constructor.arguments = arguments_node_to_arguments(arguments_node)
         constructor.is_constructor = True
         return constructor
 
@@ -626,12 +594,11 @@
 ################################################################################
 
 class IdlArgument(TypedObject):
-    def __init__(self, idl_name, node=None):
+    def __init__(self, node=None):
         self.extended_attributes = {}
         self.idl_type = None
         self.is_optional = False  # syntax: (optional T)
         self.is_variadic = False  # syntax: (T...)
-        self.idl_name = idl_name
         self.default_value = None
 
         if not node:
@@ -646,7 +613,7 @@
             if child_class == 'Type':
                 self.idl_type = type_node_to_type(child)
             elif child_class == 'ExtAttributes':
-                self.extended_attributes = ext_attributes_node_to_extended_attributes(idl_name, child)
+                self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
             elif child_class == 'Argument':
                 child_name = child.GetName()
                 if child_name != '...':
@@ -657,27 +624,18 @@
             else:
                 raise ValueError('Unrecognized node class: %s' % child_class)
 
-    def __getstate__(self):
-        # FIXME: Return a picklable object which has enough information to
-        # unpickle.
-        return {}
-
-    def __setstate__(self, state):
-        pass
-
     def accept(self, visitor):
         visitor.visit_argument(self)
 
 
-def arguments_node_to_arguments(idl_name, node):
+def arguments_node_to_arguments(node):
     # [Constructor] and [CustomConstructor] without arguments (the bare form)
     # have None instead of an arguments node, but have the same meaning as using
     # an empty argument list, [Constructor()], so special-case this.
     # http://www.w3.org/TR/WebIDL/#Constructor
     if node is None:
         return []
-    return [IdlArgument(idl_name, argument_node)
-            for argument_node in node.GetChildren()]
+    return [IdlArgument(argument_node) for argument_node in node.GetChildren()]
 
 
 ################################################################################
@@ -685,7 +643,7 @@
 ################################################################################
 
 class IdlSerializer(object):
-    def __init__(self, idl_name, node):
+    def __init__(self, node):
         self.attribute_name = node.GetProperty('ATTRIBUTE')
         self.attribute_names = None
         self.operation = None
@@ -695,12 +653,11 @@
         self.is_inherit = False
         self.is_list = False
         self.is_map = False
-        self.idl_name = idl_name
 
         for child in node.GetChildren():
             child_class = child.GetClass()
             if child_class == 'Operation':
-                self.operation = IdlOperation(idl_name, child)
+                self.operation = IdlOperation(child)
             elif child_class == 'List':
                 self.is_list = True
                 self.is_getter = bool(child.GetProperty('GETTER'))
@@ -712,7 +669,7 @@
                 self.is_inherit = bool(child.GetProperty('INHERIT'))
                 self.attributes = child.GetProperty('ATTRIBUTES')
             elif child_class == 'ExtAttributes':
-                self.extended_attributes = ext_attributes_node_to_extended_attributes(idl_name, child)
+                self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
             else:
                 raise ValueError('Unrecognized node class: %s' % child_class)
 
@@ -722,22 +679,21 @@
 ################################################################################
 
 class IdlStringifier(object):
-    def __init__(self, idl_name, node):
+    def __init__(self, node):
         self.attribute = None
         self.operation = None
         self.extended_attributes = {}
-        self.idl_name = idl_name
 
         for child in node.GetChildren():
             child_class = child.GetClass()
             if child_class == 'Attribute':
-                self.attribute = IdlAttribute(idl_name, child)
+                self.attribute = IdlAttribute(child)
             elif child_class == 'Operation':
-                operation = IdlOperation(idl_name, child)
+                operation = IdlOperation(child)
                 if operation.name:
                     self.operation = operation
             elif child_class == 'ExtAttributes':
-                self.extended_attributes = ext_attributes_node_to_extended_attributes(idl_name, child)
+                self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
             else:
                 raise ValueError('Unrecognized node class: %s' % child_class)
 
@@ -753,14 +709,14 @@
 ################################################################################
 
 class IdlIterableOrMaplikeOrSetlike(TypedObject):
-    def __init__(self, idl_name, node):
+    def __init__(self, node):
         self.extended_attributes = {}
         self.type_children = []
 
         for child in node.GetChildren():
             child_class = child.GetClass()
             if child_class == 'ExtAttributes':
-                self.extended_attributes = ext_attributes_node_to_extended_attributes(idl_name, child)
+                self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
             elif child_class == 'Type':
                 self.type_children.append(child)
             else:
@@ -770,8 +726,8 @@
 class IdlIterable(IdlIterableOrMaplikeOrSetlike):
     idl_type_attributes = ('key_type', 'value_type')
 
-    def __init__(self, idl_name, node):
-        super(IdlIterable, self).__init__(idl_name, node)
+    def __init__(self, node):
+        super(IdlIterable, self).__init__(node)
 
         if len(self.type_children) == 1:
             self.key_type = None
@@ -790,8 +746,8 @@
 class IdlMaplike(IdlIterableOrMaplikeOrSetlike):
     idl_type_attributes = ('key_type', 'value_type')
 
-    def __init__(self, idl_name, node):
-        super(IdlMaplike, self).__init__(idl_name, node)
+    def __init__(self, node):
+        super(IdlMaplike, self).__init__(node)
 
         self.is_read_only = bool(node.GetProperty('READONLY'))
 
@@ -809,8 +765,8 @@
 class IdlSetlike(IdlIterableOrMaplikeOrSetlike):
     idl_type_attributes = ('value_type',)
 
-    def __init__(self, idl_name, node):
-        super(IdlSetlike, self).__init__(idl_name, node)
+    def __init__(self, node):
+        super(IdlSetlike, self).__init__(node)
 
         self.is_read_only = bool(node.GetProperty('READONLY'))
 
@@ -833,6 +789,9 @@
         self.left_interface = node.GetName()
         self.right_interface = node.GetProperty('REFERENCE')
 
+    def accept(self, visitor):
+        visitor.visit_implement(self)
+
 
 ################################################################################
 # Extended attributes
@@ -849,7 +808,7 @@
         self.runtime_enabled = runtime_enabled
 
 
-def ext_attributes_node_to_extended_attributes(idl_name, node):
+def ext_attributes_node_to_extended_attributes(node):
     """
     Returns:
       Dictionary of {ExtAttributeName: ExtAttributeValue}.
@@ -860,7 +819,6 @@
         possible signatures of the custom constructor.
       NamedConstructor: value is a Call node, corresponding to the single
         signature of the named constructor.
-      SetWrapperReferenceTo: value is an Arguments node.
     """
     # Primarily just make a dictionary from the children.
     # The only complexity is handling various types of constructors:
@@ -899,15 +857,6 @@
             if child_class and child_class != 'Call':
                 raise ValueError('[NamedConstructor] only supports Call as child, but has child of class: %s' % child_class)
             extended_attributes[name] = child
-        elif name == 'SetWrapperReferenceTo':
-            if not child:
-                raise ValueError('[SetWrapperReferenceTo] requires a child, but has none.')
-            children = child.GetChildren()
-            if len(children) != 1:
-                raise ValueError('[SetWrapperReferenceTo] supports only one child.')
-            if child_class != 'Arguments':
-                raise ValueError('[SetWrapperReferenceTo] only supports Arguments as child, but has child of class: %s' % child_class)
-            extended_attributes[name] = IdlArgument(idl_name, children[0])
         elif name == 'Exposed':
             if child_class and child_class != 'Arguments':
                 raise ValueError('[Exposed] only supports Arguments as child, but has child of class: %s' % child_class)
@@ -915,7 +864,7 @@
             if child_class == 'Arguments':
                 exposures = [Exposure(exposed=str(arg.idl_type),
                                       runtime_enabled=arg.name)
-                             for arg in arguments_node_to_arguments('*', child)]
+                             for arg in arguments_node_to_arguments(child)]
             else:
                 value = extended_attribute_node.GetProperty('VALUE')
                 if type(value) is str:
@@ -939,7 +888,7 @@
     return extended_attributes
 
 
-def extended_attributes_to_constructors(idl_name, extended_attributes):
+def extended_attributes_to_constructors(extended_attributes):
     """Returns constructors and custom_constructors (lists of IdlOperations).
 
     Auxiliary function for IdlInterface.__init__.
@@ -947,12 +896,12 @@
 
     constructor_list = extended_attributes.get('Constructors', [])
     constructors = [
-        IdlOperation.constructor_from_arguments_node('Constructor', idl_name, arguments_node)
+        IdlOperation.constructor_from_arguments_node('Constructor', arguments_node)
         for arguments_node in constructor_list]
 
     custom_constructor_list = extended_attributes.get('CustomConstructors', [])
     custom_constructors = [
-        IdlOperation.constructor_from_arguments_node('CustomConstructor', idl_name, arguments_node)
+        IdlOperation.constructor_from_arguments_node('CustomConstructor', arguments_node)
         for arguments_node in custom_constructor_list]
 
     if 'NamedConstructor' in extended_attributes:
@@ -964,7 +913,7 @@
         if len(children) != 1:
             raise ValueError('NamedConstructor node expects 1 child, got %s.' % len(children))
         arguments_node = children[0]
-        named_constructor = IdlOperation.constructor_from_arguments_node('NamedConstructor', idl_name, arguments_node)
+        named_constructor = IdlOperation.constructor_from_arguments_node('NamedConstructor', arguments_node)
         # FIXME: should return named_constructor separately; appended for Perl
         constructors.append(named_constructor)
 
@@ -987,24 +936,17 @@
 
 def type_node_to_type(node):
     children = node.GetChildren()
-    if len(children) < 1 or len(children) > 2:
-        raise ValueError('Type node expects 1 or 2 children (type + optional array []), got %s (multi-dimensional arrays are not supported).' % len(children))
+    if len(children) != 1 and len(children) != 2:
+        raise ValueError('Type node expects 1 or 2 child(ren), got %d.' % len(children))
 
     base_type = type_node_inner_to_type(children[0])
+    if len(children) == 2:
+        extended_attributes = ext_attributes_node_to_extended_attributes(children[1])
+        base_type.set_extended_attributes(extended_attributes)
 
     if node.GetProperty('NULLABLE'):
         base_type = IdlNullableType(base_type)
 
-    if len(children) == 2:
-        array_node = children[1]
-        array_node_class = array_node.GetClass()
-        if array_node_class != 'Array':
-            raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class)
-        array_type = IdlArrayType(base_type)
-        if array_node.GetProperty('NULLABLE'):
-            return IdlNullableType(array_type)
-        return array_type
-
     return base_type
 
 
@@ -1013,31 +955,52 @@
     # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus
     # either a typedef shorthand (but not a Typedef declaration itself) or an
     # interface type. We do not distinguish these, and just use the type name.
-    if node_class in ['PrimitiveType', 'Typeref']:
+    if node_class in ['PrimitiveType', 'StringType', 'Typeref']:
         # unrestricted syntax: unrestricted double | unrestricted float
         is_unrestricted = bool(node.GetProperty('UNRESTRICTED'))
         return IdlType(node.GetName(), is_unrestricted=is_unrestricted)
     elif node_class == 'Any':
         return IdlType('any')
-    elif node_class == 'Sequence':
+    elif node_class in ['Sequence', 'FrozenArray']:
         return sequence_node_to_type(node)
     elif node_class == 'UnionType':
         return union_type_node_to_idl_union_type(node)
     elif node_class == 'Promise':
         return IdlType('Promise')
+    elif node_class == 'Record':
+        return record_node_to_type(node)
     raise ValueError('Unrecognized node class: %s' % node_class)
 
 
+def record_node_to_type(node):
+    children = node.GetChildren()
+    if len(children) != 2:
+        raise ValueError('record<K,V> node expects exactly 2 children, got %d' % (len(children)))
+    key_child = children[0]
+    value_child = children[1]
+    if key_child.GetClass() != 'StringType':
+        raise ValueError('Keys in record<K,V> nodes must be string types.')
+    if value_child.GetClass() != 'Type':
+        raise ValueError('Unrecognized node class for record<K,V> value: %s' % value_child.GetClass())
+    return IdlRecordType(IdlType(key_child.GetName()), type_node_to_type(value_child))
+
+
 def sequence_node_to_type(node):
     children = node.GetChildren()
+    class_name = node.GetClass()
     if len(children) != 1:
-        raise ValueError('Sequence node expects exactly 1 child, got %s' % len(children))
+        raise ValueError('%s node expects exactly 1 child, got %s' % (class_name, len(children)))
     sequence_child = children[0]
     sequence_child_class = sequence_child.GetClass()
     if sequence_child_class != 'Type':
         raise ValueError('Unrecognized node class: %s' % sequence_child_class)
     element_type = type_node_to_type(sequence_child)
-    sequence_type = IdlSequenceType(element_type)
+    if class_name == 'Sequence':
+        sequence_type = IdlSequenceType(element_type)
+    elif class_name == 'FrozenArray':
+        sequence_type = IdlFrozenArrayType(element_type)
+    else:
+        raise ValueError('Unexpected node: %s' % class_name)
     if node.GetProperty('NULLABLE'):
         return IdlNullableType(sequence_type)
     return sequence_type
@@ -1082,6 +1045,12 @@
     def visit_dictionary_member(self, member):
         self.visit_typed_object(member)
 
+    def visit_enumeration(self, enumeration):
+        pass
+
+    def visit_implement(self, implement):
+        pass
+
     def visit_interface(self, interface):
         pass
 
diff --git a/bindings/scripts/idl_definitions_test.py b/bindings/scripts/idl_definitions_test.py
new file mode 100644
index 0000000..78dd732
--- /dev/null
+++ b/bindings/scripts/idl_definitions_test.py
@@ -0,0 +1,21 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# pylint: disable=import-error,print-statement,relative-import
+
+"""Unit tests for idl_definitions.py."""
+
+import unittest
+
+from idl_definitions import IdlAttribute
+
+
+class IdlAttributeTest(unittest.TestCase):
+
+    def test_no_params(self):
+        try:
+            IdlAttribute()
+        except Exception as exception:  # pylint: disable=broad-except
+            self.fail('Creating an IdlAttribute with no parameters raised'
+                      'an exception: {}.'.format(exception))
diff --git a/bindings/scripts/idl_reader.py b/bindings/scripts/idl_reader.py
index f406c00..2bd219d 100644
--- a/bindings/scripts/idl_reader.py
+++ b/bindings/scripts/idl_reader.py
@@ -40,6 +40,7 @@
 from idl_validator import EXTENDED_ATTRIBUTES_RELATIVE_PATH, IDLInvalidExtendedAttributeError, IDLExtendedAttributeValidator
 from interface_dependency_resolver import InterfaceDependencyResolver
 from utilities import idl_filename_to_component
+from utilities import to_snake_case
 
 
 def validate_blink_idl_definitions(idl_filename, idl_file_basename,
@@ -47,7 +48,7 @@
     """Validate file contents with filename convention.
 
        The Blink IDL conventions are:
-       - If an IDL file defines an interface, a dictionary, or an exception,
+       - If an IDL file defines an interface or a dictionary,
          the IDL file must contain exactly one definition. The definition
          name must agree with the file's basename, unless it is a partial
          definition. (e.g., 'partial interface Foo' can be in FooBar.idl).
@@ -63,12 +64,17 @@
             'Expected exactly 1 definition in file {0}, but found {1}'
             .format(idl_filename, number_of_targets))
     if number_of_targets == 0:
-        if not (definitions.enumerations or definitions.typedefs):
+        number_of_definitions = (
+            len(definitions.enumerations) + len(definitions.typedefs) +
+            len(definitions.callback_functions))
+        if number_of_definitions == 0:
             raise Exception(
                 'No definition found in %s' % idl_filename)
         return
     target = targets[0]
-    if not target.is_partial and target.name != idl_file_basename:
+    if target.is_partial:
+        return
+    if target.name != idl_file_basename and to_snake_case(target.name) != idl_file_basename:
         raise Exception(
             'Definition name "{0}" disagrees with IDL file basename "{1}".'
             .format(target.name, idl_file_basename))
@@ -78,6 +84,7 @@
     # FIXMEDART: Added multi_interface argument and property for IdlReader class.
     def __init__(self, interfaces_info=None, outputdir='', multi_interface=False):
         self.multi_interface = multi_interface
+
         self.extended_attribute_validator = IDLExtendedAttributeValidator()
         self.interfaces_info = interfaces_info
 
@@ -113,7 +120,7 @@
         if not ast:
             raise Exception('Failed to parse %s' % idl_filename)
         idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename))
-        definitions = IdlDefinitions(idl_file_basename, ast)
+        definitions = IdlDefinitions(ast)
 
         # FIXMEDART: Added multi_interface.
         if not self.multi_interface:
diff --git a/bindings/scripts/idl_types.py b/bindings/scripts/idl_types.py
index 5d776a7..05298fe 100644
--- a/bindings/scripts/idl_types.py
+++ b/bindings/scripts/idl_types.py
@@ -8,8 +8,8 @@
  IdlType
  IdlUnionType
  IdlArrayOrSequenceType
-  IdlArrayType
   IdlSequenceType
+  IdlFrozenArrayType
  IdlNullableType
 
 IdlTypes are picklable because we store them in interfaces_info.
@@ -138,17 +138,18 @@
     # FIXME: incorporate Nullable, etc.
     # to support types like short?[] vs. short[]?, instead of treating these
     # as orthogonal properties (via flags).
-    callback_functions = set(STANDARD_CALLBACK_FUNCTIONS)
+    callback_functions = {}
     callback_interfaces = set()
     dictionaries = set()
     enums = {}  # name -> values
 
-    def __init__(self, base_type, is_unrestricted=False):
+    def __init__(self, base_type, is_unrestricted=False, extended_attributes=None):
         super(IdlType, self).__init__()
         if is_unrestricted:
             self.base_type = 'unrestricted %s' % base_type
         else:
             self.base_type = base_type
+        self.extended_attributes = extended_attributes
 
     def __str__(self):
         return self.base_type
@@ -156,18 +157,34 @@
     def __getstate__(self):
         return {
             'base_type': self.base_type,
+            'extended_attributes': self.extended_attributes,
         }
 
     def __setstate__(self, state):
         self.base_type = state['base_type']
+        self.extended_attributes = state['extended_attributes']
+
+    def set_extended_attributes(self, extended_attributes):
+        self.extended_attributes = extended_attributes
 
     @property
     def is_basic_type(self):
         return self.base_type in BASIC_TYPES
 
     @property
-    def is_callback_function(self):
-        return self.base_type in IdlType.callback_functions
+    def is_callback_function(self):  # pylint: disable=C0103
+        return self.base_type in IdlType.callback_functions or self.base_type in STANDARD_CALLBACK_FUNCTIONS
+
+    @property
+    def is_custom_callback_function(self):
+        # Treat standard callback functions as custom as they aren't generated.
+        if self.base_type in STANDARD_CALLBACK_FUNCTIONS:
+            return True
+        entry = IdlType.callback_functions.get(self.base_type)
+        callback_function = entry.get('callback_function')
+        if not callback_function:
+            return False
+        return 'Custom' in callback_function.extended_attributes
 
     @property
     def is_callback_interface(self):
@@ -196,6 +213,10 @@
         return self.base_type in INTEGER_TYPES
 
     @property
+    def is_void(self):
+        return self.base_type == 'void'
+
+    @property
     def is_numeric_type(self):
         return self.base_type in NUMERIC_TYPES
 
@@ -208,7 +229,7 @@
         # Anything that is not another type is an interface type.
         # http://www.w3.org/TR/WebIDL/#idl-types
         # http://www.w3.org/TR/WebIDL/#idl-interface
-        # In C++ these are RefPtr or PassRefPtr types.
+        # In C++ these are RefPtr types.
         return not(self.is_basic_type or
                    self.is_callback_function or
                    self.is_dictionary or
@@ -282,13 +303,54 @@
         self.member_types = state['member_types']
 
     @property
+    def flattened_member_types(self):
+        """Returns the set of the union's flattened member types.
+
+        https://heycam.github.io/webidl/#dfn-flattened-union-member-types
+        """
+        # We cannot use a set directly because each member is an IdlTypeBase-derived class, and
+        # comparing two objects of the same type is not the same as comparing their names. In
+        # other words:
+        #   x = IdlType('ByteString')
+        #   y = IdlType('ByteString')
+        #   x == y  # False
+        #   x.name == y.name  # True
+        # |flattened_members|'s keys are type names, the values are type |objects.
+        # We assume we can use two IDL objects of the same type interchangeably.
+        flattened_members = {}
+        for member in self.member_types:
+            if member.is_nullable:
+                member = member.inner_type
+            if member.is_union_type:
+                for inner_member in member.flattened_member_types:
+                    flattened_members[inner_member.name] = inner_member
+            else:
+                flattened_members[member.name] = member
+        return set(flattened_members.values())
+
+    @property
+    def number_of_nullable_member_types(self):
+        """Returns the union's number of nullable types.
+
+        http://heycam.github.io/webidl/#dfn-number-of-nullable-member-types
+        """
+        count = 0
+        for member in self.member_types:
+            if member.is_nullable:
+                count += 1
+                member = member.inner_type
+            if member.is_union_type:
+                count += member.number_of_nullable_member_types
+        return count
+
+    @property
     def is_union_type(self):
         return True
 
     def single_matching_member_type(self, predicate):
-        matching_types = filter(predicate, self.member_types)
+        matching_types = filter(predicate, self.flattened_member_types)
         if len(matching_types) > 1:
-            raise "%s is ambigious." % self.name
+            raise ValueError('%s is ambiguous.' % self.name)
         return matching_types[0] if matching_types else None
 
     @property
@@ -322,7 +384,7 @@
 
     def resolve_typedefs(self, typedefs):
         self.member_types = [
-            typedefs.get(member_type, member_type)
+            member_type.resolve_typedefs(typedefs)
             for member_type in self.member_types]
         return self
 
@@ -334,11 +396,12 @@
 
 
 ################################################################################
-# IdlArrayOrSequenceType, IdlArrayType, IdlSequenceType
+# IdlArrayOrSequenceType, IdlSequenceType, IdlFrozenArrayType
 ################################################################################
 
+# TODO(bashi): Rename this like "IdlArrayTypeBase" or something.
 class IdlArrayOrSequenceType(IdlTypeBase):
-    """Base class for IdlArrayType and IdlSequenceType."""
+    """Base class for array-like types."""
 
     def __init__(self, element_type):
         super(IdlArrayOrSequenceType, self).__init__()
@@ -361,6 +424,14 @@
         return True
 
     @property
+    def is_sequence_type(self):
+        return False
+
+    @property
+    def is_frozen_array(self):
+        return False
+
+    @property
     def enum_values(self):
         return self.element_type.enum_values
 
@@ -374,18 +445,6 @@
             yield idl_type
 
 
-class IdlArrayType(IdlArrayOrSequenceType):
-    def __init__(self, element_type):
-        super(IdlArrayType, self).__init__(element_type)
-
-    def __str__(self):
-        return '%s[]' % self.element_type
-
-    @property
-    def name(self):
-        return self.element_type.name + 'Array'
-
-
 class IdlSequenceType(IdlArrayOrSequenceType):
     def __init__(self, element_type):
         super(IdlSequenceType, self).__init__(element_type)
@@ -397,6 +456,70 @@
     def name(self):
         return self.element_type.name + 'Sequence'
 
+    @property
+    def is_sequence_type(self):
+        return True
+
+
+class IdlFrozenArrayType(IdlArrayOrSequenceType):
+    def __init__(self, element_type):
+        super(IdlFrozenArrayType, self).__init__(element_type)
+
+    def __str__(self):
+        return 'FrozenArray<%s>' % self.element_type
+
+    @property
+    def name(self):
+        return self.element_type.name + 'Array'
+
+    @property
+    def is_frozen_array(self):
+        return True
+
+
+################################################################################
+# IdlRecordType
+################################################################################
+
+class IdlRecordType(IdlTypeBase):
+    def __init__(self, key_type, value_type):
+        super(IdlRecordType, self).__init__()
+        self.key_type = key_type
+        self.value_type = value_type
+
+    def __str__(self):
+        return 'record<%s, %s>' % (self.key_type, self.value_type)
+
+    def __getstate__(self):
+        return {
+            'key_type': self.key_type,
+            'value_type': self.value_type,
+        }
+
+    def __setstate__(self, state):
+        self.key_type = state['key_type']
+        self.value_type = state['value_type']
+
+    def idl_types(self):
+        yield self
+        for idl_type in self.key_type.idl_types():
+            yield idl_type
+        for idl_type in self.value_type.idl_types():
+            yield idl_type
+
+    def resolve_typedefs(self, typedefs):
+        self.key_type = self.key_type.resolve_typedefs(typedefs)
+        self.value_type = self.value_type.resolve_typedefs(typedefs)
+        return self
+
+    @property
+    def is_record_type(self):
+        return True
+
+    @property
+    def name(self):
+        return self.key_type.name + self.value_type.name + 'Record'
+
 
 ################################################################################
 # IdlNullableType
diff --git a/bindings/scripts/idl_types_test.py b/bindings/scripts/idl_types_test.py
new file mode 100644
index 0000000..e360d5a
--- /dev/null
+++ b/bindings/scripts/idl_types_test.py
@@ -0,0 +1,174 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# pylint: disable=import-error,print-statement,relative-import
+
+"""Unit tests for idl_types.py."""
+
+import unittest
+
+from idl_types import IdlNullableType
+from idl_types import IdlRecordType
+from idl_types import IdlSequenceType
+from idl_types import IdlType
+from idl_types import IdlUnionType
+
+
+class IdlTypeTest(unittest.TestCase):
+
+    def test_is_void(self):
+        idl_type = IdlType('void')
+        self.assertTrue(idl_type.is_void)
+        idl_type = IdlType('somethingElse')
+        self.assertFalse(idl_type.is_void)
+
+
+class IdlRecordTypeTest(unittest.TestCase):
+
+    def test_idl_types(self):
+        idl_type = IdlRecordType(IdlType('USVString'), IdlType('long'))
+        idl_types = list(idl_type.idl_types())
+        self.assertEqual(len(idl_types), 3)
+        self.assertIs(idl_types[0], idl_type)
+        self.assertEqual(idl_types[1].name, 'USVString')
+        self.assertEqual(idl_types[2].name, 'Long')
+        self.assertListEqual(list(idl_type.idl_types()),
+                             [idl_type, idl_type.key_type, idl_type.value_type])
+
+        idl_type = IdlRecordType(IdlType('DOMString'), IdlSequenceType(IdlType('unrestricted float')))
+        idl_types = list(idl_type.idl_types())
+        self.assertEqual(len(idl_types), 4)
+        self.assertIs(idl_types[0], idl_type)
+        self.assertEqual(idl_types[1].name, 'String')
+        self.assertEqual(idl_types[2].name, 'UnrestrictedFloatSequence')
+        self.assertEqual(idl_types[3].name, 'UnrestrictedFloat')
+        self.assertListEqual(list(idl_type.idl_types()),
+                             [idl_type, idl_type.key_type, idl_type.value_type, idl_type.value_type.element_type])
+
+        idl_type = IdlRecordType(IdlType('ByteString'),
+                                 IdlRecordType(IdlType('DOMString'), IdlType('octet')))
+        idl_types = list(idl_type.idl_types())
+        self.assertEqual(len(idl_types), 5)
+        self.assertIs(idl_types[0], idl_type)
+        self.assertEqual(idl_types[1].name, 'ByteString')
+        self.assertEqual(idl_types[2].name, 'StringOctetRecord')
+        self.assertEqual(idl_types[3].name, 'String')
+        self.assertEqual(idl_types[4].name, 'Octet')
+        self.assertListEqual(list(idl_type.idl_types()),
+                             [idl_type, idl_type.key_type, idl_type.value_type, idl_type.value_type.key_type,
+                              idl_type.value_type.value_type])
+
+    def test_is_record(self):
+        idl_type = IdlType('USVString')
+        self.assertFalse(idl_type.is_record_type)
+        idl_type = IdlSequenceType(IdlRecordType(IdlType('DOMString'), IdlType('byte')))
+        self.assertFalse(idl_type.is_record_type)
+        idl_type = IdlRecordType(IdlType('USVString'), IdlType('long'))
+        self.assertTrue(idl_type.is_record_type)
+        idl_type = IdlRecordType(IdlType('USVString'), IdlSequenceType(IdlType('boolean')))
+        self.assertTrue(idl_type.is_record_type)
+
+    def test_name(self):
+        idl_type = IdlRecordType(IdlType('ByteString'), IdlType('octet'))
+        self.assertEqual(idl_type.name, 'ByteStringOctetRecord')
+        idl_type = IdlRecordType(IdlType('USVString'), IdlSequenceType(IdlType('double')))
+        self.assertEqual(idl_type.name, 'USVStringDoubleSequenceRecord')
+        idl_type = IdlRecordType(IdlType('DOMString'),
+                                 IdlRecordType(IdlType('ByteString'),
+                                               IdlSequenceType(IdlType('unsigned short'))))
+        self.assertEqual(idl_type.name, 'StringByteStringUnsignedShortSequenceRecordRecord')
+
+
+class IdlUnionTypeTest(unittest.TestCase):
+
+    def test_flattened_member_types(self):
+        # We are only testing the algorithm here, so we do create some ambiguous union types.
+
+        def compare_flattened_members(actual, expected):
+            """Compare a set of IDL types by name, as the objects are different"""
+            actual_names = set([member.name for member in actual])
+            expected_names = set([member.name for member in expected])
+            self.assertEqual(actual_names, expected_names)
+
+        idl_type = IdlUnionType([IdlType('long'), IdlType('SomeInterface')])
+        compare_flattened_members(
+            idl_type.flattened_member_types,
+            set([IdlType('long'), IdlType('SomeInterface')]))
+
+        idl_type = IdlUnionType([IdlUnionType([IdlType('ByteString'), IdlType('float')]),
+                                 IdlType('boolean')])
+        compare_flattened_members(
+            idl_type.flattened_member_types,
+            set([IdlType('float'), IdlType('boolean'), IdlType('ByteString')]))
+
+        idl_type = IdlUnionType([IdlUnionType([IdlType('ByteString'), IdlType('DOMString')]),
+                                 IdlType('DOMString')])
+        compare_flattened_members(
+            idl_type.flattened_member_types,
+            set([IdlType('DOMString'), IdlType('ByteString')]))
+
+        idl_type = IdlUnionType(
+            [IdlNullableType(IdlType('ByteString')), IdlType('byte')])
+        compare_flattened_members(
+            idl_type.flattened_member_types,
+            set([IdlType('ByteString'), IdlType('byte')]))
+
+        idl_type = IdlUnionType(
+            [IdlNullableType(IdlType('ByteString')), IdlType('byte'),
+             IdlUnionType([IdlType('ByteString'), IdlType('float')])])
+        self.assertEqual(len(idl_type.flattened_member_types), 3)
+        compare_flattened_members(
+            idl_type.flattened_member_types,
+            set([IdlType('ByteString'), IdlType('byte'), IdlType('float')]))
+
+        # From the example in the spec: "the flattened member types of the union type (Node or (sequence<long> or Event) or
+        # (XMLHttpRequest or DOMString)? or sequence<(sequence<double> or NodeList)>) are the six types Node, sequence<long>,
+        # Event, XMLHttpRequest, DOMString and sequence<(sequence<double> or NodeList)>"
+        idl_type = IdlUnionType(
+            [IdlType('Node'),
+             IdlUnionType([IdlSequenceType(IdlType('long')), IdlType('Event')]),
+             IdlNullableType(IdlUnionType([IdlType('XMLHttpRequest'), IdlType('DOMString')])),
+             IdlSequenceType(IdlUnionType([IdlSequenceType(IdlType('double')), IdlType('NodeList')]))])
+        self.assertEqual(len(idl_type.flattened_member_types), 6)
+        compare_flattened_members(
+            idl_type.flattened_member_types,
+            set([IdlType('Node'), IdlSequenceType(IdlType('long')), IdlType('Event'),
+                 IdlType('XMLHttpRequest'), IdlType('DOMString'),
+                 IdlSequenceType(IdlUnionType([IdlSequenceType(IdlType('double')), IdlType('NodeList')]))]))
+
+    def test_resolve_typedefs(self):
+        # This is a simplification of the typedef mechanism to avoid having to
+        # use idl_definitions and use actual nodes from //tools/idl_parser.
+        typedefs = {
+            'Foo': IdlType('unsigned short'),
+            'MyBooleanType': IdlType('boolean'),
+            'SomeInterfaceT': IdlType('MyInterface'),
+        }
+
+        # (long long or MyBooleanType)
+        union = IdlUnionType([IdlType('long long'), IdlType('MyBooleanType')]).resolve_typedefs(typedefs)
+        self.assertEqual(union.name, 'LongLongOrBoolean')
+        self.assertEqual(union.member_types[0].name, 'LongLong')
+        self.assertEqual(union.member_types[1].name, 'Boolean')
+
+        # (Foo or SomeInterfaceT)
+        union = IdlUnionType([IdlType('Foo'), IdlType('SomeInterfaceT')]).resolve_typedefs(typedefs)
+        self.assertEqual(union.name, 'UnsignedShortOrMyInterface')
+        self.assertEqual(union.member_types[0].name, 'UnsignedShort')
+        self.assertEqual(union.member_types[1].name, 'MyInterface')
+
+        # (Foo or sequence<(MyBooleanType or double)>)
+        union = IdlUnionType([
+            IdlType('Foo'),
+            IdlSequenceType(IdlUnionType([IdlType('MyBooleanType'),
+                                          IdlType('double')]))]).resolve_typedefs(typedefs)
+        self.assertEqual(union.name, 'UnsignedShortOrBooleanOrDoubleSequence')
+        self.assertEqual(union.member_types[0].name, 'UnsignedShort')
+        self.assertEqual(union.member_types[1].name, 'BooleanOrDoubleSequence')
+        self.assertEqual(union.member_types[1].element_type.name, 'BooleanOrDouble')
+        self.assertEqual(union.member_types[1].element_type.member_types[0].name,
+                         'Boolean')
+        self.assertEqual(union.member_types[1].element_type.member_types[1].name,
+                         'Double')
+        self.assertEqual(2, len(union.flattened_member_types))
diff --git a/bindings/scripts/interface_dependency_resolver.py b/bindings/scripts/interface_dependency_resolver.py
index 2fa6409..239f11e 100644
--- a/bindings/scripts/interface_dependency_resolver.py
+++ b/bindings/scripts/interface_dependency_resolver.py
@@ -45,7 +45,9 @@
 # which changes the semantics and yields different code than the same extended
 # attribute on the main interface.
 DEPENDENCY_EXTENDED_ATTRIBUTES = frozenset([
+    'OriginTrialEnabled',
     'RuntimeEnabled',
+    'SecureContext',
 ])
 
 
@@ -160,10 +162,9 @@
         dependency_component = idl_filename_to_component(dependency_idl_filename)
 
         dependency_interface = next(dependency_definitions.interfaces.itervalues())
-        dependency_interface_basename, _ = os.path.splitext(os.path.basename(dependency_idl_filename))
 
         transfer_extended_attributes(dependency_interface,
-                                     dependency_interface_basename)
+                                     dependency_idl_filename)
 
         # We need to use different checkdeps here for partial interface and
         # inheritance.
@@ -201,8 +202,8 @@
             # Because partial interface needs the original interface's
             # cpp class to obtain partial interface's cpp class.
             # e.g.. V8WindowPartial.cpp:
-            #   DOMWindow* impl = V8Window::toImpl(holder);
-            #   RawPtr<...> cppValue(DOMWindowQuota::webkitStorageInfo(impl));
+            #   DOMWindow* impl = V8Window::ToImpl(holder);
+            #   DOMWindowQuota* cppValue(DOMWindowQuota::webkitStorageInfo(impl));
             # TODO(tasak): remove ImplementedAs extended attributes
             # from all partial interfaces. Instead, rename all cpp/header
             # files correctly. ImplementedAs should not be allowed in
@@ -245,7 +246,7 @@
     return resolved_definitions
 
 
-def transfer_extended_attributes(dependency_interface, dependency_interface_basename):
+def transfer_extended_attributes(dependency_interface, dependency_idl_filename):
     """Transfer extended attributes from dependency interface onto members.
 
     Merging consists of storing certain interface-level data in extended
@@ -253,24 +254,29 @@
     interface post-merging).
 
     The data storing consists of:
-    * applying certain extended attributes from the dependency interface
-      to its members
+    * moving certain extended attributes from the dependency interface
+      to its members (deleting the extended attribute from the interface)
     * storing the C++ class of the implementation in an internal
       extended attribute of each member, [PartialInterfaceImplementedAs]
 
     No return: modifies dependency_interface in place.
     """
-    merged_extended_attributes = dict(
-        (key, value)
-        for key, value in dependency_interface.extended_attributes.iteritems()
-        if key in DEPENDENCY_EXTENDED_ATTRIBUTES)
+    merged_extended_attributes = {}
+    for key in DEPENDENCY_EXTENDED_ATTRIBUTES:
+        if key not in dependency_interface.extended_attributes:
+            continue
+
+        merged_extended_attributes[key] = dependency_interface.extended_attributes[key]
+        # Remove the merged attributes from the original dependency interface.
+        # This ensures that if other dependency interfaces are merged onto this
+        # one, its extended_attributes do not leak through
+        # (https://crbug.com/603782).
+        del dependency_interface.extended_attributes[key]
 
     # A partial interface's members are implemented as static member functions
     # in a separate C++ class. This class name is stored in
-    # [PartialInterfaceImplementedAs] which defaults to the basename of
-    # dependency IDL file.
-    # This class name can be overridden by [ImplementedAs] on the partial
-    # interface definition.
+    # [PartialInterfaceImplementedAs] which is copied from [ImplementedAs] on
+    # the partial interface definition.
     #
     # Note that implemented interfaces do *not* need [ImplementedAs], since
     # they are implemented on the C++ object |impl| itself, just like members of
@@ -288,11 +294,17 @@
     # for Blink class name and function name (or constant name), respectively.
     # Thus we do not want to copy this from the interface to the member, but
     # instead extract it and handle it separately.
-    if (dependency_interface.is_partial or
-        'LegacyTreatAsPartialInterface' in dependency_interface.extended_attributes):
+    if dependency_interface.is_partial:
+        if 'ImplementedAs' not in dependency_interface.extended_attributes:
+            raise ValueError('Partial interface in %s must have ImplementedAs.'
+                             % dependency_idl_filename)
+        merged_extended_attributes['PartialInterfaceImplementedAs'] = \
+            dependency_interface.extended_attributes.pop('ImplementedAs')
+    elif 'LegacyTreatAsPartialInterface' in \
+         dependency_interface.extended_attributes:
         merged_extended_attributes['PartialInterfaceImplementedAs'] = (
-            dependency_interface.extended_attributes.get(
-                'ImplementedAs', dependency_interface_basename))
+            dependency_interface.extended_attributes.pop(
+                'ImplementedAs', dependency_interface.name))
 
     def update_attributes(attributes, extras):
         for key, value in extras.items():
@@ -311,9 +323,9 @@
     """Inherits [Unforgeable] attributes and updates the arguments accordingly.
 
     For each interface in |resolved_definitions|, collects all [Unforgeable]
-    attributes in ancestor interfaces in the same component and adds them to
-    the interface.  'referenced_interfaces' and 'cpp_includes' in
-    |interfaces_info| are updated accordingly.
+    attributes in ancestor interfaces and adds them to the interface.
+    'referenced_interfaces' and 'cpp_includes' in |interfaces_info| are updated
+    accordingly.
     """
     def collect_unforgeable_attributes_in_ancestors(interface_name, component):
         if not interface_name:
@@ -321,7 +333,7 @@
             return [], [], set()
         interface = interfaces_info[interface_name]
         unforgeable_attributes, referenced_interfaces, cpp_includes = collect_unforgeable_attributes_in_ancestors(interface.get('parent'), component)
-        this_unforgeable = interface.get('unforgeable_attributes', {}).get(component, [])
+        this_unforgeable = interface.get('unforgeable_attributes', [])
         unforgeable_attributes.extend(this_unforgeable)
         this_referenced = [attr.idl_type.base_type for attr in this_unforgeable
                            if attr.idl_type.base_type in
diff --git a/bindings/scripts/overload_set_algorithm.py b/bindings/scripts/overload_set_algorithm.py
new file mode 100644
index 0000000..6425a84
--- /dev/null
+++ b/bindings/scripts/overload_set_algorithm.py
@@ -0,0 +1,130 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# coding=utf-8
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from collections import Counter
+import itertools
+from operator import itemgetter
+
+
+def sort_and_groupby(list_to_sort, key=None):
+    """Returns a generator of (key, list), sorting and grouping list by key."""
+    list_to_sort.sort(key=key)
+    return ((k, list(g)) for k, g in itertools.groupby(list_to_sort, key))
+
+
+def effective_overload_set(F):  # pylint: disable=invalid-name
+    """Returns the effective overload set of an overloaded function.
+
+    An effective overload set is the set of overloaded functions + signatures
+    (type list of arguments, with optional and variadic arguments included or
+    not), and is used in the overload resolution algorithm.
+
+    For example, given input [f1(optional long x), f2(DOMString s)], the output
+    is informally [f1(), f1(long), f2(DOMString)], and formally
+    [(f1, [], []), (f1, [long], [optional]), (f2, [DOMString], [required])].
+
+    Currently the optionality list is a list of |is_optional| booleans (True
+    means optional, False means required); to support variadics this needs to
+    be tri-valued as required, optional, or variadic.
+
+    Formally:
+    An effective overload set represents the allowable invocations for a
+    particular operation, constructor (specified with [Constructor] or
+    [NamedConstructor]), legacy caller or callback function.
+
+    An additional argument N (argument count) is needed when overloading
+    variadics, but we don't use that currently.
+
+    Spec: http://heycam.github.io/webidl/#dfn-effective-overload-set
+
+    Formally the input and output lists are sets, but methods are stored
+    internally as dicts, which can't be stored in a set because they are not
+    hashable, so we use lists instead.
+
+    Arguments:
+        F: list of overloads for a given callable name.
+        value_reader: an OverloadSetValueReader instance.
+
+    Returns:
+        S: list of tuples of the form (callable, type list, optionality list).
+    """
+    # Code closely follows the algorithm in the spec, for clarity and
+    # correctness, and hence is not very Pythonic.
+
+    # 1. Initialize S to ∅.
+    # (We use a list because we can't use a set, as noted above.)
+    S = []  # pylint: disable=invalid-name
+
+    # 2. Let F be a set with elements as follows, according to the kind of
+    # effective overload set:
+    # (Passed as argument, nothing to do.)
+
+    # 3. & 4. (maxarg, m) are only needed for variadics, not used.
+
+    # 5. For each operation, extended attribute or callback function X in F:
+    for X in F:  # X is the "callable". pylint: disable=invalid-name
+        arguments = X['arguments']  # pylint: disable=invalid-name
+        # 1. Let n be the number of arguments X is declared to take.
+        n = len(arguments)  # pylint: disable=invalid-name
+        # 2. Let t0..n−1 be a list of types, where ti is the type of X’s
+        # argument at index i.
+        # (“type list”)
+        t = tuple(argument['idl_type_object']  # pylint: disable=invalid-name
+                  for argument in arguments)
+        # 3. Let o0..n−1 be a list of optionality values, where oi is “variadic”
+        # if X’s argument at index i is a final, variadic argument, “optional”
+        # if the argument is optional, and “required” otherwise.
+        # (“optionality list”)
+        # (We’re just using a boolean for optional/variadic vs. required.)
+        o = tuple(argument['is_optional']  # pylint: disable=invalid-name
+                  or argument['is_variadic']
+                  for argument in arguments)
+        # 4. Add to S the tuple <X, t0..n−1, o0..n−1>.
+        S.append((X, t, o))
+        # 5. If X is declared to be variadic, then:
+        # (Not used, so not implemented.)
+        # 6. Initialize i to n−1.
+        i = n - 1
+        # 7. While i ≥ 0:
+        # Spec bug (fencepost error); should be “While i > 0:”
+        # https://www.w3.org/Bugs/Public/show_bug.cgi?id=25590
+        while i > 0:
+            # 1. If argument i of X is not optional, then break this loop.
+            if not o[i]:
+                break
+            # 2. Otherwise, add to S the tuple <X, t0..i−1, o0..i−1>.
+            S.append((X, t[:i], o[:i]))
+            # 3. Set i to i−1.
+            i = i - 1
+        # 8. If n > 0 and all arguments of X are optional, then add to S the
+        # tuple <X, (), ()> (where “()” represents the empty list).
+        if n > 0 and all(oi for oi in o):
+            S.append((X, (), ()))
+    # 6. The effective overload set is S.
+    return S
+
+
+def effective_overload_set_by_length(overloads):
+    def type_list_length(entry):
+        # Entries in the effective overload set are 3-tuples:
+        # (callable, type list, optionality list)
+        return len(entry[1])
+
+    effective_overloads = effective_overload_set(overloads)
+    return list(sort_and_groupby(effective_overloads, type_list_length))
+
+
+def method_overloads_by_name(methods):
+    """Returns generator of overloaded methods by name: [name, [method]]"""
+    # Filter to only methods that are actually overloaded
+    method_counts = Counter(method['name'] for method in methods)
+    overloaded_method_names = set(name
+                                  for name, count in method_counts.iteritems()
+                                  if count > 1)
+    overloaded_methods = [method for method in methods
+                          if method['name'] in overloaded_method_names]
+
+    # Group by name (generally will be defined together, but not necessarily)
+    return sort_and_groupby(overloaded_methods, itemgetter('name'))
diff --git a/bindings/scripts/overload_set_algorithm_test.py b/bindings/scripts/overload_set_algorithm_test.py
new file mode 100644
index 0000000..389a9ed
--- /dev/null
+++ b/bindings/scripts/overload_set_algorithm_test.py
@@ -0,0 +1,163 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# pylint: disable=import-error,print-statement,relative-import,protected-access
+
+"""Unit tests for overload_set_algorithm.py."""
+
+import unittest
+from overload_set_algorithm import effective_overload_set
+
+
+class EffectiveOverloadSetTest(unittest.TestCase):
+    def test_example_in_comments(self):
+        operation_list = [
+            {'arguments': [{'idl_type_object': 'long',  # f1(optional long x)
+                            'is_optional': True,
+                            'is_variadic': False}]},
+            {'arguments': [{'idl_type_object': 'DOMString',  # f2(DOMString s)
+                            'is_optional': False,
+                            'is_variadic': False}]}]
+
+        overload_set = [
+            ({'arguments': [{'idl_type_object': 'long',  # f1(long)
+                             'is_optional': True,
+                             'is_variadic': False}]},
+             ('long',),
+             (True,)),
+            ({'arguments': [{'idl_type_object': 'long',  # f1()
+                             'is_optional': True,
+                             'is_variadic': False}]},
+             (),
+             ()),
+            ({'arguments': [{'idl_type_object': 'DOMString',  # f2(DOMString)
+                             'is_optional': False,
+                             'is_variadic': False}]},
+             ('DOMString',),
+             (False,))]
+
+        self.assertEqual(effective_overload_set(operation_list), overload_set)
+
+    def test_example_in_spec(self):
+        """Tests the example provided in Web IDL spec:
+           https://heycam.github.io/webidl/#dfn-effective-overload-set,
+           look for example right after the algorithm.
+
+           The output differs from spec because we don't implement the part
+           of the algorithm that handles variadic arguments."""
+        operation_list = [
+            # f1: f(DOMString a)
+            {'arguments': [{'idl_type_object': 'DOMString',
+                            'is_optional': False,
+                            'is_variadic': False}]},
+            # f2: f(Node a, DOMString b, double... c)
+            {'arguments': [{'idl_type_object': 'Node',
+                            'is_optional': False,
+                            'is_variadic': False},
+                           {'idl_type_object': 'DOMString',
+                            'is_optional': False,
+                            'is_variadic': False},
+                           {'idl_type_object': 'double',
+                            'is_optional': False,
+                            'is_variadic': True}]},
+            # f3: f()
+            {'arguments': []},
+            # f4: f(Event a, DOMString b, optional DOMString c, double... d)
+            {'arguments': [{'idl_type_object': 'Event',
+                            'is_optional': False,
+                            'is_variadic': False},
+                           {'idl_type_object': 'DOMString',
+                            'is_optional': False,
+                            'is_variadic': False},
+                           {'idl_type_object': 'DOMString',
+                            'is_optional': True,
+                            'is_variadic': False},
+                           {'idl_type_object': 'double',
+                            'is_optional': False,
+                            'is_variadic': True}]}]
+        overload_set = [
+            # <f1, (DOMString), (required)>
+            ({'arguments': [{'idl_type_object': 'DOMString',
+                             'is_optional': False,
+                             'is_variadic': False}]},
+             ('DOMString',),
+             (False,)),
+            # <f2, (Node, DOMString, double), (required, required, variadic)>
+            ({'arguments': [{'idl_type_object': 'Node',
+                             'is_optional': False,
+                             'is_variadic': False},
+                            {'idl_type_object': 'DOMString',
+                             'is_optional': False,
+                             'is_variadic': False},
+                            {'idl_type_object': 'double',
+                             'is_optional': False,
+                             'is_variadic': True}]},
+             ('Node', 'DOMString', 'double'),
+             (False, False, True)),
+            # <f2, (Node, DOMString), (required, required)>
+            ({'arguments': [{'idl_type_object': 'Node',
+                             'is_optional': False,
+                             'is_variadic': False},
+                            {'idl_type_object': 'DOMString',
+                             'is_optional': False,
+                             'is_variadic': False},
+                            {'idl_type_object': 'double',
+                             'is_optional': False,
+                             'is_variadic': True}]},
+             ('Node', 'DOMString'),
+             (False, False)),
+            # Missing from the output:
+            # <f2, (Node, DOMString, double, double),
+            #       (required, required, variadic, variadic)>,
+            # <f3, (), ()>
+            ({'arguments': []}, (), ()),
+            # <f4, (Event, DOMString, DOMString, double),
+            #      (required, required, optional, variadic)>
+            ({'arguments': [{'idl_type_object': 'Event',
+                             'is_optional': False,
+                             'is_variadic': False},
+                            {'idl_type_object': 'DOMString',
+                             'is_optional': False,
+                             'is_variadic': False},
+                            {'idl_type_object': 'DOMString',
+                             'is_optional': True,
+                             'is_variadic': False},
+                            {'idl_type_object': 'double',
+                             'is_optional': False,
+                             'is_variadic': True}]},
+             ('Event', 'DOMString', 'DOMString', 'double'),
+             (False, False, True, True)),
+            # <f4, (Event, DOMString, DOMString),
+            #      (required, required, optional)>
+            ({'arguments': [{'idl_type_object': 'Event',
+                             'is_optional': False,
+                             'is_variadic': False},
+                            {'idl_type_object': 'DOMString',
+                             'is_optional': False,
+                             'is_variadic': False},
+                            {'idl_type_object': 'DOMString',
+                             'is_optional': True,
+                             'is_variadic': False},
+                            {'idl_type_object': 'double',
+                             'is_optional': False,
+                             'is_variadic': True}]},
+             ('Event', 'DOMString', 'DOMString'),
+             (False, False, True)),
+            # <f4, (Event, DOMString), (required, required)>
+            ({'arguments': [{'idl_type_object': 'Event',
+                             'is_optional': False,
+                             'is_variadic': False},
+                            {'idl_type_object': 'DOMString',
+                             'is_optional': False,
+                             'is_variadic': False},
+                            {'idl_type_object': 'DOMString',
+                             'is_optional': True,
+                             'is_variadic': False},
+                            {'idl_type_object': 'double',
+                             'is_optional': False,
+                             'is_variadic': True}]},
+             ('Event', 'DOMString'),
+             (False, False))]
+
+        self.assertEqual(effective_overload_set(operation_list), overload_set)
diff --git a/bindings/scripts/print_idl_diff.py b/bindings/scripts/print_idl_diff.py
deleted file mode 100644
index 9a8deea..0000000
--- a/bindings/scripts/print_idl_diff.py
+++ /dev/null
@@ -1,433 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Print a diff generated by generate_idl_diff.py.
-Before printing, sort the diff in the alphabetical order or the order of
-diffing tags.
-Usage: print_idl_diff.py diff_file.json order
-    diff.json:
-        Output of generate_idl_diff.py. The json file contains a dictionary
-        that represents a diff between two different Chromium versions. The
-        structure of the dictionary is like below.
-    order:
-        Specify how to sort. Either by "ALPHABET" or "TAG".
-"""
-
-from collections import OrderedDict
-import json
-import sys
-
-from generate_idl_diff import load_json_file
-from generate_idl_diff import EXTATTRIBUTES_AND_MEMBER_TYPES
-from generate_idl_diff import DIFF_TAG
-from generate_idl_diff import DIFF_TAG_ADDED
-from generate_idl_diff import DIFF_TAG_DELETED
-
-
-"""Refer to the explanation of generate_idl_diff.py's input files.
-The deffference between the input structure of generate_idl_diff.py and
-that of print_diff.py is whether diffing tags are included or not.
-    {'Interface': {
-            'diff_tag': 'deleted'
-            'ExtAttributes': [{'Name': '...'
-                               'diff_tag': 'deleted'},
-                               ...,
-                             ],
-            'Consts': [{'Type': '...',
-                        'Name': '...',
-                        'Value': '...'
-                        'diff_tag': 'deleted'},
-                        ...,
-                      ],
-            'Attributes': [{'Type': '...',
-                            'Name': '...',
-                            'ExtAttributes':[{'Name': '...'},
-                                              ...,
-                                            ]
-                            'diff_tag': 'deleted'},
-                            ...,
-                          ],
-            'Operations': [{'Type': '...',
-                            'Name': '...',
-                            'ExtAttributes':[{'Name': '...'},
-                                              ...,
-                                            ],
-                            'Arguments': [{'Type': '...',
-                                           'Name': '...'},
-                                           ...,
-                                         ]
-                            'diff_tag': 'deleted'},
-                            ...,
-                          ],
-            'Name': '...'
-        },
-        {
-            'ExtAttributes': [{'Name': '...'},
-                               ...,
-                             ],
-            'Consts': [{'Type': '...',
-                        'Name': '...',
-                        'Value': '...'
-                        'diff_tag': 'added'},
-                        ...,
-                      ],
-            'Attributes': [{'Type': '...',
-                            'Name': '...',
-                            'ExtAttributes':[{'Name': '...'},
-                                              ...,
-                                            ]},
-                            ...,
-                          ],
-            'Operations': [{'Type': '...',
-                            'Name': '...',
-                            'ExtAttributes':[{'Name': '...'},
-                                              ...,
-                                            ],
-                            'Arguments': [{'Type': '...',
-                                           'Name': '...'},
-                                           ...,
-                                         ]
-                            'diff_tag': 'deleted'},
-                            ...,
-                           ],
-            'Name': '...'
-        },
-        ...,
-    }
-"""
-
-
-class Colorize(object):
-    """This class outputs a colored text to sys.stdout.
-    TODO(bashi): This class doesn't work on Windows. Provide a way to suppress
-    escape sequences.
-    """
-
-    BLACK = 30
-    RED = 31
-    GREEN = 32
-    YELLOW = 33
-    COLORS = (BLACK, RED, GREEN, YELLOW)
-
-    def __init__(self, out):
-        self.out = out
-
-    def reset_color(self):
-        """Reset text's color to default.
-        """
-        self.out.write('\033[0m')
-
-    def change_color(self, color):
-        """Change text's color by specifing arguments.
-            Args:
-                color: A new color to change. It should be one of |COLORS|.
-        """
-        if color in self.COLORS:
-            self.out.write('\033[' + str(color) + 'm')
-        else:
-            raise Exception('Unsupported color.')
-
-    def writeln(self, string):
-        """Print text with a line-break.
-        """
-        self.out.write(string + '\n')
-
-    def write(self, string):
-        """Print text without a line-break.
-        """
-        self.out.write(string)
-
-
-def sort_member_types(interface):
-    """Sort the members in the order of EXTATTRIBUTES_AND_MEMBER_TYPES.
-    Args:
-        interface: An "interface" object
-    Returns:
-        A sorted "interface" object
-    """
-    sorted_interface = OrderedDict()
-    for member_type in EXTATTRIBUTES_AND_MEMBER_TYPES:
-        sorted_interface[member_type] = interface.get(member_type)
-    sorted_interface[DIFF_TAG] = interface.get(DIFF_TAG)
-    return sorted_interface
-
-
-def group_by_tag(interface_or_member_list):
-    """Group members of |interface_or_member_list| by tags.
-    Args:
-        interface_or_member_list: A list of interface names or a list of "members"
-    Returns:
-        A tuple of (removed, added, unchanged) where
-        removed: A list of removed members
-        added: A list of added members
-        unspecified: A list of other members
-    """
-    removed = []
-    added = []
-    unspecified = []
-    for interface_or_member in interface_or_member_list:
-        if DIFF_TAG in interface_or_member:
-            if interface_or_member[DIFF_TAG] == DIFF_TAG_DELETED:
-                removed.append(interface_or_member)
-            elif interface_or_member[DIFF_TAG] == DIFF_TAG_ADDED:
-                added.append(interface_or_member)
-        else:
-            unspecified.append(interface_or_member)
-    return (removed, added, unspecified)
-
-
-def sort_interface_names_by_tags(interfaces):
-    """Sort interface names as follows.
-    [names of deleted "interface"s
-    -> names of added "interface"s
-    -> names of other "interface"s]
-    Args:
-        interfaces: "interface" objects.
-    Returns:
-        A list of sorted interface names
-    """
-    interface_list = interfaces.values()
-    removed, added, unspecified = group_by_tag(interface_list)
-    removed = map(lambda interface: interface['Name'], removed)
-    added = map(lambda interface: interface['Name'], added)
-    unspecified = map(lambda interface: interface['Name'], unspecified)
-    sorted_interface_names = removed + added + unspecified
-    return sorted_interface_names
-
-
-def sort_members_by_tags(interface):
-    """Sort members of a given interface in the order of diffing tags.
-    Args:
-        An "interface" object
-    Returns:
-        A sorted "interface" object
-    """
-    sorted_interface = OrderedDict()
-    if DIFF_TAG in interface:
-        return interface
-    for member_type in EXTATTRIBUTES_AND_MEMBER_TYPES:
-        member_list = interface[member_type]
-        removed, added, unspecified = group_by_tag(member_list)
-        sorted_interface[member_type] = removed + added + unspecified
-    return sorted_interface
-
-
-def sort_diff_by_tags(interfaces):
-    """Sort an "interfaces" object in the order of diffing tags.
-    Args:
-        An "interfaces" object loaded by load_json_data().
-    Returns:
-        A sorted "interfaces" object
-    """
-    sorted_interfaces = OrderedDict()
-    sorted_interface_names = sort_interface_names_by_tags(interfaces)
-    for interface_name in sorted_interface_names:
-        interface = sort_members_by_tags(interfaces[interface_name])
-        sorted_interfaces[interface_name] = sort_member_types(interface)
-    return sorted_interfaces
-
-
-def sort_members_in_alphabetical_order(interface):
-    """Sort a "members" object in the alphabetical order.
-    Args:
-        An "interface" object
-    Returns:
-        A sorted "interface" object
-    """
-    sorted_interface = OrderedDict()
-    for member_type in EXTATTRIBUTES_AND_MEMBER_TYPES:
-        sorted_members = sorted(interface[member_type],
-                                key=lambda member: member['Name'])
-        sorted_interface[member_type] = sorted_members
-    return sorted_interface
-
-
-def sort_diff_in_alphabetical_order(interfaces):
-    """Sort an "interfaces" object in the alphabetical order.
-    Args:
-        An "interfaces" object.
-    Returns:
-        A sorted "interfaces" object
-    """
-    sorted_interfaces = OrderedDict()
-    for interface_name in sorted(interfaces.keys()):
-        interface = interfaces[interface_name]
-        sorted_interface = sort_members_in_alphabetical_order(interface)
-        sorted_interface[DIFF_TAG] = interface.get(DIFF_TAG)
-        sorted_interfaces[interface_name] = sorted_interface
-    return sorted_interfaces
-
-
-def print_member_with_color(member, out):
-    """Print the "member" with a colored text. '+' is added to an added
-    "member". '-' is added to a removed "member".
-    Args:
-        member: A "member" object
-    """
-    if DIFF_TAG in member:
-        if member[DIFF_TAG] == DIFF_TAG_DELETED:
-            out.change_color(Colorize.RED)
-            out.write('- ')
-        elif member[DIFF_TAG] == DIFF_TAG_ADDED:
-            out.change_color(Colorize.GREEN)
-            out.write('+ ')
-    else:
-        out.change_color(Colorize.BLACK)
-        out.write('  ')
-
-
-def print_extattributes(extattributes, out):
-    """Print extattributes in an "interface" object.
-    Args:
-        A list of "ExtAttributes" in the "interface" object
-    """
-    for extattribute in extattributes:
-        out.write('    ')
-        print_member_with_color(extattribute, out)
-        out.writeln(extattribute['Name'])
-
-
-def print_consts(consts, out):
-    """Print consts in an "interface" object.
-    Args:
-        A list of "Consts" of the "interface" object
-    """
-    for const in consts:
-        out.write('    ')
-        print_member_with_color(const, out)
-        out.write(str(const['Type']))
-        out.write(' ')
-        out.write(const['Name'])
-        out.write(' ')
-        out.writeln(const['Value'])
-
-
-def print_items(items, callback, out):
-    """Calls |callback| for each item in |items|, printing commas between
-    |callback| calls.
-    Args:
-        items: extattributes or arguments
-    """
-    count = 0
-    for item in items:
-        callback(item)
-        count += 1
-        if count < len(items):
-            out.write(', ')
-
-
-def print_extattributes_in_member(extattributes, out):
-    """Print extattributes in a "member" object.
-    Args:
-        A list of "ExtAttributes" in the "member" object
-    """
-    def callback(extattribute):
-        out.write(extattribute['Name'])
-
-    out.write('[')
-    print_items(extattributes, callback, out)
-    out.write(']')
-
-
-def print_attributes(attributes, out):
-    """Print attributes in an "interface" object.
-    Args:
-        A list of "Attributes" in the "interface" object
-    """
-    for attribute in attributes:
-        out.write('    ')
-        print_member_with_color(attribute, out)
-        if attribute['ExtAttributes']:
-            print_extattributes_in_member(attribute['ExtAttributes'], out)
-        out.write(str(attribute['Type']))
-        out.write(' ')
-        out.writeln(attribute['Name'])
-
-
-def print_arguments(arguments, out):
-    """Print arguments in a "members" object named "Operations".
-    Args: A list of "Arguments"
-    """
-    def callback(argument):
-        out.write(argument['Name'])
-
-    out.write('(')
-    print_items(arguments, callback, out)
-    out.writeln(')')
-
-
-def print_operations(operations, out):
-    """Print operations in a "member" object.
-    Args:
-        A list of "Operations"
-    """
-    for operation in operations:
-        out.write('    ')
-        print_member_with_color(operation, out)
-        if operation['ExtAttributes']:
-            print_extattributes_in_member(operation['ExtAttributes'], out)
-        out.write(str(operation['Type']))
-        out.write(' ')
-        if operation['Arguments']:
-            out.write(operation['Name'])
-            print_arguments(operation['Arguments'], out)
-        else:
-            out.writeln(operation['Name'])
-
-
-def print_diff(diff, out):
-    """Print the diff on a shell.
-    Args:
-        A sorted diff
-    """
-    for interface_name, interface in diff.iteritems():
-        print_member_with_color(interface, out)
-        out.change_color(Colorize.YELLOW)
-        out.write('[[')
-        out.write(interface_name)
-        out.writeln(']]')
-        out.reset_color()
-        for member_name, member in interface.iteritems():
-            if member_name == 'ExtAttributes':
-                out.writeln('ExtAttributes')
-                print_extattributes(member, out)
-            elif member_name == 'Consts':
-                out.writeln('  Consts')
-                print_consts(member, out)
-            elif member_name == 'Attributes':
-                out.writeln('  Attributes')
-                print_attributes(member, out)
-            elif member_name == 'Operations':
-                out.writeln('  Operations')
-                print_operations(member, out)
-            out.reset_color()
-
-
-def print_usage():
-    """Show usage."""
-    sys.stdout.write('Usage: print_diff.py <diff_file.json> <"TAG"|"ALPHABET">\n')
-
-
-def main(argv):
-    if len(argv) != 2:
-        print_usage()
-        exit(1)
-    json_data = argv[0]
-    order = argv[1]
-    diff = load_json_file(json_data)
-    if order == 'TAG':
-        sort_func = sort_diff_by_tags
-    elif order == 'ALPHABET':
-        sort_func = sort_diff_in_alphabetical_order
-    else:
-        print_usage()
-        exit(1)
-    sorted_diff = sort_func(diff)
-    out = Colorize(sys.stdout)
-    print_diff(sorted_diff, out)
-
-
-if __name__ == '__main__':
-    main(sys.argv[1:])
diff --git a/bindings/scripts/test_collect_idls_into_json.py b/bindings/scripts/test_collect_idls_into_json.py
deleted file mode 100644
index 49d6e55..0000000
--- a/bindings/scripts/test_collect_idls_into_json.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env python
-
-import unittest
-import collect_idls_into_json
-import utilities
-
-from blink_idl_parser import parse_file, BlinkIDLParser
-
-_FILE = 'Source/bindings/scripts/testdata/test_filepath.txt'
-_KEY_SET = set(['Operations', 'Name', 'FilePath', 'Inherit', 'Consts', 'ExtAttributes', 'Attributes'])
-_PARTIAL = {'Node': {'Operations': [], 'Name': 'Node', 'FilePath': 'Source/core/timing/WorkerGlobalScopePerformance.idl', 'Inherit': [], 'Consts': [], 'ExtAttributes': [], 'Attributes': [{'Static': False, 'Readonly': True, 'Type': 'WorkerPerformance', 'Name': 'performance', 'ExtAttributes': []}]}}
-
-
-class TestFunctions(unittest.TestCase):
-    def setUp(self):
-        parser = BlinkIDLParser()
-        path = utilities.read_file_to_list(_FILE)[0]
-        definitions = parse_file(parser, path)
-        self.definition = definitions.GetChildren()[0]
-
-    def test_get_definitions(self):
-        pathfile = utilities.read_file_to_list(_FILE)
-        for actual in collect_idls_into_json.get_definitions(pathfile):
-            self.assertEqual(actual.GetName(), self.definition.GetName())
-
-    def test_is_non_partial(self):
-        if self.definition.GetClass() == 'Interface' and not self.definition.GetProperty('Partial'):
-            self.assertTrue(collect_idls_into_json.is_non_partial(self.definition))
-        else:
-            self.assertFalse(collect_idls_into_json.is_non_partial(self.definition))
-
-    def test_is_partial(self):
-        if self.definition.GetClass() == 'Interface' and self.definition.GetProperty('Partial'):
-            self.assertTrue(collect_idls_into_json.is_partial(self.definition))
-        else:
-            self.assertFalse(collect_idls_into_json.is_partial(self.definition))
-
-    def test_get_filepaths(self):
-        filepath = collect_idls_into_json.get_filepath(self.definition)
-        self.assertTrue(filepath.startswith('Source'))
-        self.assertTrue(filepath.endswith('.idl'))
-
-    def test_const_node_to_dict(self):
-        const_member = set(['Name', 'Type', 'Value', 'ExtAttributes'])
-        for const in collect_idls_into_json.get_const_node_list(self.definition):
-            if const:
-                self.assertEqual(const.GetClass(), 'Const')
-                self.assertEqual(collect_idls_into_json.get_const_type(const), 'unsigned short')
-                self.assertEqual(collect_idls_into_json.get_const_value(const), '1')
-                self.assertTrue(const_member.issuperset(collect_idls_into_json.const_node_to_dict(const).keys()))
-            else:
-                self.assertEqual(const, None)
-
-    def test_attribute_node_to_dict(self):
-        attribute_member = set(['Name', 'Type', 'ExtAttributes', 'Readonly', 'Static'])
-        for attribute in collect_idls_into_json.get_attribute_node_list(self.definition):
-            if attribute:
-                self.assertEqual(attribute.GetClass(), 'Attribute')
-                self.assertEqual(attribute.GetName(), 'parentNode')
-                self.assertEqual(collect_idls_into_json.get_attribute_type(attribute), 'Node')
-                self.assertTrue(attribute_member.issuperset(collect_idls_into_json.attribute_node_to_dict(attribute).keys()))
-            else:
-                self.assertEqual(attribute, None)
-
-    def test_operation_node_to_dict(self):
-        operate_member = set(['Static', 'ExtAttributes', 'Type', 'Name', 'Arguments'])
-        argument_member = set(['Name', 'Type'])
-        for operation in collect_idls_into_json.get_operation_node_list(self.definition):
-            if operation:
-                self.assertEqual(operation.GetClass(), 'Operation')
-                self.assertEqual(operation.GetName(), 'appendChild')
-                self.assertEqual(collect_idls_into_json.get_operation_type(operation), 'Node')
-                self.assertTrue(operate_member.issuperset(collect_idls_into_json.operation_node_to_dict(operation).keys()))
-                for argument in collect_idls_into_json.get_argument_node_list(operation):
-                    if argument:
-                        self.assertEqual(argument.GetClass(), 'Argument')
-                        self.assertEqual(argument.GetName(), 'newChild')
-                        self.assertEqual(collect_idls_into_json.get_argument_type(argument), 'Node')
-                        self.assertTrue(argument_member.issuperset(collect_idls_into_json.argument_node_to_dict(argument).keys()))
-                    else:
-                        self.assertEqual(argument, None)
-            else:
-                self.assertEqual(operation, None)
-
-    def test_extattribute_node_to_dict(self):
-        for extattr in collect_idls_into_json.get_extattribute_node_list(self.definition):
-            if extattr:
-                self.assertEqual(extattr.GetClass(), 'ExtAttribute')
-                self.assertEqual(extattr.GetName(), 'CustomToV8')
-                self.assertEqual(collect_idls_into_json.extattr_node_to_dict(extattr).keys(), ['Name'])
-                self.assertEqual(collect_idls_into_json.extattr_node_to_dict(extattr).values(), ['CustomToV8'])
-            else:
-                self.assertEqual(extattr, None)
-
-    def test_inherit_node_to_dict(self):
-        inherit = collect_idls_into_json.inherit_node_to_dict(self.definition)
-        if inherit:
-            self.assertEqual(inherit.keys(), ['Parent'])
-            self.assertEqual(inherit.values(), ['EventTarget'])
-        else:
-            self.assertEqual(inherit, [])
-
-    def test_interface_node_to_dict(self):
-        self.assertTrue(_KEY_SET.issuperset(collect_idls_into_json.interface_node_to_dict(self.definition)))
-
-    def test_merge_partial_dicts(self):
-        key_name = self.definition.GetName()
-        self.assertEqual(collect_idls_into_json.merge_partial_dicts({key_name: collect_idls_into_json.interface_node_to_dict(self.definition)}, _PARTIAL)[key_name]['Partial_FilePaths'], ['Source/core/timing/WorkerGlobalScopePerformance.idl'])
-
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/bindings/scripts/testdata/test_interface.idl b/bindings/scripts/testdata/test_interface.idl
deleted file mode 100644
index 74ff3ba..0000000
--- a/bindings/scripts/testdata/test_interface.idl
+++ /dev/null
@@ -1,9 +0,0 @@
-[
-    CustomToV8
- ] interface Node : EventTarget {
-    [Reflect]const unsigned short ELEMENT_NODE = 1;
-    [Clamp]attribute Node parentNode;
-    [Custom] Node appendChild(Node newChild);
-};
-
-
diff --git a/bindings/scripts/utilities.py b/bindings/scripts/utilities.py
index 2370887..b641b42 100644
--- a/bindings/scripts/utilities.py
+++ b/bindings/scripts/utilities.py
@@ -13,14 +13,19 @@
 import shlex
 import string
 import subprocess
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', '..',
+                             'third_party', 'blink', 'tools'))
+from blinkpy.common.name_style_converter import NameStyleConverter
 
 
 KNOWN_COMPONENTS = frozenset(['core', 'modules'])
 KNOWN_COMPONENTS_WITH_TESTING = frozenset(['core', 'modules', 'testing'])
 
 
-def idl_filename_to_interface_name(idl_filename):
-    # interface name is the root of the basename: InterfaceName.idl
+def idl_filename_to_basename(idl_filename):
+    """Returns the basename without the extension."""
     return os.path.splitext(os.path.basename(idl_filename))[0]
 
 
@@ -88,9 +93,13 @@
         return set()
 
     @property
-    def include_path_for_union_types(self):
+    def include_path_for_union_types(self, union_type):
         return None
 
+    @property
+    def callback_functions(self):
+        return {}
+
 
 class ComponentInfoProviderCore(ComponentInfoProvider):
     def __init__(self, interfaces_info, component_info):
@@ -118,9 +127,13 @@
     def union_types(self):
         return self._component_info['union_types']
 
+    def include_path_for_union_types(self, union_type):
+        name = to_snake_case(shorten_union_name(union_type))
+        return 'bindings/core/v8/%s.h' % name
+
     @property
-    def include_path_for_union_types(self):
-        return 'bindings/core/v8/UnionTypesCore.h'
+    def callback_functions(self):
+        return self._component_info['callback_functions']
 
     @property
     def specifier_for_export(self):
@@ -165,9 +178,18 @@
         # generating multiple container generation.
         return self._component_info_modules['union_types'] - self._component_info_core['union_types']
 
+    def include_path_for_union_types(self, union_type):
+        core_union_type_names = [core_union_type.name for core_union_type
+                                 in self._component_info_core['union_types']]
+        name = shorten_union_name(union_type)
+        if union_type.name in core_union_type_names:
+            return 'bindings/core/v8/%s.h' % to_snake_case(name)
+        return 'bindings/modules/v8/%s.h' % to_snake_case(name)
+
     @property
-    def include_path_for_union_types(self):
-        return 'bindings/modules/v8/UnionTypesModules.h'
+    def callback_functions(self):
+        return dict(self._component_info_core['callback_functions'].items() +
+                    self._component_info_modules['callback_functions'].items())
 
     @property
     def specifier_for_export(self):
@@ -282,15 +304,21 @@
 
 def read_pickle_files(pickle_filenames):
     for pickle_filename in pickle_filenames:
-        with open(pickle_filename) as pickle_file:
-            yield pickle.load(pickle_file)
+        yield read_pickle_file(pickle_filename)
 
 
-def write_file(new_text, destination_filename, only_if_changed):
-    if only_if_changed and os.path.isfile(destination_filename):
+def read_pickle_file(pickle_filename):
+    with open(pickle_filename) as pickle_file:
+        return pickle.load(pickle_file)
+
+
+def write_file(new_text, destination_filename):
+    # If |new_text| is same with the file content, we skip updating.
+    if os.path.isfile(destination_filename):
         with open(destination_filename) as destination_file:
             if destination_file.read() == new_text:
                 return
+
     destination_dirname = os.path.dirname(destination_filename)
     if not os.path.exists(destination_dirname):
         os.makedirs(destination_dirname)
@@ -298,8 +326,9 @@
         destination_file.write(new_text)
 
 
-def write_pickle_file(pickle_filename, data, only_if_changed):
-    if only_if_changed and os.path.isfile(pickle_filename):
+def write_pickle_file(pickle_filename, data):
+    # If |data| is same with the file content, we skip updating.
+    if os.path.isfile(pickle_filename):
         with open(pickle_filename) as pickle_file:
             try:
                 if pickle.load(pickle_file) == data:
@@ -314,25 +343,29 @@
 ################################################################################
 # IDL parsing
 #
-# We use regular expressions for parsing; this is incorrect (Web IDL is not a
-# regular language), but simple and sufficient in practice.
+# TODO(bashi): We use regular expressions for parsing; this is incorrect
+# (Web IDL is not a regular language) and broken. Remove these functions and
+# always use the parser and ASTs.
 # Leading and trailing context (e.g. following '{') used to avoid false matches.
 ################################################################################
 
-def is_callback_interface_from_idl(file_contents):
+def is_non_legacy_callback_interface_from_idl(file_contents):
+    """Returns True if the specified IDL is a non-legacy callback interface."""
     match = re.search(r'callback\s+interface\s+\w+\s*{', file_contents)
-    return bool(match)
+    # Having constants means it's a legacy callback interface.
+    # https://heycam.github.io/webidl/#legacy-callback-interface-object
+    return bool(match) and not re.search(r'\s+const\b', file_contents)
 
 
 def should_generate_impl_file_from_idl(file_contents):
     """True when a given IDL file contents could generate .h/.cpp files."""
     # FIXME: This would be error-prone and we should use AST rather than
     # improving the regexp pattern.
-    match = re.search(r'(interface|dictionary|exception)\s+\w+', file_contents)
+    match = re.search(r'(interface|dictionary)\s+\w+', file_contents)
     return bool(match)
 
 
-def match_interface_extended_attributes_from_idl(file_contents):
+def match_interface_extended_attributes_and_name_from_idl(file_contents):
     # Strip comments
     # re.compile needed b/c Python 2.6 doesn't support flags in re.sub
     single_line_comment_re = re.compile(r'//.*$', flags=re.MULTILINE)
@@ -340,19 +373,18 @@
     file_contents = re.sub(single_line_comment_re, '', file_contents)
     file_contents = re.sub(block_comment_re, '', file_contents)
 
-    match = re.search(r'\[(.*)\]\s*'
-                      r'((callback|partial)\s+)?'
-                      r'(interface|exception)\s+'
-                      r'\w+\s*'
-                      r'(:\s*\w+\s*)?'
-                      r'{',
-                      file_contents, flags=re.DOTALL)
+    match = re.search(
+        r'(?:\[([^[]*)\]\s*)?'
+        r'(interface|callback\s+interface|partial\s+interface|dictionary)\s+'
+        r'(\w+)\s*'
+        r'(:\s*\w+\s*)?'
+        r'{',
+        file_contents, flags=re.DOTALL)
     return match
 
-
 def get_interface_extended_attributes_from_idl(file_contents):
-    match = match_interface_extended_attributes_from_idl(file_contents)
-    if not match:
+    match = match_interface_extended_attributes_and_name_from_idl(file_contents)
+    if not match or not match.group(1):
         return {}
 
     extended_attributes_string = match.group(1)
@@ -370,8 +402,8 @@
 
 
 def get_interface_exposed_arguments(file_contents):
-    match = match_interface_extended_attributes_from_idl(file_contents)
-    if not match:
+    match = match_interface_extended_attributes_and_name_from_idl(file_contents)
+    if not match or not match.group(1):
         return None
 
     extended_attributes_string = match.group(1)
@@ -384,3 +416,142 @@
         arguments.append({'exposed': exposed, 'runtime_enabled': runtime_enabled})
 
     return arguments
+
+
+def get_first_interface_name_from_idl(file_contents):
+    match = match_interface_extended_attributes_and_name_from_idl(file_contents)
+    if match:
+        return match.group(3)
+    return None
+
+
+# Workaround for crbug.com/611437 and crbug.com/711464
+# TODO(bashi): Remove this hack once we resolve too-long generated file names.
+# pylint: disable=line-too-long
+def shorten_union_name(union_type):
+    aliases = {
+        # modules/canvas2d/CanvasRenderingContext2D.idl
+        'CSSImageValueOrHTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmapOrOffscreenCanvas': 'CanvasImageSource',
+        # modules/canvas/HTMLCanvasElementModule.idl
+        'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContext': 'RenderingContext',
+        # core/imagebitmap/ImageBitmapFactories.idl
+        'HTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas': 'ImageBitmapSource',
+        # bindings/tests/idls/core/TestTypedefs.idl
+        'NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord': 'NestedUnionType',
+        # modules/offscreencanvas/OffscreenCanvasModules.idl
+        'OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContext': 'OffscreenRenderingContext',
+    }
+
+    idl_type = union_type
+    if union_type.is_nullable:
+        idl_type = union_type.inner_type
+    name = idl_type.cpp_type or idl_type.name
+    alias = aliases.get(name)
+    if alias:
+        return alias
+    if len(name) >= 80:
+        raise Exception('crbug.com/711464: The union name %s is too long. '
+                        'Please add an alias to shorten_union_name()' % name)
+    return name
+
+
+def to_snake_case(name):
+    if name.lower() == name:
+        return name
+    return NameStyleConverter(name).to_snake_case()
+
+
+def format_remove_duplicates(text, patterns):
+    """Removes duplicated line-basis patterns.
+
+    Based on simple pattern matching, removes duplicated lines in a block
+    of lines.  Lines that match with a same pattern are considered as
+    duplicates.
+
+    Designed to be used as a filter function for Jinja2.
+
+    Args:
+        text: A str of multi-line text.
+        patterns: A list of str where each str represents a simple
+            pattern.  The patterns are not considered as regexp, and
+            exact match is applied.
+
+    Returns:
+        A formatted str with duplicates removed.
+    """
+    pattern_founds = [False] * len(patterns)
+    output = []
+    for line in text.split('\n'):
+        to_be_removed = False
+        for i, pattern in enumerate(patterns):
+            if pattern not in line:
+                continue
+            if pattern_founds[i]:
+                to_be_removed = True
+            else:
+                pattern_founds[i] = True
+        if to_be_removed:
+            continue
+        output.append(line)
+
+    # Let |'\n'.join| emit the last newline.
+    if output:
+        output.append('')
+
+    return '\n'.join(output)
+
+
+def format_blink_cpp_source_code(text):
+    """Formats C++ source code.
+
+    Supported modifications are:
+    - Reduces successive empty lines into a single empty line.
+    - Removes empty lines just after an open brace or before closing brace.
+      This rule does not apply to namespaces.
+
+    Designed to be used as a filter function for Jinja2.
+
+    Args:
+        text: A str of C++ source code.
+
+    Returns:
+        A formatted str of the source code.
+    """
+    re_empty_line = re.compile(r'^\s*$')
+    re_first_brace = re.compile(r'(?P<first>[{}])')
+    re_last_brace = re.compile(r'.*(?P<last>[{}]).*?$')
+    was_open_brace = True  # Trick to remove the empty lines at the beginning.
+    was_empty_line = False
+    output = []
+    for line in text.split('\n'):
+        # Skip empty lines.
+        if re_empty_line.match(line):
+            was_empty_line = True
+            continue
+
+        # Emit a single empty line if needed.
+        if was_empty_line:
+            was_empty_line = False
+            match = re_first_brace.search(line)
+            if was_open_brace:
+                # No empty line just after an open brace.
+                pass
+            elif match and match.group('first') == '}' and 'namespace' not in line:
+                # No empty line just before a closing brace.
+                pass
+            else:
+                # Preserve a single empty line.
+                output.append('')
+
+        # Emit the line itself.
+        output.append(line)
+
+        # Remember an open brace.
+        match = re_last_brace.search(line)
+        was_open_brace = (match and match.group('last') == '{' and 'namespace' not in line)
+
+    # Let |'\n'.join| emit the last newline.
+    if output:
+        output.append('')
+
+    return '\n'.join(output)
diff --git a/bindings/scripts/v8_attributes.py b/bindings/scripts/v8_attributes.py
index 2987967..fad2784 100644
--- a/bindings/scripts/v8_attributes.py
+++ b/bindings/scripts/v8_attributes.py
@@ -26,6 +26,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# pylint: disable=relative-import
+
 """Generate template values for attributes.
 
 Extends IdlType with property |constructor_type_name|.
@@ -35,7 +37,7 @@
 
 import idl_types
 from idl_types import inherits_interface
-from v8_globals import includes, interfaces
+from v8_globals import includes
 import v8_types
 import v8_utilities
 from v8_utilities import (cpp_name_or_partial, capitalize, cpp_name, has_extended_attribute,
@@ -44,7 +46,19 @@
                           is_legacy_interface_type_checking)
 
 
-def attribute_context(interface, attribute):
+def attribute_context(interface, attribute, interfaces):
+    """Creates a Jinja template context for an attribute of an interface.
+
+    Args:
+        interface: An interface which |attribute| belongs to
+        attribute: An attribute to create the context for
+        interfaces: A dict which maps an interface name to the definition
+            which can be referred if needed
+
+    Returns:
+        A Jinja template context for |attribute|
+    """
+
     idl_type = attribute.idl_type
     base_idl_type = idl_type.base_type
     extended_attributes = attribute.extended_attributes
@@ -54,61 +68,63 @@
         includes.add('core/inspector/ConsoleMessage.h')
 
     # [CheckSecurity]
-    is_do_not_check_security = 'DoNotCheckSecurity' in extended_attributes
+    is_cross_origin = 'CrossOrigin' in extended_attributes
     is_check_security_for_receiver = (
         has_extended_attribute_value(interface, 'CheckSecurity', 'Receiver') and
-        not is_do_not_check_security)
+        is_cross_origin)
     is_check_security_for_return_value = (
         has_extended_attribute_value(attribute, 'CheckSecurity', 'ReturnValue'))
     if is_check_security_for_receiver or is_check_security_for_return_value:
         includes.add('bindings/core/v8/BindingSecurity.h')
+    # [CrossOrigin]
+    if has_extended_attribute_value(attribute, 'CrossOrigin', 'Setter'):
+        includes.add('bindings/core/v8/V8CrossOriginSetterInfo.h')
     # [Constructor]
     # TODO(yukishiino): Constructors are much like methods although constructors
     # are not methods.  Constructors must be data-type properties, and we can
     # support them as a kind of methods.
     constructor_type = idl_type.constructor_type_name if is_constructor_attribute(attribute) else None
+    # [CEReactions]
+    is_ce_reactions = 'CEReactions' in extended_attributes
+    if is_ce_reactions:
+        includes.add('core/html/custom/CEReactionsScope.h')
     # [CustomElementCallbacks], [Reflect]
     is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attributes
     is_reflect = 'Reflect' in extended_attributes
     if is_custom_element_callbacks or is_reflect:
-        includes.add('core/dom/custom/CustomElementProcessingStack.h')
-    # [ImplementedInPrivateScript]
-    is_implemented_in_private_script = 'ImplementedInPrivateScript' in extended_attributes
-    if is_implemented_in_private_script:
-        includes.add('bindings/core/v8/PrivateScriptRunner.h')
-        includes.add('core/frame/LocalFrame.h')
-        includes.add('platform/ScriptForbiddenScope.h')
-    # [OnlyExposedToPrivateScript]
-    is_only_exposed_to_private_script = 'OnlyExposedToPrivateScript' in extended_attributes
+        includes.add('core/html/custom/V0CustomElementProcessingStack.h')
     # [PerWorldBindings]
     if 'PerWorldBindings' in extended_attributes:
         assert idl_type.is_wrapper_type or 'LogActivity' in extended_attributes, '[PerWorldBindings] should only be used with wrapper types: %s.%s' % (interface.name, attribute.name)
+    # [SaveSameObject]
+    is_save_same_object = (
+        'SameObject' in attribute.extended_attributes and
+        'SaveSameObject' in attribute.extended_attributes)
+    if is_save_same_object:
+        includes.add('platform/bindings/V8PrivateProperty.h')
 
     if (base_idl_type == 'EventHandler' and
-        interface.name in ['Window', 'WorkerGlobalScope'] and
-        attribute.name == 'onerror'):
+            interface.name in ['Window', 'WorkerGlobalScope'] and
+            attribute.name == 'onerror'):
         includes.add('bindings/core/v8/V8ErrorHandler.h')
 
     cached_attribute_validation_method = extended_attributes.get('CachedAttribute')
     keep_alive_for_gc = is_keep_alive_for_gc(interface, attribute)
     if cached_attribute_validation_method or keep_alive_for_gc:
-        includes.add('bindings/core/v8/V8HiddenValue.h')
+        includes.add('platform/bindings/V8PrivateProperty.h')
 
-    if 'RuntimeEnabled' in extended_attributes:
-        includes.add('platform/RuntimeEnabledFeatures.h')
-
-    if 'OriginTrialEnabled' in extended_attributes:
-        includes.add('core/inspector/ConsoleMessage.h')
-        includes.add('core/origin_trials/OriginTrials.h')
+    # [CachedAccessor]
+    is_cached_accessor = 'CachedAccessor' in extended_attributes
+    if is_cached_accessor:
+        includes.add('platform/bindings/V8PrivateProperty.h')
 
     context = {
-        'access_control_list': access_control_list(interface, attribute),
         'activity_logging_world_list_for_getter': v8_utilities.activity_logging_world_list(attribute, 'Getter'),  # [ActivityLogging]
         'activity_logging_world_list_for_setter': v8_utilities.activity_logging_world_list(attribute, 'Setter'),  # [ActivityLogging]
         'activity_logging_world_check': v8_utilities.activity_logging_world_check(attribute),  # [ActivityLogging]
-        'argument_cpp_type': idl_type.cpp_type_args(used_as_rvalue_type=True),
         'cached_attribute_validation_method': cached_attribute_validation_method,
         'constructor_type': constructor_type,
+        'context_enabled_feature_name': v8_utilities.context_enabled_feature_name(attribute),
         'cpp_name': cpp_name(attribute),
         'cpp_type': idl_type.cpp_type,
         'cpp_type_initializer': idl_type.cpp_type_initializer,
@@ -116,26 +132,32 @@
         'enum_type': idl_type.enum_type,
         'enum_values': idl_type.enum_values,
         'exposed_test': v8_utilities.exposed(attribute, interface),  # [Exposed]
+        'has_cross_origin_getter':
+            has_extended_attribute_value(attribute, 'CrossOrigin', None) or
+            has_extended_attribute_value(attribute, 'CrossOrigin', 'Getter'),
+        'has_cross_origin_setter': has_extended_attribute_value(attribute, 'CrossOrigin', 'Setter'),
         'has_custom_getter': has_custom_getter(attribute),
         'has_custom_setter': has_custom_setter(attribute),
-        'has_setter': has_setter(attribute),
-        'idl_type': str(idl_type),  # need trailing [] on array for Dictionary::ConversionContext::setConversionType
-        'is_origin_trial_enabled': v8_utilities.origin_trial_enabled_function(attribute) or v8_utilities.origin_trial_enabled_function(interface),  # [OriginTrialEnabled]
+        'has_promise_type': idl_type.name == 'Promise',
+        'has_setter': has_setter(interface, attribute),
+        'idl_type': str(idl_type),
+        'is_cached_accessor': is_cached_accessor,
         'is_call_with_execution_context': has_extended_attribute_value(attribute, 'CallWith', 'ExecutionContext'),
         'is_call_with_script_state': has_extended_attribute_value(attribute, 'CallWith', 'ScriptState'),
+        'is_ce_reactions': is_ce_reactions,
         'is_check_security_for_receiver': is_check_security_for_receiver,
         'is_check_security_for_return_value': is_check_security_for_return_value,
         'is_custom_element_callbacks': is_custom_element_callbacks,
         # TODO(yukishiino): Make all DOM attributes accessor-type properties.
-        'is_data_type_property': constructor_type or interface.name == 'Window' or interface.name == 'Location',
+        'is_data_type_property': is_data_type_property(interface, attribute),
         'is_getter_raises_exception':  # [RaisesException]
             'RaisesException' in extended_attributes and
             extended_attributes['RaisesException'] in (None, 'Getter'),
-        'is_implemented_in_private_script': is_implemented_in_private_script,
         'is_keep_alive_for_gc': keep_alive_for_gc,
         'is_lenient_this': 'LenientThis' in extended_attributes,
         'is_nullable': idl_type.is_nullable,
         'is_explicit_nullable': idl_type.is_explicit_nullable,
+        'is_named_constructor': is_named_constructor_attribute(attribute),
         'is_partial_interface_member':
             'PartialInterfaceImplementedAs' in extended_attributes,
         'is_per_world_bindings': 'PerWorldBindings' in extended_attributes,
@@ -143,43 +165,121 @@
         'is_read_only': attribute.is_read_only,
         'is_reflect': is_reflect,
         'is_replaceable': 'Replaceable' in attribute.extended_attributes,
+        'is_save_same_object': is_save_same_object,
         'is_static': attribute.is_static,
         'is_url': 'URL' in extended_attributes,
         'is_unforgeable': is_unforgeable(interface, attribute),
         'on_instance': v8_utilities.on_instance(interface, attribute),
         'on_interface': v8_utilities.on_interface(interface, attribute),
         'on_prototype': v8_utilities.on_prototype(interface, attribute),
-        'origin_trial_enabled': v8_utilities.origin_trial_enabled_function(attribute),  # [OriginTrialEnabled]
-        'origin_trial_enabled_per_interface': v8_utilities.origin_trial_enabled_function(interface),  # [OriginTrialEnabled]
-        'origin_trial_name': extended_attributes.get('OriginTrialEnabled'),  # [OriginTrialEnabled]
+        'origin_trial_enabled_function': v8_utilities.origin_trial_enabled_function_name(attribute),  # [OriginTrialEnabled]
+        'origin_trial_feature_name': v8_utilities.origin_trial_feature_name(attribute),  # [OriginTrialEnabled]
         'use_output_parameter_for_result': idl_type.use_output_parameter_for_result,
         'measure_as': v8_utilities.measure_as(attribute, interface),  # [MeasureAs]
         'name': attribute.name,
-        'only_exposed_to_private_script': is_only_exposed_to_private_script,
-        'private_script_v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value(
-            extended_attributes, 'v8Value', 'cppValue', bailout_return_value='false', isolate='scriptState->isolate()'),
         'property_attributes': property_attributes(interface, attribute),
         'reflect_empty': extended_attributes.get('ReflectEmpty'),
         'reflect_invalid': extended_attributes.get('ReflectInvalid', ''),
         'reflect_missing': extended_attributes.get('ReflectMissing'),
         'reflect_only': extended_attribute_value_as_list(attribute, 'ReflectOnly'),
-        'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(attribute),  # [RuntimeEnabled]
-        'should_be_exposed_to_script': not (is_implemented_in_private_script and is_only_exposed_to_private_script),
-        'world_suffixes': ['', 'ForMainWorld']
-                          if 'PerWorldBindings' in extended_attributes
-                          else [''],  # [PerWorldBindings]
+        'runtime_enabled_feature_name': v8_utilities.runtime_enabled_feature_name(attribute),  # [RuntimeEnabled]
+        'secure_context_test': v8_utilities.secure_context(attribute, interface),  # [SecureContext]
+        'cached_accessor_name': '%s%sCachedAccessor' % (interface.name, attribute.name.capitalize()),
+        'world_suffixes': (
+            ['', 'ForMainWorld']
+            if 'PerWorldBindings' in extended_attributes
+            else ['']),  # [PerWorldBindings]
     }
 
-    if is_constructor_attribute(attribute):
-        update_constructor_attribute_context(interface, attribute, context)
     if not has_custom_getter(attribute):
         getter_context(interface, attribute, context)
-    if not has_custom_setter(attribute) and has_setter(attribute):
-        setter_context(interface, attribute, context)
+    if not has_custom_setter(attribute) and has_setter(interface, attribute):
+        setter_context(interface, attribute, interfaces, context)
+
+    # [RuntimeCallStatsCounter]
+    runtime_call_stats_context(interface, attribute, context)
+
+    # [CrossOrigin] is incompatible with a number of other attributes, so check
+    # for them here.
+    if is_cross_origin:
+        if context['has_cross_origin_setter'] and context['has_custom_setter']:
+            raise Exception('[CrossOrigin] and [Custom] are incompatible on the same setter: %s.%s', interface.name, attribute.name)
+        if context['is_per_world_bindings']:
+            raise Exception('[CrossOrigin] and [PerWorldBindings] are incompatible: %s.%s', interface.name, attribute.name)
+        if context['constructor_type']:
+            raise Exception('[CrossOrigin] cannot be used for constructors: %s.%s', interface.name, attribute.name)
 
     return context
 
 
+def runtime_call_stats_context(interface, attribute, context):
+    includes.add('platform/bindings/RuntimeCallStats.h')
+    generic_counter_name = 'Blink_' + v8_utilities.cpp_name(interface) + '_' + attribute.name
+    (counter, extended_attribute_defined) = v8_utilities.rcs_counter_name(attribute, generic_counter_name)
+    runtime_call_stats = {
+        'extended_attribute_defined': extended_attribute_defined,
+        'getter_counter': '%s_Getter' % counter,
+        'setter_counter': '%s_Setter' % counter,
+        'constructor_getter_callback_counter': '%s_ConstructorGetterCallback' % generic_counter_name,
+    }
+    context.update({
+        'runtime_call_stats': runtime_call_stats
+    })
+
+
+def is_secure_context(attribute):
+    return bool(attribute['secure_context_test'])
+
+
+def filter_accessors(attributes):
+    return [attribute for attribute in attributes if
+            not (attribute['exposed_test'] or
+                 is_secure_context(attribute) or
+                 attribute['context_enabled_feature_name'] or
+                 attribute['origin_trial_enabled_function'] or
+                 attribute['runtime_enabled_feature_name']) and
+            not attribute['is_data_type_property']]
+
+
+def is_data_attribute(attribute):
+    return (not (attribute['exposed_test'] or
+                 is_secure_context(attribute) or
+                 attribute['context_enabled_feature_name'] or
+                 attribute['origin_trial_enabled_function'] or
+                 attribute['runtime_enabled_feature_name']) and
+            attribute['is_data_type_property'])
+
+
+def is_lazy_data_attribute(attribute):
+    return ((attribute['constructor_type'] and not
+             (attribute['measure_as'] or attribute['deprecate_as'])) or
+            (attribute['idl_type'] == 'Window' and attribute['name'] == 'frames') or
+            (attribute['idl_type'] == 'Window' and attribute['name'] == 'self') or
+            (attribute['idl_type'] == 'Window' and attribute['name'] == 'window'))
+
+
+def filter_data_attributes(attributes):
+    return [attribute for attribute in attributes if is_data_attribute(attribute) and not is_lazy_data_attribute(attribute)]
+
+
+def filter_lazy_data_attributes(attributes):
+    return [attribute for attribute in attributes if is_data_attribute(attribute) and is_lazy_data_attribute(attribute)]
+
+
+def filter_runtime_enabled(attributes):
+    return [attribute for attribute in attributes if
+            not (attribute['exposed_test'] or
+                 is_secure_context(attribute)) and
+            attribute['runtime_enabled_feature_name']]
+
+
+def filter_conditionally_enabled(attributes):
+    return [attribute for attribute in attributes if
+            attribute['exposed_test'] or
+            (is_secure_context(attribute) and
+             not attribute['origin_trial_feature_name'])]
+
+
 ################################################################################
 # Getter
 ################################################################################
@@ -196,39 +296,29 @@
     # exceptions), we need to use a local variable.
     # FIXME: check if compilers are smart enough to inline this, and if so,
     # always use a local variable (for readability and CG simplicity).
-    release = False
-    if 'ImplementedInPrivateScript' in extended_attributes:
-        if (not idl_type.is_wrapper_type and
-            not idl_type.is_basic_type and
-            not idl_type.is_enum):
-            raise Exception('Private scripts supports only primitive types and DOM wrappers.')
-
-        context['cpp_value_original'] = cpp_value
-        cpp_value = 'result'
-        # EventHandler has special handling
-        if base_idl_type != 'EventHandler':
-            release = idl_type.release
-    elif (idl_type.is_explicit_nullable or
-        base_idl_type == 'EventHandler' or
-        'CachedAttribute' in extended_attributes or
-        'ReflectOnly' in extended_attributes or
-        context['is_keep_alive_for_gc'] or
-        context['is_getter_raises_exception']):
+    if (idl_type.is_explicit_nullable or
+            base_idl_type == 'EventHandler' or
+            'CachedAttribute' in extended_attributes or
+            'ReflectOnly' in extended_attributes or
+            context['is_keep_alive_for_gc'] or
+            context['is_getter_raises_exception']):
         context['cpp_value_original'] = cpp_value
         cpp_value = 'cppValue'
-        # EventHandler has special handling
-        if base_idl_type != 'EventHandler':
-            release = idl_type.release
 
     def v8_set_return_value_statement(for_main_world=False):
         if context['is_keep_alive_for_gc'] or 'CachedAttribute' in extended_attributes:
-            return 'v8SetReturnValue(info, v8Value)'
+            return 'V8SetReturnValue(info, v8Value)'
         return idl_type.v8_set_return_value(
             cpp_value, extended_attributes=extended_attributes, script_wrappable='impl',
-            release=release, for_main_world=for_main_world, is_static=attribute.is_static)
+            for_main_world=for_main_world, is_static=attribute.is_static)
+
+    cpp_value_to_script_wrappable = cpp_value
+    if idl_type.is_array_buffer_view_or_typed_array:
+        cpp_value_to_script_wrappable += '.View()'
 
     context.update({
         'cpp_value': cpp_value,
+        'cpp_value_to_script_wrappable': cpp_value_to_script_wrappable,
         'cpp_value_to_v8_value': idl_type.cpp_value_to_v8_value(
             cpp_value=cpp_value, creation_context='holder',
             extended_attributes=extended_attributes),
@@ -241,18 +331,13 @@
     this_getter_base_name = getter_base_name(interface, attribute, arguments)
     getter_name = scoped_name(interface, attribute, this_getter_base_name)
 
-    if 'ImplementedInPrivateScript' in attribute.extended_attributes:
-        arguments.append('toLocalFrame(toFrameIfNotDetached(info.GetIsolate()->GetCurrentContext()))')
-        arguments.append('impl')
-        arguments.append('&result')
     arguments.extend(v8_utilities.call_with_arguments(
         attribute.extended_attributes.get('CallWith')))
     # Members of IDL partial interface definitions are implemented in C++ as
     # static member functions, which for instance members (non-static members)
     # take *impl as their first argument
     if ('PartialInterfaceImplementedAs' in attribute.extended_attributes and
-        not 'ImplementedInPrivateScript' in attribute.extended_attributes and
-        not attribute.is_static):
+            not attribute.is_static):
         arguments.append('*impl')
     if attribute.idl_type.is_explicit_nullable:
         arguments.append('isNull')
@@ -260,29 +345,35 @@
         arguments.append('exceptionState')
     if attribute.idl_type.use_output_parameter_for_result:
         arguments.append('result')
-    return '%s(%s)' % (getter_name, ', '.join(arguments))
+
+    expression = '%s(%s)' % (getter_name, ', '.join(arguments))
+    # Needed to handle getter expressions returning Type& as the
+    # use site for |expression| expects Type*.
+    if (attribute.idl_type.is_interface_type and len(arguments) == 0 and
+            not attribute.idl_type.is_array_buffer_view_or_typed_array):
+        return 'WTF::GetPtr(%s)' % expression
+    return expression
 
 
 CONTENT_ATTRIBUTE_GETTER_NAMES = {
-    'boolean': 'fastHasAttribute',
-    'long': 'getIntegralAttribute',
-    'unsigned long': 'getUnsignedIntegralAttribute',
+    'boolean': 'FastHasAttribute',
+    'long': 'GetIntegralAttribute',
+    'unsigned long': 'GetUnsignedIntegralAttribute',
 }
 
 
 def getter_base_name(interface, attribute, arguments):
     extended_attributes = attribute.extended_attributes
 
-    if 'ImplementedInPrivateScript' in extended_attributes:
-        return '%sAttributeGetter' % uncapitalize(cpp_name(attribute))
-
     if 'Reflect' not in extended_attributes:
-        return uncapitalize(cpp_name(attribute))
+        name = cpp_name(attribute)
+        return name if 'ImplementedAs' in extended_attributes \
+            else uncapitalize(name)
 
     content_attribute_name = extended_attributes['Reflect'] or attribute.name.lower()
     if content_attribute_name in ['class', 'id', 'name']:
         # Special-case for performance optimization.
-        return 'get%sAttribute' % content_attribute_name.capitalize()
+        return 'Get%sAttribute' % content_attribute_name.capitalize()
 
     arguments.append(scoped_content_attribute_name(interface, attribute))
 
@@ -290,14 +381,16 @@
     if base_idl_type in CONTENT_ATTRIBUTE_GETTER_NAMES:
         return CONTENT_ATTRIBUTE_GETTER_NAMES[base_idl_type]
     if 'URL' in attribute.extended_attributes:
-        return 'getURLAttribute'
-    return 'fastGetAttribute'
+        return 'GetURLAttribute'
+    return 'FastGetAttribute'
 
 
 def is_keep_alive_for_gc(interface, attribute):
     idl_type = attribute.idl_type
     base_idl_type = idl_type.base_type
     extended_attributes = attribute.extended_attributes
+    if attribute.is_static:
+        return False
     return (
         # For readonly attributes, for performance reasons we keep the attribute
         # wrapper alive while the owner wrapper is alive, because the attribute
@@ -320,25 +413,27 @@
 # Setter
 ################################################################################
 
-def setter_context(interface, attribute, context):
+def setter_context(interface, attribute, interfaces, context):
     if 'PutForwards' in attribute.extended_attributes:
-        # Use target interface and attribute in place of original interface and
-        # attribute from this point onwards.
+        # Make sure the target interface and attribute exist.
         target_interface_name = attribute.idl_type.base_type
         target_attribute_name = attribute.extended_attributes['PutForwards']
         interface = interfaces[target_interface_name]
         try:
-            attribute = next(candidate
-                             for candidate in interface.attributes
-                             if candidate.name == target_attribute_name)
+            next(candidate
+                 for candidate in interface.attributes
+                 if candidate.name == target_attribute_name)
         except StopIteration:
             raise Exception('[PutForward] target not found:\n'
                             'Attribute "%s" is not present in interface "%s"' %
                             (target_attribute_name, target_interface_name))
+        context['target_attribute_name'] = target_attribute_name
+        return
 
-    if ('Replaceable' in attribute.extended_attributes or
-            is_constructor_attribute(attribute)):
-        context['cpp_setter'] = '%sCreateDataProperty(propertyName, v8Value, info)' % cpp_name(interface)
+    if ('Replaceable' in attribute.extended_attributes):
+        context['cpp_setter'] = (
+            'V8CallBoolean(info.Holder()->CreateDataProperty(' +
+            'info.GetIsolate()->GetCurrentContext(), propertyName, v8Value))')
         return
 
     extended_attributes = attribute.extended_attributes
@@ -361,9 +456,6 @@
         'is_setter_call_with_execution_context': has_extended_attribute_value(
             attribute, 'SetterCallWith', 'ExecutionContext'),
         'is_setter_raises_exception': is_setter_raises_exception,
-        'private_script_cpp_value_to_v8_value': idl_type.cpp_value_to_v8_value(
-            'cppValue', isolate='scriptState->isolate()',
-            creation_context='scriptState->context()->Global()'),
         'v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value(
             extended_attributes, 'v8Value', 'cppValue'),
     })
@@ -385,29 +477,28 @@
     # static member functions, which for instance members (non-static members)
     # take *impl as their first argument
     if ('PartialInterfaceImplementedAs' in extended_attributes and
-        not 'ImplementedInPrivateScript' in extended_attributes and
-        not attribute.is_static):
+            not attribute.is_static):
         arguments.append('*impl')
     idl_type = attribute.idl_type
-    if 'ImplementedInPrivateScript' in extended_attributes:
-        arguments.append('toLocalFrame(toFrameIfNotDetached(info.GetIsolate()->GetCurrentContext()))')
-        arguments.append('impl')
-        arguments.append('cppValue')
-    elif idl_type.base_type == 'EventHandler':
+    if idl_type.base_type == 'EventHandler':
         getter_name = scoped_name(interface, attribute, cpp_name(attribute))
         context['event_handler_getter_expression'] = '%s(%s)' % (
             getter_name, ', '.join(arguments))
         if (interface.name in ['Window', 'WorkerGlobalScope'] and
-            attribute.name == 'onerror'):
+                attribute.name == 'onerror'):
             includes.add('bindings/core/v8/V8ErrorHandler.h')
-            arguments.append('V8EventListenerList::findOrCreateWrapper<V8ErrorHandler>(v8Value, true, ScriptState::current(info.GetIsolate()))')
+            arguments.append(
+                'V8EventListenerHelper::EnsureErrorHandler(' +
+                'ScriptState::ForRelevantRealm(info), v8Value)')
         else:
-            arguments.append('V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate)')
-    elif idl_type.is_interface_type:
-        # FIXME: should be able to eliminate WTF::getPtr in most or all cases
-        arguments.append('WTF::getPtr(cppValue)')
+            arguments.append(
+                'V8EventListenerHelper::GetEventListener(' +
+                'ScriptState::ForRelevantRealm(info), v8Value, true, ' +
+                'kListenerFindOrCreate)')
     else:
         arguments.append('cppValue')
+    if idl_type.is_explicit_nullable:
+        arguments.append('isNull')
     if context['is_setter_raises_exception']:
         arguments.append('exceptionState')
 
@@ -415,16 +506,13 @@
 
 
 CONTENT_ATTRIBUTE_SETTER_NAMES = {
-    'boolean': 'setBooleanAttribute',
-    'long': 'setIntegralAttribute',
-    'unsigned long': 'setUnsignedIntegralAttribute',
+    'boolean': 'SetBooleanAttribute',
+    'long': 'SetIntegralAttribute',
+    'unsigned long': 'SetUnsignedIntegralAttribute',
 }
 
 
 def setter_base_name(interface, attribute, arguments):
-    if 'ImplementedInPrivateScript' in attribute.extended_attributes:
-        return '%sAttributeSetter' % uncapitalize(cpp_name(attribute))
-
     if 'Reflect' not in attribute.extended_attributes:
         return 'set%s' % capitalize(cpp_name(attribute))
     arguments.append(scoped_content_attribute_name(interface, attribute))
@@ -439,9 +527,10 @@
     content_attribute_name = attribute.extended_attributes['Reflect'] or attribute.name.lower()
     if interface.name.startswith('SVG'):
         namespace = 'SVGNames'
+        includes.add('core/svg_names.h')
     else:
         namespace = 'HTMLNames'
-    includes.add('core/%s.h' % namespace)
+        includes.add('core/html_names.h')
     return '%s::%sAttr' % (namespace, content_attribute_name)
 
 
@@ -449,28 +538,28 @@
 # Attribute configuration
 ################################################################################
 
-# [PutForwards], [Replaceable]
-def has_setter(attribute):
+# Property descriptor's {writable: boolean}
+def is_writable(attribute):
     return (not attribute.is_read_only or
             'PutForwards' in attribute.extended_attributes or
             'Replaceable' in attribute.extended_attributes)
 
 
-# [DoNotCheckSecurity], [Unforgeable]
-def access_control_list(interface, attribute):
-    extended_attributes = attribute.extended_attributes
-    access_control = []
-    if 'DoNotCheckSecurity' in extended_attributes:
-        do_not_check_security = extended_attributes['DoNotCheckSecurity']
-        if do_not_check_security == 'Setter':
-            access_control.append('v8::ALL_CAN_WRITE')
-        else:
-            access_control.append('v8::ALL_CAN_READ')
-            if has_setter(attribute):
-                access_control.append('v8::ALL_CAN_WRITE')
-    if is_unforgeable(interface, attribute):
-        access_control.append('v8::PROHIBITS_OVERWRITING')
-    return access_control or ['v8::DEFAULT']
+def is_data_type_property(interface, attribute):
+    if 'CachedAccessor' in attribute.extended_attributes:
+        return False
+    return (is_constructor_attribute(attribute) or
+            'CrossOrigin' in attribute.extended_attributes)
+
+
+# [PutForwards], [Replaceable]
+def has_setter(interface, attribute):
+    if (is_data_type_property(interface, attribute) and
+        (is_constructor_attribute(attribute) or
+         'Replaceable' in attribute.extended_attributes)):
+        return False
+
+    return is_writable(attribute)
 
 
 # [NotEnumerable], [Unforgeable]
@@ -478,10 +567,12 @@
     extended_attributes = attribute.extended_attributes
     property_attributes_list = []
     if ('NotEnumerable' in extended_attributes or
-        is_constructor_attribute(attribute)):
+            is_constructor_attribute(attribute)):
         property_attributes_list.append('v8::DontEnum')
     if is_unforgeable(interface, attribute):
         property_attributes_list.append('v8::DontDelete')
+    if not is_writable(attribute):
+        property_attributes_list.append('v8::ReadOnly')
     return property_attributes_list or ['v8::None']
 
 
@@ -505,19 +596,12 @@
 ################################################################################
 
 idl_types.IdlType.constructor_type_name = property(
-    # FIXME: replace this with a [ConstructorAttribute] extended attribute
     lambda self: strip_suffix(self.base_type, 'Constructor'))
 
 
 def is_constructor_attribute(attribute):
-    # FIXME: replace this with [ConstructorAttribute] extended attribute
     return attribute.idl_type.name.endswith('Constructor')
 
 
-def update_constructor_attribute_context(interface, attribute, context):
-    context['needs_constructor_getter_callback'] = context['measure_as'] or context['deprecate_as'] or context['origin_trial_name']
-    # When the attribute name is the same as the interface name, do not generate
-    # callback functions for each attribute and use
-    # {{cpp_class}}ConstructorAttributeSetterCallback.  Otherwise, generate
-    # a callback function in order to hard-code the attribute name.
-    context['needs_constructor_setter_callback'] = context['name'] != context['constructor_type']
+def is_named_constructor_attribute(attribute):
+    return attribute.idl_type.name.endswith('ConstructorConstructor')
diff --git a/bindings/scripts/v8_callback_function.py b/bindings/scripts/v8_callback_function.py
new file mode 100644
index 0000000..4f51dd2
--- /dev/null
+++ b/bindings/scripts/v8_callback_function.py
@@ -0,0 +1,110 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generate template values for a callback function.
+
+Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
+"""
+
+from utilities import to_snake_case
+from v8_globals import includes
+
+CALLBACK_FUNCTION_H_INCLUDES = frozenset([
+    'bindings/core/v8/NativeValueTraits.h',
+    'platform/bindings/CallbackFunctionBase.h',
+    'platform/bindings/ScriptWrappable.h',
+    'platform/bindings/TraceWrapperV8Reference.h',
+    'platform/heap/Handle.h',
+    'platform/wtf/text/WTFString.h',
+])
+CALLBACK_FUNCTION_CPP_INCLUDES = frozenset([
+    'bindings/core/v8/ExceptionState.h',
+    'platform/bindings/ScriptState.h',
+    'bindings/core/v8/NativeValueTraitsImpl.h',
+    'bindings/core/v8/ToV8ForCore.h',
+    'bindings/core/v8/V8BindingForCore.h',
+    'core/dom/ExecutionContext.h',
+    'platform/wtf/Assertions.h',
+])
+
+
+def callback_function_context(callback_function):
+    includes.clear()
+    includes.update(CALLBACK_FUNCTION_CPP_INCLUDES)
+    idl_type = callback_function.idl_type
+    idl_type_str = str(idl_type)
+
+    for argument in callback_function.arguments:
+        argument.idl_type.add_includes_for_type(
+            callback_function.extended_attributes)
+
+    context = {
+        # While both |callback_function_name| and |cpp_class| are identical at
+        # the moment, the two are being defined because their values may change
+        # in the future (e.g. if we support [ImplementedAs=] in callback
+        # functions).
+        'callback_function_name': callback_function.name,
+        'cpp_class': 'V8%s' % callback_function.name,
+        'cpp_includes': sorted(includes),
+        'forward_declarations': sorted(forward_declarations(callback_function)),
+        'header_includes': sorted(CALLBACK_FUNCTION_H_INCLUDES),
+        'idl_type': idl_type_str,
+        'this_include_header_name': to_snake_case('V8%s' % callback_function.name),
+    }
+
+    if idl_type_str != 'void':
+        context.update({
+            'return_cpp_type': idl_type.cpp_type + '&',
+            'return_value': idl_type.v8_value_to_local_cpp_value(
+                callback_function.extended_attributes,
+                'v8ReturnValue', 'cppValue',
+                isolate='script_state_->GetIsolate()',
+                bailout_return_value='false'),
+        })
+
+    context.update(arguments_context(callback_function.arguments, context.get('return_cpp_type')))
+    return context
+
+
+def forward_declarations(callback_function):
+    def find_forward_declaration(idl_type):
+        if idl_type.is_interface_type or idl_type.is_dictionary:
+            return idl_type.implemented_as
+        elif idl_type.is_array_or_sequence_type:
+            return find_forward_declaration(idl_type.element_type)
+        return None
+
+    declarations = []
+    for argument in callback_function.arguments:
+        name = find_forward_declaration(argument.idl_type)
+        if name:
+            declarations.append(name)
+    return declarations
+
+
+def arguments_context(arguments, return_cpp_type):
+    def argument_context(argument):
+        idl_type = argument.idl_type
+        return {
+            'cpp_value_to_v8_value': idl_type.cpp_value_to_v8_value(
+                argument.name, isolate='script_state_->GetIsolate()',
+                creation_context='script_state_->GetContext()->Global()'),
+            'enum_type': idl_type.enum_type,
+            'enum_values': idl_type.enum_values,
+            'name': argument.name,
+            'v8_name': 'v8_%s' % argument.name,
+        }
+
+    argument_declarations = [
+        'ScriptWrappable* scriptWrappable',
+    ]
+    argument_declarations.extend(
+        '%s %s' % (argument.idl_type.callback_cpp_type, argument.name)
+        for argument in arguments)
+    if return_cpp_type:
+        argument_declarations.append('%s returnValue' % return_cpp_type)
+    return {
+        'argument_declarations': argument_declarations,
+        'arguments': [argument_context(argument) for argument in arguments],
+    }
diff --git a/bindings/scripts/v8_callback_interface.py b/bindings/scripts/v8_callback_interface.py
index 682cb55..c034dd3 100644
--- a/bindings/scripts/v8_callback_interface.py
+++ b/bindings/scripts/v8_callback_interface.py
@@ -35,21 +35,28 @@
 
 from idl_types import IdlTypeBase
 from v8_globals import includes
+from v8_interface import constant_context
 import v8_types
 import v8_utilities
 
 CALLBACK_INTERFACE_H_INCLUDES = frozenset([
-    'bindings/core/v8/ActiveDOMCallback.h',
-    'bindings/core/v8/DOMWrapperWorld.h',
-    'bindings/core/v8/ScopedPersistent.h',
+    'platform/bindings/DOMWrapperWorld.h',
+    'platform/bindings/ScopedPersistent.h',
 ])
 CALLBACK_INTERFACE_CPP_INCLUDES = frozenset([
     'bindings/core/v8/ScriptController.h',
-    'bindings/core/v8/V8Binding.h',
+    'bindings/core/v8/V8BindingForCore.h',
     'core/dom/ExecutionContext.h',
-    'wtf/Assertions.h',
-    'wtf/GetPtr.h',
-    'wtf/RefPtr.h',
+    'platform/wtf/Assertions.h',
+    'platform/wtf/GetPtr.h',
+    'platform/wtf/RefPtr.h',
+])
+LEGACY_CALLBACK_INTERFACE_CPP_INCLUDES = frozenset([
+    'bindings/core/v8/ScriptController.h',
+    'bindings/core/v8/V8BindingForCore.h',
+    'bindings/core/v8/V8DOMConfiguration.h',
+    'core/dom/ExecutionContext.h',
+    'platform/wtf/Assertions.h',
 ])
 
 
@@ -57,21 +64,21 @@
     # FIXME: remove this function by making callback types consistent
     # (always use usual v8_types.cpp_type)
     idl_type_name = idl_type.name
-    if idl_type_name == 'String':
+    if idl_type_name == 'String' or idl_type.is_enum:
         return 'const String&'
     if idl_type_name == 'void':
         return 'void'
     # Callbacks use raw pointers, so raw_type=True
     raw_cpp_type = idl_type.cpp_type_args(raw_type=True)
     # Pass containers and dictionaries to callback method by const reference rather than by value
-    if raw_cpp_type.startswith(('Vector', 'HeapVector', 'WillBeHeapVector')) or idl_type.is_dictionary:
+    if raw_cpp_type.startswith(('Vector', 'HeapVector')) or idl_type.is_dictionary:
         return 'const %s&' % raw_cpp_type
     return raw_cpp_type
 
 IdlTypeBase.callback_cpp_type = property(cpp_type)
 
 
-def callback_interface_context(callback_interface):
+def callback_interface_context(callback_interface, _):
     includes.clear()
     includes.update(CALLBACK_INTERFACE_CPP_INCLUDES)
     return {
@@ -83,6 +90,20 @@
     }
 
 
+def legacy_callback_interface_context(callback_interface, _):
+    includes.clear()
+    includes.update(LEGACY_CALLBACK_INTERFACE_CPP_INCLUDES)
+    return {
+        # TODO(bashi): Fix crbug.com/630986, and add 'methods'.
+        'constants': [constant_context(constant, callback_interface)
+                      for constant in callback_interface.constants],
+        'cpp_class': callback_interface.name,
+        'header_includes': set(CALLBACK_INTERFACE_H_INCLUDES),
+        'interface_name': callback_interface.name,
+        'v8_class': v8_utilities.v8_class_name(callback_interface),
+    }
+
+
 def add_includes_for_operation(operation):
     operation.idl_type.add_includes_for_type()
     for argument in operation.arguments:
@@ -117,8 +138,8 @@
         return {
             'handle': '%sHandle' % argument.name,
             'cpp_value_to_v8_value': argument.idl_type.cpp_value_to_v8_value(
-                argument.name, isolate='m_scriptState->isolate()',
-                creation_context='m_scriptState->context()->Global()'),
+                argument.name, isolate='script_state_->GetIsolate()',
+                creation_context='script_state_->GetContext()->Global()'),
         }
 
     argument_declarations = ['ScriptValue thisValue'] if call_with_this_handle else []
diff --git a/bindings/scripts/v8_dictionary.py b/bindings/scripts/v8_dictionary.py
index dde7e1c..0909d11 100644
--- a/bindings/scripts/v8_dictionary.py
+++ b/bindings/scripts/v8_dictionary.py
@@ -8,6 +8,7 @@
 
 import operator
 from idl_types import IdlType
+from utilities import to_snake_case
 from v8_globals import includes
 import v8_types
 import v8_utilities
@@ -15,8 +16,9 @@
 
 
 DICTIONARY_H_INCLUDES = frozenset([
-    'bindings/core/v8/ToV8.h',
-    'bindings/core/v8/V8Binding.h',
+    'bindings/core/v8/NativeValueTraits.h',
+    'bindings/core/v8/ToV8ForCore.h',
+    'bindings/core/v8/V8BindingForCore.h',
     'platform/heap/Handle.h',
 ])
 
@@ -25,6 +27,11 @@
 ])
 
 
+def getter_name_for_dictionary_member(member):
+    name = v8_utilities.cpp_name(member)
+    return name
+
+
 def setter_name_for_dictionary_member(member):
     name = v8_utilities.cpp_name(member)
     return 'set%s' % v8_utilities.capitalize(name)
@@ -53,13 +60,25 @@
 def dictionary_context(dictionary, interfaces_info):
     includes.clear()
     includes.update(DICTIONARY_CPP_INCLUDES)
+
+    if 'RuntimeEnabled' in dictionary.extended_attributes:
+        raise Exception(
+            'Dictionary cannot be RuntimeEnabled: %s' % dictionary.name)
+
+    members = [member_context(dictionary, member)
+               for member in sorted(dictionary.members,
+                                    key=operator.attrgetter('name'))]
+
+    for member in members:
+        if member['runtime_enabled_feature_name']:
+            includes.add('platform/runtime_enabled_features.h')
+            break
+
     cpp_class = v8_utilities.cpp_name(dictionary)
     context = {
         'cpp_class': cpp_class,
         'header_includes': set(DICTIONARY_H_INCLUDES),
-        'members': [member_context(dictionary, member)
-                    for member in sorted(dictionary.members,
-                                         key=operator.attrgetter('name'))],
+        'members': members,
         'required_member_names': sorted([member.name
                                          for member in dictionary.members
                                          if member.is_required]),
@@ -101,7 +120,8 @@
         return cpp_default_value, v8_default_value
 
     cpp_default_value, v8_default_value = default_values()
-    cpp_name = v8_utilities.cpp_name(member)
+    cpp_name = to_snake_case(v8_utilities.cpp_name(member))
+    getter_name = getter_name_for_dictionary_member(member)
     is_deprecated_dictionary = unwrapped_idl_type.name == 'Dictionary'
 
     return {
@@ -109,26 +129,27 @@
         'cpp_name': cpp_name,
         'cpp_type': unwrapped_idl_type.cpp_type,
         'cpp_value_to_v8_value': unwrapped_idl_type.cpp_value_to_v8_value(
-            cpp_value='impl.%s()' % cpp_name, isolate='isolate',
+            cpp_value='impl.%s()' % getter_name, isolate='isolate',
             creation_context='creationContext',
             extended_attributes=extended_attributes),
         'deprecate_as': v8_utilities.deprecate_as(member),
         'enum_type': idl_type.enum_type,
         'enum_values': unwrapped_idl_type.enum_values,
+        'getter_name': getter_name,
         'has_method_name': has_method_name_for_dictionary_member(member),
         'idl_type': idl_type.base_type,
-        'is_interface_type': idl_type.is_interface_type and not (idl_type.is_dictionary_type or is_deprecated_dictionary),
+        'is_interface_type': idl_type.is_interface_type and not is_deprecated_dictionary,
         'is_nullable': idl_type.is_nullable,
         'is_object': unwrapped_idl_type.name == 'Object' or is_deprecated_dictionary,
         'is_required': member.is_required,
         'name': member.name,
-        'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(member),  # [RuntimeEnabled]
+        'runtime_enabled_feature_name': v8_utilities.runtime_enabled_feature_name(member),  # [RuntimeEnabled]
         'setter_name': setter_name_for_dictionary_member(member),
         'null_setter_name': null_setter_name_for_dictionary_member(member),
         'v8_default_value': v8_default_value,
         'v8_value_to_local_cpp_value': unwrapped_idl_type.v8_value_to_local_cpp_value(
             extended_attributes, member.name + 'Value',
-            member.name, isolate='isolate', use_exception_state=True),
+            member.name + 'CppValue', isolate='isolate', use_exception_state=True),
     }
 
 
@@ -149,11 +170,14 @@
         return sorted(members_dict.values(), key=lambda member: member['cpp_name'])
 
     includes.clear()
+    header_forward_decls = set()
     header_includes = set(['platform/heap/Handle.h'])
-    members = [member_impl_context(member, interfaces_info, header_includes)
+    members = [member_impl_context(member, interfaces_info,
+                                   header_includes, header_forward_decls)
                for member in dictionary.members]
     members = remove_duplicate_members(members)
     context = {
+        'header_forward_decls': header_forward_decls,
         'header_includes': header_includes,
         'cpp_class': v8_utilities.cpp_name(dictionary),
         'members': members,
@@ -165,49 +189,68 @@
         if parent_interface_info:
             context['header_includes'].add(
                 parent_interface_info['include_path'])
+    else:
+        context['parent_cpp_class'] = 'IDLDictionaryBase'
+        context['header_includes'].add(
+            'bindings/core/v8/IDLDictionaryBase.h')
     return context
 
 
-def member_impl_context(member, interfaces_info, header_includes):
+def member_impl_context(member, interfaces_info, header_includes,
+                        header_forward_decls):
     idl_type = unwrap_nullable_if_needed(member.idl_type)
-    cpp_name = v8_utilities.cpp_name(member)
+    cpp_name = to_snake_case(v8_utilities.cpp_name(member))
 
-    def getter_expression():
-        if idl_type.impl_should_use_nullable_container:
-            return 'm_%s.get()' % cpp_name
-        return 'm_%s' % cpp_name
+    nullable_indicator_name = None
+    if not idl_type.cpp_type_has_null_value:
+        nullable_indicator_name = 'has_' + cpp_name + '_'
 
     def has_method_expression():
-        if idl_type.impl_should_use_nullable_container or idl_type.is_enum or idl_type.is_string_type or idl_type.is_union_type:
-            return '!m_%s.isNull()' % cpp_name
-        elif idl_type.name in ['Any', 'Object']:
-            return '!(m_{0}.isEmpty() || m_{0}.isNull() || m_{0}.isUndefined())'.format(cpp_name)
-        elif idl_type.name == 'Dictionary':
-            return '!m_%s.isUndefinedOrNull()' % cpp_name
-        else:
-            return 'm_%s' % cpp_name
-
-    def member_cpp_type():
-        member_cpp_type = idl_type.cpp_type_args(used_in_cpp_sequence=True)
-        if idl_type.impl_should_use_nullable_container:
-            return v8_types.cpp_template_type('Nullable', member_cpp_type)
-        return member_cpp_type
+        if nullable_indicator_name:
+            return nullable_indicator_name
+        if idl_type.is_union_type or idl_type.is_enum or idl_type.is_string_type:
+            return '!%s_.IsNull()' % cpp_name
+        if idl_type.name in ['Any', 'Object']:
+            return '!({0}_.IsEmpty() || {0}_.IsNull() || {0}_.IsUndefined())'.format(cpp_name)
+        if idl_type.name == 'Dictionary':
+            return '!%s_.IsUndefinedOrNull()' % cpp_name
+        return '%s_' % cpp_name
 
     cpp_default_value = None
     if member.default_value and not member.default_value.is_null:
         cpp_default_value = idl_type.literal_cpp_value(member.default_value)
 
-    header_includes.update(idl_type.impl_includes_for_type(interfaces_info))
+    forward_decl_name = idl_type.impl_forward_declaration_name
+    if forward_decl_name:
+        includes.update(idl_type.impl_includes_for_type(interfaces_info))
+        header_forward_decls.add(forward_decl_name)
+    else:
+        header_includes.update(idl_type.impl_includes_for_type(interfaces_info))
+
+    setter_value = 'value'
+    if idl_type.is_array_buffer_view_or_typed_array:
+        setter_value += '.View()'
+
+    non_null_type = idl_type.inner_type if idl_type.is_nullable else idl_type
+    setter_inline = 'inline ' if (
+        non_null_type.is_basic_type or
+        non_null_type.is_enum or
+        non_null_type.is_wrapper_type) else ''
+
     return {
         'cpp_default_value': cpp_default_value,
         'cpp_name': cpp_name,
-        'getter_expression': getter_expression(),
+        'getter_expression': cpp_name + '_',
+        'getter_name': getter_name_for_dictionary_member(member),
         'has_method_expression': has_method_expression(),
         'has_method_name': has_method_name_for_dictionary_member(member),
         'is_nullable': idl_type.is_nullable,
         'is_traceable': idl_type.is_traceable,
-        'member_cpp_type': member_cpp_type(),
+        'member_cpp_type': idl_type.cpp_type_args(used_in_cpp_sequence=True),
         'null_setter_name': null_setter_name_for_dictionary_member(member),
+        'nullable_indicator_name': nullable_indicator_name,
         'rvalue_cpp_type': idl_type.cpp_type_args(used_as_rvalue_type=True),
+        'setter_inline': setter_inline,
         'setter_name': setter_name_for_dictionary_member(member),
+        'setter_value': setter_value,
     }
diff --git a/bindings/scripts/v8_globals.py b/bindings/scripts/v8_globals.py
index 9ca2a35..55ed257 100644
--- a/bindings/scripts/v8_globals.py
+++ b/bindings/scripts/v8_globals.py
@@ -29,4 +29,3 @@
 """Module to share global variables (includes and interfaces) across modules."""
 
 includes = set()
-interfaces = {}
diff --git a/bindings/scripts/v8_interface.py b/bindings/scripts/v8_interface.py
index 35edaee..c8b3245 100644
--- a/bindings/scripts/v8_interface.py
+++ b/bindings/scripts/v8_interface.py
@@ -27,49 +27,175 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# pylint: disable=relative-import
+
 """Generate template values for an interface.
 
 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
 """
+from operator import or_
 
-from collections import defaultdict
-import itertools
-from operator import itemgetter
-
-import idl_definitions
-from idl_definitions import IdlOperation, IdlArgument
-import idl_types
+from idl_definitions import IdlAttribute, IdlOperation, IdlArgument
 from idl_types import IdlType, inherits_interface
+from overload_set_algorithm import effective_overload_set_by_length
+from overload_set_algorithm import method_overloads_by_name
+
 import v8_attributes
 from v8_globals import includes
 import v8_methods
 import v8_types
-from v8_types import cpp_ptr_type, cpp_template_type
 import v8_utilities
-from v8_utilities import (origin_trial_enabled_function, cpp_name_or_partial, capitalize, cpp_name, gc_type,
-                          has_extended_attribute_value, runtime_enabled_function_name,
-                          extended_attribute_value_as_list, is_legacy_interface_type_checking)
+from v8_utilities import (context_enabled_feature_name, cpp_name_or_partial, cpp_name,
+                          has_extended_attribute_value, runtime_enabled_feature_name,
+                          is_legacy_interface_type_checking)
 
 
 INTERFACE_H_INCLUDES = frozenset([
-    'bindings/core/v8/ScriptWrappable.h',
-    'bindings/core/v8/ToV8.h',
-    'bindings/core/v8/V8Binding.h',
-    'bindings/core/v8/V8DOMWrapper.h',
-    'bindings/core/v8/WrapperTypeInfo.h',
+    'bindings/core/v8/GeneratedCodeHelper.h',
+    'bindings/core/v8/NativeValueTraits.h',
+    'platform/bindings/ScriptWrappable.h',
+    'bindings/core/v8/ToV8ForCore.h',
+    'bindings/core/v8/V8BindingForCore.h',
+    'platform/bindings/V8DOMWrapper.h',
+    'platform/bindings/WrapperTypeInfo.h',
     'platform/heap/Handle.h',
 ])
 INTERFACE_CPP_INCLUDES = frozenset([
     'bindings/core/v8/ExceptionState.h',
     'bindings/core/v8/V8DOMConfiguration.h',
-    'bindings/core/v8/V8ObjectConstructor.h',
-    'core/dom/Document.h',
-    'wtf/GetPtr.h',
-    'wtf/RefPtr.h',
+    'platform/bindings/V8ObjectConstructor.h',
+    'core/dom/ExecutionContext.h',
+    'platform/wtf/GetPtr.h',
+    'platform/wtf/RefPtr.h',
 ])
 
 
-def interface_context(interface):
+def filter_has_constant_configuration(constants):
+    return [constant for constant in constants if
+            not constant['measure_as'] and
+            not constant['deprecate_as'] and
+            not constant['runtime_enabled_feature_name'] and
+            not constant['origin_trial_feature_name']]
+
+
+def filter_has_special_getter(constants):
+    return [constant for constant in constants if
+            constant['measure_as'] or
+            constant['deprecate_as']]
+
+
+def filter_runtime_enabled(constants):
+    return [constant for constant in constants if
+            constant['runtime_enabled_feature_name']]
+
+
+def filter_origin_trial_enabled(constants):
+    return [constant for constant in constants if
+            constant['origin_trial_feature_name']]
+
+
+def constant_filters():
+    return {'has_constant_configuration': filter_has_constant_configuration,
+            'has_special_getter': filter_has_special_getter,
+            'runtime_enabled_constants': filter_runtime_enabled,
+            'origin_trial_enabled_constants': filter_origin_trial_enabled}
+
+
+def origin_trial_features(interface, constants, attributes, methods):
+    """ Returns a list of the origin trial features used in this interface.
+
+    Each element is a dictionary with keys 'name' and 'needs_instance'.
+    'needs_instance' is true if any member associated with the interface needs
+    to be installed on every instance of the interface. This list is the union
+    of the sets of features used for constants, attributes and methods.
+    """
+    KEY = 'origin_trial_feature_name'  # pylint: disable=invalid-name
+
+    def member_filter(members):
+        return sorted([member for member in members if member.get(KEY) and not member.get('exposed_test')])
+
+    def member_filter_by_name(members, name):
+        return [member for member in members if member[KEY] == name]
+
+    # Collect all members visible on this interface with a defined origin trial
+    origin_trial_constants = member_filter(constants)
+    origin_trial_attributes = member_filter(attributes)
+    origin_trial_methods = member_filter([method for method in methods
+                                          if v8_methods.method_is_visible(method, interface.is_partial) and
+                                          not v8_methods.custom_registration(method)])
+
+    feature_names = set([member[KEY] for member in origin_trial_constants + origin_trial_attributes + origin_trial_methods])
+
+    # Construct the list of dictionaries. 'needs_instance' will be true if any
+    # member for the feature has 'on_instance' defined as true.
+    features = [{'name': name,
+                 'constants': member_filter_by_name(origin_trial_constants, name),
+                 'attributes': member_filter_by_name(origin_trial_attributes, name),
+                 'methods': member_filter_by_name(origin_trial_methods, name)}
+                for name in feature_names]
+    for feature in features:
+        members = feature['constants'] + feature['attributes'] + feature['methods']
+        feature['needs_instance'] = any(member.get('on_instance', False) for member in members)
+        # TODO(chasej): Need to handle method overloads? e.g.
+        # (method['overloads']['secure_context_test_all'] if 'overloads' in method else method['secure_context_test'])
+        feature['needs_secure_context'] = any(member.get('secure_context_test', False) for member in members)
+
+    if features:
+        includes.add('platform/bindings/ScriptState.h')
+        includes.add('core/origin_trials/origin_trials.h')
+    return features
+
+
+def context_enabled_features(attributes):
+    """ Returns a list of context-enabled features from a set of attributes.
+
+    Each element is a dictionary with the feature's |name| and lists of
+    |attributes| associated with the feature.
+    """
+    KEY = 'context_enabled_feature_name'  # pylint: disable=invalid-name
+
+    def member_filter(members):
+        return sorted([member for member in members if member.get(KEY) and not member.get('exposed_test')])
+
+    def member_filter_by_name(members, name):
+        return [member for member in members if member[KEY] == name]
+
+    # Collect all members visible on this interface with a defined origin trial
+    context_enabled_attributes = member_filter(attributes)
+    feature_names = set([member[KEY] for member in context_enabled_attributes])
+    features = [{'name': name,
+                 'attributes': member_filter_by_name(context_enabled_attributes, name),
+                 'needs_instance': False}
+                for name in feature_names]
+    if features:
+        includes.add('platform/bindings/ScriptState.h')
+    return features
+
+
+def runtime_call_stats_context(interface):
+    counter_prefix = 'Blink_' + v8_utilities.cpp_name(interface) + '_'
+    return {
+        'constructor_counter': counter_prefix + 'Constructor',
+        'cross_origin_named_getter_counter': counter_prefix + 'CrossOriginNamedGetter',
+        'cross_origin_named_setter_counter': counter_prefix + 'CrossOriginNamedSetter',
+        'indexed_property_getter_counter': counter_prefix + 'IndexedPropertyGetter',
+        'named_property_getter_counter': counter_prefix + 'NamedPropertyGetter',
+        'named_property_query_counter': counter_prefix + 'NamedPropertyQuery',
+        'named_property_setter_counter': counter_prefix + 'NamedPropertySetter',
+    }
+
+def interface_context(interface, interfaces):
+    """Creates a Jinja template context for an interface.
+
+    Args:
+        interface: An interface to create the context for
+        interfaces: A dict which maps an interface name to the definition
+            which can be referred if needed
+
+    Returns:
+        A Jinja template context for |interface|
+    """
+
     includes.clear()
     includes.update(INTERFACE_CPP_INCLUDES)
     header_includes = set(INTERFACE_H_INCLUDES)
@@ -108,10 +234,14 @@
             'bindings/core/v8/V8Float64Array.h',
             'bindings/core/v8/V8DataView.h'))
 
+    # [ActiveScriptWrappable]
+    active_scriptwrappable = 'ActiveScriptWrappable' in extended_attributes
+
     # [CheckSecurity]
     is_check_security = 'CheckSecurity' in extended_attributes
     if is_check_security:
         includes.add('bindings/core/v8/BindingSecurity.h')
+        includes.add('core/frame/LocalDOMWindow.h')
 
     # [DependentLifetime]
     is_dependent_lifetime = 'DependentLifetime' in extended_attributes
@@ -120,81 +250,62 @@
     is_global = ('PrimaryGlobal' in extended_attributes or
                  'Global' in extended_attributes)
 
-    # [SetWrapperReferenceFrom]
-    set_wrapper_reference_from = extended_attributes.get('SetWrapperReferenceFrom')
-    if set_wrapper_reference_from:
-        includes.update(['bindings/core/v8/V8GCController.h',
-                         'core/dom/Element.h'])
+    # [ImmutablePrototype]
+    # TODO(littledan): Is it possible to deduce this based on inheritance,
+    # as in the WebIDL spec?
+    is_immutable_prototype = is_global or 'ImmutablePrototype' in extended_attributes
 
-    # [SetWrapperReferenceTo]
-    set_wrapper_reference_to_argument = extended_attributes.get('SetWrapperReferenceTo')
-    set_wrapper_reference_to = None
-    if set_wrapper_reference_to_argument:
-        set_wrapper_reference_to = {
-            'name': set_wrapper_reference_to_argument.name,
-            # FIXME: properly should be:
-            # 'cpp_type': set_wrapper_reference_to_argument.idl_type.cpp_type_args(raw_type=True),
-            # (if type is non-wrapper type like NodeFilter, normally RefPtr)
-            # Raw pointers faster though, and NodeFilter hacky anyway.
-            'cpp_type': set_wrapper_reference_to_argument.idl_type.implemented_as + '*',
-            'idl_type': set_wrapper_reference_to_argument.idl_type,
-            'v8_type': v8_types.v8_type(set_wrapper_reference_to_argument.idl_type.name),
-        }
-        set_wrapper_reference_to['idl_type'].add_includes_for_type()
+    wrapper_class_id = ('kNodeClassId' if inherits_interface(interface.name, 'Node') else 'kObjectClassId')
 
-    # [SetWrapperReferenceFrom]
-    has_visit_dom_wrapper = (
-        has_extended_attribute_value(interface, 'Custom', 'VisitDOMWrapper') or
-        set_wrapper_reference_from or set_wrapper_reference_to)
+    # [ActiveScriptWrappable] must be accompanied with [DependentLifetime].
+    if active_scriptwrappable and not is_dependent_lifetime:
+        raise Exception('[ActiveScriptWrappable] interface must also specify '
+                        '[DependentLifetime]: %s' % interface.name)
 
-    this_gc_type = gc_type(interface)
-
-    wrapper_class_id = ('NodeClassId' if inherits_interface(interface.name, 'Node') else 'ObjectClassId')
+    # [LegacyUnenumerableNamedProperties]
+    # pylint: disable=C0103
+    has_legacy_unenumerable_named_properties = (interface.has_named_property_getter and
+                                                'LegacyUnenumerableNamedProperties' in extended_attributes)
 
     v8_class_name = v8_utilities.v8_class_name(interface)
     cpp_class_name = cpp_name(interface)
     cpp_class_name_or_partial = cpp_name_or_partial(interface)
     v8_class_name_or_partial = v8_utilities.v8_class_name_or_partial(interface)
 
-    if 'RuntimeEnabled' in extended_attributes:
-        includes.add('platform/RuntimeEnabledFeatures.h')
-
-    if 'OriginTrialEnabled' in extended_attributes:
-        includes.add('core/inspector/ConsoleMessage.h')
-        includes.add('core/origin_trials/OriginTrials.h')
+    # TODO(peria): Generate the target list from 'Window' and 'HTMLDocument'.
+    needs_runtime_enabled_installer = v8_class_name in [
+        'V8Window', 'V8HTMLDocument', 'V8Document', 'V8Node', 'V8EventTarget']
 
     context = {
+        'active_scriptwrappable': active_scriptwrappable,
+        'context_enabled_feature_name': context_enabled_feature_name(interface),  # [ContextEnabled]
         'cpp_class': cpp_class_name,
         'cpp_class_or_partial': cpp_class_name_or_partial,
-        'event_target_inheritance': 'InheritFromEventTarget' if is_event_target else 'NotInheritFromEventTarget',
-        'gc_type': this_gc_type,
+        'is_gc_type': True,
         # FIXME: Remove 'EventTarget' special handling, http://crbug.com/383699
         'has_access_check_callbacks': (is_check_security and
-                                       interface.name != 'Window' and
                                        interface.name != 'EventTarget'),
         'has_custom_legacy_call_as_function': has_extended_attribute_value(interface, 'Custom', 'LegacyCallAsFunction'),  # [Custom=LegacyCallAsFunction]
+        'has_legacy_unenumerable_named_properties': has_legacy_unenumerable_named_properties,
         'has_partial_interface': len(interface.partial_interfaces) > 0,
-        'has_visit_dom_wrapper': has_visit_dom_wrapper,
         'header_includes': header_includes,
         'interface_name': interface.name,
         'is_array_buffer_or_view': is_array_buffer_or_view,
         'is_check_security': is_check_security,
         'is_event_target': is_event_target,
-        'is_exception': interface.is_exception,
         'is_global': is_global,
+        'is_immutable_prototype': is_immutable_prototype,
         'is_node': inherits_interface(interface.name, 'Node'),
         'is_partial': interface.is_partial,
         'is_typed_array_type': is_typed_array_type,
-        'lifetime': 'Dependent' if (has_visit_dom_wrapper or is_dependent_lifetime) else 'Independent',
+        'lifetime': 'kDependent' if is_dependent_lifetime else 'kIndependent',
         'measure_as': v8_utilities.measure_as(interface, None),  # [MeasureAs]
-        'origin_trial_name': v8_utilities.origin_trial_name(interface),
+        'needs_runtime_enabled_installer': needs_runtime_enabled_installer,
+        'origin_trial_enabled_function': v8_utilities.origin_trial_enabled_function_name(interface),
         'parent_interface': parent_interface,
-        'pass_cpp_type': cpp_template_type(
-            cpp_ptr_type('PassRefPtr', 'RawPtr', this_gc_type),
-            cpp_name(interface)),
-        'runtime_enabled_function': runtime_enabled_function_name(interface),  # [RuntimeEnabled]
-        'set_wrapper_reference_from': set_wrapper_reference_from,
-        'set_wrapper_reference_to': set_wrapper_reference_to,
+        'pass_cpp_type': cpp_name(interface) + '*',
+        'runtime_call_stats': runtime_call_stats_context(interface),
+        'runtime_enabled_feature_name': runtime_enabled_feature_name(interface),  # [RuntimeEnabled]
         'v8_class': v8_class_name,
         'v8_class_or_partial': v8_class_name_or_partial,
         'wrapper_class_id': wrapper_class_id,
@@ -216,6 +327,16 @@
             number_of_required_arguments(constructor),
     } for constructor in interface.custom_constructors]
 
+    # [HTMLConstructor]
+    has_html_constructor = 'HTMLConstructor' in extended_attributes
+    # https://html.spec.whatwg.org/multipage/dom.html#html-element-constructors
+    if has_html_constructor:
+        if ('Constructor' in extended_attributes) or ('NoInterfaceObject' in extended_attributes):
+            raise Exception('[Constructor] and [NoInterfaceObject] MUST NOT be'
+                            ' specified with [HTMLConstructor]: '
+                            '%s' % interface.name)
+        includes.add('bindings/core/v8/V8HTMLConstructor.h')
+
     # [NamedConstructor]
     named_constructor = named_constructor_context(interface)
 
@@ -224,91 +345,241 @@
             raise Exception('[Constructor] and [NamedConstructor] MUST NOT be'
                             ' specified on partial interface definitions: '
                             '%s' % interface.name)
+        if named_constructor:
+            includes.add('platform/bindings/V8PrivateProperty.h')
 
-        includes.add('bindings/core/v8/V8ObjectConstructor.h')
+        includes.add('platform/bindings/V8ObjectConstructor.h')
         includes.add('core/frame/LocalDOMWindow.h')
     elif 'Measure' in extended_attributes or 'MeasureAs' in extended_attributes:
-        raise Exception('[Measure] or [MeasureAs] specified for interface without a constructor: '
-                        '%s' % interface.name)
+        if not interface.is_partial:
+            raise Exception('[Measure] or [MeasureAs] specified for interface without a constructor: '
+                            '%s' % interface.name)
 
-    # [Unscopeable] attributes and methods
-    unscopeables = []
+    # [ConstructorCallWith=Document]
+    if has_extended_attribute_value(interface, 'ConstructorCallWith', 'Document'):
+        includes.add('core/dom/Document.h')
+
+    # [Unscopable] attributes and methods
+    unscopables = []
     for attribute in interface.attributes:
-        if 'Unscopeable' in attribute.extended_attributes:
-            unscopeables.append((attribute.name, v8_utilities.runtime_enabled_function_name(attribute)))
+        if 'Unscopable' in attribute.extended_attributes:
+            unscopables.append((attribute.name, runtime_enabled_feature_name(attribute)))
     for method in interface.operations:
-        if 'Unscopeable' in method.extended_attributes:
-            unscopeables.append((method.name, v8_utilities.runtime_enabled_function_name(method)))
+        if 'Unscopable' in method.extended_attributes:
+            unscopables.append((method.name, runtime_enabled_feature_name(method)))
+
+    # [CEReactions]
+    setter_or_deleters = (
+        interface.indexed_property_setter,
+        interface.indexed_property_deleter,
+        interface.named_property_setter,
+        interface.named_property_deleter,
+    )
+    has_ce_reactions = any(setter_or_deleter and 'CEReactions' in setter_or_deleter.extended_attributes
+                           for setter_or_deleter in setter_or_deleters)
+    if has_ce_reactions:
+        includes.add('core/html/custom/CEReactionsScope.h')
 
     context.update({
         'constructors': constructors,
         'has_custom_constructor': bool(custom_constructors),
+        'has_html_constructor': has_html_constructor,
         'interface_length':
-            interface_length(interface, constructors + custom_constructors),
+            interface_length(constructors + custom_constructors),
         'is_constructor_raises_exception': extended_attributes.get('RaisesException') == 'Constructor',  # [RaisesException=Constructor]
         'named_constructor': named_constructor,
-        'unscopeables': sorted(unscopeables),
+        'unscopables': sorted(unscopables),
     })
 
-    constants = [constant_context(constant, interface) for constant in interface.constants]
-
-    special_getter_constants = []
-    runtime_enabled_constants = dict()
-    constant_configuration_constants = []
-
-    for constant in constants:
-        if constant['measure_as'] or constant['deprecate_as'] or constant['origin_trial_name']:
-            special_getter_constants.append(constant)
-            continue
-        runtime_enabled_function = constant['runtime_enabled_function']
-        if runtime_enabled_function:
-            if runtime_enabled_function not in runtime_enabled_constants:
-                runtime_enabled_constants[runtime_enabled_function] = []
-            runtime_enabled_constants[runtime_enabled_function].append(constant)
-            continue
-        constant_configuration_constants.append(constant)
-
     # Constants
     context.update({
-        'constant_configuration_constants': constant_configuration_constants,
-        'constants': constants,
+        'constants': [constant_context(constant, interface) for constant in interface.constants],
         'do_not_check_constants': 'DoNotCheckConstants' in extended_attributes,
-        'has_constant_configuration': any(
-            not constant['runtime_enabled_function']
-            for constant in constants),
-        'runtime_enabled_constants': sorted(runtime_enabled_constants.iteritems()),
-        'special_getter_constants': special_getter_constants,
     })
 
     # Attributes
-    attributes = [v8_attributes.attribute_context(interface, attribute)
+    attributes = attributes_context(interface, interfaces)
+
+    context.update({
+        'attributes': attributes,
+        # Elements in attributes are broken in following members.
+        'accessors': v8_attributes.filter_accessors(attributes),
+        'data_attributes': v8_attributes.filter_data_attributes(attributes),
+        'lazy_data_attributes': v8_attributes.filter_lazy_data_attributes(attributes),
+        'runtime_enabled_attributes': v8_attributes.filter_runtime_enabled(attributes),
+    })
+
+    # Conditionally enabled attributes
+    conditional_enabled_attributes = v8_attributes.filter_conditionally_enabled(attributes)
+    has_conditional_attributes_on_prototype = any(  # pylint: disable=invalid-name
+        attribute['on_prototype'] for attribute in conditional_enabled_attributes)
+    has_conditionally_enabled_constructors = any(  # pylint: disable=invalid-name
+        attribute['constructor_type'] for attribute in conditional_enabled_attributes)
+    has_conditionally_enabled_secure_attributes = any(  # pylint: disable=invalid-name
+        v8_attributes.is_secure_context(attribute) for attribute in conditional_enabled_attributes)
+    context.update({
+        'has_conditionally_enabled_constructors':
+            has_conditionally_enabled_constructors,
+        'has_conditionally_enabled_secure_attributes':
+            has_conditionally_enabled_secure_attributes,
+        'conditionally_enabled_attributes': conditional_enabled_attributes,
+    })
+
+    # Methods
+    context.update(methods_context(interface))
+    methods = context['methods']
+    context.update({
+        'has_origin_safe_method_setter': any(method['is_cross_origin'] and not method['is_unforgeable']
+            for method in methods),
+    })
+
+    # Conditionally enabled methods
+    conditionally_enabled_methods = v8_methods.filter_conditionally_enabled(methods, interface.is_partial)
+    has_conditionally_enabled_secure_methods = any(  # pylint: disable=invalid-name
+        v8_methods.is_secure_context(method) for method in conditionally_enabled_methods)
+    context.update({
+        'has_conditionally_enabled_secure_methods':
+            has_conditionally_enabled_secure_methods,
+        'conditionally_enabled_methods': conditionally_enabled_methods,
+    })
+
+    # Window.idl in Blink has indexed properties, but the spec says Window
+    # interface doesn't have indexed properties, instead the WindowProxy exotic
+    # object has indexed properties.  Thus, Window interface must not support
+    # iterators.
+    has_array_iterator = (not interface.is_partial and
+                          interface.has_indexed_elements and
+                          interface.name != 'Window')
+    context.update({
+        'has_array_iterator': has_array_iterator,
+        'iterable': interface.iterable,
+    })
+
+    # Conditionally enabled members
+    prepare_prototype_and_interface_object_func = None  # pylint: disable=invalid-name
+    if (unscopables or has_conditional_attributes_on_prototype or
+            context['conditionally_enabled_methods']):
+        prepare_prototype_and_interface_object_func = '%s::preparePrototypeAndInterfaceObject' % v8_class_name_or_partial  # pylint: disable=invalid-name
+    has_install_conditional_features_on_global_func = has_conditionally_enabled_constructors  # pylint: disable=invalid-name
+
+    context.update({
+        'prepare_prototype_and_interface_object_func': prepare_prototype_and_interface_object_func,
+        'has_install_conditional_features_on_global_func': has_install_conditional_features_on_global_func,
+    })
+
+    context.update({
+        'legacy_caller': legacy_caller(interface.legacy_caller, interface),
+        'indexed_property_getter': property_getter(interface.indexed_property_getter, ['index']),
+        'indexed_property_setter': property_setter(interface.indexed_property_setter, interface),
+        'indexed_property_deleter': property_deleter(interface.indexed_property_deleter),
+        'is_override_builtins': 'OverrideBuiltins' in extended_attributes,
+        'named_property_getter': property_getter(interface.named_property_getter, ['name']),
+        'named_property_setter': property_setter(interface.named_property_setter, interface),
+        'named_property_deleter': property_deleter(interface.named_property_deleter),
+    })
+    context.update({
+        'has_named_properties_object': is_global and context['named_property_getter'],
+    })
+
+    # Origin Trials and ContextEnabled features
+    context.update({
+        'optional_features':
+            sorted(origin_trial_features(interface, context['constants'], context['attributes'], context['methods']) +
+                   context_enabled_features(context['attributes'])),
+    })
+
+    # Cross-origin interceptors
+    has_cross_origin_named_getter = False
+    has_cross_origin_named_setter = False
+    has_cross_origin_indexed_getter = False
+
+    for attribute in attributes:
+        if attribute['has_cross_origin_getter']:
+            has_cross_origin_named_getter = True
+        if attribute['has_cross_origin_setter']:
+            has_cross_origin_named_setter = True
+
+    # Methods are exposed as getter attributes on the interface: e.g.
+    # window.location gets the location attribute on the Window interface. For
+    # the cross-origin case, this attribute getter is guaranteed to only return
+    # a Function object, which the actual call is dispatched against.
+    for method in methods:
+        if method['is_cross_origin']:
+            has_cross_origin_named_getter = True
+
+    has_cross_origin_named_enumerator = has_cross_origin_named_getter or has_cross_origin_named_setter  # pylint: disable=invalid-name
+
+    if context['named_property_getter'] and context['named_property_getter']['is_cross_origin']:
+        has_cross_origin_named_getter = True
+
+    if context['indexed_property_getter'] and context['indexed_property_getter']['is_cross_origin']:
+        has_cross_origin_indexed_getter = True
+
+    context.update({
+        'has_cross_origin_named_getter': has_cross_origin_named_getter,
+        'has_cross_origin_named_setter': has_cross_origin_named_setter,
+        'has_cross_origin_named_enumerator': has_cross_origin_named_enumerator,
+        'has_cross_origin_indexed_getter': has_cross_origin_indexed_getter,
+    })
+
+    return context
+
+
+def attributes_context(interface, interfaces):
+    """Creates a list of Jinja template contexts for attributes of an interface.
+
+    Args:
+        interface: An interface to create contexts for
+        interfaces: A dict which maps an interface name to the definition
+            which can be referred if needed
+
+    Returns:
+        A list of attribute contexts
+    """
+
+    attributes = [v8_attributes.attribute_context(interface, attribute, interfaces)
                   for attribute in interface.attributes]
 
     has_conditional_attributes = any(attribute['exposed_test'] for attribute in attributes)
     if has_conditional_attributes and interface.is_partial:
-        raise Exception('Conditional attributes between partial interfaces in modules and the original interfaces(%s) in core are not allowed.' % interface.name)
+        raise Exception(
+            'Conditional attributes between partial interfaces in modules '
+            'and the original interfaces(%s) in core are not allowed.'
+            % interface.name)
 
-    context.update({
-        'attributes': attributes,
-        'has_accessor_configuration': any(
-            not (attribute['exposed_test'] or
-                 attribute['runtime_enabled_function']) and
-            not attribute['is_data_type_property'] and
-            attribute['should_be_exposed_to_script']
-            for attribute in attributes),
-        'has_attribute_configuration': any(
-            not (attribute['exposed_test'] or
-                 attribute['runtime_enabled_function']) and
-            attribute['is_data_type_property'] and
-            attribute['should_be_exposed_to_script']
-            for attribute in attributes),
-        'has_constructor_attributes': any(attribute['constructor_type'] for attribute in attributes),
-        'needs_constructor_setter_callback': any(attribute['constructor_type'] == attribute['name'] for attribute in attributes),
-        'has_replaceable_attributes': any(attribute['is_replaceable'] for attribute in attributes),
-    })
+    # See also comment in methods_context.
+    if not interface.is_partial and (interface.maplike or interface.setlike):
+        if any(attribute['name'] == 'size' for attribute in attributes):
+            raise ValueError(
+                'An interface cannot define an attribute called "size"; it is '
+                'implied by maplike/setlike in the IDL.')
+        size_attribute = IdlAttribute()
+        size_attribute.name = 'size'
+        size_attribute.idl_type = IdlType('unsigned long')
+        size_attribute.is_read_only = True
+        size_attribute.extended_attributes['NotEnumerable'] = None
+        attributes.append(v8_attributes.attribute_context(
+            interface, size_attribute, interfaces))
 
-    # Methods
+    return attributes
+
+
+def methods_context(interface):
+    """Creates a list of Jinja template contexts for methods of an interface.
+
+    Args:
+        interface: An interface to create contexts for
+
+    Returns:
+        A dictionary with 3 keys:
+        'iterator_method': An iterator context if available or None.
+        'iterator_method_alias': A string that can also be used to refer to the
+                                 @@iterator symbol or None.
+        'methods': A list of method contexts.
+    """
+
     methods = []
+
     if interface.original_interface:
         methods.extend([v8_methods.method_context(interface, operation, is_visible=False)
                         for operation in interface.original_interface.operations
@@ -325,7 +596,7 @@
     compute_method_overloads_context(interface, methods)
 
     def generated_method(return_type, name, arguments=None, extended_attributes=None, implemented_as=None):
-        operation = IdlOperation(interface.idl_name)
+        operation = IdlOperation()
         operation.idl_type = return_type
         operation.name = name
         if arguments:
@@ -338,7 +609,7 @@
         return v8_methods.method_context(interface, operation)
 
     def generated_argument(idl_type, name, is_optional=False, extended_attributes=None):
-        argument = IdlArgument(interface.idl_name)
+        argument = IdlArgument()
         argument.idl_type = idl_type
         argument.name = name
         argument.is_optional = is_optional
@@ -346,17 +617,20 @@
             argument.extended_attributes.update(extended_attributes)
         return argument
 
-    # [Iterable], iterable<>, maplike<> and setlike<>
+    # iterable<>, maplike<> and setlike<>
     iterator_method = None
-    has_array_iterator = False
+
+    # Depending on the declaration, @@iterator may be a synonym for e.g.
+    # 'entries' or 'values'.
+    iterator_method_alias = None
 
     # FIXME: support Iterable in partial interfaces. However, we don't
     # need to support iterator overloads between interface and
     # partial interface definitions.
     # http://heycam.github.io/webidl/#idl-overloading
-    if (not interface.is_partial
-        and (interface.iterable or interface.maplike or interface.setlike
-             or interface.has_indexed_elements or 'Iterable' in extended_attributes)):
+    if (not interface.is_partial and (
+            interface.iterable or interface.maplike or interface.setlike or
+            interface.has_indexed_elements)):
 
         used_extended_attributes = {}
 
@@ -389,31 +663,45 @@
                 extended_attributes=used_extended_attributes,
                 implemented_as=implemented_as)
 
-        if interface.iterable or interface.maplike or interface.setlike or 'Iterable' in extended_attributes:
-            iterator_method = generated_iterator_method('iterator', implemented_as='iterator')
-        elif interface.has_indexed_elements:
-            has_array_iterator = True
+        if not interface.has_indexed_elements:
+            iterator_method = generated_iterator_method('iterator', implemented_as='GetIterator')
 
         if interface.iterable or interface.maplike or interface.setlike:
-            implicit_methods = [
-                generated_iterator_method('keys'),
-                generated_iterator_method('values'),
-                generated_iterator_method('entries'),
+            non_overridable_methods = []
+            overridable_methods = []
 
-                # void forEach(Function callback, [Default=Undefined] optional any thisArg)
-                generated_method(IdlType('void'), 'forEach',
-                                 arguments=[generated_argument(IdlType('Function'), 'callback'),
-                                            generated_argument(IdlType('any'), 'thisArg',
-                                                               is_optional=True,
-                                                               extended_attributes={'Default': 'Undefined'})],
-                                 extended_attributes=forEach_extended_attributes),
-            ]
+            is_value_iterator = interface.iterable and interface.iterable.key_type is None
+
+            # For value iterators, the |entries|, |forEach|, |keys| and |values| are originally set
+            # to corresponding properties in %ArrayPrototype%.
+            # For pair iterators and maplike declarations, |entries| is an alias for @@iterator
+            # itself. For setlike declarations, |values| is an alias for @@iterator.
+            if not is_value_iterator:
+                if not interface.setlike:
+                    iterator_method_alias = 'entries'
+                    entries_or_values_method = generated_iterator_method('values')
+                else:
+                    iterator_method_alias = 'values'
+                    entries_or_values_method = generated_iterator_method('entries')
+
+                non_overridable_methods.extend([
+                    generated_iterator_method('keys'),
+                    entries_or_values_method,
+
+                    # void forEach(Function callback, [Default=Undefined] optional any thisArg)
+                    generated_method(IdlType('void'), 'forEach',
+                                     arguments=[generated_argument(IdlType('Function'), 'callback'),
+                                                generated_argument(IdlType('any'), 'thisArg',
+                                                                   is_optional=True,
+                                                                   extended_attributes={'Default': 'Undefined'})],
+                                     extended_attributes=forEach_extended_attributes),
+                ])
 
             if interface.maplike:
                 key_argument = generated_argument(interface.maplike.key_type, 'key')
                 value_argument = generated_argument(interface.maplike.value_type, 'value')
 
-                implicit_methods.extend([
+                non_overridable_methods.extend([
                     generated_method(IdlType('boolean'), 'has',
                                      arguments=[key_argument],
                                      extended_attributes=used_extended_attributes),
@@ -423,7 +711,7 @@
                 ])
 
                 if not interface.maplike.is_read_only:
-                    implicit_methods.extend([
+                    overridable_methods.extend([
                         generated_method(IdlType('void'), 'clear',
                                          extended_attributes=used_extended_attributes),
                         generated_method(IdlType('boolean'), 'delete',
@@ -437,14 +725,14 @@
             if interface.setlike:
                 value_argument = generated_argument(interface.setlike.value_type, 'value')
 
-                implicit_methods.extend([
+                non_overridable_methods.extend([
                     generated_method(IdlType('boolean'), 'has',
                                      arguments=[value_argument],
                                      extended_attributes=used_extended_attributes),
                 ])
 
                 if not interface.setlike.is_read_only:
-                    implicit_methods.extend([
+                    overridable_methods.extend([
                         generated_method(IdlType(interface.name), 'add',
                                          arguments=[value_argument],
                                          extended_attributes=used_extended_attributes),
@@ -459,11 +747,19 @@
             for method in methods:
                 methods_by_name.setdefault(method['name'], []).append(method)
 
-            for implicit_method in implicit_methods:
-                if implicit_method['name'] in methods_by_name:
+            for non_overridable_method in non_overridable_methods:
+                if non_overridable_method['name'] in methods_by_name:
+                    raise ValueError(
+                        'An interface cannot define an operation called "%s()", it '
+                        'comes from the iterable, maplike or setlike declaration '
+                        'in the IDL.' % non_overridable_method['name'])
+                methods.append(non_overridable_method)
+
+            for overridable_method in overridable_methods:
+                if overridable_method['name'] in methods_by_name:
                     # FIXME: Check that the existing method is compatible.
                     continue
-                methods.append(implicit_method)
+                methods.append(overridable_method)
 
         # FIXME: maplike<> and setlike<> should also imply the presence of a
         # 'size' attribute.
@@ -502,45 +798,6 @@
             extended_attributes=stringifier_ext_attrs,
             implemented_as=implemented_as))
 
-    conditionally_enabled_methods = []
-    custom_registration_methods = []
-    method_configuration_methods = []
-
-    for method in methods:
-        # Skip all but one method in each set of overloaded methods.
-        if 'overload_index' in method and 'overloads' not in method:
-            continue
-
-        if 'overloads' in method:
-            overloads = method['overloads']
-            if not overloads['visible']:
-                continue
-            # original interface will register instead of partial interface.
-            if overloads['has_partial_overloads'] and interface.is_partial:
-                continue
-            conditionally_exposed_function = overloads['exposed_test_all']
-            runtime_enabled_function = overloads['runtime_enabled_function_all']
-            has_custom_registration = (overloads['has_custom_registration_all'] or
-                                       overloads['runtime_determined_lengths'])
-        else:
-            if not method['visible']:
-                continue
-            conditionally_exposed_function = method['exposed_test']
-            runtime_enabled_function = method['runtime_enabled_function']
-            has_custom_registration = method['has_custom_registration']
-
-        if has_custom_registration:
-            custom_registration_methods.append(method)
-            continue
-        if conditionally_exposed_function:
-            conditionally_enabled_methods.append(method)
-            continue
-        if runtime_enabled_function:
-            custom_registration_methods.append(method)
-            continue
-        if method['should_be_exposed_to_script']:
-            method_configuration_methods.append(method)
-
     for method in methods:
         # The value of the Function object’s “length” property is a Number
         # determined as follows:
@@ -556,71 +813,41 @@
         method['length'] = (method['overloads']['length'] if 'overloads' in method else
                             method['number_of_required_arguments'])
 
-    context.update({
-        'conditionally_enabled_methods': conditionally_enabled_methods,
-        'custom_registration_methods': custom_registration_methods,
-        'has_origin_safe_method_setter': is_global and any(
-            method['is_check_security_for_receiver'] and not method['is_unforgeable']
-            for method in methods),
-        'has_private_script': any(attribute['is_implemented_in_private_script'] for attribute in attributes) or
-            any(method['is_implemented_in_private_script'] for method in methods),
+    return {
         'iterator_method': iterator_method,
-        'has_array_iterator': has_array_iterator,
-        'method_configuration_methods': method_configuration_methods,
+        'iterator_method_alias': iterator_method_alias,
         'methods': methods,
-    })
+    }
 
-    # Conditionally enabled members
-    has_conditional_attributes_on_instance = any(
-        attribute['exposed_test'] and attribute['on_instance']
-        for attribute in attributes)
-    has_conditional_attributes_on_prototype = any(
-        attribute['exposed_test'] and attribute['on_prototype']
-        for attribute in attributes)
-    context.update({
-        'has_conditional_attributes_on_instance':
-            has_conditional_attributes_on_instance,
-        'has_conditional_attributes_on_prototype':
-            has_conditional_attributes_on_prototype,
-    })
 
-    context.update({
-        'indexed_property_getter': property_getter(interface.indexed_property_getter, ['index']),
-        'indexed_property_setter': property_setter(interface.indexed_property_setter, interface),
-        'indexed_property_deleter': property_deleter(interface.indexed_property_deleter),
-        'is_override_builtins': 'OverrideBuiltins' in extended_attributes,
-        'named_property_getter': property_getter(interface.named_property_getter, ['propertyName']),
-        'named_property_setter': property_setter(interface.named_property_setter, interface),
-        'named_property_deleter': property_deleter(interface.named_property_deleter),
-    })
-    context.update({
-        'has_named_properties_object': is_global and context['named_property_getter'],
-    })
+def reflected_name(constant_name):
+    """Returns the name to use for the matching constant name in blink code.
 
-    return context
+    Given an all-uppercase 'CONSTANT_NAME', returns a camel-case
+    'kConstantName'.
+    """
+    # Check for SHOUTY_CASE constants
+    if constant_name.upper() != constant_name:
+        return constant_name
+    return 'k' + ''.join(part.title() for part in constant_name.split('_'))
 
 
 # [DeprecateAs], [OriginTrialEnabled], [Reflect], [RuntimeEnabled]
 def constant_context(constant, interface):
     extended_attributes = constant.extended_attributes
 
-    if 'OriginTrialEnabled' in extended_attributes:
-        includes.add('core/inspector/ConsoleMessage.h')
-        includes.add('core/origin_trials/OriginTrials.h')
-
     return {
         'cpp_class': extended_attributes.get('PartialInterfaceImplementedAs'),
         'deprecate_as': v8_utilities.deprecate_as(constant),  # [DeprecateAs]
         'idl_type': constant.idl_type.name,
-        'is_origin_trial_enabled': v8_utilities.origin_trial_enabled_function(constant) or v8_utilities.origin_trial_enabled_function(interface),  # [OriginTrialEnabled]
         'measure_as': v8_utilities.measure_as(constant, interface),  # [MeasureAs]
         'name': constant.name,
-        'origin_trial_enabled': v8_utilities.origin_trial_enabled_function(constant),  # [OriginTrialEnabled]
-        'origin_trial_enabled_per_interface': v8_utilities.origin_trial_enabled_function(interface),  # [OriginTrialEnabled]
-        'origin_trial_name': extended_attributes.get('OriginTrialEnabled'),  # [OriginTrialEnabled]
+        'origin_trial_enabled_function': v8_utilities.origin_trial_enabled_function_name(constant),  # [OriginTrialEnabled]
+        'origin_trial_feature_name': v8_utilities.origin_trial_feature_name(constant),  # [OriginTrialEnabled]
         # FIXME: use 'reflected_name' as correct 'name'
-        'reflected_name': extended_attributes.get('Reflect', constant.name),
-        'runtime_enabled_function': runtime_enabled_function_name(constant),  # [RuntimeEnabled]
+        'rcs_counter': 'Blink_' + v8_utilities.cpp_name(interface) + '_' + constant.name + '_ConstantGetter',
+        'reflected_name': extended_attributes.get('Reflect', reflected_name(constant.name)),
+        'runtime_enabled_feature_name': runtime_enabled_feature_name(constant),  # [RuntimeEnabled]
         'value': constant.value,
     }
 
@@ -656,18 +883,6 @@
         overloads[-1]['overloads']['name'] = name
 
 
-def method_overloads_by_name(methods):
-    """Returns generator of overloaded methods by name: [name, [method]]"""
-    # Filter to only methods that are actually overloaded
-    method_counts = Counter(method['name'] for method in methods)
-    overloaded_method_names = set(name
-                                  for name, count in method_counts.iteritems()
-                                  if count > 1)
-    overloaded_methods = [method for method in methods
-                          if method['name'] in overloaded_method_names]
-
-    # Group by name (generally will be defined together, but not necessarily)
-    return sort_and_groupby(overloaded_methods, itemgetter('name'))
 
 
 def overloads_context(interface, overloads):
@@ -680,6 +895,13 @@
     for index, method in enumerate(overloads, 1):
         method['overload_index'] = index
 
+    # [OriginTrialEnabled]
+    # TODO(iclelland): Allow origin trials on method overloads
+    # (crbug.com/621641)
+    if any(method.get('origin_trial_feature_name') for method in overloads):
+        raise Exception('[OriginTrialEnabled] cannot be specified on '
+                        'overloaded methods: %s.%s' % (interface.name, overloads[0]['name']))
+
     effective_overloads_by_length = effective_overload_set_by_length(overloads)
     lengths = [length for length, _ in effective_overloads_by_length]
     name = overloads[0].get('name', '<constructor>')
@@ -691,26 +913,26 @@
 
     # The special case handling below is not needed if all overloads are
     # runtime enabled by the same feature.
-    if not common_value(overloads, 'runtime_enabled_function'):
+    if not common_value(overloads, 'runtime_enabled_feature_name'):
         # Check if all overloads with the shortest acceptable arguments list are
         # runtime enabled, in which case we need to have a runtime determined
         # Function.length.
         shortest_overloads = effective_overloads_by_length[0][1]
-        if (all(method.get('runtime_enabled_function')
+        if (all(method.get('runtime_enabled_feature_name')
                 for method, _, _ in shortest_overloads)):
-            # Generate a list of (length, runtime_enabled_functions) tuples.
+            # Generate a list of (length, runtime_enabled_feature_names) tuples.
             runtime_determined_lengths = []
             for length, effective_overloads in effective_overloads_by_length:
-                runtime_enabled_functions = set(
-                    method['runtime_enabled_function']
+                runtime_enabled_feature_names = set(
+                    method['runtime_enabled_feature_name']
                     for method, _, _ in effective_overloads
-                    if method.get('runtime_enabled_function'))
-                if not runtime_enabled_functions:
+                    if method.get('runtime_enabled_feature_name'))
+                if not runtime_enabled_feature_names:
                     # This "length" is unconditionally enabled, so stop here.
                     runtime_determined_lengths.append((length, [None]))
                     break
                 runtime_determined_lengths.append(
-                    (length, sorted(runtime_enabled_functions)))
+                    (length, sorted(runtime_enabled_feature_names)))
             function_length = ('%sV8Internal::%sMethodLength()'
                                % (cpp_name_or_partial(interface), name))
 
@@ -718,38 +940,25 @@
         # runtime enabled, in which case we need to have a runtime determined
         # maximum distinguishing argument index.
         longest_overloads = effective_overloads_by_length[-1][1]
-        if (not common_value(overloads, 'runtime_enabled_function') and
-            all(method.get('runtime_enabled_function')
-                for method, _, _ in longest_overloads)):
-            # Generate a list of (length, runtime_enabled_functions) tuples.
+        if (not common_value(overloads, 'runtime_enabled_feature_name') and
+                all(method.get('runtime_enabled_feature_name')
+                    for method, _, _ in longest_overloads)):
+            # Generate a list of (length, runtime_enabled_feature_name) tuples.
             runtime_determined_maxargs = []
             for length, effective_overloads in reversed(effective_overloads_by_length):
-                runtime_enabled_functions = set(
-                    method['runtime_enabled_function']
+                runtime_enabled_feature_names = set(
+                    method['runtime_enabled_feature_name']
                     for method, _, _ in effective_overloads
-                    if method.get('runtime_enabled_function'))
-                if not runtime_enabled_functions:
+                    if method.get('runtime_enabled_feature_name'))
+                if not runtime_enabled_feature_names:
                     # This "length" is unconditionally enabled, so stop here.
                     runtime_determined_maxargs.append((length, [None]))
                     break
                 runtime_determined_maxargs.append(
-                    (length, sorted(runtime_enabled_functions)))
+                    (length, sorted(runtime_enabled_feature_names)))
             maxarg = ('%sV8Internal::%sMethodMaxArg()'
                       % (cpp_name_or_partial(interface), name))
 
-    # Check and fail if overloads disagree on any of the extended attributes
-    # that affect how the method should be registered.
-    # Skip the check for overloaded constructors, since they don't support any
-    # of the extended attributes in question.
-    if not overloads[0].get('is_constructor'):
-        overload_extended_attributes = [
-            method['custom_registration_extended_attributes']
-            for method in overloads]
-        for extended_attribute in v8_methods.CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES:
-            if common_key(overload_extended_attributes, extended_attribute) is None:
-                raise ValueError('Overloads of %s have conflicting extended attribute %s'
-                                 % (name, extended_attribute))
-
     # Check and fail if overloads disagree about whether the return type
     # is a Promise or not.
     promise_overload_count = sum(1 for method in overloads if method.get('returns_promise'))
@@ -774,7 +983,6 @@
     return {
         'deprecate_all_as': common_value(overloads, 'deprecate_as'),  # [DeprecateAs]
         'exposed_test_all': common_value(overloads, 'exposed_test'),  # [Exposed]
-        'has_custom_registration_all': common_value(overloads, 'has_custom_registration'),
         'length': function_length,
         'length_tests_methods': length_tests_methods(effective_overloads_by_length),
         # 1. Let maxarg be the length of the longest type list of the
@@ -784,115 +992,18 @@
         'returns_promise_all': promise_overload_count > 0,
         'runtime_determined_lengths': runtime_determined_lengths,
         'runtime_determined_maxargs': runtime_determined_maxargs,
-        'runtime_enabled_function_all': common_value(overloads, 'runtime_enabled_function'),  # [RuntimeEnabled]
-        'valid_arities': lengths
-            # Only need to report valid arities if there is a gap in the
-            # sequence of possible lengths, otherwise invalid length means
-            # "not enough arguments".
-            if lengths[-1] - lengths[0] != len(lengths) - 1 else None,
+        'runtime_enabled_all': common_value(overloads, 'runtime_enabled_feature_name'),  # [RuntimeEnabled]
+        'secure_context_test_all': common_value(overloads, 'secure_context_test'),  # [SecureContext]
+        'valid_arities': (lengths
+                          # Only need to report valid arities if there is a gap in the
+                          # sequence of possible lengths, otherwise invalid length means
+                          # "not enough arguments".
+                          if lengths[-1] - lengths[0] != len(lengths) - 1 else None),
         'visible': has_overload_visible,
         'has_partial_overloads': has_partial_overloads,
     }
 
 
-def effective_overload_set(F):
-    """Returns the effective overload set of an overloaded function.
-
-    An effective overload set is the set of overloaded functions + signatures
-    (type list of arguments, with optional and variadic arguments included or
-    not), and is used in the overload resolution algorithm.
-
-    For example, given input [f1(optional long x), f2(DOMString s)], the output
-    is informally [f1(), f1(long), f2(DOMString)], and formally
-    [(f1, [], []), (f1, [long], [optional]), (f2, [DOMString], [required])].
-
-    Currently the optionality list is a list of |is_optional| booleans (True
-    means optional, False means required); to support variadics this needs to
-    be tri-valued as required, optional, or variadic.
-
-    Formally:
-    An effective overload set represents the allowable invocations for a
-    particular operation, constructor (specified with [Constructor] or
-    [NamedConstructor]), legacy caller or callback function.
-
-    An additional argument N (argument count) is needed when overloading
-    variadics, but we don't use that currently.
-
-    Spec: http://heycam.github.io/webidl/#dfn-effective-overload-set
-
-    Formally the input and output lists are sets, but methods are stored
-    internally as dicts, which can't be stored in a set because they are not
-    hashable, so we use lists instead.
-
-    Arguments:
-        F: list of overloads for a given callable name.
-
-    Returns:
-        S: list of tuples of the form (callable, type list, optionality list).
-    """
-    # Code closely follows the algorithm in the spec, for clarity and
-    # correctness, and hence is not very Pythonic.
-
-    # 1. Initialize S to ∅.
-    # (We use a list because we can't use a set, as noted above.)
-    S = []
-
-    # 2. Let F be a set with elements as follows, according to the kind of
-    # effective overload set:
-    # (Passed as argument, nothing to do.)
-
-    # 3. & 4. (maxarg, m) are only needed for variadics, not used.
-
-    # 5. For each operation, extended attribute or callback function X in F:
-    for X in F:  # X is the "callable", F is the overloads.
-        arguments = X['arguments']
-        # 1. Let n be the number of arguments X is declared to take.
-        n = len(arguments)
-        # 2. Let t0..n−1 be a list of types, where ti is the type of X’s
-        # argument at index i.
-        # (“type list”)
-        t = tuple(argument['idl_type_object'] for argument in arguments)
-        # 3. Let o0..n−1 be a list of optionality values, where oi is “variadic”
-        # if X’s argument at index i is a final, variadic argument, “optional”
-        # if the argument is optional, and “required” otherwise.
-        # (“optionality list”)
-        # (We’re just using a boolean for optional/variadic vs. required.)
-        o = tuple(argument['is_optional'] or argument['is_variadic']
-                  for argument in arguments)
-        # 4. Add to S the tuple <X, t0..n−1, o0..n−1>.
-        S.append((X, t, o))
-        # 5. If X is declared to be variadic, then:
-        # (Not used, so not implemented.)
-        # 6. Initialize i to n−1.
-        i = n - 1
-        # 7. While i ≥ 0:
-        # Spec bug (fencepost error); should be “While i > 0:”
-        # https://www.w3.org/Bugs/Public/show_bug.cgi?id=25590
-        while i > 0:
-            # 1. If argument i of X is not optional, then break this loop.
-            if not o[i]:
-                break
-            # 2. Otherwise, add to S the tuple <X, t0..i−1, o0..i−1>.
-            S.append((X, t[:i], o[:i]))
-            # 3. Set i to i−1.
-            i = i - 1
-        # 8. If n > 0 and all arguments of X are optional, then add to S the
-        # tuple <X, (), ()> (where “()” represents the empty list).
-        if n > 0 and all(oi for oi in o):
-            S.append((X, [], []))
-    # 6. The effective overload set is S.
-    return S
-
-
-def effective_overload_set_by_length(overloads):
-    def type_list_length(entry):
-        # Entries in the effective overload set are 3-tuples:
-        # (callable, type list, optionality list)
-        return len(entry[1])
-
-    effective_overloads = effective_overload_set(overloads)
-    return list(sort_and_groupby(effective_overloads, type_list_length))
-
 
 def distinguishing_argument_index(entries):
     """Returns the distinguishing argument index for a sequence of entries.
@@ -966,7 +1077,7 @@
     distinguishing_argument_type_names = [type_list[index]
                                           for type_list in type_lists]
     if (len(set(distinguishing_argument_type_names)) !=
-        len(distinguishing_argument_type_names)):
+            len(distinguishing_argument_type_names)):
         raise ValueError('Types in distinguishing argument are not distinct:\n'
                          '%s' % distinguishing_argument_type_names)
 
@@ -1052,7 +1163,7 @@
     try:
         method = next(method for idl_type, method in idl_types_methods
                       if idl_type.is_nullable)
-        test = 'isUndefinedOrNull(%s)' % cpp_value
+        test = 'IsUndefinedOrNull(%s)' % cpp_value
         yield test, method
     except StopIteration:
         pass
@@ -1067,7 +1178,10 @@
     for idl_type, method in ((idl_type, method)
                              for idl_type, method in idl_types_methods
                              if idl_type.is_wrapper_type):
-        test = 'V8{idl_type}::hasInstance({cpp_value}, info.GetIsolate())'.format(idl_type=idl_type.base_type, cpp_value=cpp_value)
+        if idl_type.is_array_buffer_or_view:
+            test = '{cpp_value}->Is{idl_type}()'.format(idl_type=idl_type.base_type, cpp_value=cpp_value)
+        else:
+            test = 'V8{idl_type}::hasInstance({cpp_value}, info.GetIsolate())'.format(idl_type=idl_type.base_type, cpp_value=cpp_value)
         yield test, method
 
     # 13. Otherwise: if IsCallable(V) is true, and there is an entry in S that
@@ -1080,7 +1194,7 @@
     # same thing.
     try:
         method = next(method for idl_type, method in idl_types_methods
-                      if idl_type.is_callback_function)
+                      if idl_type.is_custom_callback_function)
         test = '%s->IsFunction()' % cpp_value
         yield test, method
     except StopIteration:
@@ -1113,9 +1227,10 @@
             # Array in overloaded method: http://crbug.com/262383
             yield '%s->IsArray()' % cpp_value, method
     for idl_type, method in idl_types_methods:
-        if idl_type.is_dictionary or idl_type.name == 'Dictionary':
-            # FIXME: should be '{1}->IsObject() && !{1}->IsDate() && !{1}->IsRegExp()'.format(cpp_value)
-            # FIXME: the IsDate and IsRegExp checks can be skipped if we've
+        if idl_type.is_dictionary or idl_type.name == 'Dictionary' or \
+           idl_type.is_callback_interface or idl_type.is_record_type:
+            # FIXME: should be '{1}->IsObject() && !{1}->IsRegExp()'.format(cpp_value)
+            # FIXME: the IsRegExp checks can be skipped if we've
             # already generated tests for them.
             yield '%s->IsObject()' % cpp_value, method
 
@@ -1170,14 +1285,6 @@
 # Utility functions
 ################################################################################
 
-def Counter(iterable):
-    # Once using Python 2.7, using collections.Counter
-    counter = defaultdict(lambda: 0)
-    for item in iterable:
-        counter[item] += 1
-    return counter
-
-
 def common(dicts, f):
     """Returns common result of f across an iterable of dicts, or None.
 
@@ -1208,12 +1315,6 @@
     return common(dicts, lambda d: d.get(key))
 
 
-def sort_and_groupby(l, key=None):
-    """Returns a generator of (key, list), sorting and grouping list by key."""
-    l.sort(key=key)
-    return ((k, list(g)) for k, g in itertools.groupby(l, key))
-
-
 ################################################################################
 # Constructors
 ################################################################################
@@ -1230,27 +1331,25 @@
 
     return {
         'arguments': argument_contexts,
-        'cpp_type': cpp_template_type(
-            cpp_ptr_type('RefPtr', 'RawPtr', gc_type(interface)),
-            cpp_name(interface)),
+        'cpp_type': cpp_name(interface) + '*',
         'cpp_value': v8_methods.cpp_value(
             interface, constructor, len(constructor.arguments)),
         'has_exception_state':
             is_constructor_raises_exception or
             any(argument for argument in constructor.arguments
                 if argument.idl_type.name == 'SerializedScriptValue' or
-                   argument.idl_type.v8_conversion_needs_exception_state),
+                argument.idl_type.v8_conversion_needs_exception_state),
         'has_optional_argument_without_default_value':
             any(True for argument_context in argument_contexts
                 if argument_context['is_optional_without_default_value']),
         'is_call_with_document':
             # [ConstructorCallWith=Document]
             has_extended_attribute_value(interface,
-                'ConstructorCallWith', 'Document'),
+                                         'ConstructorCallWith', 'Document'),
         'is_call_with_execution_context':
             # [ConstructorCallWith=ExecutionContext]
             has_extended_attribute_value(interface,
-                'ConstructorCallWith', 'ExecutionContext'),
+                                         'ConstructorCallWith', 'ExecutionContext'),
         'is_call_with_script_state':
             # [ConstructorCallWith=ScriptState]
             has_extended_attribute_value(
@@ -1260,6 +1359,7 @@
         'is_raises_exception': is_constructor_raises_exception,
         'number_of_required_arguments':
             number_of_required_arguments(constructor),
+        'rcs_counter': 'Blink_' + v8_utilities.cpp_name(interface) + '_ConstructorCallback'
     }
 
 
@@ -1286,7 +1386,7 @@
                 if not argument.is_optional])
 
 
-def interface_length(interface, constructors):
+def interface_length(constructors):
     # Docs: http://heycam.github.io/webidl/#es-interface-call
     if not constructors:
         return 0
@@ -1299,19 +1399,23 @@
 # http://heycam.github.io/webidl/#idl-special-operations
 ################################################################################
 
+def legacy_caller(caller, interface):
+    if not caller:
+        return None
+
+    return v8_methods.method_context(interface, caller)
+
 def property_getter(getter, cpp_arguments):
     if not getter:
         return None
 
     def is_null_expression(idl_type):
-        if idl_type.use_output_parameter_for_result:
-            return 'result.isNull()'
-        if idl_type.is_string_type:
-            return 'result.isNull()'
+        if idl_type.use_output_parameter_for_result or idl_type.is_string_type:
+            return 'result.IsNull()'
         if idl_type.is_interface_type:
             return '!result'
         if idl_type.base_type in ('any', 'object'):
-            return 'result.isEmpty()'
+            return 'result.IsEmpty()'
         return ''
 
     extended_attributes = getter.extended_attributes
@@ -1336,8 +1440,8 @@
     return {
         'cpp_type': idl_type.cpp_type,
         'cpp_value': cpp_value,
-        'do_not_check_security': 'DoNotCheckSecurity' in extended_attributes,
         'is_call_with_script_state': is_call_with_script_state,
+        'is_cross_origin': 'CrossOrigin' in extended_attributes,
         'is_custom':
             'Custom' in extended_attributes and
             (not extended_attributes['Custom'] or
@@ -1346,12 +1450,14 @@
             getter, 'Custom', 'PropertyEnumerator'),
         'is_custom_property_query': has_extended_attribute_value(
             getter, 'Custom', 'PropertyQuery'),
+        # TODO(rakuco): [NotEnumerable] does not make sense here and is only
+        # used in non-standard IDL operations. We need to get rid of them.
         'is_enumerable': 'NotEnumerable' not in extended_attributes,
         'is_null_expression': is_null_expression(idl_type),
         'is_raises_exception': is_raises_exception,
         'name': cpp_name(getter),
         'use_output_parameter_for_result': use_output_parameter_for_result,
-        'v8_set_return_value': idl_type.v8_set_return_value('result', extended_attributes=extended_attributes, script_wrappable='impl', release=idl_type.release),
+        'v8_set_return_value': idl_type.v8_set_return_value('result', extended_attributes=extended_attributes, script_wrappable='impl'),
     }
 
 
@@ -1364,6 +1470,7 @@
     idl_type.add_includes_for_type(extended_attributes)
     is_call_with_script_state = v8_utilities.has_extended_attribute_value(setter, 'CallWith', 'ScriptState')
     is_raises_exception = 'RaisesException' in extended_attributes
+    is_ce_reactions = 'CEReactions' in extended_attributes
 
     # [LegacyInterfaceTypeChecking]
     has_type_checking_interface = (
@@ -1376,6 +1483,7 @@
         'has_type_checking_interface': has_type_checking_interface,
         'idl_type': idl_type.base_type,
         'is_call_with_script_state': is_call_with_script_state,
+        'is_ce_reactions': is_ce_reactions,
         'is_custom': 'Custom' in extended_attributes,
         'is_nullable': idl_type.is_nullable,
         'is_raises_exception': is_raises_exception,
@@ -1390,10 +1498,11 @@
         return None
 
     extended_attributes = deleter.extended_attributes
-    idl_type = deleter.idl_type
     is_call_with_script_state = v8_utilities.has_extended_attribute_value(deleter, 'CallWith', 'ScriptState')
+    is_ce_reactions = 'CEReactions' in extended_attributes
     return {
         'is_call_with_script_state': is_call_with_script_state,
+        'is_ce_reactions': is_ce_reactions,
         'is_custom': 'Custom' in extended_attributes,
         'is_raises_exception': 'RaisesException' in extended_attributes,
         'name': cpp_name(deleter),
diff --git a/bindings/scripts/v8_methods.py b/bindings/scripts/v8_methods.py
index a3d4232..b199947 100644
--- a/bindings/scripts/v8_methods.py
+++ b/bindings/scripts/v8_methods.py
@@ -43,24 +43,83 @@
                           is_legacy_interface_type_checking)
 
 
-# Methods with any of these require custom method registration code in the
-# interface's configure*Template() function.
-CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES = frozenset([
-    'DoNotCheckSecurity',
-    'DoNotCheckSignature',
-])
+def method_is_visible(method, interface_is_partial):
+    if 'overloads' in method:
+        return method['overloads']['visible'] and not (method['overloads']['has_partial_overloads'] and interface_is_partial)
+    return method['visible'] and 'overload_index' not in method
+
+
+def is_origin_trial_enabled(method):
+    return bool(method['origin_trial_feature_name'])
+
+
+def is_secure_context(method):
+    return bool(method['overloads']['secure_context_test_all'] if 'overloads' in method else method['secure_context_test'])
+
+
+def is_conditionally_enabled(method):
+    exposed = method['overloads']['exposed_test_all'] if 'overloads' in method else method['exposed_test']
+    return exposed or is_secure_context(method)
+
+
+def filter_conditionally_enabled(methods, interface_is_partial):
+    return [method for method in methods if (
+        method_is_visible(method, interface_is_partial) and
+        is_conditionally_enabled(method) and
+        not is_origin_trial_enabled(method))]
+
+
+def custom_registration(method):
+    # TODO(dcheng): Currently, bindings must create a function object for each
+    # realm as a hack to support the incumbent realm. Remove the need for custom
+    # registration when Blink properly supports the incumbent realm.
+    if method['is_cross_origin']:
+        return True
+    if 'overloads' in method:
+        return (method['overloads']['runtime_determined_lengths'] or
+                (method['overloads']['runtime_enabled_all'] and not is_conditionally_enabled(method)))
+    return method['runtime_enabled_feature_name'] and not is_conditionally_enabled(method)
+
+
+def filter_custom_registration(methods, interface_is_partial):
+    return [method for method in methods if (
+        method_is_visible(method, interface_is_partial) and custom_registration(method))]
+
+
+def filter_method_configuration(methods, interface_is_partial):
+    return [method for method in methods if
+            method_is_visible(method, interface_is_partial) and
+            not is_origin_trial_enabled(method) and
+            not is_conditionally_enabled(method) and
+            not custom_registration(method)]
+
+
+def method_filters():
+    return {'custom_registration': filter_custom_registration,
+            'has_method_configuration': filter_method_configuration}
 
 
 def use_local_result(method):
     extended_attributes = method.extended_attributes
     idl_type = method.idl_type
     return (has_extended_attribute_value(method, 'CallWith', 'ScriptState') or
-            'ImplementedInPrivateScript' in extended_attributes or
+            'NewObject' in extended_attributes or
             'RaisesException' in extended_attributes or
             idl_type.is_union_type or
             idl_type.is_explicit_nullable)
 
 
+def runtime_call_stats_context(interface, method):
+    includes.add('platform/bindings/RuntimeCallStats.h')
+    generic_counter_name = 'Blink_' + v8_utilities.cpp_name(interface) + '_' + method.name
+    (method_counter, extended_attribute_defined) = v8_utilities.rcs_counter_name(method, generic_counter_name)
+    return {
+        'extended_attribute_defined': extended_attribute_defined,
+        'method_counter': method_counter,
+        'origin_safe_method_getter_counter': generic_counter_name + '_OriginSafeMethodGetter'
+    }
+
+
 def method_context(interface, method, is_visible=True):
     arguments = method.arguments
     extended_attributes = method.extended_attributes
@@ -73,15 +132,6 @@
 
     this_cpp_value = cpp_value(interface, method, len(arguments))
 
-    is_implemented_in_private_script = 'ImplementedInPrivateScript' in extended_attributes
-    if is_implemented_in_private_script:
-        includes.add('bindings/core/v8/PrivateScriptRunner.h')
-        includes.add('core/frame/LocalFrame.h')
-        includes.add('platform/ScriptForbiddenScope.h')
-
-    # [OnlyExposedToPrivateScript]
-    is_only_exposed_to_private_script = 'OnlyExposedToPrivateScript' in extended_attributes
-
     is_call_with_script_arguments = has_extended_attribute_value(method, 'CallWith', 'ScriptArguments')
     if is_call_with_script_arguments:
         includes.update(['bindings/core/v8/ScriptCallStack.h',
@@ -89,42 +139,38 @@
     is_call_with_script_state = has_extended_attribute_value(method, 'CallWith', 'ScriptState')
     is_call_with_this_value = has_extended_attribute_value(method, 'CallWith', 'ThisValue')
     if is_call_with_script_state or is_call_with_this_value:
-        includes.add('bindings/core/v8/ScriptState.h')
+        includes.add('platform/bindings/ScriptState.h')
 
     # [CheckSecurity]
-    is_do_not_check_security = 'DoNotCheckSecurity' in extended_attributes
+    is_cross_origin = 'CrossOrigin' in extended_attributes
     is_check_security_for_receiver = (
         has_extended_attribute_value(interface, 'CheckSecurity', 'Receiver') and
-        not is_do_not_check_security)
+        not is_cross_origin)
     is_check_security_for_return_value = (
         has_extended_attribute_value(method, 'CheckSecurity', 'ReturnValue'))
     if is_check_security_for_receiver or is_check_security_for_return_value:
         includes.add('bindings/core/v8/BindingSecurity.h')
 
+    is_ce_reactions = 'CEReactions' in extended_attributes
+    if is_ce_reactions:
+        includes.add('core/html/custom/CEReactionsScope.h')
     is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attributes
     if is_custom_element_callbacks:
-        includes.add('core/dom/custom/CustomElementProcessingStack.h')
+        includes.add('core/html/custom/V0CustomElementProcessingStack.h')
 
     is_raises_exception = 'RaisesException' in extended_attributes
     is_custom_call_prologue = has_extended_attribute_value(method, 'Custom', 'CallPrologue')
     is_custom_call_epilogue = has_extended_attribute_value(method, 'Custom', 'CallEpilogue')
     is_post_message = 'PostMessage' in extended_attributes
     if is_post_message:
-        includes.add('bindings/core/v8/SerializedScriptValueFactory.h')
-        includes.add('core/dom/DOMArrayBuffer.h')
-        includes.add('core/dom/MessagePort.h')
-        includes.add('core/frame/ImageBitmap.h')
+        includes.add('bindings/core/v8/serialization/SerializedScriptValueFactory.h')
+        includes.add('bindings/core/v8/serialization/Transferables.h')
+        includes.add('core/typed_arrays/DOMArrayBufferBase.h')
+        includes.add('core/imagebitmap/ImageBitmap.h')
 
     if 'LenientThis' in extended_attributes:
         raise Exception('[LenientThis] is not supported for operations.')
 
-    if 'RuntimeEnabled' in extended_attributes:
-        includes.add('platform/RuntimeEnabledFeatures.h')
-
-    if 'OriginTrialEnabled' in extended_attributes:
-        includes.add('core/inspector/ConsoleMessage.h')
-        includes.add('core/origin_trials/OriginTrials.h')
-
     argument_contexts = [
         argument_context(interface, method, argument, index, is_visible=is_visible)
         for index, argument in enumerate(arguments)]
@@ -132,22 +178,13 @@
     return {
         'activity_logging_world_list': v8_utilities.activity_logging_world_list(method),  # [ActivityLogging]
         'arguments': argument_contexts,
-        'argument_declarations_for_private_script':
-            argument_declarations_for_private_script(interface, method),
         'cpp_type': (v8_types.cpp_template_type('Nullable', idl_type.cpp_type)
                      if idl_type.is_explicit_nullable else idl_type.cpp_type),
         'cpp_value': this_cpp_value,
         'cpp_type_initializer': idl_type.cpp_type_initializer,
-        'custom_registration_extended_attributes':
-            CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES.intersection(
-                extended_attributes.iterkeys()),
         'deprecate_as': v8_utilities.deprecate_as(method),  # [DeprecateAs]
+        'do_not_test_new_object': 'DoNotTestNewObject' in extended_attributes,
         'exposed_test': v8_utilities.exposed(method, interface),  # [Exposed]
-        # TODO(yukishiino): Retire has_custom_registration flag.  Should be
-        # replaced with V8DOMConfiguration::PropertyLocationConfiguration.
-        'has_custom_registration':
-            v8_utilities.has_extended_attribute(
-                method, CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES),
         'has_exception_state':
             is_raises_exception or
             is_check_security_for_receiver or
@@ -158,22 +195,21 @@
             any(True for argument_context in argument_contexts
                 if argument_context['is_optional_without_default_value']),
         'idl_type': idl_type.base_type,
-        'is_origin_trial_enabled': v8_utilities.origin_trial_enabled_function(method) or v8_utilities.origin_trial_enabled_function(interface),  # [OriginTrialEnabled]
         'is_call_with_execution_context': has_extended_attribute_value(method, 'CallWith', 'ExecutionContext'),
         'is_call_with_script_arguments': is_call_with_script_arguments,
         'is_call_with_script_state': is_call_with_script_state,
         'is_call_with_this_value': is_call_with_this_value,
+        'is_ce_reactions': is_ce_reactions,
         'is_check_security_for_receiver': is_check_security_for_receiver,
         'is_check_security_for_return_value': is_check_security_for_return_value,
+        'is_cross_origin': 'CrossOrigin' in extended_attributes,
         'is_custom': 'Custom' in extended_attributes and
             not (is_custom_call_prologue or is_custom_call_epilogue),
         'is_custom_call_prologue': is_custom_call_prologue,
         'is_custom_call_epilogue': is_custom_call_epilogue,
         'is_custom_element_callbacks': is_custom_element_callbacks,
-        'is_do_not_check_security': is_do_not_check_security,
-        'is_do_not_check_signature': 'DoNotCheckSignature' in extended_attributes,
         'is_explicit_nullable': idl_type.is_explicit_nullable,
-        'is_implemented_in_private_script': is_implemented_in_private_script,
+        'is_new_object': 'NewObject' in extended_attributes,
         'is_partial_interface_member':
             'PartialInterfaceImplementedAs' in extended_attributes,
         'is_per_world_bindings': 'PerWorldBindings' in extended_attributes,
@@ -194,15 +230,13 @@
         'on_instance': v8_utilities.on_instance(interface, method),
         'on_interface': v8_utilities.on_interface(interface, method),
         'on_prototype': v8_utilities.on_prototype(interface, method),
-        'only_exposed_to_private_script': is_only_exposed_to_private_script,
-        'origin_trial_enabled': v8_utilities.origin_trial_enabled_function(method),  # [OriginTrialEnabled]
-        'origin_trial_enabled_per_interface': v8_utilities.origin_trial_enabled_function(interface),  # [OriginTrialEnabled]
-        'private_script_v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value(
-            extended_attributes, 'v8Value', 'cppValue', isolate='scriptState->isolate()', bailout_return_value='false'),
+        'origin_trial_enabled_function': v8_utilities.origin_trial_enabled_function_name(method),  # [OriginTrialEnabled]
+        'origin_trial_feature_name': v8_utilities.origin_trial_feature_name(method),  # [OriginTrialEnabled]
         'property_attributes': property_attributes(interface, method),
         'returns_promise': method.returns_promise,
-        'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(method),  # [RuntimeEnabled]
-        'should_be_exposed_to_script': not (is_implemented_in_private_script and is_only_exposed_to_private_script),
+        'runtime_call_stats': runtime_call_stats_context(interface, method),
+        'runtime_enabled_feature_name': v8_utilities.runtime_enabled_feature_name(method),  # [RuntimeEnabled]
+        'secure_context_test': v8_utilities.secure_context(method, interface),  # [SecureContext]
         'use_output_parameter_for_result': idl_type.use_output_parameter_for_result,
         'use_local_result': use_local_result(method),
         'v8_set_return_value': v8_set_return_value(interface.name, method, this_cpp_value),
@@ -225,11 +259,6 @@
         not is_legacy_interface_type_checking(interface, method) and
         idl_type.is_wrapper_type)
 
-    if ('ImplementedInPrivateScript' in extended_attributes and
-            not idl_type.is_wrapper_type and
-            not idl_type.is_basic_type):
-        raise Exception('Private scripts supports only primitive types and DOM wrappers.')
-
     set_default_value = argument.set_default_value
     this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes,
                                            raw_type=True,
@@ -263,13 +292,10 @@
         'is_variadic_wrapper_type': is_variadic_wrapper_type,
         'is_wrapper_type': idl_type.is_wrapper_type,
         'name': argument.name,
-        'private_script_cpp_value_to_v8_value': idl_type.cpp_value_to_v8_value(
-            argument.name, isolate='scriptState->isolate()',
-            creation_context='scriptState->context()->Global()'),
         'use_permissive_dictionary_conversion': 'PermissiveDictionaryConversion' in extended_attributes,
         'v8_set_return_value': v8_set_return_value(interface.name, method, this_cpp_value),
         'v8_set_return_value_for_main_world': v8_set_return_value(interface.name, method, this_cpp_value, for_main_world=True),
-        'v8_value_to_local_cpp_value': v8_value_to_local_cpp_value(method, argument, index),
+        'v8_value_to_local_cpp_value': v8_value_to_local_cpp_value(interface.name, method, argument, index),
     }
     context.update({
         'is_optional_without_default_value':
@@ -281,37 +307,14 @@
     return context
 
 
-def argument_declarations_for_private_script(interface, method):
-    argument_declarations = ['LocalFrame* frame']
-    argument_declarations.append('%s* holderImpl' % interface.name)
-    argument_declarations.extend(['%s %s' % (argument.idl_type.cpp_type_args(
-        used_as_rvalue_type=True), argument.name) for argument in method.arguments])
-    if method.idl_type.name != 'void':
-        argument_declarations.append('%s* %s' % (method.idl_type.cpp_type, 'result'))
-    return argument_declarations
-
-
 ################################################################################
 # Value handling
 ################################################################################
 
 def cpp_value(interface, method, number_of_arguments):
-    def cpp_argument(argument):
-        idl_type = argument.idl_type
-        if idl_type.name == 'EventListener':
-            return argument.name
-        if (idl_type.name in ['NodeFilter', 'NodeFilterOrNull',
-                              'XPathNSResolver', 'XPathNSResolverOrNull']):
-            # FIXME: remove this special case
-            return '%s.release()' % argument.name
-        return argument.name
-
     # Truncate omitted optional arguments
     arguments = method.arguments[:number_of_arguments]
     cpp_arguments = []
-    if 'ImplementedInPrivateScript' in method.extended_attributes:
-        cpp_arguments.append('toLocalFrame(toFrameIfNotDetached(info.GetIsolate()->GetCurrentContext()))')
-        cpp_arguments.append('impl')
 
     if method.is_constructor:
         call_with_values = interface.extended_attributes.get('ConstructorCallWith')
@@ -323,15 +326,11 @@
     # static member functions, which for instance members (non-static members)
     # take *impl as their first argument
     if ('PartialInterfaceImplementedAs' in method.extended_attributes and
-            'ImplementedInPrivateScript' not in method.extended_attributes and
             not method.is_static):
         cpp_arguments.append('*impl')
-    cpp_arguments.extend(cpp_argument(argument) for argument in arguments)
+    cpp_arguments.extend(argument.name for argument in arguments)
 
-    if 'ImplementedInPrivateScript' in method.extended_attributes:
-        if method.idl_type.name != 'void':
-            cpp_arguments.append('&result')
-    elif ('RaisesException' in method.extended_attributes or
+    if ('RaisesException' in method.extended_attributes or
           (method.is_constructor and
            has_extended_attribute_value(interface, 'RaisesException', 'Constructor'))):
         cpp_arguments.append('exceptionState')
@@ -343,11 +342,9 @@
         cpp_arguments.append('result')
 
     if method.name == 'Constructor':
-        base_name = 'create'
+        base_name = 'Create'
     elif method.name == 'NamedConstructor':
-        base_name = 'createForJSConstructor'
-    elif 'ImplementedInPrivateScript' in method.extended_attributes:
-        base_name = '%sMethod' % method.name
+        base_name = 'CreateForJSConstructor'
     else:
         base_name = v8_utilities.cpp_name(method)
 
@@ -362,23 +359,16 @@
         # Constructors and void methods don't have a return type
         return None
 
-    if ('ImplementedInPrivateScript' in extended_attributes and
-            not idl_type.is_wrapper_type and
-            not idl_type.is_basic_type):
-        raise Exception('Private scripts supports only primitive types and DOM wrappers.')
-
-    release = False
     # [CallWith=ScriptState], [RaisesException]
     if use_local_result(method):
         if idl_type.is_explicit_nullable:
             # result is of type Nullable<T>
-            cpp_value = 'result.get()'
+            cpp_value = 'result.Get()'
         else:
             cpp_value = 'result'
-        release = idl_type.release
 
     script_wrappable = 'impl' if inherits_interface(interface_name, 'Node') else ''
-    return idl_type.v8_set_return_value(cpp_value, extended_attributes, script_wrappable=script_wrappable, release=release, for_main_world=for_main_world, is_static=method.is_static)
+    return idl_type.v8_set_return_value(cpp_value, extended_attributes, script_wrappable=script_wrappable, for_main_world=for_main_world, is_static=method.is_static)
 
 
 def v8_value_to_local_cpp_variadic_value(method, argument, index, return_promise):
@@ -386,35 +376,66 @@
     idl_type = argument.idl_type
     this_cpp_type = idl_type.cpp_type
 
-    if method.returns_promise:
-        check_expression = 'exceptionState.hadException()'
-    else:
-        check_expression = 'exceptionState.throwIfNeeded()'
-
     if idl_type.is_dictionary or idl_type.is_union_type:
         vector_type = 'HeapVector'
     else:
         vector_type = 'Vector'
 
     return {
-        'assign_expression': 'toImplArguments<%s<%s>>(info, %s, exceptionState)' % (vector_type, this_cpp_type, index),
-        'check_expression': check_expression,
+        'assign_expression': 'ToImplArguments<%s<%s>>(info, %s, exceptionState)' % (vector_type, this_cpp_type, index),
+        'check_expression': 'exceptionState.HadException()',
         'cpp_type': this_cpp_type,
         'cpp_name': argument.name,
         'declare_variable': False,
     }
 
 
-def v8_value_to_local_cpp_value(method, argument, index, return_promise=False, restricted_float=False):
+def v8_value_to_local_cpp_ssv_value(extended_attributes, idl_type, v8_value, variable_name, for_storage):
+    this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes, raw_type=True)
+
+    storage_policy = 'kForStorage' if for_storage else 'kNotForStorage'
+    arguments = ', '.join([
+        'info.GetIsolate()',
+        v8_value,
+        '{ssv}::SerializeOptions({ssv}::{storage_policy})',
+        'exceptionState'
+    ])
+    cpp_expression_format = 'NativeValueTraits<{ssv}>::NativeValue(%s)' % arguments
+    this_cpp_value = cpp_expression_format.format(
+        ssv='SerializedScriptValue',
+        storage_policy=storage_policy
+    )
+
+    return {
+        'assign_expression': this_cpp_value,
+        'check_expression': 'exceptionState.HadException()',
+        'cpp_type': this_cpp_type,
+        'cpp_name': variable_name,
+        'declare_variable': False,
+    }
+
+
+def v8_value_to_local_cpp_value(interface_name, method, argument, index, return_promise=False):
     extended_attributes = argument.extended_attributes
     idl_type = argument.idl_type
     name = argument.name
+    v8_value = 'info[%s]' % index
+
+    # History.pushState and History.replaceState are explicitly specified as
+    # serializing the value for storage. The default is to not serialize for
+    # storage. See https://html.spec.whatwg.org/multipage/browsers.html#dom-history-pushstate
+    if idl_type.name == 'SerializedScriptValue':
+        for_storage = (interface_name == 'History' and
+                       method.name in ('pushState', 'replaceState'))
+        return v8_value_to_local_cpp_ssv_value(extended_attributes, idl_type,
+                                               v8_value, name,
+                                               for_storage=for_storage)
+
     if argument.is_variadic:
         return v8_value_to_local_cpp_variadic_value(method, argument, index, return_promise)
-    return idl_type.v8_value_to_local_cpp_value(extended_attributes, 'info[%s]' % index,
-                                                name, index=index, declare_variable=False,
-                                                use_exception_state=method.returns_promise,
-                                                restricted_float=restricted_float)
+    return idl_type.v8_value_to_local_cpp_value(extended_attributes, v8_value,
+                                                name, declare_variable=False,
+                                                use_exception_state=method.returns_promise)
 
 
 ################################################################################
@@ -470,7 +491,7 @@
         member_type_name = (member_type.inner_type.name
                             if member_type.is_nullable else
                             member_type.name)
-        return '%s.set%s(%s)' % (argument.name, member_type_name,
+        return '%s.Set%s(%s)' % (argument.name, member_type_name,
                                  member_type.literal_cpp_value(default_value))
     return '%s = %s' % (argument.name,
                         idl_type.literal_cpp_value(default_value))
diff --git a/bindings/scripts/v8_types.py b/bindings/scripts/v8_types.py
index 04739d2..b59f393 100644
--- a/bindings/scripts/v8_types.py
+++ b/bindings/scripts/v8_types.py
@@ -26,6 +26,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# pylint: disable=relative-import
+
 """Functions for type handling and type conversion (Blink/C++ <-> V8/JS).
 
 Extends IdlType and IdlUnionType with V8-specific properties, methods, and
@@ -39,9 +41,16 @@
 
 import posixpath
 
-from idl_types import IdlTypeBase, IdlType, IdlUnionType, IdlArrayOrSequenceType, IdlNullableType
+from idl_types import IdlArrayOrSequenceType
+from idl_types import IdlNullableType
+from idl_types import IdlRecordType
+from idl_types import IdlType
+from idl_types import IdlTypeBase
+from idl_types import IdlUnionType
+from utilities import to_snake_case
 import v8_attributes  # for IdlType.constructor_type_name
 from v8_globals import includes
+from v8_utilities import extended_attribute_value_contains
 
 
 ################################################################################
@@ -66,6 +75,9 @@
     'Uint16Array',
     'Uint32Array',
 ])
+ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES = TYPED_ARRAY_TYPES.union(frozenset([
+    'ArrayBufferView'
+]))
 ARRAY_BUFFER_AND_VIEW_TYPES = TYPED_ARRAY_TYPES.union(frozenset([
     'ArrayBuffer',
     'ArrayBufferView',
@@ -77,6 +89,9 @@
 IdlType.is_array_buffer_or_view = property(
     lambda self: self.base_type in ARRAY_BUFFER_AND_VIEW_TYPES)
 
+IdlType.is_array_buffer_view_or_typed_array = property(
+    lambda self: self.base_type in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES)
+
 IdlType.is_typed_array = property(
     lambda self: self.base_type in TYPED_ARRAY_TYPES)
 
@@ -93,29 +108,27 @@
 CPP_TYPE_SAME_AS_IDL_TYPE = set([
     'double',
     'float',
-    'long long',
-    'unsigned long long',
 ])
-CPP_INT_TYPES = set([
-    'byte',
-    'long',
-    'short',
-])
-CPP_UNSIGNED_TYPES = set([
-    'octet',
-    'unsigned int',
-    'unsigned long',
-    'unsigned short',
-])
+CPP_INTEGER_CONVERSION_RULES = {
+    'byte': 'int8_t',
+    'octet': 'uint8_t',
+    'short': 'int16_t',
+    'unsigned short': 'uint16_t',
+    'long': 'int32_t',
+    'unsigned long': 'uint32_t',
+    'long long': 'int64_t',
+    'unsigned long long': 'uint64_t',
+}
 CPP_SPECIAL_CONVERSION_RULES = {
     'Date': 'double',
     'Dictionary': 'Dictionary',
     'EventHandler': 'EventListener*',
-    'NodeFilter': 'RefPtrWillBeRawPtr<NodeFilter>',
+    'EventListener': 'EventListener*',
+    'NodeFilter': 'V8NodeFilterCondition*',
     'Promise': 'ScriptPromise',
     'ScriptValue': 'ScriptValue',
     # FIXME: Eliminate custom bindings for XPathNSResolver  http://crbug.com/345529
-    'XPathNSResolver': 'RawPtr<XPathNSResolver>',
+    'XPathNSResolver': 'XPathNSResolver*',
     'boolean': 'bool',
     'unrestricted double': 'double',
     'unrestricted float': 'float',
@@ -139,15 +152,25 @@
             bool, True if the C++ type is used as a variadic argument of a method.
         used_in_cpp_sequence:
             bool, True if the C++ type is used as an element of a container.
-            Containers can be an array, a sequence or a dictionary.
+            Containers can be an array, a sequence, a dictionary or a record.
     """
+
     def string_mode():
+        if idl_type.is_nullable:
+            return 'kTreatNullAndUndefinedAsNullString'
+        # TODO(lisabelle): Remove these 4 lines when we have fully supported
+        # annoteted types. (crbug.com/714866)
+        # It is because at that time 'TreatNullAs' will only appear in
+        # type_extended_attributes, not in extended_attributes.
         if extended_attributes.get('TreatNullAs') == 'EmptyString':
-            return 'TreatNullAsEmptyString'
-        if idl_type.is_nullable or extended_attributes.get('TreatNullAs') == 'NullString':
-            if extended_attributes.get('TreatUndefinedAs') == 'NullString':
-                return 'TreatNullAndUndefinedAsNullString'
-            return 'TreatNullAsNullString'
+            return 'kTreatNullAsEmptyString'
+        if extended_attributes.get('TreatNullAs') == 'NullString':
+            return 'kTreatNullAsNullString'
+        type_extended_attributes = idl_type.extended_attributes or {}
+        if type_extended_attributes.get('TreatNullAs') == 'EmptyString':
+            return 'kTreatNullAsEmptyString'
+        if type_extended_attributes.get('TreatNullAs') == 'NullString':
+            return 'kTreatNullAsNullString'
         return ''
 
     extended_attributes = extended_attributes or {}
@@ -159,43 +182,59 @@
     else:
         native_array_element_type = idl_type.native_array_element_type
     if native_array_element_type:
-        vector_type = cpp_ptr_type('Vector', 'HeapVector', native_array_element_type.gc_type)
+        vector_type = cpp_ptr_type('Vector', 'HeapVector', native_array_element_type.is_gc_type)
         vector_template_type = cpp_template_type(vector_type, native_array_element_type.cpp_type_args(used_in_cpp_sequence=True))
         if used_as_rvalue_type:
             return 'const %s&' % vector_template_type
         return vector_template_type
 
+    # Record types.
+    if idl_type.is_record_type:
+        vector_type = cpp_ptr_type('Vector', 'HeapVector', idl_type.value_type.is_gc_type)
+        value_type = idl_type.value_type.cpp_type_args(used_in_cpp_sequence=True)
+        vector_template_type = cpp_template_type(vector_type,
+                                                 'std::pair<String, %s>' % value_type)
+        if used_as_rvalue_type:
+            return 'const %s&' % vector_template_type
+        return vector_template_type
+
     # Simple types
     base_idl_type = idl_type.base_type
 
     if base_idl_type in CPP_TYPE_SAME_AS_IDL_TYPE:
         return base_idl_type
-    if base_idl_type in CPP_INT_TYPES:
-        return 'int'
-    if base_idl_type in CPP_UNSIGNED_TYPES:
-        return 'unsigned'
+    if base_idl_type in CPP_INTEGER_CONVERSION_RULES:
+        return CPP_INTEGER_CONVERSION_RULES[base_idl_type]
     if base_idl_type in CPP_SPECIAL_CONVERSION_RULES:
         return CPP_SPECIAL_CONVERSION_RULES[base_idl_type]
 
-    if base_idl_type in NON_WRAPPER_TYPES:
-        return ('PassRefPtr<%s>' if used_as_rvalue_type else 'RefPtr<%s>') % base_idl_type
+    if base_idl_type == 'SerializedScriptValue':
+        return 'RefPtr<%s>' % base_idl_type
     if idl_type.is_string_type:
         if not raw_type:
-            return 'String'
+            return 'const String&' if used_as_rvalue_type else 'String'
         return 'V8StringResource<%s>' % string_mode()
 
-    if idl_type.base_type == 'ArrayBufferView' and 'FlexibleArrayBufferView' in extended_attributes:
+    if base_idl_type == 'ArrayBufferView' and 'FlexibleArrayBufferView' in extended_attributes:
         return 'FlexibleArrayBufferView'
-    if idl_type.base_type in TYPED_ARRAY_TYPES and 'FlexibleArrayBufferView' in extended_attributes:
-        return 'Flexible' + idl_type.base_type + 'View'
+    if base_idl_type in TYPED_ARRAY_TYPES and 'FlexibleArrayBufferView' in extended_attributes:
+        return 'Flexible' + base_idl_type + 'View'
+    if base_idl_type in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES:
+        if not used_in_cpp_sequence:
+            if 'AllowShared' in extended_attributes:
+                return cpp_template_type('MaybeShared', idl_type.implemented_as)
+            else:
+                return cpp_template_type('NotShared', idl_type.implemented_as)
     if idl_type.is_interface_type:
         implemented_as_class = idl_type.implemented_as
-        if raw_type or (used_as_rvalue_type and idl_type.is_garbage_collected):
+        if raw_type or (used_as_rvalue_type and idl_type.is_garbage_collected) or not used_in_cpp_sequence:
             return implemented_as_class + '*'
-        new_type = 'Member' if used_in_cpp_sequence else 'RawPtr'
-        ptr_type = cpp_ptr_type(('PassRefPtr' if used_as_rvalue_type else 'RefPtr'), new_type, idl_type.gc_type)
-        return cpp_template_type(ptr_type, implemented_as_class)
+        if not used_in_cpp_sequence:
+            return implemented_as_class + '*'
+        return cpp_template_type('Member', implemented_as_class)
     if idl_type.is_dictionary:
+        if used_as_rvalue_type:
+            return 'const %s&' % base_idl_type
         return base_idl_type
     if idl_type.is_union_type:
         # Avoid "AOrNullOrB" for cpp type of (A? or B) because we generate
@@ -204,10 +243,16 @@
             if idl_type.is_nullable:
                 return idl_type.inner_type.name
             return idl_type.name
-        idl_type_name = "Or".join(member_cpp_name(member)
+        idl_type_name = 'Or'.join(member_cpp_name(member)
                                   for member in idl_type.member_types)
         return 'const %s&' % idl_type_name if used_as_rvalue_type else idl_type_name
+    if idl_type.is_callback_function:
+        if idl_type.is_custom_callback_function:
+            return 'V8%s' % base_idl_type
+        return 'V8%s*' % base_idl_type
 
+    if base_idl_type == 'void':
+        return base_idl_type
     # Default, assume native type is a pointer with same type name as idl type
     return base_idl_type + '*'
 
@@ -253,13 +298,9 @@
     return format_string.format(template=template, inner_type=inner_type)
 
 
-def cpp_ptr_type(old_type, new_type, gc_type):
-    if gc_type == 'GarbageCollectedObject':
+def cpp_ptr_type(old_type, new_type, is_gc_type):
+    if is_gc_type:
         return new_type
-    if gc_type == 'WillBeGarbageCollectedObject':
-        if old_type == 'Vector':
-            return 'WillBe' + new_type
-        return old_type + 'WillBe' + new_type
     return old_type
 
 
@@ -303,71 +344,55 @@
         cls.garbage_collected_types.update(new_garbage_collected_types))
 
 
-# [WillBeGarbageCollected]
-IdlType.will_be_garbage_collected_types = set()
-
-IdlType.is_will_be_garbage_collected = property(
-    lambda self: self.base_type in IdlType.will_be_garbage_collected_types)
-
-IdlType.set_will_be_garbage_collected_types = classmethod(
-    lambda cls, new_will_be_garbage_collected_types:
-        cls.will_be_garbage_collected_types.update(new_will_be_garbage_collected_types))
+def is_gc_type(idl_type):
+    return idl_type.is_garbage_collected or idl_type.is_dictionary or idl_type.is_union_type
 
 
-def gc_type(idl_type):
-    if idl_type.is_garbage_collected or idl_type.is_dictionary or idl_type.is_union_type:
-        return 'GarbageCollectedObject'
-    if idl_type.is_will_be_garbage_collected:
-        return 'WillBeGarbageCollectedObject'
-    return 'RefCountedObject'
-
-IdlTypeBase.gc_type = property(gc_type)
+IdlTypeBase.is_gc_type = property(is_gc_type)
 
 
 def is_traceable(idl_type):
-    return (idl_type.is_garbage_collected
-            or idl_type.is_will_be_garbage_collected
-            or idl_type.is_dictionary)
+    return (idl_type.is_garbage_collected or idl_type.is_dictionary)
 
 IdlTypeBase.is_traceable = property(is_traceable)
 IdlUnionType.is_traceable = property(lambda self: True)
 IdlArrayOrSequenceType.is_traceable = property(
     lambda self: self.element_type.is_traceable)
+IdlRecordType.is_traceable = property(
+    lambda self: self.value_type.is_traceable)
 
 
 ################################################################################
 # Includes
 ################################################################################
 
-def includes_for_cpp_class(class_name, relative_dir_posix):
-    return set([posixpath.join('bindings', relative_dir_posix, class_name + '.h')])
-
-
 INCLUDES_FOR_TYPE = {
     'object': set(),
     'ArrayBufferView': set(['bindings/core/v8/V8ArrayBufferView.h',
-                            'core/dom/FlexibleArrayBufferView.h']),
+                            'core/typed_arrays/ArrayBufferViewHelpers.h',
+                            'core/typed_arrays/FlexibleArrayBufferView.h']),
     'Dictionary': set(['bindings/core/v8/Dictionary.h']),
     'EventHandler': set(['bindings/core/v8/V8AbstractEventListener.h',
-                         'bindings/core/v8/V8EventListenerList.h']),
+                         'bindings/core/v8/V8EventListenerHelper.h']),
     'EventListener': set(['bindings/core/v8/BindingSecurity.h',
-                          'bindings/core/v8/V8EventListenerList.h',
+                          'bindings/core/v8/V8EventListenerHelper.h',
                           'core/frame/LocalDOMWindow.h']),
     'HTMLCollection': set(['bindings/core/v8/V8HTMLCollection.h',
                            'core/dom/ClassCollection.h',
                            'core/dom/TagCollection.h',
                            'core/html/HTMLCollection.h',
-                           'core/html/HTMLDataListOptionsCollection.h',
-                           'core/html/HTMLFormControlsCollection.h',
-                           'core/html/HTMLTableRowsCollection.h']),
+                           'core/html/HTMLTableRowsCollection.h',
+                           'core/html/forms/HTMLDataListOptionsCollection.h',
+                           'core/html/forms/HTMLFormControlsCollection.h']),
+    'NodeFilter': set(['bindings/core/v8/V8NodeFilterCondition.h']),
     'NodeList': set(['bindings/core/v8/V8NodeList.h',
                      'core/dom/NameNodeList.h',
                      'core/dom/NodeList.h',
                      'core/dom/StaticNodeList.h',
-                     'core/html/LabelsNodeList.h']),
+                     'core/html/forms/LabelsNodeList.h']),
     'Promise': set(['bindings/core/v8/ScriptPromise.h']),
-    'SerializedScriptValue': set(['bindings/core/v8/SerializedScriptValue.h',
-                                  'bindings/core/v8/SerializedScriptValueFactory.h']),
+    'SerializedScriptValue': set(['bindings/core/v8/serialization/SerializedScriptValue.h',
+                                  'bindings/core/v8/serialization/SerializedScriptValueFactory.h']),
     'ScriptValue': set(['bindings/core/v8/ScriptValue.h']),
 }
 
@@ -380,12 +405,13 @@
     base_idl_type = idl_type.base_type
     if base_idl_type in INCLUDES_FOR_TYPE:
         return INCLUDES_FOR_TYPE[base_idl_type]
-    if idl_type.base_type in TYPED_ARRAY_TYPES:
+    if base_idl_type in TYPED_ARRAY_TYPES:
         return INCLUDES_FOR_TYPE['ArrayBufferView'].union(
             set(['bindings/%s/v8/V8%s.h' % (component_dir[base_idl_type], base_idl_type)])
         )
     if idl_type.is_basic_type:
-        return set()
+        return set(['bindings/core/v8/IDLTypes.h',
+                    'bindings/core/v8/NativeValueTraitsImpl.h'])
     if base_idl_type.endswith('ConstructorConstructor'):
         # FIXME: rename to NamedConstructor
         # FIXME: replace with a [NamedConstructorAttribute] extended attribute
@@ -396,6 +422,11 @@
     if base_idl_type.endswith('Constructor'):
         # FIXME: replace with a [ConstructorAttribute] extended attribute
         base_idl_type = idl_type.constructor_type_name
+    if idl_type.is_custom_callback_function:
+        return set()
+    if idl_type.is_callback_function:
+        component = IdlType.callback_functions[base_idl_type]['component_dir']
+        return set(['bindings/%s/v8/%s.h' % (component, to_snake_case('V8%s' % base_idl_type))])
     if base_idl_type not in component_dir:
         return set()
     return set(['bindings/%s/v8/V8%s.h' % (component_dir[base_idl_type],
@@ -412,11 +443,20 @@
 
 
 def includes_for_array_or_sequence_type(idl_type, extended_attributes=None):
-    return idl_type.element_type.includes_for_type(extended_attributes)
+    return set.union(set(['bindings/core/v8/IDLTypes.h',
+                          'bindings/core/v8/NativeValueTraitsImpl.h']),
+                     idl_type.element_type.includes_for_type(extended_attributes))
 
 IdlArrayOrSequenceType.includes_for_type = includes_for_array_or_sequence_type
 
 
+def includes_for_record_type(idl_type, extended_attributes=None):
+    return set.union(idl_type.key_type.includes_for_type(extended_attributes),
+                     idl_type.value_type.includes_for_type(extended_attributes))
+
+IdlRecordType.includes_for_type = includes_for_record_type
+
+
 def add_includes_for_type(idl_type, extended_attributes=None):
     includes.update(idl_type.includes_for_type(extended_attributes))
 
@@ -431,36 +471,26 @@
     includes.update(includes_for_interface(interface_name))
 
 
-def impl_should_use_nullable_container(idl_type):
-    return not(idl_type.cpp_type_has_null_value)
-
-IdlTypeBase.impl_should_use_nullable_container = property(
-    impl_should_use_nullable_container)
-
-
 def impl_includes_for_type(idl_type, interfaces_info):
     includes_for_type = set()
-    if idl_type.impl_should_use_nullable_container:
-        includes_for_type.add('bindings/core/v8/Nullable.h')
 
     idl_type = idl_type.preprocessed_type
     native_array_element_type = idl_type.native_array_element_type
     if native_array_element_type:
         includes_for_type.update(impl_includes_for_type(
                 native_array_element_type, interfaces_info))
-        includes_for_type.add('wtf/Vector.h')
+        includes_for_type.add('platform/wtf/Vector.h')
 
     base_idl_type = idl_type.base_type
     if idl_type.is_string_type:
-        includes_for_type.add('wtf/text/WTFString.h')
+        includes_for_type.add('platform/wtf/text/WTFString.h')
     if base_idl_type in interfaces_info:
-        interface_info = interfaces_info[idl_type.base_type]
-        if interface_info['include_path']:
-            includes_for_type.add(interface_info['include_path'])
+        interface_info = interfaces_info[base_idl_type]
+        includes_for_type.add(interface_info['include_path'])
     if base_idl_type in INCLUDES_FOR_TYPE:
         includes_for_type.update(INCLUDES_FOR_TYPE[base_idl_type])
-    if idl_type.is_typed_array:
-        return set(['core/dom/DOMTypedArray.h'])
+    if idl_type.is_array_buffer_view_or_typed_array:
+        return set(['core/typed_arrays/DOMTypedArray.h', 'core/typed_arrays/ArrayBufferViewHelpers.h'])
     return includes_for_type
 
 
@@ -474,6 +504,20 @@
 IdlUnionType.impl_includes_for_type = impl_includes_for_type_union
 
 
+def impl_forward_declaration_name(idl_type):
+    element_type = idl_type.native_array_element_type
+    if element_type:
+        return element_type.impl_forward_declaration_name
+
+    if idl_type.is_wrapper_type and not idl_type.is_typed_array:
+        return idl_type.implemented_as
+    return None
+
+
+IdlTypeBase.impl_forward_declaration_name = property(
+    impl_forward_declaration_name)
+
+
 component_dir = {}
 
 
@@ -485,35 +529,18 @@
 # V8 -> C++
 ################################################################################
 
+# TODO(rakuco): Get rid of this definition altogether and move to NativeValueTraits<T>::nativeValue().
+#               That requires not requiring ExceptionState where it is not used, and we must be careful not
+#               to introduce any performance regressions.
 V8_VALUE_TO_CPP_VALUE = {
     # Basic
-    'Date': 'toCoreDate({isolate}, {v8_value})',
     'DOMString': '{v8_value}',
-    'ByteString': 'toByteString({isolate}, {arguments})',
-    'USVString': 'toUSVString({isolate}, {arguments})',
-    'boolean': 'toBoolean({isolate}, {arguments})',
-    'float': 'toRestrictedFloat({isolate}, {arguments})',
-    'unrestricted float': 'toFloat({isolate}, {arguments})',
-    'double': 'toRestrictedDouble({isolate}, {arguments})',
-    'unrestricted double': 'toDouble({isolate}, {arguments})',
-    'byte': 'toInt8({isolate}, {arguments})',
-    'octet': 'toUInt8({isolate}, {arguments})',
-    'short': 'toInt16({isolate}, {arguments})',
-    'unsigned short': 'toUInt16({isolate}, {arguments})',
-    'long': 'toInt32({isolate}, {arguments})',
-    'unsigned long': 'toUInt32({isolate}, {arguments})',
-    'long long': 'toInt64({isolate}, {arguments})',
-    'unsigned long long': 'toUInt64({isolate}, {arguments})',
     # Interface types
-    'Dictionary': 'Dictionary({v8_value}, {isolate}, exceptionState)',
-    'EventTarget': 'toEventTarget({isolate}, {v8_value})',
-    'FlexibleArrayBufferView': 'toFlexibleArrayBufferView({isolate}, {v8_value}, {variable_name}, allocateFlexibleArrayBufferViewStorage({v8_value}))',
-    'NodeFilter': 'toNodeFilter({v8_value}, info.Holder(), ScriptState::current({isolate}))',
-    'Promise': 'ScriptPromise::cast(ScriptState::current({isolate}), {v8_value})',
-    'SerializedScriptValue': 'SerializedScriptValueFactory::instance().create({isolate}, {v8_value}, nullptr, nullptr, nullptr, exceptionState)',
-    'ScriptValue': 'ScriptValue(ScriptState::current({isolate}), {v8_value})',
-    'Window': 'toDOMWindow({isolate}, {v8_value})',
-    'XPathNSResolver': 'toXPathNSResolver(ScriptState::current({isolate}), {v8_value})',
+    'FlexibleArrayBufferView': 'ToFlexibleArrayBufferView({isolate}, {v8_value}, {variable_name}, allocateFlexibleArrayBufferViewStorage({v8_value}))',
+    'Promise': 'ScriptPromise::Cast(ScriptState::Current({isolate}), {v8_value})',
+    'ScriptValue': 'ScriptValue(ScriptState::Current({isolate}), {v8_value})',
+    'Window': 'ToDOMWindow({isolate}, {v8_value})',
+    'XPathNSResolver': 'ToXPathNSResolver(ScriptState::Current({isolate}), {v8_value})',
 }
 
 
@@ -521,10 +548,12 @@
     return (idl_type.is_numeric_type or
             idl_type.is_enum or
             idl_type.is_dictionary or
-            idl_type.name in ('Boolean', 'ByteString', 'Dictionary', 'USVString', 'SerializedScriptValue'))
+            idl_type.is_array_buffer_view_or_typed_array or
+            idl_type.name in ('Boolean', 'ByteString', 'Date', 'Dictionary', 'USVString', 'SerializedScriptValue'))
 
 IdlType.v8_conversion_needs_exception_state = property(v8_conversion_needs_exception_state)
 IdlArrayOrSequenceType.v8_conversion_needs_exception_state = True
+IdlRecordType.v8_conversion_needs_exception_state = True
 IdlUnionType.v8_conversion_needs_exception_state = True
 
 
@@ -548,85 +577,112 @@
 IdlType.v8_conversion_is_trivial = property(v8_conversion_is_trivial)
 
 
-def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, variable_name, index, isolate, restricted_float=False):
+def native_value_traits_type_name(idl_type):
+    idl_type = idl_type.preprocessed_type
+
+    if idl_type.is_nullable:
+        idl_type = idl_type.inner_type
+
+    if idl_type.native_array_element_type:
+        name = 'IDLSequence<%s>' % native_value_traits_type_name(idl_type.native_array_element_type)
+    elif idl_type.is_record_type:
+        name = 'IDLRecord<%s, %s>' % (native_value_traits_type_name(idl_type.key_type),
+                                      native_value_traits_type_name(idl_type.value_type))
+    elif idl_type.is_basic_type or idl_type.name == 'Promise':
+        name = 'IDL%s' % idl_type.name
+    elif idl_type.implemented_as is not None:
+        name = idl_type.implemented_as
+    else:
+        name = idl_type.name
+    return name
+
+
+def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, variable_name, isolate):
     if idl_type.name == 'void':
         return ''
 
-    # Array or sequence types
-    native_array_element_type = idl_type.native_array_element_type
-    if native_array_element_type:
-        return v8_value_to_cpp_value_array_or_sequence(native_array_element_type, v8_value, index, isolate)
-
     # Simple types
     idl_type = idl_type.preprocessed_type
     base_idl_type = idl_type.as_union_type.name if idl_type.is_union_type else idl_type.base_type
+    type_extended_attributes = idl_type.extended_attributes or {}
 
     if 'FlexibleArrayBufferView' in extended_attributes:
-        if base_idl_type not in TYPED_ARRAY_TYPES.union(set(['ArrayBufferView'])):
-            raise "Unrecognized base type for extended attribute 'FlexibleArrayBufferView': %s" % (idl_type.base_type)
+        if base_idl_type not in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES:
+            raise ValueError('Unrecognized base type for extended attribute "FlexibleArrayBufferView": %s' % (idl_type.base_type))
         base_idl_type = 'FlexibleArrayBufferView'
 
+    if 'AllowShared' in extended_attributes and not idl_type.is_array_buffer_view_or_typed_array:
+        raise ValueError('Unrecognized base type for extended attribute "AllowShared": %s' % (idl_type.base_type))
+
     if idl_type.is_integer_type:
-        configuration = 'NormalConversion'
+        configuration = 'kNormalConversion'
+        # TODO(lisabelle): Remove these 4 lines when we have fully supported
+        # annoteted types.
+        # It is because at that time 'Clamp' and 'EnforceRange' will only
+        # appear in type_extended_attributes, not in extended_attributes.
         if 'EnforceRange' in extended_attributes:
-            configuration = 'EnforceRange'
+            configuration = 'kEnforceRange'
         elif 'Clamp' in extended_attributes:
-            configuration = 'Clamp'
-        arguments = ', '.join([v8_value, configuration, 'exceptionState'])
+            configuration = 'kClamp'
+        if 'EnforceRange' in type_extended_attributes:
+            configuration = 'kEnforceRange'
+        elif 'Clamp' in type_extended_attributes:
+            configuration = 'kClamp'
+        arguments = ', '.join([v8_value, 'exceptionState', configuration])
+    elif base_idl_type == 'SerializedScriptValue':
+        arguments = ', '.join([
+            v8_value,
+            'SerializedScriptValue::SerializeOptions(SerializedScriptValue::kNotForStorage)',
+            'exceptionState'])
     elif idl_type.v8_conversion_needs_exception_state:
         arguments = ', '.join([v8_value, 'exceptionState'])
     else:
         arguments = v8_value
+
     if base_idl_type in V8_VALUE_TO_CPP_VALUE:
         cpp_expression_format = V8_VALUE_TO_CPP_VALUE[base_idl_type]
-    elif idl_type.is_array_buffer_or_view:
+    elif idl_type.name == 'ArrayBuffer':
         cpp_expression_format = (
             '{v8_value}->Is{idl_type}() ? '
-            'V8{idl_type}::toImpl(v8::Local<v8::{idl_type}>::Cast({v8_value})) : 0')
+            'V8{idl_type}::ToImpl(v8::Local<v8::{idl_type}>::Cast({v8_value})) : 0')
+    elif idl_type.is_array_buffer_view_or_typed_array:
+        this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes)
+        if 'AllowShared' in extended_attributes:
+            cpp_expression_format = ('ToMaybeShared<%s>({isolate}, {v8_value}, exceptionState)' % this_cpp_type)
+        else:
+            cpp_expression_format = ('ToNotShared<%s>({isolate}, {v8_value}, exceptionState)' % this_cpp_type)
+
     elif idl_type.is_union_type:
-        nullable = 'UnionTypeConversionMode::Nullable' if idl_type.includes_nullable_type else 'UnionTypeConversionMode::NotNullable'
-        cpp_expression_format = 'V8{idl_type}::toImpl({isolate}, {v8_value}, {variable_name}, %s, exceptionState)' % nullable
+        nullable = 'UnionTypeConversionMode::kNullable' if idl_type.includes_nullable_type \
+            else 'UnionTypeConversionMode::kNotNullable'
+        cpp_expression_format = 'V8{idl_type}::ToImpl({isolate}, {v8_value}, {variable_name}, %s, exceptionState)' % nullable
     elif idl_type.use_output_parameter_for_result:
-        cpp_expression_format = 'V8{idl_type}::toImpl({isolate}, {v8_value}, {variable_name}, exceptionState)'
+        cpp_expression_format = 'V8{idl_type}::ToImpl({isolate}, {v8_value}, {variable_name}, exceptionState)'
+    elif idl_type.is_callback_function:
+        cpp_expression_format = (
+            'V8{idl_type}::Create(ScriptState::Current({isolate}), {v8_value})')
+    elif idl_type.v8_conversion_needs_exception_state:
+        # Effectively, this if branch means everything with v8_conversion_needs_exception_state == True
+        # except for unions and dictionary interfaces.
+        base_idl_type = native_value_traits_type_name(idl_type)
+        cpp_expression_format = (
+            'NativeValueTraits<{idl_type}>::NativeValue({isolate}, {arguments})')
     else:
         cpp_expression_format = (
-            'V8{idl_type}::toImplWithTypeCheck({isolate}, {v8_value})')
+            'V8{idl_type}::ToImplWithTypeCheck({isolate}, {v8_value})')
 
     return cpp_expression_format.format(arguments=arguments, idl_type=base_idl_type, v8_value=v8_value, variable_name=variable_name, isolate=isolate)
 
 
-def v8_value_to_cpp_value_array_or_sequence(native_array_element_type, v8_value, index, isolate='info.GetIsolate()'):
-    # Index is None for setters, index (starting at 0) for method arguments,
-    # and is used to provide a human-readable exception message
-    if index is None:
-        index = 0  # special case, meaning "setter"
-    else:
-        index += 1  # human-readable index
-    if (native_array_element_type.is_interface_type and
-        native_array_element_type.name != 'Dictionary'):
-        this_cpp_type = None
-        ref_ptr_type = cpp_ptr_type('RefPtr', 'Member', native_array_element_type.gc_type)
-        expression_format = '(to{ref_ptr_type}NativeArray<{native_array_element_type}, V8{native_array_element_type}>({v8_value}, {index}, {isolate}, exceptionState))'
-    else:
-        ref_ptr_type = None
-        this_cpp_type = native_array_element_type.cpp_type
-        if native_array_element_type.is_dictionary or native_array_element_type.is_union_type:
-            vector_type = 'HeapVector'
-        else:
-            vector_type = 'Vector'
-        expression_format = 'toImplArray<%s<{cpp_type}>>({v8_value}, {index}, {isolate}, exceptionState)' % vector_type
-    expression = expression_format.format(native_array_element_type=native_array_element_type.name, cpp_type=this_cpp_type, index=index, ref_ptr_type=ref_ptr_type, v8_value=v8_value, isolate=isolate)
-    return expression
-
-
 # FIXME: this function should be refactored, as this takes too many flags.
-def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variable_name, index=None, declare_variable=True, isolate='info.GetIsolate()', bailout_return_value=None, use_exception_state=False, restricted_float=False):
+def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variable_name, declare_variable=True,
+                                isolate='info.GetIsolate()', bailout_return_value=None, use_exception_state=False):
     """Returns an expression that converts a V8 value to a C++ value and stores it as a local value."""
 
     this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes, raw_type=True)
     idl_type = idl_type.preprocessed_type
 
-    cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, variable_name, index, isolate, restricted_float=restricted_float)
+    cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, variable_name, isolate)
 
     # Optional expression that returns a value to be assigned to the local variable.
     assign_expression = None
@@ -638,13 +694,14 @@
     # meaningful if 'check_expression' is not None.
     return_expression = bailout_return_value
 
-    if idl_type.is_string_type or idl_type.v8_conversion_needs_exception_state:
+    if 'FlexibleArrayBufferView' in extended_attributes:
+        if idl_type.base_type not in ARRAY_BUFFER_VIEW_AND_TYPED_ARRAY_TYPES:
+            raise ValueError('Unrecognized base type for extended attribute "FlexibleArrayBufferView": %s' % (idl_type.base_type))
+        set_expression = cpp_value
+    elif idl_type.is_string_type or idl_type.v8_conversion_needs_exception_state:
         # Types for which conversion can fail and that need error handling.
 
-        if use_exception_state:
-            check_expression = 'exceptionState.hadException()'
-        else:
-            check_expression = 'exceptionState.throwIfNeeded()'
+        check_expression = 'exceptionState.HadException()'
 
         if idl_type.is_dictionary or idl_type.is_union_type:
             set_expression = cpp_value
@@ -656,17 +713,13 @@
             # as the condition here would be wrong.
             if not idl_type.v8_conversion_needs_exception_state:
                 if use_exception_state:
-                    check_expression = '!%s.prepare(exceptionState)' % variable_name
+                    check_expression = '!%s.Prepare(exceptionState)' % variable_name
                 else:
-                    check_expression = '!%s.prepare()' % variable_name
-    elif not idl_type.v8_conversion_is_trivial:
+                    check_expression = '!%s.Prepare()' % variable_name
+    elif not idl_type.v8_conversion_is_trivial and not idl_type.is_callback_function:
         return {
             'error_message': 'no V8 -> C++ conversion for IDL type: %s' % idl_type.name
         }
-    elif 'FlexibleArrayBufferView' in extended_attributes:
-        if idl_type.base_type not in TYPED_ARRAY_TYPES.union(set(['ArrayBufferView'])):
-            raise "Unrecognized base type for extended attribute 'FlexibleArrayBufferView': %s" % (idl_type.base_type)
-        set_expression = cpp_value
     else:
         assign_expression = cpp_value
 
@@ -701,13 +754,16 @@
 ################################################################################
 
 def preprocess_idl_type(idl_type):
+    extended_attributes = idl_type.extended_attributes
     if idl_type.is_nullable:
         return IdlNullableType(idl_type.inner_type.preprocessed_type)
     if idl_type.is_enum:
         # Enumerations are internally DOMStrings
-        return IdlType('DOMString')
-    if idl_type.base_type in ['any', 'object'] or idl_type.is_callback_function:
-        return IdlType('ScriptValue')
+        return IdlType('DOMString', extended_attributes)
+    if idl_type.base_type in ['any', 'object'] or idl_type.is_custom_callback_function:
+        return IdlType('ScriptValue', extended_attributes)
+    if idl_type.is_callback_function:
+        return idl_type
     return idl_type
 
 IdlTypeBase.preprocessed_type = property(preprocess_idl_type)
@@ -732,8 +788,8 @@
     extended_attributes = extended_attributes or {}
     if ('Reflect' in extended_attributes and
         idl_type.base_type in ['unsigned long', 'unsigned short']):
-        cpp_value = cpp_value.replace('getUnsignedIntegralAttribute',
-                                      'getIntegralAttribute')
+        cpp_value = cpp_value.replace('GetUnsignedIntegralAttribute',
+                                      'GetIntegralAttribute')
         cpp_value = 'std::max(0, static_cast<int>(%s))' % cpp_value
     return idl_type, cpp_value
 
@@ -742,7 +798,7 @@
     """Returns V8 conversion type, adding any additional includes.
 
     The V8 conversion type is used to select the C++ -> V8 conversion function
-    or v8SetReturnValue* function; it can be an idl_type, a cpp_type, or a
+    or V8SetReturnValue* function; it can be an idl_type, a cpp_type, or a
     separate name for the type of conversion (e.g., 'DOMWrapper').
     """
     extended_attributes = extended_attributes or {}
@@ -758,15 +814,17 @@
     # Array or sequence types
     native_array_element_type = idl_type.native_array_element_type
     if native_array_element_type:
-        return 'array'
+        return 'FrozenArray' if idl_type.is_frozen_array else 'sequence'
+
+    # Record types.
+    if idl_type.is_record_type:
+        return 'Record'
 
     # Simple types
     base_idl_type = idl_type.base_type
     # Basic types, without additional includes
-    if base_idl_type in CPP_INT_TYPES:
-        return 'int'
-    if base_idl_type in CPP_UNSIGNED_TYPES:
-        return 'unsigned'
+    if base_idl_type in CPP_INTEGER_CONVERSION_RULES:
+        return CPP_INTEGER_CONVERSION_RULES[base_idl_type]
     if idl_type.is_string_type:
         if idl_type.is_nullable:
             return 'StringOrNull'
@@ -778,7 +836,7 @@
         return 'Dictionary'
 
     # Data type with potential additional includes
-    if base_idl_type in V8_SET_RETURN_VALUE:  # Special v8SetReturnValue treatment
+    if base_idl_type in V8_SET_RETURN_VALUE:  # Special V8SetReturnValue treatment
         return base_idl_type
 
     # Pointer type
@@ -788,52 +846,82 @@
 
 
 V8_SET_RETURN_VALUE = {
-    'boolean': 'v8SetReturnValueBool(info, {cpp_value})',
-    'int': 'v8SetReturnValueInt(info, {cpp_value})',
-    'unsigned': 'v8SetReturnValueUnsigned(info, {cpp_value})',
-    'DOMString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
-    'ByteString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
-    'USVString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
-    'StringOrNull': 'v8SetReturnValueStringOrNull(info, {cpp_value}, info.GetIsolate())',
+    'boolean': 'V8SetReturnValueBool(info, {cpp_value})',
+    'DOMString': 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
+    'ByteString': 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
+    'USVString': 'V8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
+    'StringOrNull': 'V8SetReturnValueStringOrNull(info, {cpp_value}, info.GetIsolate())',
     'void': '',
-    # No special v8SetReturnValue* function (set value directly)
-    'float': 'v8SetReturnValue(info, {cpp_value})',
-    'unrestricted float': 'v8SetReturnValue(info, {cpp_value})',
-    'double': 'v8SetReturnValue(info, {cpp_value})',
-    'unrestricted double': 'v8SetReturnValue(info, {cpp_value})',
-    # No special v8SetReturnValue* function, but instead convert value to V8
-    # and then use general v8SetReturnValue.
-    'array': 'v8SetReturnValue(info, {cpp_value})',
-    'Date': 'v8SetReturnValue(info, {cpp_value})',
-    'EventHandler': 'v8SetReturnValue(info, {cpp_value})',
-    'ScriptValue': 'v8SetReturnValue(info, {cpp_value})',
-    'SerializedScriptValue': 'v8SetReturnValue(info, {cpp_value})',
+    # All the int types below are converted to (u)int32_t in the V8SetReturnValue{Int,Unsigned}() calls.
+    # The 64-bit int types have already been converted to double when V8_SET_RETURN_VALUE is used, so they are not
+    # listed here.
+    'int8_t': 'V8SetReturnValueInt(info, {cpp_value})',
+    'int16_t': 'V8SetReturnValueInt(info, {cpp_value})',
+    'int32_t': 'V8SetReturnValueInt(info, {cpp_value})',
+    'uint8_t': 'V8SetReturnValueUnsigned(info, {cpp_value})',
+    'uint16_t': 'V8SetReturnValueUnsigned(info, {cpp_value})',
+    'uint32_t': 'V8SetReturnValueUnsigned(info, {cpp_value})',
+    # No special V8SetReturnValue* function (set value directly)
+    'float': 'V8SetReturnValue(info, {cpp_value})',
+    'unrestricted float': 'V8SetReturnValue(info, {cpp_value})',
+    'double': 'V8SetReturnValue(info, {cpp_value})',
+    'unrestricted double': 'V8SetReturnValue(info, {cpp_value})',
+    # No special V8SetReturnValue* function, but instead convert value to V8
+    # and then use general V8SetReturnValue.
+    'sequence': 'V8SetReturnValue(info, {cpp_value})',
+    'FrozenArray': 'V8SetReturnValue(info, {cpp_value})',
+    'Date': 'V8SetReturnValue(info, {cpp_value})',
+    'EventHandler': 'V8SetReturnValue(info, {cpp_value})',
+    'NodeFilter': 'V8SetReturnValue(info, {cpp_value})',
+    'ScriptValue': 'V8SetReturnValue(info, {cpp_value})',
+    'SerializedScriptValue': 'V8SetReturnValue(info, {cpp_value})',
+    # Records.
+    'Record': 'V8SetReturnValue(info, ToV8({cpp_value}, info.Holder(), info.GetIsolate()))',
     # DOMWrapper
-    'DOMWrapperForMainWorld': 'v8SetReturnValueForMainWorld(info, WTF::getPtr({cpp_value}))',
-    'DOMWrapperFast': 'v8SetReturnValueFast(info, WTF::getPtr({cpp_value}), {script_wrappable})',
-    'DOMWrapperDefault': 'v8SetReturnValue(info, {cpp_value})',
+    'DOMWrapperForMainWorld': 'V8SetReturnValueForMainWorld(info, {cpp_value})',
+    'DOMWrapperFast': 'V8SetReturnValueFast(info, {cpp_value}, {script_wrappable})',
+    'DOMWrapperDefault': 'V8SetReturnValue(info, {cpp_value})',
+    # If [CheckSecurity=ReturnValue] is specified, the returned object must be
+    # wrapped in its own realm, which can be different from the realm of the
+    # receiver object.
+    #
+    # [CheckSecurity=ReturnValue] is used only for contentDocument and
+    # getSVGDocument attributes of HTML{IFrame,Frame,Object,Embed}Element,
+    # and Window.frameElement.  Except for Window.frameElement, all interfaces
+    # support contentWindow(), so we create a new wrapper in the realm of
+    # contentWindow().  Note that DOMWindow* has its own realm and there is no
+    # need to pass |creationContext| in for ToV8(DOMWindow*).
+    # Window.frameElement is implemented with [Custom].
+    'DOMWrapperAcrossContext': (
+        'V8SetReturnValue(info, ToV8({cpp_value}, ' +
+        'ToV8(impl->contentWindow(), v8::Local<v8::Object>(), ' +
+        'info.GetIsolate()).As<v8::Object>(), info.GetIsolate()))'),
     # Note that static attributes and operations do not check whether |this| is
     # an instance of the interface nor |this|'s creation context is the same as
     # the current context.  So we must always use the current context as the
     # creation context of the DOM wrapper for the return value.
-    'DOMWrapperStatic': 'v8SetReturnValue(info, {cpp_value}, info.GetIsolate()->GetCurrentContext()->Global())',
+    'DOMWrapperStatic': 'V8SetReturnValue(info, {cpp_value}, info.GetIsolate()->GetCurrentContext()->Global())',
     # Generic dictionary type
-    'Dictionary': 'v8SetReturnValue(info, {cpp_value})',
+    'Dictionary': 'V8SetReturnValue(info, {cpp_value})',
     'DictionaryStatic': '#error not implemented yet',
     # Nullable dictionaries
-    'NullableDictionary': 'v8SetReturnValue(info, result.get())',
-    'NullableDictionaryStatic': '#error not implemented yet',
+    'NullableDictionary': 'V8SetReturnValue(info, result.Get())',
+    'NullableDictionaryStatic': 'V8SetReturnValue(info, result.Get(), info.GetIsolate()->GetCurrentContext()->Global())',
     # Union types or dictionaries
-    'DictionaryOrUnion': 'v8SetReturnValue(info, result)',
-    'DictionaryOrUnionStatic': '#error not implemented yet',
+    'DictionaryOrUnion': 'V8SetReturnValue(info, result)',
+    'DictionaryOrUnionStatic': 'V8SetReturnValue(info, result, info.GetIsolate()->GetCurrentContext()->Global())',
 }
 
 
-def v8_set_return_value(idl_type, cpp_value, extended_attributes=None, script_wrappable='', release=False, for_main_world=False, is_static=False):
+def v8_set_return_value(idl_type, cpp_value, extended_attributes=None, script_wrappable='', for_main_world=False, is_static=False):
     """Returns a statement that converts a C++ value to a V8 value and sets it as a return value.
 
     """
     def dom_wrapper_conversion_type():
+        if ('CheckSecurity' in extended_attributes and
+                extended_attribute_value_contains(
+                    extended_attributes['CheckSecurity'], 'ReturnValue')):
+            return 'DOMWrapperAcrossContext'
         if is_static:
             return 'DOMWrapperStatic'
         if not script_wrappable:
@@ -845,8 +933,9 @@
     idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes)
     this_v8_conversion_type = idl_type.v8_conversion_type(extended_attributes)
     # SetReturn-specific overrides
-    if this_v8_conversion_type in ['Date', 'EventHandler', 'ScriptValue', 'SerializedScriptValue', 'array']:
-        # Convert value to V8 and then use general v8SetReturnValue
+    if this_v8_conversion_type in ('Date', 'EventHandler', 'NodeFilter', 'ScriptValue',
+                                   'SerializedScriptValue', 'sequence', 'FrozenArray'):
+        # Convert value to V8 and then use general V8SetReturnValue
         cpp_value = idl_type.cpp_value_to_v8_value(cpp_value, extended_attributes=extended_attributes)
     if this_v8_conversion_type == 'DOMWrapper':
         this_v8_conversion_type = dom_wrapper_conversion_type()
@@ -854,42 +943,50 @@
         this_v8_conversion_type += 'Static'
 
     format_string = V8_SET_RETURN_VALUE[this_v8_conversion_type]
-    # FIXME: oilpan: Remove .release() once we remove all RefPtrs from generated code.
-    if release:
-        cpp_value = '%s.release()' % cpp_value
     statement = format_string.format(cpp_value=cpp_value, script_wrappable=script_wrappable)
     return statement
 
 
 IdlTypeBase.v8_set_return_value = v8_set_return_value
 
-IdlType.release = property(lambda self: self.is_interface_type)
-IdlUnionType.release = False
-
 
 CPP_VALUE_TO_V8_VALUE = {
     # Built-in types
-    'Date': 'v8DateOrNaN({isolate}, {cpp_value})',
-    'DOMString': 'v8String({isolate}, {cpp_value})',
-    'ByteString': 'v8String({isolate}, {cpp_value})',
-    'USVString': 'v8String({isolate}, {cpp_value})',
-    'boolean': 'v8Boolean({cpp_value}, {isolate})',
-    'int': 'v8::Integer::New({isolate}, {cpp_value})',
-    'unsigned': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
+    'Date': 'V8DateOrNaN({isolate}, {cpp_value})',
+    'DOMString': 'V8String({isolate}, {cpp_value})',
+    'ByteString': 'V8String({isolate}, {cpp_value})',
+    'USVString': 'V8String({isolate}, {cpp_value})',
+    'boolean': 'v8::Boolean::New({isolate}, {cpp_value})',
+    # All the int types below are converted to (u)int32_t in the v8::Integer::New*() calls.
+    # The 64-bit int types have already been converted to double when CPP_VALUE_TO_V8_VALUE is used, so they are not
+    # listed here.
+    'int8_t': 'v8::Integer::New({isolate}, {cpp_value})',
+    'int16_t': 'v8::Integer::New({isolate}, {cpp_value})',
+    'int32_t': 'v8::Integer::New({isolate}, {cpp_value})',
+    'uint8_t': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
+    'uint16_t': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
+    'uint32_t': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
     'float': 'v8::Number::New({isolate}, {cpp_value})',
     'unrestricted float': 'v8::Number::New({isolate}, {cpp_value})',
     'double': 'v8::Number::New({isolate}, {cpp_value})',
     'unrestricted double': 'v8::Number::New({isolate}, {cpp_value})',
     'void': 'v8Undefined()',
-    'StringOrNull': '{cpp_value}.isNull() ? v8::Local<v8::Value>(v8::Null({isolate})) : v8String({isolate}, {cpp_value})',
+    'StringOrNull': '{cpp_value}.IsNull() ? v8::Local<v8::Value>(v8::Null({isolate})) : V8String({isolate}, {cpp_value})',
     # Special cases
-    'Dictionary': '{cpp_value}.v8Value()',
-    'EventHandler': '{cpp_value} ? v8::Local<v8::Value>(V8AbstractEventListener::cast({cpp_value})->getListenerObject(impl->executionContext())) : v8::Local<v8::Value>(v8::Null({isolate}))',
-    'ScriptValue': '{cpp_value}.v8Value()',
-    'SerializedScriptValue': '{cpp_value} ? {cpp_value}->deserialize() : v8::Local<v8::Value>(v8::Null({isolate}))',
+    'Dictionary': '{cpp_value}.V8Value()',
+    'EventHandler': (
+        '{cpp_value} ? ' +
+        'V8AbstractEventListener::Cast({cpp_value})->GetListenerOrNull(' +
+        '{isolate}, impl->GetExecutionContext()) : ' +
+        'v8::Null({isolate}).As<v8::Value>()'),
+    'NodeFilter': 'ToV8({cpp_value}, {creation_context}, {isolate})',
+    'Record': 'ToV8({cpp_value}, {creation_context}, {isolate})',
+    'ScriptValue': '{cpp_value}.V8Value()',
+    'SerializedScriptValue': 'V8Deserialize({isolate}, {cpp_value})',
     # General
-    'array': 'toV8({cpp_value}, {creation_context}, {isolate})',
-    'DOMWrapper': 'toV8({cpp_value}, {creation_context}, {isolate})',
+    'sequence': 'ToV8({cpp_value}, {creation_context}, {isolate})',
+    'FrozenArray': 'FreezeV8Object(ToV8({cpp_value}, {creation_context}, {isolate}), {isolate})',
+    'DOMWrapper': 'ToV8({cpp_value}, {creation_context}, {isolate})',
     # Passing nullable dictionaries isn't a pattern currently used
     # anywhere in the web platform, and more work would be needed in
     # the code generator to distinguish between passing null, and
@@ -900,7 +997,7 @@
     # nullable dictionary type.
     #
     # Union types or dictionaries
-    'DictionaryOrUnion': 'toV8({cpp_value}, {creation_context}, {isolate})',
+    'DictionaryOrUnion': 'ToV8({cpp_value}, {creation_context}, {isolate})',
 }
 
 
@@ -922,7 +1019,7 @@
     if idl_type.base_type in ('any', 'object') and idl_literal.is_null:
         return 'ScriptValue()'
     literal_value = str(idl_literal)
-    if idl_type.base_type in CPP_UNSIGNED_TYPES:
+    if idl_type.base_type in ('octet', 'unsigned short', 'unsigned long'):
         return literal_value + 'u'
     return literal_value
 
@@ -939,12 +1036,12 @@
     else:
         raise ValueError('Unsupported literal type: ' + idl_literal.idl_type)
 
-    return '%s::from%s(%s)' % (idl_type.name, member_type.name,
+    return '%s::From%s(%s)' % (idl_type.name, member_type.name,
                                member_type.literal_cpp_value(idl_literal))
 
 
 def array_or_sequence_literal_cpp_value(idl_type, idl_literal):
-    # Only support empty arrays.
+    # Only support empty sequences.
     if idl_literal.value == '[]':
         return cpp_type(idl_type) + '()'
     raise ValueError('Unsupported literal type: ' + idl_literal.idl_type)
@@ -962,16 +1059,20 @@
 
 def cpp_type_has_null_value(idl_type):
     # - String types (String/AtomicString) represent null as a null string,
-    #   i.e. one for which String::isNull() returns true.
+    #   i.e. one for which String::IsNull() returns true.
     # - Enum types, as they are implemented as Strings.
-    # - Interface types (raw pointer or RefPtr/PassRefPtr) represent null as
+    # - Interface types (raw pointer or RefPtr) represent null as
     #   a null pointer.
     # - Union types, as thier container classes can represent null value.
     # - 'Object' and 'any' type. We use ScriptValue for object type.
-    return (idl_type.is_string_type or idl_type.is_interface_type or
-            idl_type.is_enum or idl_type.is_union_type
-            or idl_type.base_type == 'object' or idl_type.base_type == 'any'
-            or idl_type.is_callback_function or idl_type.is_callback_interface)
+    return (idl_type.is_string_type
+            or idl_type.is_enum
+            or idl_type.is_interface_type
+            or idl_type.is_callback_interface
+            or idl_type.is_callback_function
+            or idl_type.is_custom_callback_function
+            or idl_type.is_union_type
+            or idl_type.base_type == 'object' or idl_type.base_type == 'any')
 
 IdlTypeBase.cpp_type_has_null_value = property(cpp_type_has_null_value)
 
@@ -991,21 +1092,6 @@
 IdlTypeBase.is_explicit_nullable = property(is_explicit_nullable)
 
 
-def number_of_nullable_member_types_union(idl_type):
-    # http://heycam.github.io/webidl/#dfn-number-of-nullable-member-types
-    count = 0
-    for member in idl_type.member_types:
-        if member.is_nullable:
-            count += 1
-            member = member.inner_type
-        if member.is_union_type:
-            count += number_of_nullable_member_types_union(member)
-    return count
-
-IdlUnionType.number_of_nullable_member_types = property(
-    number_of_nullable_member_types_union)
-
-
 def includes_nullable_type_union(idl_type):
     # http://heycam.github.io/webidl/#dfn-includes-a-nullable-type
     return idl_type.number_of_nullable_member_types == 1
diff --git a/bindings/scripts/v8_union.py b/bindings/scripts/v8_union.py
index fa22cdb..7778c88 100644
--- a/bindings/scripts/v8_union.py
+++ b/bindings/scripts/v8_union.py
@@ -2,63 +2,35 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from utilities import to_snake_case
+import v8_types
 import v8_utilities
 
 
+UNION_CPP_INCLUDES = frozenset([
+    'bindings/core/v8/ToV8ForCore.h',
+])
+
 UNION_H_INCLUDES = frozenset([
     'bindings/core/v8/Dictionary.h',
     'bindings/core/v8/ExceptionState.h',
-    'bindings/core/v8/V8Binding.h',
+    'bindings/core/v8/NativeValueTraits.h',
+    'bindings/core/v8/V8BindingForCore.h',
     'platform/heap/Handle.h',
 ])
 
-UNION_CPP_INCLUDES_BLACKLIST = frozenset([
-    # This header defines static functions needed to implement event handler
-    # attributes in interfaces that implement GlobalEventHandlers. They are not
-    # needed or used by UnionTypes*.cpp, so including the header causes
-    # compilation errors.
-    # FIXME: We should solve this problem in a way that doesn't involve special-
-    # casing a header like this.
-    'core/dom/GlobalEventHandlers.h',
-])
-
 
 cpp_includes = set()
 header_forward_decls = set()
 header_includes = set()
 
 
-def union_context(union_types, interfaces_info):
+def container_context(union_type, info_provider):
     cpp_includes.clear()
     header_forward_decls.clear()
     header_includes.clear()
+    cpp_includes.update(UNION_CPP_INCLUDES)
     header_includes.update(UNION_H_INCLUDES)
-
-    # For container classes we strip nullable wrappers. For example,
-    # both (A or B)? and (A? or B) will become AOrB. This should be OK
-    # because container classes can handle null and it seems that
-    # distinguishing (A or B)? and (A? or B) doesn't make sense.
-    container_cpp_types = set()
-    union_types_for_containers = set()
-    for union_type in union_types:
-        cpp_type = union_type.cpp_type
-        if cpp_type not in container_cpp_types:
-            union_types_for_containers.add(union_type)
-            container_cpp_types.add(cpp_type)
-
-    union_types_for_containers = sorted(union_types_for_containers,
-                                        key=lambda union_type: union_type.cpp_type)
-
-    return {
-        'containers': [container_context(union_type, interfaces_info)
-                       for union_type in union_types_for_containers],
-        'cpp_includes': sorted(cpp_includes - UNION_CPP_INCLUDES_BLACKLIST),
-        'header_forward_decls': sorted(header_forward_decls),
-        'header_includes': sorted(header_includes),
-    }
-
-
-def container_context(union_type, interfaces_info):
     members = []
 
     # These variables refer to member contexts if the given union type has
@@ -71,9 +43,10 @@
     interface_types = []
     numeric_type = None
     object_type = None
+    record_type = None
     string_type = None
-    for member in union_type.member_types:
-        context = member_context(member, interfaces_info)
+    for member in sorted(union_type.flattened_member_types, key=lambda m: m.name):
+        context = member_context(member, info_provider)
         members.append(context)
         if member.base_type == 'ArrayBuffer':
             if array_buffer_type:
@@ -93,9 +66,13 @@
             array_or_sequence_type = context
         # "Dictionary" is an object, rather than an IDL dictionary.
         elif member.base_type == 'Dictionary':
-            if object_type:
+            if object_type or record_type:
                 raise Exception('%s is ambiguous.' % union_type.name)
             object_type = context
+        elif member.is_record_type:
+            if object_type or record_type:
+                raise Exception('%s is ambiguous.' % union_type.name)
+            record_type = context
         elif member.is_interface_type:
             interface_types.append(context)
         elif member is union_type.boolean_member_type:
@@ -114,63 +91,73 @@
     if dictionary_type and nullable_members == 1:
         raise Exception('%s has a dictionary and a nullable member' % union_type.name)
 
+    cpp_class = union_type.cpp_type
     return {
         'array_buffer_type': array_buffer_type,
         'array_buffer_view_type': array_buffer_view_type,
         'array_or_sequence_type': array_or_sequence_type,
         'boolean_type': boolean_type,
-        'cpp_class': union_type.cpp_type,
+        'cpp_class': cpp_class,
+        'cpp_includes': sorted(cpp_includes),
         'dictionary_type': dictionary_type,
+        'header_includes': sorted(header_includes),
+        'header_forward_decls': sorted(header_forward_decls),
         'includes_nullable_type': union_type.includes_nullable_type,
         'interface_types': interface_types,
         'members': members,
         'numeric_type': numeric_type,
         'object_type': object_type,
+        'record_type': record_type,
         'string_type': string_type,
         'type_string': str(union_type),
+        'v8_class': v8_types.v8_type(cpp_class),
     }
 
 
-def _update_includes_and_forward_decls(member, interface_info):
+def _update_includes_and_forward_decls(member, info_provider):
+    interface_info = info_provider.interfaces_info.get(member.name, None)
     if interface_info:
         cpp_includes.update(interface_info.get(
             'dependencies_include_paths', []))
-        # TODO(bashi): Workaround for http://crbug.com/524424
-        # Avoid using forward declaration for IDL dictionaries so that they
-        # aren't imcomplete types in UnionTypes.h. This enables an IDL
-        # dictionary to have a union type which has an IDL dictionary. e.g.
-        #   dictionary DictA { (boolean or DictB) member; }
-        # Note that this doesn't cover all cases. We still can't use an IDL
-        # dictionary in a union type when the dictionary contains a union type.
-        # e.g.
-        #   void foo((DOMString or DictA) arg);  // won't compile
-        if member.is_dictionary:
+        # We need complete types for IDL dictionaries in union containers.
+        if member.is_dictionary or member.is_array_buffer_view_or_typed_array:
             header_includes.update(member.includes_for_type())
         else:
             cpp_includes.update(member.includes_for_type())
             header_forward_decls.add(member.implemented_as)
     else:
+        if member.is_record_type:
+            _update_includes_and_forward_decls(member.key_type, info_provider)
+            _update_includes_and_forward_decls(member.value_type, info_provider)
+        elif member.is_array_or_sequence_type:
+            _update_includes_and_forward_decls(member.element_type, info_provider)
+        elif member.is_union_type:
+            # Reaching this block means we have a union that is inside a
+            # record or sequence.
+            header_forward_decls.add(member.name)
+            cpp_includes.update([info_provider.include_path_for_union_types(member)])
         cpp_includes.update(member.includes_for_type())
 
 
-def member_context(member, interfaces_info):
-    interface_info = interfaces_info.get(member.name, None)
-    _update_includes_and_forward_decls(member, interface_info)
+def member_context(member, info_provider):
+    _update_includes_and_forward_decls(member, info_provider)
     if member.is_nullable:
         member = member.inner_type
     return {
-        'cpp_name': v8_utilities.uncapitalize(member.name),
+        'cpp_name': to_snake_case(v8_utilities.cpp_name(member)),
         'cpp_type': member.cpp_type_args(used_in_cpp_sequence=True),
         'cpp_local_type': member.cpp_type,
         'cpp_value_to_v8_value': member.cpp_value_to_v8_value(
-            cpp_value='impl.getAs%s()' % member.name, isolate='isolate',
+            cpp_value='impl.GetAs%s()' % member.name, isolate='isolate',
             creation_context='creationContext'),
         'enum_values': member.enum_values,
+        'is_array_buffer_or_view_type': member.is_array_buffer_or_view,
+        'is_array_buffer_view_or_typed_array': member.is_array_buffer_view_or_typed_array,
         'is_traceable': member.is_traceable,
         'rvalue_cpp_type': member.cpp_type_args(used_as_rvalue_type=True),
-        'specific_type_enum': 'SpecificType' + member.name,
+        'specific_type_enum': 'k' + member.name,
         'type_name': member.name,
         'v8_value_to_local_cpp_value': member.v8_value_to_local_cpp_value(
             {}, 'v8Value', 'cppValue', isolate='isolate',
-            use_exception_state=True, restricted_float=True),
+            use_exception_state=True)
     }
diff --git a/bindings/scripts/v8_utilities.py b/bindings/scripts/v8_utilities.py
index 1e8733a..08c4fe8 100644
--- a/bindings/scripts/v8_utilities.py
+++ b/bindings/scripts/v8_utilities.py
@@ -31,11 +31,14 @@
 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
 """
 
+import os
 import re
+import sys
 
 from idl_types import IdlTypeBase
 import idl_types
 from idl_definitions import Exposure, IdlInterface, IdlAttribute
+from utilities import to_snake_case
 from v8_globals import includes
 
 ACRONYMS = [
@@ -44,6 +47,7 @@
     'HTML',
     'IME',
     'JS',
+    'SMIL',
     'SVG',
     'URL',
     'WOFF',
@@ -112,13 +116,16 @@
     return name[0].lower() + name[1:]
 
 
+def runtime_enabled_function(name):
+    """Returns a function call of a runtime enabled feature."""
+    return 'RuntimeEnabledFeatures::%sEnabled()' % name
+
+
 ################################################################################
 # C++
 ################################################################################
 
 def scoped_name(interface, definition, base_name):
-    if 'ImplementedInPrivateScript' in definition.extended_attributes:
-        return '%s::PrivateScript::%s' % (v8_class_name(interface), base_name)
     # partial interfaces are implemented as separate classes, with their members
     # implemented as static member functions
     partial_interface_implemented_as = definition.extended_attributes.get('PartialInterfaceImplementedAs')
@@ -141,6 +148,26 @@
     return class_name
 
 
+def build_basename(name, snake_case, prefix=None, ext=None):
+    basename = name
+    if prefix:
+        basename = prefix + name
+    if snake_case:
+        basename = to_snake_case(basename)
+        if not ext:
+            return basename
+        if ext == '.cpp':
+            return basename + '.cc'
+        return basename + ext
+    if ext:
+        return basename + ext
+    return basename
+
+
+def binding_header_basename(name, snake_case):
+    return build_basename(name, snake_case, prefix='V8', ext='.h')
+
+
 ################################################################################
 # Specific extended attributes
 ################################################################################
@@ -158,7 +185,7 @@
     if log_activity and not log_activity.startswith(access_type):
         return set()
 
-    includes.add('bindings/core/v8/V8DOMActivityLogger.h')
+    includes.add('platform/bindings/V8DOMActivityLogger.h')
     if 'LogAllWorlds' in extended_attributes:
         return set(['', 'ForMainWorld'])
     return set([''])  # At minimum, include isolated worlds.
@@ -185,19 +212,19 @@
 CALL_WITH_ARGUMENTS = {
     'ScriptState': 'scriptState',
     'ExecutionContext': 'executionContext',
-    'ScriptArguments': 'scriptArguments.release()',
-    'ActiveWindow': 'currentDOMWindow(info.GetIsolate())',
-    'FirstWindow': 'enteredDOMWindow(info.GetIsolate())',
+    'ScriptArguments': 'scriptArguments',
+    'CurrentWindow': 'CurrentDOMWindow(info.GetIsolate())',
+    'EnteredWindow': 'EnteredDOMWindow(info.GetIsolate())',
     'Document': 'document',
-    'ThisValue': 'ScriptValue(scriptState, info.This())',
+    'ThisValue': 'ScriptValue(scriptState, info.Holder())',
 }
 # List because key order matters, as we want arguments in deterministic order
 CALL_WITH_VALUES = [
     'ScriptState',
     'ExecutionContext',
     'ScriptArguments',
-    'ActiveWindow',
-    'FirstWindow',
+    'CurrentWindow',
+    'EnteredWindow',
     'Document',
     'ThisValue',
 ]
@@ -229,18 +256,19 @@
 
 # [Exposed]
 EXPOSED_EXECUTION_CONTEXT_METHOD = {
-    'CompositorWorker': 'isCompositorWorkerGlobalScope',
-    'DedicatedWorker': 'isDedicatedWorkerGlobalScope',
-    'ServiceWorker': 'isServiceWorkerGlobalScope',
-    'SharedWorker': 'isSharedWorkerGlobalScope',
-    'Window': 'isDocument',
-    'Worker': 'isWorkerGlobalScope',
-    'Worklet': 'isWorkletGlobalScope',
+    'AnimationWorklet': 'IsAnimationWorkletGlobalScope',
+    'AudioWorklet': 'IsAudioWorkletGlobalScope',
+    'DedicatedWorker': 'IsDedicatedWorkerGlobalScope',
+    'PaintWorklet': 'IsPaintWorkletGlobalScope',
+    'ServiceWorker': 'IsServiceWorkerGlobalScope',
+    'SharedWorker': 'IsSharedWorkerGlobalScope',
+    'Window': 'IsDocument',
+    'Worker': 'IsWorkerGlobalScope',
+    'Worklet': 'IsWorkletGlobalScope',
 }
 
 
 EXPOSED_WORKERS = set([
-    'CompositorWorker',
     'DedicatedWorker',
     'SharedWorker',
     'ServiceWorker',
@@ -282,8 +310,7 @@
         exposed = ('executionContext->%s()' %
                    EXPOSED_EXECUTION_CONTEXT_METHOD[exposure.exposed])
         if exposure.runtime_enabled is not None:
-            runtime_enabled = ('RuntimeEnabledFeatures::%sEnabled()' %
-                               uncapitalize(exposure.runtime_enabled))
+            runtime_enabled = (runtime_enabled_function(exposure.runtime_enabled))
             return '({0} && {1})'.format(exposed, runtime_enabled)
         return exposed
 
@@ -305,8 +332,8 @@
       => context->isDocument()
 
     EXAMPLE: [Exposed(Window Feature1, Window Feature2)]
-      => context->isDocument() && RuntimeEnabledFeatures::feature1Enabled() ||
-         context->isDocument() && RuntimeEnabledFeatures::feature2Enabled()
+      => context->isDocument() && RuntimeEnabledFeatures::Feature1Enabled() ||
+         context->isDocument() && RuntimeEnabledFeatures::Feature2Enabled()
     """
     exposure_set = ExposureSet(
         extended_attribute_value_as_list(member, 'Exposed'))
@@ -323,22 +350,21 @@
     return exposure_set.code()
 
 
-# [GarbageCollected], [WillBeGarbageCollected]
-def gc_type(definition):
-    extended_attributes = definition.extended_attributes
-    if 'GarbageCollected' in extended_attributes:
-        return 'GarbageCollectedObject'
-    elif 'WillBeGarbageCollected' in extended_attributes:
-        return 'WillBeGarbageCollectedObject'
-    return 'RefCountedObject'
+# [SecureContext]
+def secure_context(member, interface):
+    """Returns C++ code that checks whether an interface/method/attribute/etc. is exposed
+    to the current context."""
+    if 'SecureContext' in member.extended_attributes or 'SecureContext' in interface.extended_attributes:
+        return 'executionContext->IsSecureContext()'
+    return None
 
 
 # [ImplementedAs]
 def cpp_name(definition_or_member):
     extended_attributes = definition_or_member.extended_attributes
-    if 'ImplementedAs' not in extended_attributes:
-        return definition_or_member.name
-    return extended_attributes['ImplementedAs']
+    if extended_attributes and 'ImplementedAs' in extended_attributes:
+        return extended_attributes['ImplementedAs']
+    return definition_or_member.name
 
 
 def cpp_name_from_interfaces_info(name, interfaces_info):
@@ -367,48 +393,83 @@
     return None
 
 
-def runtime_feature_name(definition_or_member):
+# [OriginTrialEnabled]
+def origin_trial_enabled_function_name(definition_or_member):
+    """Returns the name of the OriginTrials enabled function.
+
+    An exception is raised if OriginTrialEnabled is used in conjunction with any
+    of the following (which must be mutually exclusive with origin trials):
+      - RuntimeEnabled
+
+    The returned function checks if the IDL member should be enabled.
+    Given extended attribute OriginTrialEnabled=FeatureName, return:
+        OriginTrials::{featureName}Enabled
+
+    If the OriginTrialEnabled extended attribute is found, the includes are
+    also updated as a side-effect.
+    """
     extended_attributes = definition_or_member.extended_attributes
-    if 'RuntimeEnabled' not in extended_attributes:
-        return None
-    return extended_attributes['RuntimeEnabled']
+    is_origin_trial_enabled = 'OriginTrialEnabled' in extended_attributes
+
+    if is_origin_trial_enabled and 'RuntimeEnabled' in extended_attributes:
+        raise Exception('[OriginTrialEnabled] and [RuntimeEnabled] must '
+                        'not be specified on the same definition: %s'
+                        % definition_or_member.name)
+
+    if is_origin_trial_enabled:
+        trial_name = extended_attributes['OriginTrialEnabled']
+        return 'OriginTrials::%sEnabled' % uncapitalize(trial_name)
+
+    is_feature_policy_enabled = 'FeaturePolicy' in extended_attributes
+
+    if is_feature_policy_enabled and 'RuntimeEnabled' in extended_attributes:
+        raise Exception('[FeaturePolicy] and [RuntimeEnabled] must '
+                        'not be specified on the same definition: %s'
+                        % definition_or_member.name)
+
+    if is_feature_policy_enabled and 'SecureContext' in extended_attributes:
+        raise Exception('[FeaturePolicy] and [SecureContext] must '
+                        'not be specified on the same definition '
+                        '(see https://crbug.com/695123 for workaround): %s'
+                        % definition_or_member.name)
+
+    if is_feature_policy_enabled:
+        includes.add('platform/bindings/ScriptState.h')
+        includes.add('platform/feature_policy/FeaturePolicy.h')
+
+        trial_name = extended_attributes['FeaturePolicy']
+        return 'FeaturePolicy::%sEnabled' % uncapitalize(trial_name)
+
+    return None
 
 
-def is_origin_trial_enabled(definition_or_member):
-    return 'OriginTrialEnabled' in definition_or_member.extended_attributes
+def origin_trial_feature_name(definition_or_member):
+    extended_attributes = definition_or_member.extended_attributes
+    return extended_attributes.get('OriginTrialEnabled') or extended_attributes.get('FeaturePolicy')
 
 
-def origin_trial_name(definition_or_member):
-    return definition_or_member.extended_attributes['OriginTrialEnabled'] if is_origin_trial_enabled(definition_or_member) else None
+# [ContextEnabled]
+def context_enabled_feature_name(definition_or_member):
+    return definition_or_member.extended_attributes.get('ContextEnabled')
 
 
-def origin_trial_enabled_function(definition_or_member):
-    trial_name = origin_trial_name(definition_or_member)
-    feature_name = runtime_feature_name(definition_or_member)
-    if not feature_name or not trial_name:
-        return
-    return 'OriginTrials::%sEnabled' % uncapitalize(feature_name)
+# [RuntimeCallStatsCounter]
+def rcs_counter_name(member, generic_counter_name):
+    extended_attribute_defined = 'RuntimeCallStatsCounter' in member.extended_attributes
+    if extended_attribute_defined:
+        counter = 'k' + member.extended_attributes['RuntimeCallStatsCounter']
+    else:
+        counter = generic_counter_name
+    return (counter, extended_attribute_defined)
 
 
 # [RuntimeEnabled]
-def runtime_enabled_function_name(definition_or_member):
-    """Returns the name of the RuntimeEnabledFeatures function.
-
-    The returned function checks if a method/attribute is enabled.
-    Given extended attribute RuntimeEnabled=FeatureName, return:
-        RuntimeEnabledFeatures::{featureName}Enabled
-    """
-    feature_name = runtime_feature_name(definition_or_member)
-
-    # If an origin trial is on the method/attribute, it overrides the runtime
-    # enabled status. For now, we are unconditionally installing these
-    # attributes/methods, so we are acting as though the runtime enabled
-    # function doesn't exist. (It is checked in the generated OriginTrials
-    # function, instead)
-    trial_name = origin_trial_name(definition_or_member)
-    if not feature_name or trial_name:
-        return
-    return 'RuntimeEnabledFeatures::%sEnabled' % uncapitalize(feature_name)
+def runtime_enabled_feature_name(definition_or_member):
+    extended_attributes = definition_or_member.extended_attributes
+    if 'RuntimeEnabled' not in extended_attributes:
+        return None
+    includes.add('platform/runtime_enabled_features.h')
+    return extended_attributes['RuntimeEnabled']
 
 
 # [Unforgeable]
@@ -429,16 +490,16 @@
     """Returns True if the interface's member needs to be defined on every
     instance object.
 
-    The following members must be defiend on an instance object.
+    The following members must be defined on an instance object.
     - [Unforgeable] members
     - regular members of [Global] or [PrimaryGlobal] interfaces
     """
     if member.is_static:
         return False
 
-    # TODO(yukishiino): Remove a hack for toString once we support
-    # Symbol.toStringTag.
-    if (interface.name == 'Window' and member.name == 'toString'):
+    # TODO(yukishiino): Remove a hack for ToString once we support
+    # Symbol.ToStringTag.
+    if interface.name == 'Window' and member.name == 'ToString':
         return False
 
     # TODO(yukishiino): Implement "interface object" and its [[Call]] method
@@ -500,6 +561,27 @@
 
 
 ################################################################################
+# Legacy callers
+# https://heycam.github.io/webidl/#idl-legacy-callers
+################################################################################
+
+def legacy_caller(interface):
+    try:
+        # Find legacy caller, if present; has form:
+        # legacycaller TYPE [OPTIONAL_IDENTIFIER](OPTIONAL_ARGUMENTS)
+        caller = next(
+            method
+            for method in interface.operations
+            if 'legacycaller' in method.specials)
+        if not caller.name:
+            raise Exception('legacycaller with no identifier is not supported: '
+                            '%s' % interface.name)
+        return caller
+    except StopIteration:
+        return None
+
+
+################################################################################
 # Indexed properties
 # http://heycam.github.io/webidl/#idl-indexed-properties
 ################################################################################
@@ -561,7 +643,7 @@
             if ('getter' in method.specials and
                 len(method.arguments) == 1 and
                 str(method.arguments[0].idl_type) == 'DOMString'))
-        getter.name = getter.name or 'anonymousNamedGetter'
+        getter.name = getter.name or 'AnonymousNamedGetter'
         return getter
     except StopIteration:
         return None
@@ -595,6 +677,7 @@
         return None
 
 
+IdlInterface.legacy_caller = property(legacy_caller)
 IdlInterface.indexed_property_getter = property(indexed_property_getter)
 IdlInterface.indexed_property_setter = property(indexed_property_setter)
 IdlInterface.indexed_property_deleter = property(indexed_property_deleter)
diff --git a/bindings/tests/idls/core/ArrayBuffer.idl b/bindings/tests/idls/core/ArrayBuffer.idl
index 7878c57..c0203e1 100644
--- a/bindings/tests/idls/core/ArrayBuffer.idl
+++ b/bindings/tests/idls/core/ArrayBuffer.idl
@@ -5,7 +5,7 @@
 // https://www.khronos.org/registry/typedarray/specs/latest/#ARRAYBUFFER
 
 [
-    ImplementedAs=TestArrayBuffer,
+    ImplementedAs=TestArrayBuffer
 ] interface ArrayBuffer {
     readonly attribute unsigned long byteLength;
 };
diff --git a/bindings/tests/idls/core/ArrayBufferView.idl b/bindings/tests/idls/core/ArrayBufferView.idl
index e6e9262..3ea88e3 100644
--- a/bindings/tests/idls/core/ArrayBufferView.idl
+++ b/bindings/tests/idls/core/ArrayBufferView.idl
@@ -5,7 +5,7 @@
 // https://www.khronos.org/registry/typedarray/specs/latest/#ARRAYBUFFERVIEW
 
 [
-    ImplementedAs=TestArrayBufferView,
+    ImplementedAs=TestArrayBufferView
 ] interface ArrayBufferView {
     readonly attribute ArrayBuffer buffer;
     readonly attribute unsigned long byteOffset;
diff --git a/bindings/tests/idls/core/DataView.idl b/bindings/tests/idls/core/DataView.idl
index e26468d..d21b90b 100644
--- a/bindings/tests/idls/core/DataView.idl
+++ b/bindings/tests/idls/core/DataView.idl
@@ -5,7 +5,7 @@
 // https://www.khronos.org/registry/typedarray/specs/latest/#DATAVIEW
 
 [
-    ImplementedAs=TestDataView,
+    ImplementedAs=TestDataView
 ] interface DataView : ArrayBufferView {
     [RaisesException] octet getUint8(unsigned long byteOffset);
     [RaisesException] double getFloat64(unsigned long byteOffset, optional boolean littleEndian);
diff --git a/bindings/tests/idls/core/SVGTestInterface.idl b/bindings/tests/idls/core/SVGTestInterface.idl
index 81e8997..43fb132 100644
--- a/bindings/tests/idls/core/SVGTestInterface.idl
+++ b/bindings/tests/idls/core/SVGTestInterface.idl
@@ -28,11 +28,10 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-
 // This test files starts with 'SVG' because /^SVG/ is used as a check
 // for SVG interfaces (to use SVGNames for [Reflect] attributes)
 [
-    DependentLifetime,
+    DependentLifetime
 ] interface SVGTestInterface {
     [Reflect] attribute DOMString type; // Test SVGNames namespace
 };
diff --git a/bindings/tests/idls/core/TestAttributeGetters.idl b/bindings/tests/idls/core/TestAttributeGetters.idl
new file mode 100644
index 0000000..0bb8eb4
--- /dev/null
+++ b/bindings/tests/idls/core/TestAttributeGetters.idl
@@ -0,0 +1,30 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://heycam.github.io/webidl/#dfn-attribute-getter
+
+// Attribute getters must behave differently based on whether [LenientThis] has
+// been specified or whether the attribute's type is Promise<T>.
+// All attributes below are marked readonly because we are only interested in
+// the behavior of attribute getters.
+
+interface TestAttributeGetters {
+    // [LenientThis] causes some V8 type checks to be bypassed; they are done
+    // on the Blink side instead and access exceptions just return undefined.
+    [LenientThis] readonly attribute long lenientThisLongAttribute;
+
+    // Promise types must turn exceptions into promise rejections.
+    readonly attribute Promise<DOMString> stringPromiseAttribute;
+
+    // Mixing both should cause [LenientThis] to return without raising an
+    // exception if type checking fails.
+    [LenientThis] readonly attribute Promise<DOMString> lenientThisStringPromiseAttribute;
+
+    // [RaisesException] also creates an ExceptionState instance. Make sure it
+    // is not declared twice.
+    [RaisesException] readonly attribute Promise<short> raisesExceptionShortPromiseAttribute;
+
+    // Regular attribute with no special rules.
+    readonly attribute float floatAttribute;
+};
diff --git a/bindings/tests/idls/core/TestCallbackFunctions.idl b/bindings/tests/idls/core/TestCallbackFunctions.idl
new file mode 100644
index 0000000..10edce1
--- /dev/null
+++ b/bindings/tests/idls/core/TestCallbackFunctions.idl
@@ -0,0 +1,33 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+callback VoidCallbackFunction = void ();
+callback AnyCallbackFunctionOptionalAnyArg = any (optional any optionalAnyArg);
+callback LongCallbackFunction = long (long num1, long num2);
+
+// Following callback functions are to be generated as expected.
+callback VoidCallbackFunctionInterfaceArg = void (HTMLDivElement divElement);
+callback VoidCallbackFunctionDictionaryArg = void (TestDictionary arg);
+callback VoidCallbackFunctionTestInterfaceSequenceArg = void (sequence<TestInterface> arg);
+callback StringSequenceCallbackFunctionLongSequenceArg = sequence<DOMString> (sequence<long> arg);
+callback VoidCallbackFunctionEnumArg = void (TestEnum arg);
+callback VoidCallbackFunctionTypedef = void (String arg);
+
+interface TestCallbackFunctions {
+    // Extended attributes
+    [CustomElementCallbacks] readonly attribute long customElementsCallbacksReadonlyAttribute;
+
+    // Methods
+    VoidCallbackFunction returnCallbackFunctionMethod();
+    AnyCallbackFunctionOptionalAnyArg returnCallbackFunctionMethod2();
+
+    void voidMethodCallbackFunctionInArg(VoidCallbackFunction voidCallbackFunctionArg);
+    void voidMethodCallbackFunctionInArg2(AnyCallbackFunctionOptionalAnyArg anyCallbackFunctionOptionalAnyArgArg);
+    void voidMethodCallbackFunctionWithReturnValueInArg(LongCallbackFunction longCallbackFunctionArg);
+
+    void voidMethodOptionalCallbackFunctionInArg(optional VoidCallbackFunction voidCallbackFunctionArg);
+    void voidMethodNullableCallbackFunctionInArg(VoidCallbackFunction? voidCallbackFunctionArg);
+    // Extended attributes
+    [CustomElementCallbacks] void customElementCallbacksMethod();
+};
diff --git a/bindings/tests/idls/core/TestCallbackInterface.idl b/bindings/tests/idls/core/TestCallbackInterface.idl
index cebfa19..283ffb2 100644
--- a/bindings/tests/idls/core/TestCallbackInterface.idl
+++ b/bindings/tests/idls/core/TestCallbackInterface.idl
@@ -36,7 +36,4 @@
   void voidMethodTestInterfaceEmptyStringArg(TestInterfaceEmpty testInterfaceEmptyArg, DOMString stringArg);
   [CallWith=ThisValue] void callbackWithThisValueVoidMethodStringArg(DOMString stringArg);
   [Custom] void customVoidMethodTestInterfaceEmptyArg(TestInterfaceEmpty testInterfaceEmptyArg);
-  // [WillBeGarbageCollected]
-  void voidMethodWillBeGarbageCollectedSequenceArg(sequence<TestInterfaceWillBeGarbageCollected> sequenceArg);
-  void voidMethodWillBeGarbageCollectedArrayArg(TestInterfaceWillBeGarbageCollected[] arrayArg);
 };
diff --git a/bindings/tests/idls/core/TestConstants.idl b/bindings/tests/idls/core/TestConstants.idl
new file mode 100644
index 0000000..8c604a6
--- /dev/null
+++ b/bindings/tests/idls/core/TestConstants.idl
@@ -0,0 +1,39 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+interface TestConstants {
+    const unsigned short CONST_VALUE_ZERO = 0;
+    const unsigned short CONST_VALUE_ONE = 1;
+    const unsigned short CONST_VALUE_TWO = 2;
+    const short CONST_VALUE_NEGATIVE = -1;
+    const unsigned short CONST_VALUE_32_BITS = 0xffffffff;
+    const unsigned short CONST_VALUE_HEX = 0x01;
+    const unsigned short CONST_VALUE_HEX2 = 0X20;
+    const unsigned short CONST_VALUE_HEX3 = 0x1abc;
+    const unsigned short CONST_VALUE_OCT = 010;
+    const unsigned short CONST_VALUE_NEGATIVE_OCT = -010;
+    const unsigned short CONST_VALUE_NEGATIVE_HEX = -0x1A;
+    const unsigned short CONST_VALUE_NEGATIVE_HEX2 = -0X1a;  // lower case
+    const double CONST_VALUE_DECIMAL = 0.123;
+    const double CONST_VALUE_DECIMAL2 = 4e9;
+    const double CONST_VALUE_DECIMAL3 = 3.4e5;
+    const double CONST_VALUE_DECIMAL4 = .123;
+    const double CONST_VALUE_DECIMAL5 = 5E+4;
+    const double CONST_VALUE_NEGATIVE_DECIMAL = -1.3;
+    const double CONST_VALUE_NEGATIVE_DECIMAL2 = -4e-9;
+    const float CONST_VALUE_FLOAT = 1;
+
+    // Extended attributes
+    [DeprecateAs=Constant] const short DEPRECATED_CONSTANT = 1;
+    [MeasureAs=Constant] const short MEASURED_CONSTANT = 1;
+    [RuntimeEnabled=FeatureName1] const short FEATURE1_ENABLED_CONST1 = 1;
+    [RuntimeEnabled=FeatureName1] const short FEATURE1_ENABLED_CONST2 = 2;
+    [RuntimeEnabled=FeatureName2] const short FEATURE2_ENABLED_CONST1 = 3;
+    [RuntimeEnabled=FeatureName2] const short FEATURE2_ENABLED_CONST2 = 4;
+    [OriginTrialEnabled=FeatureName1] const short FEATURE1_ORIGIN_TRIAL_ENABLED_CONST1 = 6;
+    [OriginTrialEnabled=FeatureName1] const short FEATURE1_ORIGIN_TRIAL_ENABLED_CONST2 = 7;
+    [OriginTrialEnabled=FeatureName2] const short FEATURE2_ORIGIN_TRIAL_ENABLED_CONST1 = 8;
+    [OriginTrialEnabled=FeatureName2] const short FEATURE2_ORIGIN_TRIAL_ENABLED_CONST2 = 9;
+    [Reflect=CONST_IMPL] const short CONST_JAVASCRIPT = 1;
+};
diff --git a/bindings/tests/idls/core/TestDictionary.idl b/bindings/tests/idls/core/TestDictionary.idl
index 0ac0a68..136eb3d 100644
--- a/bindings/tests/idls/core/TestDictionary.idl
+++ b/bindings/tests/idls/core/TestDictionary.idl
@@ -14,13 +14,11 @@
     TestInterface? testInterfaceOrNullMember;
     TestInterfaceGarbageCollected testInterfaceGarbageCollectedMember;
     TestInterfaceGarbageCollected? testInterfaceGarbageCollectedOrNullMember;
-    TestInterfaceWillBeGarbageCollected testInterfaceWillBeGarbageCollectedMember;
-    TestInterfaceWillBeGarbageCollected? testInterfaceWillBeGarbageCollectedOrNullMember;
-    DOMString[] stringArrayMember;
     sequence<DOMString> stringSequenceMember = [];
+    sequence<[TreatNullAs=EmptyString] DOMString> treatNullAsStringSequenceMember = [];
     sequence<TestInterface> testInterfaceSequenceMember = [];
+    sequence<TestObject> testObjectSequenceMember;
     sequence<TestInterfaceGarbageCollected> testInterfaceGarbageCollectedSequenceMember = [];
-    sequence<TestInterfaceWillBeGarbageCollected> testInterfaceWillBeGarbageCollectedSequenceMember = [];
     TestEnum enumMember = "foo";
     sequence<TestEnum> enumSequenceMember;
     Element? elementOrNullMember;
@@ -28,6 +26,8 @@
     object? objectOrNullMember;
     [ImplementedAs=createMember] boolean create;
     [DeprecateAs=CreateMember, ImplementedAs=createMember] boolean deprecatedCreateMember;
+    // If done naively, collides with a C++ keyword.
+    [ImplementedAs=isPublic] boolean public;
     (double or DOMString) doubleOrStringMember = 3.14;
     sequence<(double or DOMString)> doubleOrStringSequenceMember;
     (double or DOMString) otherDoubleOrStringMember = "default string value";
@@ -37,5 +37,12 @@
     EventTarget eventTargetMember;
     any anyMember = null;
     Dictionary dictionaryMember;
-    [RuntimeEnabled=runtimeFeature] boolean runtimeMember;
+    [RuntimeEnabled=RuntimeFeature] boolean runtimeMember;
+    record<ByteString, byte> recordMember;
+    record<USVString, TestObject> garbageCollectedRecordMember;
+    record<ByteString, (long or boolean)> unionInRecordMember;
+    record<DOMString, any> anyInRecordMember;
+    (Float or BooleanType) unionWithTypedefs;
+    [Clamp] long applicableToTypeLongMember;
+    [TreatNullAs=EmptyString] DOMString applicableToTypeStringMember;
 };
diff --git a/bindings/tests/idls/core/TestDictionaryDerived.idl b/bindings/tests/idls/core/TestDictionaryDerived.idl
index 51817ef..4f274f1 100644
--- a/bindings/tests/idls/core/TestDictionaryDerived.idl
+++ b/bindings/tests/idls/core/TestDictionaryDerived.idl
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 [
-    ImplementedAs=TestDictionaryDerivedImplementedAs,
+    ImplementedAs=TestDictionaryDerivedImplementedAs
 ] dictionary TestDictionaryDerived : TestDictionary {
     DOMString derivedStringMember;
     DOMString derivedStringMemberWithDefault = "default string value";
diff --git a/bindings/tests/idls/core/TestException.idl b/bindings/tests/idls/core/TestException.idl
deleted file mode 100644
index 0c918b4..0000000
--- a/bindings/tests/idls/core/TestException.idl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-[
-    Constructor(unsigned short argument),
-    DoNotCheckConstants,
-] exception TestException {
-    readonly attribute unsigned short readonlyUnsignedShortAttribute;
-    readonly attribute DOMString readonlyStringAttribute;
-
-    const unsigned short UNSIGNED_SHORT_CONSTANT = 1;
-
-    [NotEnumerable] DOMString toString();
-};
diff --git a/bindings/tests/idls/core/TestImplements.idl b/bindings/tests/idls/core/TestImplements.idl
index ffe8372..601c050 100644
--- a/bindings/tests/idls/core/TestImplements.idl
+++ b/bindings/tests/idls/core/TestImplements.idl
@@ -27,7 +27,7 @@
  */
 
 [
-    NoInterfaceObject, // Always used on target of 'implements'
+    NoInterfaceObject // Always used on target of 'implements'
 ] interface TestImplements {
     static readonly attribute long implementsStaticReadOnlyLongAttribute;
     static attribute DOMString implementsStaticStringAttribute;
@@ -45,4 +45,7 @@
     [Reflect=IMPLEMENTS_REFLECT_CONSTANT] const unsigned short IMPLEMENTS_CONSTANT_2 = 2;
 
     [RuntimeEnabled=ImplementsFeatureName] attribute Node implementsRuntimeEnabledNodeAttribute;
+
+    [NotEnumerable] stringifier;
+    [NotEnumerable, RaisesException] serializer;
 };
diff --git a/bindings/tests/idls/core/TestImplements2.idl b/bindings/tests/idls/core/TestImplements2.idl
index ce0e357..e3e7905 100644
--- a/bindings/tests/idls/core/TestImplements2.idl
+++ b/bindings/tests/idls/core/TestImplements2.idl
@@ -31,7 +31,7 @@
 [
     LegacyTreatAsPartialInterface, // Conflicts with default implements behavior
     NoInterfaceObject, // Always used on target of 'implements'
-    RuntimeEnabled=Implements2FeatureName, // conflicts with [RuntimeEnabled] on member
+    RuntimeEnabled=Implements2FeatureName // conflicts with [RuntimeEnabled] on member
 ] interface TestImplements2 {
     static attribute DOMString implements2StaticStringAttribute;
     attribute DOMString implements2StringAttribute;
diff --git a/bindings/tests/idls/core/TestImplements3.idl b/bindings/tests/idls/core/TestImplements3.idl
index 4d18506..dff66fd 100644
--- a/bindings/tests/idls/core/TestImplements3.idl
+++ b/bindings/tests/idls/core/TestImplements3.idl
@@ -5,7 +5,7 @@
 [
     LegacyTreatAsPartialInterface, // used by [ImplementedAs]
     ImplementedAs=TestImplements3Implementation, // Conflicts with default implements class name
-    NoInterfaceObject, // Always used on target of 'implements'
+    NoInterfaceObject // Always used on target of 'implements'
 ] interface TestImplements3 {
     attribute DOMString implements3StringAttribute;
     static attribute DOMString implements3StaticStringAttribute;
diff --git a/bindings/tests/idls/core/TestIntegerIndexed.idl b/bindings/tests/idls/core/TestIntegerIndexed.idl
index ddc9d20..606bf12 100644
--- a/bindings/tests/idls/core/TestIntegerIndexed.idl
+++ b/bindings/tests/idls/core/TestIntegerIndexed.idl
@@ -12,5 +12,7 @@
     [Custom] setter Node (DOMString name, Node value);
     [Custom] deleter boolean (DOMString name);
 
+    iterable <[Clamp] long, DOMString>;
+
     void voidMethodDocument(Document document);
 };
diff --git a/bindings/tests/idls/core/TestInterface.idl b/bindings/tests/idls/core/TestInterface.idl
index 58c1e12..ec52097 100644
--- a/bindings/tests/idls/core/TestInterface.idl
+++ b/bindings/tests/idls/core/TestInterface.idl
@@ -32,15 +32,14 @@
 // Also used as a target by TestObject
 
 [
+    ActiveScriptWrappable,
     DependentLifetime,
     Custom=LegacyCallAsFunction,
     DoNotCheckConstants,
     ImplementedAs=TestInterfaceImplementation,
-    Iterable,
-    OriginTrialEnabled=OriginTrialFeatureName,
     RuntimeEnabled=FeatureName,
-    SetWrapperReferenceTo(TestInterface referencedName),
-    Exposed=(Worker,Window),
+    ContextEnabled=FeatureName,
+    Exposed=(Worker,Window)
 ] interface TestInterface : TestInterfaceEmpty {
     // members needed to test [ImplementedAs], as this affect attribute
     // configuration and method configuration
@@ -57,6 +56,8 @@
     attribute unrestricted float unrestrictedFloatAttribute;
     attribute TestEnum testEnumAttribute;
     attribute DOMStringOrDouble stringOrDoubleAttribute;
+    attribute [EnforceRange] long withExtendedAttributeStringAttribute;
+    [ImplementedAs=CapitalImplementation] attribute Implementation uncapitalAttribute;
     [RuntimeEnabled=FeatureName] attribute long conditionalLongAttribute;
     [RuntimeEnabled=FeatureName] readonly attribute long conditionalReadOnlyLongAttribute;
     static attribute DOMString staticStringAttribute;
@@ -73,18 +74,15 @@
     [PerWorldBindings] void voidMethod();
 
     // Anonymous indexed property operations
-    [DoNotCheckSecurity] getter DOMString (unsigned long index);
+    [CrossOrigin] getter DOMString (unsigned long index);
     setter DOMString (unsigned long index, DOMString value);
     deleter boolean (unsigned long index);
 
     // Anonymous named property operations
-    [DoNotCheckSecurity] getter DOMString (DOMString name);
+    [CrossOrigin] getter DOMString (DOMString name);
     setter DOMString (DOMString name, DOMString value);
     deleter boolean (DOMString name);
 
-    [NotEnumerable] stringifier;
-    [NotEnumerable, RaisesException] serializer;
-
     // Per-method [Exposed] annotation support.
     void alwaysExposedMethod();
     [Exposed=Worker] void workerExposedMethod();
@@ -116,9 +114,24 @@
     Promise promiseMethodPartialOverload(Window window);
     static Promise staticPromiseMethodPartialOverload();
 
+    iterable<ByteString, long>;
+
     [LenientThis] attribute any lenientThisAttribute;
 
     [LegacyInterfaceTypeChecking] void legacyInterfaceTypeCheckingMethod(TestInterfaceEmpty testInterfaceEmptyArg);
+
+    [SecureContext] void secureContextMethod();
+    [SecureContext] attribute bool secureContextAttribute;
+    [SecureContext,RuntimeEnabled=SecureFeature] void secureContextRuntimeEnabledMethod();
+    [SecureContext,RuntimeEnabled=SecureFeature] attribute bool secureContextRuntimeEnabledAttribute;
+    [SecureContext,Exposed=Window] void secureContextWindowExposedMethod();
+    [SecureContext,Exposed=Window] attribute bool secureContextWindowExposedAttribute;
+    [SecureContext,Exposed=Worker] void secureContextWorkerExposedMethod();
+    [SecureContext,Exposed=Worker] attribute bool secureContextWorkerExposedAttribute;
+    [SecureContext,Exposed=Window,RuntimeEnabled=SecureFeature] void secureContextWindowExposedRuntimeEnabledMethod();
+    [SecureContext,Exposed=Window,RuntimeEnabled=SecureFeature] attribute bool secureContextWindowExposedRuntimeEnabledAttribute;
+    [SecureContext,Exposed=Worker,RuntimeEnabled=SecureFeature] void secureContextWorkerExposedRuntimeEnabledMethod();
+    [SecureContext,Exposed=Worker,RuntimeEnabled=SecureFeature] attribute bool secureContextWorkerExposedRuntimeEnabledAttribute;
 };
 
 TestInterface implements TestImplements;
diff --git a/bindings/tests/idls/core/TestInterface2.idl b/bindings/tests/idls/core/TestInterface2.idl
index 18ab03f..30ed232 100644
--- a/bindings/tests/idls/core/TestInterface2.idl
+++ b/bindings/tests/idls/core/TestInterface2.idl
@@ -34,16 +34,19 @@
 // The more *minor* extended attribute should be put in this file.
 
 [
+    ActiveScriptWrappable, // Covered by [ActiveScriptWrappable]
     Constructor,
     DependentLifetime, // Covered by [DependentLifetime]
-    SetWrapperReferenceFrom=ownerNode, // Conflicts with [SetWrapperReferenceTo]
     // Note that Exposed(Arguments) has no effect on bindings-tests. It is
     // processed in generate_global_constructors.py.
-    Exposed(Window FeatureName), // Conflicts with Exposed=(Window,Worker)
+    Exposed(Window FeatureName) // Conflicts with Exposed=(Window,Worker)
 ] interface TestInterface2 {
     // This interface has only runtime enabled constants.
     [RuntimeEnabled=FeatureName] const unsigned short CONST_VALUE_1 = 1;
 
+    // Legacy caller with an identifier
+    legacycaller TestInterfaceEmpty legacyCaller(unsigned long index);
+
     // Indexed property operations with an identifier
     [RaisesException] getter TestInterfaceEmpty item(unsigned long index);
     [RaisesException] setter TestInterfaceEmpty setItem(unsigned long index, TestInterfaceEmpty value);
diff --git a/bindings/tests/idls/core/TestInterface3.idl b/bindings/tests/idls/core/TestInterface3.idl
index 4470f7c..8b9e423 100644
--- a/bindings/tests/idls/core/TestInterface3.idl
+++ b/bindings/tests/idls/core/TestInterface3.idl
@@ -34,9 +34,12 @@
 // The more *minor* extended attribute should be put in this file.
 
 [
-    Custom=VisitDOMWrapper, // Conflict with [SetWrapperReferenceTo] and [SetWrapperReferenceFrom]
-    NoImplHeader,
+    WebAgentAPI
 ] interface TestInterface3 {
+    // iterable<V> needs a "length" property accompanying the indexed property
+    // getter below.
+    readonly attribute unsigned long length;
+
     [Custom] getter boolean (unsigned long index);
     [Custom] setter boolean (unsigned long index, Node value);
     [Custom] deleter boolean (unsigned long index);
@@ -48,5 +51,6 @@
     void voidMethodDocument(Document document);
 
     [RuntimeEnabled=FeatureName] iterable<any>;
-    [RuntimeEnabled=FeatureName, CallWith=ScriptState, RaisesException, ImplementedAs=iterableKeys] Iterator keys();
+
+    stringifier readonly attribute DOMString readonlyStringifierAttribute;
 };
diff --git a/bindings/tests/idls/core/TestInterfaceCheckSecurity.idl b/bindings/tests/idls/core/TestInterfaceCheckSecurity.idl
index 5aaf41d..fd04326 100644
--- a/bindings/tests/idls/core/TestInterfaceCheckSecurity.idl
+++ b/bindings/tests/idls/core/TestInterfaceCheckSecurity.idl
@@ -28,19 +28,18 @@
 
 [
     CheckSecurity=Receiver,
-    Global,
+    Global
 ] interface TestInterfaceCheckSecurity {
     readonly attribute long readonlyLongAttribute;
     attribute long longAttribute;
     void voidMethod();
 
-    [DoNotCheckSecurity] attribute long doNotCheckSecurityLongAttribute;
-    [DoNotCheckSecurity] readonly attribute long doNotCheckSecurityReadonlyLongAttribute; // Separate read only attribute to check attribute configuration
-    [DoNotCheckSecurity=Setter] attribute long doNotCheckSecurityOnSetterLongAttribute;
-    [DoNotCheckSecurity, Replaceable] readonly attribute long doNotCheckSecurityReplaceableReadonlyLongAttribute;
+    [CrossOrigin] attribute long doNotCheckSecurityLongAttribute;
+    [CrossOrigin] readonly attribute long doNotCheckSecurityReadonlyLongAttribute; // Separate read only attribute to check attribute configuration
+    [CrossOrigin=Setter] attribute long doNotCheckSecurityOnSetterLongAttribute;
+    [CrossOrigin, Replaceable] readonly attribute long doNotCheckSecurityReplaceableReadonlyLongAttribute;
 
-    [DoNotCheckSecurity] void doNotCheckSecurityVoidMethod();
-    [DoNotCheckSecurity, DoNotCheckSignature] void doNotCheckSecurityDoNotCheckSignatureVoidMethod();
-    [DoNotCheckSecurity, PerWorldBindings] void doNotCheckSecurityPerWorldBindingsVoidMethod();
-    [DoNotCheckSecurity, Unforgeable] void doNotCheckSecurityUnforgeableVoidMethod();
+    [CrossOrigin] void doNotCheckSecurityVoidMethod();
+    [CrossOrigin, PerWorldBindings] void doNotCheckSecurityPerWorldBindingsVoidMethod();
+    [CrossOrigin, Unforgeable] void doNotCheckSecurityUnforgeableVoidMethod();
 };
diff --git a/bindings/tests/idls/core/TestInterfaceConstructor.idl b/bindings/tests/idls/core/TestInterfaceConstructor.idl
index 29878ae..e60065d 100644
--- a/bindings/tests/idls/core/TestInterfaceConstructor.idl
+++ b/bindings/tests/idls/core/TestInterfaceConstructor.idl
@@ -46,6 +46,6 @@
     NamedConstructor=Audio(DOMString arg, optional DOMString optArg),
     ConstructorCallWith=(ScriptState,ExecutionContext,Document),
     MeasureAs=TestFeature,
-    RaisesException=Constructor,
+    RaisesException=Constructor
 ] interface TestInterfaceConstructor {
 };
diff --git a/bindings/tests/idls/core/TestInterfaceConstructor2.idl b/bindings/tests/idls/core/TestInterfaceConstructor2.idl
index 209a000..097b27c 100644
--- a/bindings/tests/idls/core/TestInterfaceConstructor2.idl
+++ b/bindings/tests/idls/core/TestInterfaceConstructor2.idl
@@ -47,6 +47,6 @@
         [Default=Undefined] optional DOMString defaultUndefinedOptionalStringArg,
         optional DOMString defaultNullStringOptionalStringArg = null,
         [Default=Undefined] optional Dictionary defaultUndefinedOptionalDictionaryArg,
-        optional DOMString optionalStringArg),
+        optional DOMString optionalStringArg)
 ] interface TestInterfaceConstructor2 {
 };
diff --git a/bindings/tests/idls/core/TestInterfaceConstructor3.idl b/bindings/tests/idls/core/TestInterfaceConstructor3.idl
index 19b6669..00d23be 100644
--- a/bindings/tests/idls/core/TestInterfaceConstructor3.idl
+++ b/bindings/tests/idls/core/TestInterfaceConstructor3.idl
@@ -30,6 +30,6 @@
 
 // Test for length > 0, non-overloaded constructor.
 [
-    Constructor(DOMString stringArg),
+    Constructor(DOMString stringArg)
 ] interface TestInterfaceConstructor3 {
 };
diff --git a/bindings/tests/idls/core/TestInterfaceConstructor4.idl b/bindings/tests/idls/core/TestInterfaceConstructor4.idl
index 2153167..e6980fb 100644
--- a/bindings/tests/idls/core/TestInterfaceConstructor4.idl
+++ b/bindings/tests/idls/core/TestInterfaceConstructor4.idl
@@ -6,6 +6,6 @@
 // argument.
 [
     Constructor(TestInterfaceConstructor4 testInterface4Arg),
-    Constructor(USVString usvStringArg),
+    Constructor(USVString usvStringArg)
 ] interface TestInterfaceConstructor4 {
 };
diff --git a/bindings/tests/idls/core/TestInterfaceCustomConstructor.idl b/bindings/tests/idls/core/TestInterfaceCustomConstructor.idl
index dba8b7a..35fccd7 100644
--- a/bindings/tests/idls/core/TestInterfaceCustomConstructor.idl
+++ b/bindings/tests/idls/core/TestInterfaceCustomConstructor.idl
@@ -31,6 +31,6 @@
 [
     CustomConstructor,
     CustomConstructor(TestInterfaceEmpty testInterfaceEmptyArg),
-    CustomConstructor(double doubleArg, optional double optionalDoubleArg),
+    CustomConstructor(double doubleArg, optional double optionalDoubleArg)
 ] interface TestInterfaceCustomConstructor {
 };
diff --git a/bindings/tests/idls/core/TestInterfaceEventInitConstructor.idl b/bindings/tests/idls/core/TestInterfaceEventInitConstructor.idl
index 2fa3746..0e30790 100644
--- a/bindings/tests/idls/core/TestInterfaceEventInitConstructor.idl
+++ b/bindings/tests/idls/core/TestInterfaceEventInitConstructor.idl
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 [
-    Constructor(DOMString type, TestInterfaceEventInit testInterfaceEventInit),
+    Constructor(DOMString type, TestInterfaceEventInit testInterfaceEventInit)
 ] interface TestInterfaceEventInitConstructor : Event {
     readonly attribute DOMString readonlyStringAttribute;
 };
diff --git a/bindings/tests/idls/core/TestInterfaceEventTarget.idl b/bindings/tests/idls/core/TestInterfaceEventTarget.idl
index 742c6d7..f86dbfd 100644
--- a/bindings/tests/idls/core/TestInterfaceEventTarget.idl
+++ b/bindings/tests/idls/core/TestInterfaceEventTarget.idl
@@ -30,6 +30,6 @@
 
 [
     NamedConstructor=Name(),
-    ConstructorCallWith=Document,
+    ConstructorCallWith=Document
 ] interface TestInterfaceEventTarget : EventTarget {
 };
diff --git a/bindings/tests/idls/core/TestInterfaceGarbageCollected.idl b/bindings/tests/idls/core/TestInterfaceGarbageCollected.idl
index 216cbed..7e5313d 100644
--- a/bindings/tests/idls/core/TestInterfaceGarbageCollected.idl
+++ b/bindings/tests/idls/core/TestInterfaceGarbageCollected.idl
@@ -3,11 +3,10 @@
 // found in the LICENSE file.
 
 [
-    Constructor(DOMString str),
-    GarbageCollected,
+    Constructor(DOMString str)
 ] interface TestInterfaceGarbageCollected : EventTarget { // Inherit from EventTarget to test order of internal fields
     attribute TestInterfaceGarbageCollected attr1;
     void func(TestInterfaceGarbageCollected arg);
 
-    setlike<DOMString>;
+    setlike<[TreatNullAs=EmptyString] DOMString>;
 };
diff --git a/bindings/tests/idls/core/TestInterfaceNamedConstructor.idl b/bindings/tests/idls/core/TestInterfaceNamedConstructor.idl
index 1185fab..4d57a70 100644
--- a/bindings/tests/idls/core/TestInterfaceNamedConstructor.idl
+++ b/bindings/tests/idls/core/TestInterfaceNamedConstructor.idl
@@ -27,6 +27,7 @@
  */
 
 [
+    ActiveScriptWrappable,
     DependentLifetime,
     NamedConstructor=Audio(
         DOMString stringArg,
@@ -36,7 +37,7 @@
         optional DOMString defaultNullStringOptionalstringArg = null,
         optional DOMString optionalStringArg),
     ConstructorCallWith=Document,
-    RaisesException=Constructor,
+    RaisesException=Constructor
 ] interface TestInterfaceNamedConstructor {
     // An attribute of type {interface_name}ConstructorConstructor is generated
     // in *Constructors.idl file, which is a partial interface for the global
diff --git a/bindings/tests/idls/core/TestInterfaceNamedConstructor2.idl b/bindings/tests/idls/core/TestInterfaceNamedConstructor2.idl
index 1494ffd..1f3aa01 100644
--- a/bindings/tests/idls/core/TestInterfaceNamedConstructor2.idl
+++ b/bindings/tests/idls/core/TestInterfaceNamedConstructor2.idl
@@ -30,6 +30,6 @@
 
 // "Number of arguments" check varies if [RaisesException=Constructor] or not
 [
-    NamedConstructor=Audio(DOMString stringArg),
+    NamedConstructor=Audio(DOMString stringArg)
 ] interface TestInterfaceNamedConstructor2 {
 };
diff --git a/bindings/tests/idls/core/TestInterfaceOriginTrialEnabled.idl b/bindings/tests/idls/core/TestInterfaceOriginTrialEnabled.idl
new file mode 100644
index 0000000..959db4b
--- /dev/null
+++ b/bindings/tests/idls/core/TestInterfaceOriginTrialEnabled.idl
@@ -0,0 +1,25 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Test for [OriginTrialEnabled] extended attribute applied to an interface.
+// This is separate from TestInterface (and TestInterface[2|3]), as the
+// [OriginTrialEnabled] attribute takes precedence over [RuntimeEnabled].
+
+[
+    OriginTrialEnabled=InterfaceFeatureName
+] interface TestInterfaceOriginTrialEnabled {
+    const unsigned long UNSIGNED_LONG = 0;
+    const short CONST_JAVASCRIPT = 1;
+
+    attribute double doubleAttribute;
+    [RuntimeEnabled=FeatureName] attribute long conditionalLongAttribute;
+    [RuntimeEnabled=FeatureName] readonly attribute long conditionalReadOnlyLongAttribute;
+    static attribute DOMString staticStringAttribute;
+    [RuntimeEnabled=FeatureName] static readonly attribute long staticConditionalReadOnlyLongAttribute;
+
+    void voidMethodDoubleArgFloatArg(double doubleArg, float floatArg);
+
+    void voidMethodPartialOverload();
+    void voidMethodPartialOverload(double doubleArg);
+};
diff --git a/bindings/tests/idls/core/TestInterfacePartial.idl b/bindings/tests/idls/core/TestInterfacePartial.idl
new file mode 100644
index 0000000..fe896b2
--- /dev/null
+++ b/bindings/tests/idls/core/TestInterfacePartial.idl
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+enum PartialEnumType {
+    "foo",
+    "bar"
+};
+
+typedef DOMString PartialString;
+
+[Custom] callback PartialCallbackType = void (PartialString value);
+[
+    ImplementedAs=TestInterfacePartial,
+    RuntimeEnabled=PartialFeatureName
+] partial interface TestInterface {
+    const unsigned short PARTIAL_UNSIGNED_SHORT = 0;
+    const double PARTIAL_DOUBLE = 3.14;
+
+    attribute long partialLongAttribute;
+    static attribute long partialStaticLongAttribute;
+    [CallWith=ExecutionContext] attribute long partialCallWithExecutionContextLongAttribute;
+
+    void partialVoidMethod();
+    static void partialStaticVoidMethod();
+    void partialVoidMethodLongArg(long longArg);
+    [CallWith=ExecutionContext, RaisesException] void partialCallWithExecutionContextRaisesExceptionVoidMethod();
+
+    attribute PartialEnumType partialPartialEnumTypeAttribute;
+    void partialVoidMethodPartialCallbackTypeArg(PartialCallbackType partialCallbackTypeArg);
+
+    [SecureContext] attribute long partialSecureContextLongAttribute;
+};
diff --git a/bindings/tests/idls/core/TestInterfacePartial2.idl b/bindings/tests/idls/core/TestInterfacePartial2.idl
new file mode 100644
index 0000000..59993ef
--- /dev/null
+++ b/bindings/tests/idls/core/TestInterfacePartial2.idl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    ImplementedAs=TestInterfacePartial2Implementation // Conflicts with default partial interface class name
+] partial interface TestInterface {
+    const unsigned short PARTIAL2_UNSIGNED_SHORT = 0;
+
+    attribute long partial2LongAttribute;
+    static attribute long partial2StaticLongAttribute;
+
+    void partial2VoidMethod();
+    static void partial2StaticVoidMethod();
+
+    [SecureContext] void partial2SecureContextMethod();
+    [SecureContext] attribute bool partial2SecureContextAttribute;
+};
diff --git a/bindings/tests/idls/core/TestInterfacePartialSecureContext.idl b/bindings/tests/idls/core/TestInterfacePartialSecureContext.idl
new file mode 100644
index 0000000..8b22d79
--- /dev/null
+++ b/bindings/tests/idls/core/TestInterfacePartialSecureContext.idl
@@ -0,0 +1,22 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+    SecureContext,
+    Exposed=(Window,Worker),
+    ImplementedAs=TestInterfacePartialSecureContext // Conflicts with default partial interface class name
+] partial interface TestInterface {
+    void partialSecureContextMethod();
+    attribute bool partialSecureContextAttribute;
+    [RuntimeEnabled=SecureFeature] void partialSecureContextRuntimeEnabledMethod();
+    [RuntimeEnabled=SecureFeature] attribute bool partialSecureContextRuntimeEnabledAttribute;
+    [Exposed=Window] void partialSecureContextWindowExposedMethod();
+    [Exposed=Window] attribute bool partialSecureContextWindowExposedAttribute;
+    [Exposed=Worker] void partialSecureContextWorkerExposedMethod();
+    [Exposed=Worker] attribute bool partialSecureContextWorkerExposedAttribute;
+    [Exposed=Window,RuntimeEnabled=SecureFeature] void partialSecureContextWindowExposedRuntimeEnabledMethod();
+    [Exposed=Window,RuntimeEnabled=SecureFeature] attribute bool partialSecureContextWindowExposedRuntimeEnabledAttribute;
+    [Exposed=Worker,RuntimeEnabled=SecureFeature] void partialSecureContextWorkerExposedRuntimeEnabledMethod();
+    [Exposed=Worker,RuntimeEnabled=SecureFeature] attribute bool partialSecureContextWorkerExposedRuntimeEnabledAttribute;
+};
diff --git a/bindings/tests/idls/core/TestInterfaceSecureContext.idl b/bindings/tests/idls/core/TestInterfaceSecureContext.idl
new file mode 100644
index 0000000..e43c2b2
--- /dev/null
+++ b/bindings/tests/idls/core/TestInterfaceSecureContext.idl
@@ -0,0 +1,21 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+    SecureContext,
+    Exposed=(Window,Worker)
+] interface TestInterfaceSecureContext {
+    void secureContextMethod();
+    attribute bool secureContextAttribute;
+    [RuntimeEnabled=SecureFeature] void secureContextRuntimeEnabledMethod();
+    [RuntimeEnabled=SecureFeature] attribute bool secureContextRuntimeEnabledAttribute;
+    [Exposed=Window] void secureContextWindowExposedMethod();
+    [Exposed=Window] attribute bool secureContextWindowExposedAttribute;
+    [Exposed=Worker] void secureContextWorkerExposedMethod();
+    [Exposed=Worker] attribute bool secureContextWorkerExposedAttribute;
+    [Exposed=Window,RuntimeEnabled=SecureFeature] void secureContextWindowExposedRuntimeEnabledMethod();
+    [Exposed=Window,RuntimeEnabled=SecureFeature] attribute bool secureContextWindowExposedRuntimeEnabledAttribute;
+    [Exposed=Worker,RuntimeEnabled=SecureFeature] void secureContextWorkerExposedRuntimeEnabledMethod();
+    [Exposed=Worker,RuntimeEnabled=SecureFeature] attribute bool secureContextWorkerExposedRuntimeEnabledAttribute;
+};
diff --git a/bindings/tests/idls/core/TestInterfaceWillBeGarbageCollected.idl b/bindings/tests/idls/core/TestInterfaceWillBeGarbageCollected.idl
deleted file mode 100644
index 8515a03..0000000
--- a/bindings/tests/idls/core/TestInterfaceWillBeGarbageCollected.idl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-[
-    Constructor(DOMString str),
-    NamedConstructor=TestInterface(DOMString str),
-    WillBeGarbageCollected,
-    Unforgeable,
-] interface TestInterfaceWillBeGarbageCollected : EventTarget { // Inherit from EventTarget to test order of internal fields
-    attribute TestInterfaceWillBeGarbageCollected attr1;
-    void func(TestInterfaceWillBeGarbageCollected arg);
-};
diff --git a/bindings/tests/idls/core/TestLegacyCallbackInterface.idl b/bindings/tests/idls/core/TestLegacyCallbackInterface.idl
new file mode 100644
index 0000000..78d7a1a
--- /dev/null
+++ b/bindings/tests/idls/core/TestLegacyCallbackInterface.idl
@@ -0,0 +1,9 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+callback interface TestLegacyCallbackInterface {
+  const unsigned short CONST_VALUE_USHORT_42 = 42;
+
+  unsigned short acceptNode(Node node);
+};
diff --git a/bindings/tests/idls/core/TestNode