GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — lib: harden webidl dictionary member reads · nodejs/node@151ca7e

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • lib/internal
    • webidl.js
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎lib/internal/webidl.js‎

Copy file name to clipboardExpand all lines: lib/internal/webidl.js
+45-11Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const {
2020
NumberIsNaN,
2121
NumberMAX_SAFE_INTEGER,
2222
NumberMIN_SAFE_INTEGER,
23+
ObjectPrototypeHasOwnProperty,
2324
ObjectPrototypeIsPrototypeOf,
2425
SafeArrayIterator,
2526
SafeSet,
@@ -699,16 +700,47 @@ function createDictionaryConverter(
699700
const dictionaries = ArrayIsArray(members[0]) ? members : [members];
700701
const sortedDictionaries = [];
701702

703+
function ownMember(member, key) {
704+
return ObjectPrototypeHasOwnProperty(member, key) ? member[key] : undefined;
705+
}
706+
707+
// Dictionaries with no defaults and no required members skip steps
708+
// 4.1.5/4.1.6 entirely, keeping the absent-member path free.
709+
let anyMissingMemberHandling = false;
710+
702711
// Web IDL dictionary conversion steps 3-4 process inherited dictionaries
703712
// from least-derived to most-derived and sort only within each dictionary.
704713
// Callers with inheritance pass one member array per dictionary level.
705714
for (let i = 0; i < dictionaries.length; i++) {
706-
ArrayPrototypePush(
707-
sortedDictionaries,
708-
ArrayPrototypeToSorted(dictionaries[i], compareMembers),
715+
const sortedMembers = ArrayPrototypeToSorted(
716+
dictionaries[i],
717+
compareMembers,
709718
);
719+
// Definition sites spell out only the members they need, so reading the
720+
// optional ones below would resolve through %Object.prototype%.
721+
// Re-materialize each descriptor once with every key present, copied from
722+
// own properties only. The ordinary prototype is deliberate: nothing
723+
// consults it now, and detaching it measurably slows these reads down.
724+
for (let j = 0; j < sortedMembers.length; j++) {
725+
const member = sortedMembers[j];
726+
const defaultValue = ownMember(member, 'defaultValue');
727+
const required = ownMember(member, 'required');
728+
if (typeof defaultValue === 'function' || required) {
729+
anyMissingMemberHandling = true;
730+
}
731+
sortedMembers[j] = {
732+
key: ownMember(member, 'key'),
733+
converter: ownMember(member, 'converter'),
734+
defaultValue,
735+
required,
736+
validator: ownMember(member, 'validator'),
737+
};
738+
}
739+
ArrayPrototypePush(sortedDictionaries, sortedMembers);
710740
}
711741

742+
const hasMissingMemberHandling = anyMissingMemberHandling;
743+
712744
return function(jsDict, options = kEmptyObject) {
713745
// Step 1: reject non-object, non-null, non-undefined values.
714746
if (jsDict != null && type(jsDict) !== 'Object') {
@@ -747,14 +779,16 @@ function createDictionaryConverter(
747779
member.validator?.(idlMemberValue, jsDict);
748780
// Step 4.1.4.2: set idlDict[key] to the IDL value.
749781
idlDict[key] = idlMemberValue;
750-
} else if (typeof member.defaultValue === 'function') {
751-
// Step 4.1.5: store the member default value.
752-
idlDict[key] = member.defaultValue();
753-
} else if (member.required) {
754-
// Step 4.1.6: required missing members throw.
755-
throw makeException(
756-
missingDictionaryMemberMessage(dictionaryName, key),
757-
makeOptions(options, options.context, 'ERR_MISSING_OPTION'));
782+
} else if (hasMissingMemberHandling) {
783+
if (typeof member.defaultValue === 'function') {
784+
// Step 4.1.5: store the member default value.
785+
idlDict[key] = member.defaultValue();
786+
} else if (member.required) {
787+
// Step 4.1.6: required missing members throw.
788+
throw makeException(
789+
missingDictionaryMemberMessage(dictionaryName, key),
790+
makeOptions(options, options.context, 'ERR_MISSING_OPTION'));
791+
}
758792
}
759793
}
760794
}

0 commit comments

Comments
0 (0)
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.