Files
sdk/tools/dom/scripts/fremontcutbuilder.py
Srujan Gaddam 67bda7c22b [dart2js/ddc/dart2wasm/dart:js_interop] Support SharedArrayBuffers in JS typed data wrappers
https://github.com/dart-lang/sdk/issues/56455

The existing native typed data implementation in dart2js/ddc
and the JS typed data wrappers in dart2wasm do not support
SharedArrayBuffers.

In dart2js/ddc, this is because the native type for ByteBuffer
is simply ArrayBuffer, leading to type failures when using
SharedArrayBuffers. To handle this, this change makes NativeByteBuffer
an abstract parent class to NativeArrayBuffer and NativeSharedArrayBuffer.
This allows ByteBuffer to support both types. There is a preexisting
SharedArrayBuffer type in dart:html that we should avoid breaking, so
we add an interface that NativeSharedArrayBuffer implements and expose
that interface.

In dart2wasm, JSArrayBufferImpl only allows ArrayBuffers as its
extern ref. This change makes that wrapper support SharedArrayBuffers
as well.

In dart:js_interop, the existing toJS conversion on ByteBuffer
now throws if the underlying buffer was actually a SharedArrayBuffer.
This is to support the return type of JSArrayBuffer. This behavior
technically already existed due to type differences in the JS
compilers, but was never possible with dart2wasm.

CoreLibraryReviewExempt: Backend-specific libraries with no real functional changes to public APIs.
Change-Id: I4dac9fb808590bf0c274da815c152cd4637316b1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/437526
Reviewed-by: Stephen Adams <sra@google.com>
Commit-Queue: Srujan Gaddam <srujzs@google.com>
2025-07-07 12:50:25 -07:00

218 lines
7.7 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright (c) 2011, 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.
import database
import databasebuilder
import idlnode
import logging.config
import os.path
import sys
import time
import utilities
import dependency
from idlnode import IDLType, resolveTypedef
_logger = logging.getLogger('fremontcutbuilder')
# See:
# http://src.chromium.org/viewvc/multivm/trunk/webkit/Source/core/features.gypi
# for ENABLE_* flags defined in Chromium / Blink.
# We list all ENABLE flags used in IDL in one of these two lists.
FEATURE_DISABLED = [
'ENABLE_CUSTOM_SCHEME_HANDLER',
'ENABLE_MEDIA_CAPTURE', # Only enabled on Android.
'ENABLE_ORIENTATION_EVENTS', # Only enabled on Android.
'ENABLE_WEBVTT_REGIONS',
]
FEATURE_DEFINES = [
'ENABLE_CALENDAR_PICKER', # Not on Android
'ENABLE_ENCRYPTED_MEDIA_V2',
'ENABLE_INPUT_SPEECH', # Not on Android
'ENABLE_LEGACY_NOTIFICATIONS', # Not on Android
'ENABLE_NAVIGATOR_CONTENT_UTILS', # Not on Android
'ENABLE_NOTIFICATIONS', # Not on Android
'ENABLE_SVG_FONTS',
'ENABLE_WEB_AUDIO', # Not on Android
]
# Resolve all typedefs encountered while parsing (see idlnode.py), resolve any typedefs not resolved
# during parsing. This must be done before the database is created, merged, and augmented to
# exact type matching. Typedefs can be encountered in any IDL and usage can cross IDL boundaries.
def ResolveAllTypedefs(all_interfaces):
# Resolve all typedefs.
for interface, db_Opts in all_interfaces:
def IsIdentified(idl_node):
node_name = idl_node.id if idl_node.id else 'parent'
for idl_type in idl_node.all(idlnode.IDLType):
# One last check is the type a typedef in an IDL file (the typedefs
# are treated as global).
resolvedType = resolveTypedef(idl_type)
if (resolvedType != idl_type):
idl_type.id = resolvedType.id
idl_type.nullable = resolvedType.nullable
continue
return True
interface.constants = list(filter(IsIdentified, interface.constants))
interface.attributes = list(filter(IsIdentified, interface.attributes))
interface.operations = list(filter(IsIdentified, interface.operations))
interface.parents = list(filter(IsIdentified, interface.parents))
def build_database(idl_files,
database_dir,
feature_defines=None,
logging_level=logging.WARNING,
examine_idls=False):
"""This code reconstructs the FremontCut IDL database from W3C,
WebKit and Dart IDL files."""
current_dir = os.path.dirname(__file__)
logging.config.fileConfig(os.path.join(current_dir, "logging.conf"))
_logger.setLevel(logging_level)
db = database.Database(database_dir)
# Delete all existing IDLs in the DB.
db.Delete()
builder = databasebuilder.DatabaseBuilder(db)
dependency.set_builder(builder)
# TODO(vsm): Move this to a README.
# This is the Chrome revision.
webkit_revision = '63'
# TODO(vsm): Reconcile what is exposed here and inside WebKit code
# generation. We need to recheck this periodically for now.
webkit_defines = ['LANGUAGE_DART', 'LANGUAGE_JAVASCRIPT']
if feature_defines is None:
feature_defines = FEATURE_DEFINES
webkit_options = databasebuilder.DatabaseBuilderOptions(
# TODO(vsm): What else should we define as on when processing IDL?
idl_defines=webkit_defines + feature_defines,
source='WebKit',
source_attributes={'revision': webkit_revision},
logging_level=logging_level)
# Import WebKit IDLs.
builder.import_idl_files(idl_files, webkit_options, False)
# Import Dart idl:
dart_options = databasebuilder.DatabaseBuilderOptions(
source='Dart',
rename_operation_arguments_on_merge=True,
logging_level=logging_level)
utilities.KNOWN_COMPONENTS = frozenset(['core', 'modules', 'dart'])
builder.import_idl_files(
[os.path.join(current_dir, '..', 'idl', 'dart', 'dart.idl')],
dart_options, True)
start_time = time.time()
# All typedefs MUST be resolved here before any database fixups (merging, implements, etc.)
ResolveAllTypedefs(builder._imported_interfaces)
# Merging:
builder.merge_imported_interfaces()
builder.fetch_constructor_data(webkit_options)
builder.fix_displacements('WebKit')
# Cleanup:
builder.normalize_annotations(['WebKit', 'Dart'])
# Map any IDL defined dictionaries to Dictionary.
builder.map_dictionaries()
# Examine all IDL and produce a diagnoses of areas (e.g., list dictionaries
# declared and usage, etc.)
if examine_idls:
builder.examine_database()
conditionals_met = set(
'ENABLE_' + conditional for conditional in builder.conditionals_met)
known_conditionals = set(FEATURE_DEFINES + FEATURE_DISABLED)
unused_conditionals = known_conditionals - conditionals_met
if unused_conditionals:
_logger.warning('There are some unused conditionals %s' %
sorted(unused_conditionals))
_logger.warning('Please update fremontcutbuilder.py')
unknown_conditionals = conditionals_met - known_conditionals
if unknown_conditionals:
_logger.warning('There are some unknown conditionals %s' %
sorted(unknown_conditionals))
_logger.warning('Please update fremontcutbuilder.py')
print('Merging interfaces %s seconds' % round(time.time() - start_time, 2))
return db
def main(parallel=False, logging_level=logging.WARNING, examine_idls=False):
current_dir = os.path.dirname(__file__)
idl_files = []
# Check default location in a regular dart enlistment.
webcore_dir = os.path.join(current_dir, '..', '..', '..', 'third_party',
'WebCore')
if not os.path.exists(webcore_dir):
# Check default location in a dartium enlistment.
webcore_dir = os.path.join(current_dir, '..', '..', '..', '..',
'third_party', 'WebKit', 'Source')
if not os.path.exists(webcore_dir):
raise RuntimeError('directory not found: %s' % webcore_dir)
DIRS_TO_IGNORE = [
'bindings', # Various test IDLs
'testing', # IDLs to expose testing APIs
'networkinfo', # Not yet used in Blink yet
'vibration', # Not yet used in Blink yet
'inspector',
'idl_parser', # idl_parser has test IDL files.
]
# TODO(terry): Integrate this into the htmlrenamer's
# _suppressed_html_interfaces (if possible).
FILES_TO_IGNORE = [
'InspectorFrontendHostFileSystem.idl', # Uses interfaces in inspector dir (which is ignored)
'WebKitGamepad.idl', # Gamepad.idl is the new one.
'WebKitGamepadList.idl', # GamepadList is the new one.
]
for (dir_name, dirs, files) in os.walk(webcore_dir):
if os.path.basename(dir_name) in DIRS_TO_IGNORE:
dirs[:] = [] # Do not go underneath
else:
for name in files:
file_name = os.path.join(dir_name, name)
(interface, ext) = os.path.splitext(file_name)
if ext == '.idl' and not (name in FILES_TO_IGNORE):
idl_files.append(file_name)
database_dir = os.path.join(current_dir, '..', 'database')
return build_database(
idl_files,
database_dir,
logging_level=logging_level,
examine_idls=examine_idls)
if __name__ == '__main__':
sys.exit(main())